io.v.android.apps.namespace_browser.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for io.v.android.apps.namespace_browser.MainActivity.java

Source

// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.android.apps.namespace_browser;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import org.joda.time.Duration;

import java.util.List;

import io.v.android.libs.security.BlessingsManager;
import io.v.android.v23.V;
import io.v.v23.InputChannelCallback;
import io.v.v23.InputChannels;
import io.v.v23.context.VContext;
import io.v.v23.naming.GlobError;
import io.v.v23.naming.GlobReply;
import io.v.v23.naming.MountEntry;
import io.v.v23.naming.MountedServer;
import io.v.v23.security.Blessings;

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private static final String BLESSINGS_KEY = "BlessingsKey";

    private static final String PREF_NAMESPACE_GLOB_ROOT = "pref_namespace_glob_root";
    private static final String DEFAULT_NAMESPACE_GLOB_ROOT = "";
    private static final String SAVED_VIEW_STATE_KEY = "browser_viewstate";

    private VContext mBaseContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBaseContext = V.init(this);
        String root = PreferenceManager.getDefaultSharedPreferences(this).getString(PREF_NAMESPACE_GLOB_ROOT,
                DEFAULT_NAMESPACE_GLOB_ROOT);
        View dirView = findViewById(R.id.directory);
        dirView.setPadding( // remove left padding for the root.
                0, dirView.getPaddingTop(), dirView.getPaddingRight(), dirView.getPaddingBottom());
        dirView.setTag(new GlobReply.Entry(new MountEntry(root, ImmutableList.<MountedServer>of(), true, false)));
        TextView nameView = (TextView) dirView.findViewById(R.id.name);
        nameView.setText("/");
        Drawable d = getResources().getDrawable(R.drawable.ic_account_box_black_36dp);
        d.setColorFilter(new LightingColorFilter(Color.BLACK, Color.GRAY));
        Futures.addCallback(BlessingsManager.getBlessings(mBaseContext, this, BLESSINGS_KEY, true),
                new FutureCallback<Blessings>() {
                    @Override
                    public void onSuccess(Blessings result) {
                        android.util.Log.i(TAG, "Success.");
                    }

                    @Override
                    public void onFailure(Throwable t) {
                        android.util.Log.e(TAG, "Couldn't get blessings: " + t.getMessage());
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBaseContext.cancel();
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        Parcel parcel = Parcel.obtain();
        ViewUtil.serializeView(findViewById(R.id.directory), parcel);
        savedInstanceState.putByteArray(SAVED_VIEW_STATE_KEY, parcel.marshall());
        parcel.recycle();
        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        byte[] data = savedInstanceState.getByteArray(SAVED_VIEW_STATE_KEY);
        Parcel parcel = Parcel.obtain();
        parcel.unmarshall(data, 0, data.length);
        parcel.setDataPosition(0);
        LinearLayout dirView = (LinearLayout) ViewUtil.deserializeView(parcel, getLayoutInflater());
        parcel.recycle();
        // Replace old directory view with the new one.
        LinearLayout oldDirView = (LinearLayout) findViewById(R.id.directory);
        ViewGroup parent = (ViewGroup) oldDirView.getParent();
        int index = parent.indexOfChild(oldDirView);
        parent.removeView(oldDirView);
        parent.addView(dirView, index);
        super.onRestoreInstanceState(savedInstanceState);
    }

    public void onItemClick(View view) {
        switch (view.getId()) {
        case R.id.directory:
            handleDirectoryClick(view);
            break;
        case R.id.object:
            handleObjectClick(view);
            break;
        case R.id.method:
            handleMethodClick(view);
            break;
        default:
            android.util.Log.e(TAG, String.format("Click on an illegal view with id: %d", view.getId()));
        }
    }

    private void handleDirectoryClick(View view) {
        LinearLayout dirView = (LinearLayout) view;
        if (!dirView.isActivated()) {
            // Add new views.
            fetchNames(dirView);
        } else {
            // Remove all but the first view.
            if (dirView.getChildCount() > 1) {
                dirView.removeViews(1, dirView.getChildCount() - 1);
            }
            ViewUtil.updateDirectoryView(dirView, false);
        }
    }

    private void handleObjectClick(View view) {
        LinearLayout objView = (LinearLayout) view;
        if (!objView.isActivated()) {
            // Add new views.
            fetchMethods(objView);
        } else {
            // Remove all but the first view.
            if (objView.getChildCount() > 1) {
                objView.removeViews(1, objView.getChildCount() - 1);
            }
            ViewUtil.updateObjectView(objView, false);
        }
    }

    private void handleMethodClick(View view) {
        LinearLayout methodView = (LinearLayout) view;
        // Add claiming logic here.
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_account: {
            Futures.addCallback(BlessingsManager.mintBlessings(mBaseContext, this, BLESSINGS_KEY, true),
                    new FutureCallback<Blessings>() {
                        @Override
                        public void onSuccess(Blessings result) {
                            Toast.makeText(MainActivity.this, "Success.", Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onFailure(Throwable t) {
                            Log.e(TAG, "Couldn't get blessings: " + t.getMessage());
                        }
                    });
            return true;
        }
        case R.id.action_settings: {
            Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
            startActivity(intent);
            return true;
        }
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private void fetchNames(final LinearLayout dirView) {
        ViewUtil.updateDirectoryView(dirView, true);
        GlobReply entry = (GlobReply) dirView.getTag();
        if (!(entry instanceof GlobReply.Entry)) {
            return;
        }
        final MountEntry dirEntry = ((GlobReply.Entry) entry).getElem();
        final ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setMessage("Fetching Names...");
        progressDialog.show();
        String root = dirEntry.getName();
        io.v.v23.namespace.Namespace n = V.getNamespace(mBaseContext);
        VContext ctxT = mBaseContext.withTimeout(new Duration(20000)); // 20s
        Futures.addCallback(InputChannels.withCallback(n.glob(ctxT, root.isEmpty() ? "*" : root + "/*"),
                new InputChannelCallback<GlobReply>() {
                    @Override
                    public ListenableFuture<Void> onNext(GlobReply reply) {
                        if (reply instanceof GlobReply.Error) {
                            GlobError error = ((GlobReply.Error) reply).getElem();
                            String msg = String.format("Couldn't fetch namespace subtree \"%s\": %s",
                                    error.getName(), error.getError().getMessage());
                            android.util.Log.e(TAG, msg);
                            return null;
                        }
                        MountEntry entry = ((GlobReply.Entry) reply).getElem();
                        String text = "";
                        if (dirEntry.getName().isEmpty()) {
                            text = entry.getName();
                        } else if (entry.getName().startsWith(dirEntry.getName() + "/")) {
                            text = entry.getName().substring(dirEntry.getName().length() + 1);
                        } else {
                            Log.e(TAG, String.format("Entry %s doesn't start with parent prefix %s",
                                    entry.getName(), dirEntry.getName() + "/"));
                            return null;
                        }
                        LinearLayout childView = (entry.getServers() == null || entry.getServers().size() <= 0)
                                ? ViewUtil.createDirectoryView(text, reply, getLayoutInflater())
                                : ViewUtil.createObjectView(text, reply, getLayoutInflater());
                        dirView.addView(childView);
                        return null;
                    }
                }), new FutureCallback<Void>() {
                    @Override
                    public void onSuccess(Void result) {
                        progressDialog.dismiss();
                    }

                    @Override
                    public void onFailure(Throwable t) {
                        progressDialog.dismiss();
                        Log.e(TAG, "Error fetching names: " + t.getMessage());
                    }
                });
    }

    private void fetchMethods(final LinearLayout objView) {
        ViewUtil.updateObjectView(objView, true);
        final GlobReply entry = (GlobReply) objView.getTag();
        if (!(entry instanceof GlobReply.Entry)) {
            return;
        }
        final MountEntry objEntry = ((GlobReply.Entry) entry).getElem();
        final ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setMessage("Fetching Methods...");
        progressDialog.show();
        Futures.addCallback(Methods.get(mBaseContext, objEntry.getName()), new FutureCallback<List<String>>() {
            @Override
            public void onSuccess(List<String> methods) {
                for (String method : methods) {
                    LinearLayout childView = ViewUtil.createMethodView(method, entry, getLayoutInflater());
                    objView.addView(childView);
                }
                progressDialog.dismiss();
            }

            @Override
            public void onFailure(Throwable t) {
                progressDialog.dismiss();
                Log.e(TAG, "Error fetching methods: " + t.getMessage());
            }
        });
    }
}