I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
I2PActivityBase.java 16.3 KiB
Newer Older
package net.i2p.android.router;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
import android.support.v7.app.ActionBarActivity;
str4d's avatar
str4d committed
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import net.i2p.android.i2ptunnel.TunnelListActivity;
import net.i2p.android.router.addressbook.AddressbookActivity;
import net.i2p.android.router.log.LogActivity;
import net.i2p.android.router.netdb.NetDbActivity;
import net.i2p.android.router.service.RouterBinder;
import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.stats.PeersActivity;
import net.i2p.android.router.stats.RateGraphActivity;
import net.i2p.android.router.util.Util;
import net.i2p.android.router.web.WebActivity;
import net.i2p.android.router.web.WebFragment;
import net.i2p.router.RouterContext;
public abstract class I2PActivityBase extends ActionBarActivity implements
        I2PFragmentBase.RouterContextProvider {
    /**
     * Navigation drawer variables
     */
    protected DrawerLayout mDrawerLayout;
    protected ListView mDrawerList;
    protected ActionBarDrawerToggle mDrawerToggle;

    private CharSequence mDrawerTitle;
    private CharSequence mTitle;

    /**
     * Router variables
     */
    protected boolean _isBound;
    protected boolean _triedBind;
    protected ServiceConnection _connection;
    protected RouterService _routerService;
    private SharedPreferences _sharedPrefs;
    private static final String SHARED_PREFS = "net.i2p.android.router";
    protected static final String PREF_AUTO_START = "autoStart";
str4d's avatar
str4d committed
    /**
     * true leads to a poor install experience, very slow to paint the screen
     */
    protected static final boolean DEFAULT_AUTO_START = false;
    protected static final String PREF_NAV_DRAWER_OPENED = "navDrawerOpened";
    /**
     * Override this in subclasses that need a ViewPager, such as a
     * category view.
str4d's avatar
str4d committed
     *
     * @return whether this Activity needs a ViewPager.
     */
    protected boolean useViewPager() {
        return false;
    }

    /**
     * Override this in subclasses that can use two panes, such as a
str4d's avatar
str4d committed
     *
     * @return whether this Activity can use a two-pane layout.
     */
    protected boolean canUseTwoPanes() {
        return false;
    }

str4d's avatar
str4d committed
    /**
     * Called when the activity is first created.
     */
str4d's avatar
str4d committed
    public void onCreate(Bundle savedInstanceState) {
        Util.d(this + " onCreate called");
        super.onCreate(savedInstanceState);
        _sharedPrefs = getSharedPreferences(SHARED_PREFS, 0);
        // If the Activity wants to use a ViewPager, provide it.
        // If the Activity can make use of two panes (if available),
        // load the layout that will enable them. Otherwise, load the
        // layout that will only ever have a single pane.
        if (useViewPager())
            setContentView(R.layout.activity_navdrawer_viewpager);
        else if (canUseTwoPanes())
            setContentView(R.layout.activity_navdrawer);
        else
            setContentView(R.layout.activity_navdrawer_onepane);

str4d's avatar
str4d committed
        // Set the action bar
        Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
        setSupportActionBar(toolbar);

        mTitle = mDrawerTitle = getTitle();
        String[] activityTitles = getResources().getStringArray(R.array.navdrawer_activity_titles);
        if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("i2pandroid.main.showStats", false)) {
            String[] advActivityTitles = getResources().getStringArray(R.array.navdrawer_activity_titles_advanced);
            String[] allTitles = new String[activityTitles.length + advActivityTitles.length];
            System.arraycopy(activityTitles, 0, allTitles, 0, activityTitles.length);
            System.arraycopy(advActivityTitles, 0, allTitles, activityTitles.length, advActivityTitles.length);
            activityTitles = allTitles;
        }
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.drawer);

        // Set a custom shadow that overlays the main content when the drawer opens
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
        mDrawerList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        // Set the adapter for the list view
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
str4d's avatar
str4d committed
                R.layout.listitem_navdrawer, activityTitles));
        // Set the list's click listener
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
str4d's avatar
str4d committed
                R.string.drawer_open, R.string.drawer_close) {
            private boolean wasDragged = false;

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                // Don't mark as opened if the user closed by dragging
                // but uses the action bar icon to open
                wasDragged = false;
                getSupportActionBar().setTitle(mTitle);
                supportInvalidateOptionsMenu();
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View view) {
                if (wasDragged && !getPref(PREF_NAV_DRAWER_OPENED, false))
                    setPref(PREF_NAV_DRAWER_OPENED, true);
                getSupportActionBar().setTitle(mDrawerTitle);
                supportInvalidateOptionsMenu();
            }

            /** Called when the drawer motion state changes. */
            public void onDrawerStateChanged(int newState) {
                if (newState == DrawerLayout.STATE_DRAGGING)
                    wasDragged = true;
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerLayout.setDrawerListener(mDrawerToggle);
    }

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
            selectItem(pos);
        }
    }

    private void selectItem(int pos) {
        switch (pos) {
str4d's avatar
str4d committed
            case 1:
                if (!(this instanceof NewsActivity)) {
                    Intent news = new Intent(I2PActivityBase.this, NewsActivity.class);
                    startActivity(news);
                }
str4d's avatar
str4d committed
                break;
            case 2:
                Intent ab = new Intent(I2PActivityBase.this, AddressbookActivity.class);
                startActivity(ab);
                break;
            case 3:
                Intent itb = new Intent(I2PActivityBase.this, TunnelListActivity.class);
                startActivity(itb);
                break;
            case 4:
                if (!(this instanceof LogActivity)) {
                    Intent log = new Intent(I2PActivityBase.this, LogActivity.class);
                    startActivity(log);
                }
str4d's avatar
str4d committed
                break;
            case 5:
                Intent wp = new Intent(I2PActivityBase.this, WebActivity.class);
                wp.putExtra(WebFragment.HTML_RESOURCE_ID, R.raw.welcome_html);
                startActivity(wp);
                break;
            case 6:
                if (!(this instanceof RateGraphActivity)) {
                    Intent active = new Intent(I2PActivityBase.this, RateGraphActivity.class);
                    startActivity(active);
                }
str4d's avatar
str4d committed
                break;
            case 7:
                Intent peers = new Intent(I2PActivityBase.this, PeersActivity.class);
                startActivity(peers);
                break;
            case 8:
                if (!(this instanceof NetDbActivity)) {
                    Intent netdb = new Intent(I2PActivityBase.this, NetDbActivity.class);
                    startActivity(netdb);
                }
str4d's avatar
str4d committed
                break;
            default:
                Intent main = new Intent(I2PActivityBase.this, MainActivity.class);
                startActivity(main);
                break;
        }
        mDrawerLayout.closeDrawer(mDrawerList);
str4d's avatar
str4d committed
    public void onRestart() {
        Util.d(this + " onRestart called");
        super.onRestart();
    }
str4d's avatar
str4d committed
    public void onStart() {
        Util.d(this + " onStart called");
        super.onStart();
        if (_sharedPrefs.getBoolean(PREF_AUTO_START, DEFAULT_AUTO_START))
            startRouter();
            bindRouter(false);
    }
str4d's avatar
str4d committed
    /**
     * @param def default
     */
    public boolean getPref(String pref, boolean def) {
        return _sharedPrefs.getBoolean(pref, def);
    }

str4d's avatar
str4d committed
    /**
     * @param def default
     */
    public String getPref(String pref, String def) {
        return _sharedPrefs.getString(pref, def);
str4d's avatar
str4d committed
    /**
     * @return success
     */
    public boolean setPref(String pref, boolean val) {
        SharedPreferences.Editor edit = _sharedPrefs.edit();
        edit.putBoolean(pref, val);
        return edit.commit();
str4d's avatar
str4d committed
    /**
     * @return success
     */
    public boolean setPref(String pref, String val) {
        SharedPreferences.Editor edit = _sharedPrefs.edit();
        edit.putString(pref, val);
        return edit.commit();
str4d's avatar
str4d committed
    public void onResume() {
        Util.d(this + " onResume called");
        super.onResume();
str4d's avatar
str4d committed
    public void onPause() {
        Util.d(this + " onPause called");
        super.onPause();
str4d's avatar
str4d committed
    public void onSaveInstanceState(Bundle outState) {
        Util.d(this + " onSaveInstanceState called");
        super.onSaveInstanceState(outState);
str4d's avatar
str4d committed
    public void onStop() {
        Util.d(this + " onStop called");
        unbindRouter();
        super.onStop();
    }
str4d's avatar
str4d committed
    public void onDestroy() {
        Util.d(this + " onDestroy called");
        super.onDestroy();
    /**
     * Called whenever we call invalidateOptionsMenu()
     */
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        onDrawerChange(drawerOpen);

        return super.onPrepareOptionsMenu(menu);
    /**
     * Override in subclass with e.g.
     * menu.findItem(R.id.action_add_to_addressbook).setVisible(!drawerOpen);
str4d's avatar
str4d committed
     *
     * @param drawerOpen true if the drawer is open
     */
    protected void onDrawerChange(boolean drawerOpen) {
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        // The action bar home/up action should open or close the drawer.
        // ActionBarDrawerToggle will take care of this.
        if (mDrawerToggle.onOptionsItemSelected(item))
            return true;
        else if (item.getItemId() == android.R.id.home) {
            // This happens when mDrawerToggle.setDrawerIndicatorEnabled(false)
            onBackPressed();
        }

        // Handle action buttons and overflow
str4d's avatar
str4d committed
        return super.onOptionsItemSelected(item);
    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getSupportActionBar().setTitle(mTitle);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggle
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    public static class TabListener implements ActionBar.TabListener {
        protected Fragment mFragment;

        public TabListener(Fragment fragment) {
            mFragment = fragment;
        }

        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            ft.replace(R.id.main_fragment, mFragment);
        }

        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            ft.remove(mFragment);
        }

        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            // User selected the already selected tab.
        }
    }

    ////// Service stuff
str4d's avatar
str4d committed
     * Start the service and bind to it
     */
    protected boolean startRouter() {
        Intent intent = new Intent();
        intent.setClassName(this, "net.i2p.android.router.service.RouterService");
        Util.d(this + " calling startService");
        ComponentName name = startService(intent);
        if (name == null)
            Util.d(this + " XXXXXXXXXXXXXXXXXXXX got null from startService!");
        Util.d(this + " got from startService: " + name);
        boolean success = bindRouter(true);
        if (!success)
            Util.d(this + " Bind router failed");
str4d's avatar
str4d committed
     * Bind only
     */
    protected boolean bindRouter(boolean autoCreate) {
        Intent intent = new Intent(RouterBinder.class.getName());
        intent.setClassName(this, "net.i2p.android.router.service.RouterService");
        Util.d(this + " calling bindService");
        _connection = new RouterConnection();
        _triedBind = bindService(intent, _connection, autoCreate ? BIND_AUTO_CREATE : 0);
        Util.d(this + " bindService: auto create? " + autoCreate + " success? " + _triedBind);
        return _triedBind;
    }

    protected void unbindRouter() {
        Util.d(this + " unbindRouter called with _isBound:" + _isBound + " _connection:" + _connection + " _triedBind:" + _triedBind);
        if (_triedBind && _connection != null)
str4d's avatar
str4d committed
            unbindService(_connection);
        _triedBind = false;
        _connection = null;
        _routerService = null;
        _isBound = false;
    }

    /**
     * Class for interacting with the main interface of the RouterService.
     */
    protected class RouterConnection implements ServiceConnection {

        public void onServiceConnected(ComponentName name, IBinder service) {
            Util.d(this + " connected to router service");
            RouterBinder binder = (RouterBinder) service;
            RouterService svc = binder.getService();
            _routerService = svc;
            _isBound = true;
            onRouterBind(svc);
        public void onServiceDisconnected(ComponentName name) {
            Util.d(this + " disconnected from router service!!!!!!!");
            // save memory
            _routerService = null;
            _isBound = false;
            onRouterUnbind();
str4d's avatar
str4d committed
    /**
     * callback from ServiceConnection, override as necessary
     */
    protected void onRouterBind(RouterService svc) {
        Fragment f = getSupportFragmentManager().findFragmentById(R.id.main_fragment);
        if (f instanceof I2PFragmentBase)
            ((I2PFragmentBase) f).onRouterBind();
        else if (f instanceof I2PFragmentBase.RouterContextUser)
            ((I2PFragmentBase.RouterContextUser) f).onRouterBind();

        if (canUseTwoPanes()) {
            f = getSupportFragmentManager().findFragmentById(R.id.detail_fragment);
            if (f instanceof I2PFragmentBase)
                ((I2PFragmentBase) f).onRouterBind();
            else if (f instanceof I2PFragmentBase.RouterContextUser)
                ((I2PFragmentBase.RouterContextUser) f).onRouterBind();
        }
str4d's avatar
str4d committed
    /**
     * callback from ServiceConnection, override as necessary
     */
    protected void onRouterUnbind() {
    }
    // I2PFragmentBase.RouterContextProvider
    public RouterContext getRouterContext() {
        RouterService svc = _routerService;
        if (svc == null || !_isBound)
            return null;
        return svc.getRouterContext();
    }