im.vector.activity.MXCActionBarActivity.java Source code

Java tutorial

Introduction

Here is the source code for im.vector.activity.MXCActionBarActivity.java

Source

/*
 * Copyright 2014 OpenMarket Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package im.vector.activity;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ListView;

import org.matrix.androidsdk.MXSession;
import im.vector.VectorApp;
import im.vector.Matrix;
import im.vector.R;
import im.vector.adapters.DrawerAdapter;
import im.vector.services.EventStreamService;

import java.lang.reflect.Method;

/**
 * extends ActionBarActivity to manage the rageshake
 */
public class MXCActionBarActivity extends ActionBarActivity {
    public static final String TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG = "org.matrix.console.ActionBarActivity.TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG";
    public static final String EXTRA_MATRIX_ID = "org.matrix.console.MXCActionBarActivity.EXTRA_MATRIX_ID";

    /**
     * Return the used MXSession from an intent.
     * @param intent
     * @return the MXsession if it exists.
     */
    protected MXSession getSession(Intent intent) {
        String matrixId = null;

        if (intent.hasExtra(EXTRA_MATRIX_ID)) {
            matrixId = intent.getStringExtra(EXTRA_MATRIX_ID);
        }

        return Matrix.getInstance(getApplicationContext()).getSession(matrixId);
    }

    // add left sliding menu
    protected DrawerLayout mDrawerLayout;
    protected ListView mDrawerList;
    protected ActionBarDrawerToggle mDrawerToggle;

    protected int mSelectedSlidingMenuIndex = -1;

    @Override
    public void startActivity(Intent intent) {
        super.startActivity(intent);

        // create a "lollipop like " animation
        // not sure it is the save animation curve
        // appcompat does not support (it does nothing)
        //
        // ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(...
        // ActivityCompat.startActivity(activity, new Intent(activity, DetailActivity.class),  options.toBundle());

        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
            this.overridePendingTransition(R.anim.anim_slide_in_bottom, R.anim.anim_slide_nothing);
        } else {
            // the animation is enabled in the theme
        }
    }

    @Override
    public void finish() {
        super.finish();

        // create a "lollipop like " animation
        // not sure it is the save animation curve
        //
        // ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(...
        // ActivityCompat.startActivity(activity, new Intent(activity, DetailActivity.class),  options.toBundle());
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
            this.overridePendingTransition(R.anim.anim_slide_nothing, R.anim.anim_slide_out_bottom);
        } else {
            // the animation is enabled in the theme
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_MENU) && (null == getSupportActionBar())) {
            // This is to fix a bug in the v7 support lib. If there is no options menu and you hit MENU, it will crash with a
            // NPE @ android.support.v7.app.ActionBarImplICS.getThemedContext(ActionBarImplICS.java:274)
            // This can safely be removed if we add in menu options on this screen
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onPause() {
        super.onPause();
        VectorApp.setCurrentActivity(null);

        ((VectorApp) getApplication()).startActivityTransitionTimer();

        // close any opened dialog
        FragmentManager fm = getSupportFragmentManager();
        java.util.List<android.support.v4.app.Fragment> fragments = fm.getFragments();

        if (null != fragments) {
            for (Fragment fragment : fragments) {
                if (fragment instanceof DialogFragment) {
                    ((DialogFragment) fragment).dismissAllowingStateLoss();
                }
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        VectorApp.setCurrentActivity(this);

        // refresh the push rules when debackgrounding the application
        if (VectorApp.isAppInBackground()) {
            Matrix matrixInstance = Matrix.getInstance(getApplicationContext());

            // sanity check
            if (null != matrixInstance) {
                matrixInstance.refreshPushRules();
            }

            EventStreamService.cancelNotificationsForRoomId(null);
        }

        ((VectorApp) getApplication()).stopActivityTransitionTimer();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if ((null != mDrawerToggle) && mDrawerToggle.onOptionsItemSelected(item)) {
            dismissKeyboard(this);
            return true;
        }

        if (item.getItemId() == android.R.id.home) {
            // pop the activity to avoid creating a new instance of the parent activity
            this.onBackPressed();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        // display the menu icon with the text
        if (((featureId == Window.FEATURE_ACTION_BAR) || ((featureId == Window.FEATURE_OPTIONS_PANEL)))
                && menu != null) {
            if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
                try {
                    Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                } catch (NoSuchMethodException e) {
                    //Log.e(TAG, "onMenuOpened", e);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return super.onMenuOpened(featureId, menu);
    }

    /**
     * Dismiss the soft keyboard if one view in the activity has the focus.
     * @param activity the activity
     */
    public static void dismissKeyboard(Activity activity) {
        // hide the soft keyboard
        View view = activity.getCurrentFocus();
        if (view != null) {
            InputMethodManager inputManager = (InputMethodManager) activity
                    .getSystemService(Context.INPUT_METHOD_SERVICE);
            inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    /**
     * Define a sliding menu
     * @param iconResourceIds the icons resource Ids
     * @param textResourceIds the text resources Ids
     * @param replaceUpButton The icon replaces the up button (left side)
     */
    protected void addSlidingMenu(Integer[] iconResourceIds, Integer[] textResourceIds, Boolean replaceUpButton) {
        // sanity checks
        if ((null == iconResourceIds) || (null == textResourceIds)
                || (iconResourceIds.length != textResourceIds.length)) {
            return;
        }

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        // check if the dedicated resource exists
        if ((null != mDrawerLayout) && (null != mDrawerList)) {

            mDrawerList.setBackgroundColor(Color.WHITE);

            // Set the adapter for the list view
            DrawerAdapter adapter = new DrawerAdapter(this, R.layout.adapter_drawer_header,
                    R.layout.adapter_drawer_item);

            adapter.mTextColor = this.getResources().getColor(R.color.vector_title_color);
            adapter.setNotifyOnChange(false);
            for (int index = 0; index < iconResourceIds.length; index++) {
                adapter.add(iconResourceIds[index], getString(textResourceIds[index]));
            }
            adapter.setNotifyOnChange(true);
            mDrawerList.setAdapter(adapter);

            // Set the list's click listener
            mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

            if (replaceUpButton) {
                mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
                        mDrawerLayout, /* DrawerLayout object */
                        R.drawable.ic_material_menu, /* nav drawer icon to replace 'Up' caret */
                        R.string.action_open, /* "open drawer" description */
                        R.string.action_close /* "close drawer" description */
                ) {

                    public void onDrawerClosed(View view) {
                        if (mSelectedSlidingMenuIndex >= 0) {
                            selectDrawItem(mSelectedSlidingMenuIndex);
                            mSelectedSlidingMenuIndex = -1;
                        }
                    }

                    public void onDrawerOpened(View drawerView) {
                        mSelectedSlidingMenuIndex = -1;
                        //dismissKeyboard(thisApp);
                    }
                };
            }

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

            // display the home and title button
            if (null != getSupportActionBar()) {
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);
                getSupportActionBar().setHomeButtonEnabled(true);

                if (replaceUpButton) {
                    getSupportActionBar()
                            .setHomeAsUpIndicator(getResources().getDrawable(R.drawable.ic_material_menu));
                }
            }
        }
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        if (null != mDrawerToggle) {
            // Sync the toggle state after onRestoreInstanceState has occurred.
            mDrawerToggle.syncState();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        if (null != mDrawerToggle) {
            mDrawerToggle.onConfigurationChanged(newConfig);
        }
    }

    /**
     * Run the dedicated sliding menu action
     * @param position selected menu entry
     */
    protected void selectDrawItem(int position) {
    }

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView parent, View view, int position, long id) {
            // wait that the activity sliding animation is done
            // before performing the dedicated task
            // 1- because it triggers weird UI effect
            // 2- the application used to crash when logging out because adapter was refreshed with a null MXSession.
            mSelectedSlidingMenuIndex = position;
            mDrawerLayout.closeDrawer(mDrawerList);

            // the drawer button does not replace the home button.
            // trigger the
            if (null == mDrawerToggle) {
                mDrawerLayout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        selectDrawItem(mSelectedSlidingMenuIndex);
                        mSelectedSlidingMenuIndex = -1;
                    }
                }, 300);
            }
        }
    }
}