ca.rmen.android.scrumchatter.main.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for ca.rmen.android.scrumchatter.main.MainActivity.java

Source

/**
 * Copyright 2013 Carmen Alvarez
 *
 * This file is part of Scrum Chatter.
 *
 * Scrum Chatter is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * Scrum Chatter is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scrum Chatter. If not, see <http://www.gnu.org/licenses/>.
 */
package ca.rmen.android.scrumchatter.main;

import java.io.File;
import java.util.Locale;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import ca.rmen.android.scrumchatter.Constants;
import ca.rmen.android.scrumchatter.R;
import ca.rmen.android.scrumchatter.about.AboutActivity;
import ca.rmen.android.scrumchatter.export.DBExport;
import ca.rmen.android.scrumchatter.export.FileExport;
import ca.rmen.android.scrumchatter.export.MeetingsExport;
import ca.rmen.android.scrumchatter.meeting.list.MeetingsListFragment;
import ca.rmen.android.scrumchatter.member.list.MembersListFragment;
import ca.rmen.android.scrumchatter.provider.DBImport;
import ca.rmen.android.scrumchatter.provider.TeamColumns;
import ca.rmen.android.scrumchatter.team.Teams;
import ca.rmen.android.scrumchatter.team.Teams.Team;
import ca.rmen.android.scrumchatter.ui.ScrumChatterDialog;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

/**
 * The main screen of the app. Part of this code was generated by the ADT
 * plugin.
 */
public class MainActivity extends SherlockFragmentActivity implements ActionBar.TabListener { // NO_UCD (use default)

    private static final String TAG = Constants.TAG + "/" + MainActivity.class.getSimpleName();
    private static final int ACTIVITY_REQUEST_CODE_IMPORT = 1;
    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
     * will keep every loaded fragment in memory. If this becomes too memory
     * intensive, it may be best to switch to a {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    private SectionsPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;

    private Teams mTeams = new Teams(this);
    private Team mTeam = null;
    private int mTeamCount = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.v(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //StrictMode.setThreadPolicy(new ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().penaltyLog().penaltyDeath().build());
        // Set up the action bar.
        final ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the app.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title defined by
            // the adapter. Also specify this Activity object, which implements
            // the TabListener interface, as the callback (listener) for when
            // this tab is selected.
            actionBar
                    .addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
        }

        onTeamChanged();
        // If our activity was opened by choosing a file from a mail attachment, file browser, or other program, 
        // import the database from this file.
        Intent intent = getIntent();
        if (intent != null) {
            if (Intent.ACTION_VIEW.equals(intent.getAction()))
                importDB(intent.getData());
        }
    }

    @Override
    protected void onResume() {
        Log.v(TAG, "onResume");
        super.onResume();
        getContentResolver().registerContentObserver(TeamColumns.CONTENT_URI, true, mContentObserver);
        PreferenceManager.getDefaultSharedPreferences(this)
                .registerOnSharedPreferenceChangeListener(mSharedPrefsListener);
    }

    @Override
    protected void onPause() {
        Log.v(TAG, "onPause");
        PreferenceManager.getDefaultSharedPreferences(this)
                .unregisterOnSharedPreferenceChangeListener(mSharedPrefsListener);
        getContentResolver().unregisterContentObserver(mContentObserver);
        super.onPause();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getSupportMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        Log.v(TAG, "onPrepareOptionsMenu " + menu);
        // Only enable the "delete team" menu item if we have at least two teams.
        MenuItem deleteItem = menu.findItem(R.id.action_team_delete);
        deleteItem.setEnabled(mTeamCount > 1);
        // Add the current team name to the delete and rename menu items
        if (mTeam != null) {
            deleteItem.setTitle(getString(R.string.action_team_delete_name, mTeam.teamName));
            MenuItem renameItem = menu.findItem(R.id.action_team_rename);
            renameItem.setTitle(getString(R.string.action_team_rename_name, mTeam.teamName));
        }
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_team_switch:
            mTeams.selectTeam(mTeam);
            return true;
        case R.id.action_team_rename:
            mTeams.renameTeam(mTeam);
            return true;
        case R.id.action_team_delete:
            mTeams.deleteTeam(mTeam);
            return true;
        case R.id.action_import:
            Intent importIntent = new Intent(Intent.ACTION_GET_CONTENT);
            importIntent.setType("file/*");
            startActivityForResult(
                    Intent.createChooser(importIntent, getResources().getText(R.string.action_import)),
                    ACTIVITY_REQUEST_CODE_IMPORT);
            return true;
        case R.id.action_share:
            // Build a chooser dialog for the file format.
            ScrumChatterDialog.showChoiceDialog(this, R.string.export_choice_title, R.array.export_choices, -1,
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            String[] exportChoices = getResources().getStringArray(R.array.export_choices);
                            FileExport fileExport = null;
                            if (getString(R.string.export_format_excel).equals(exportChoices[which]))
                                fileExport = new MeetingsExport(MainActivity.this);
                            else if (getString(R.string.export_format_db).equals(exportChoices[which]))
                                fileExport = new DBExport(MainActivity.this);
                            shareFile(fileExport);
                        }
                    });
            return true;
        case R.id.action_about:
            Intent intent = new Intent(this, AboutActivity.class);
            startActivity(intent);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
        // When the given tab is selected, switch to the corresponding page in
        // the ViewPager.
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == ACTIVITY_REQUEST_CODE_IMPORT && resultCode == Activity.RESULT_OK) {
            if (intent.getData() == null) {
                Toast.makeText(this, R.string.import_result_no_file, Toast.LENGTH_SHORT).show();
                return;
            }
            final String filePath = intent.getData().getPath();
            if (TextUtils.isEmpty(filePath)) {
                Toast.makeText(this, R.string.import_result_no_file, Toast.LENGTH_SHORT).show();
                return;
            }
            final File file = new File(filePath);
            if (!file.exists()) {
                Toast.makeText(this, getString(R.string.import_result_file_does_not_exist, file.getName()),
                        Toast.LENGTH_SHORT).show();
                return;
            }
            importDB(Uri.fromFile(file));
        } else {
            super.onActivityResult(requestCode, resultCode, intent);
        }
    }

    /**
     * Import the given database file. This will replace the current database.
     */
    private void importDB(final Uri uri) {
        ScrumChatterDialog.showDialog(this, getString(R.string.import_confirm_title),
                getString(R.string.import_confirm_message, uri.getEncodedPath()), new OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if (which == DialogInterface.BUTTON_POSITIVE) {
                            AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
                                private ProgressDialog mProgressDialog;

                                @Override
                                protected void onPreExecute() {
                                    mProgressDialog = ProgressDialog.show(MainActivity.this, null,
                                            getString(R.string.progress_dialog_message), true);
                                }

                                @Override
                                protected Boolean doInBackground(Void... params) {
                                    try {
                                        Log.v(TAG, "Importing db from " + uri);
                                        DBImport.importDB(MainActivity.this, uri);
                                    } catch (Exception e) {
                                        Log.e(TAG, "Error importing db: " + e.getMessage(), e);
                                        return false;
                                    }
                                    return true;
                                }

                                @Override
                                protected void onPostExecute(Boolean result) {
                                    mProgressDialog.cancel();
                                    Toast.makeText(MainActivity.this,
                                            result ? R.string.import_result_success : R.string.import_result_failed,
                                            Toast.LENGTH_SHORT).show();
                                }

                            };
                            task.execute();
                        }
                    }
                });

    }

    /**
     * Share a file using an intent chooser.
     * 
     * @param fileExport The object responsible for creating the file to share.
     */
    private void shareFile(final FileExport fileExport) {
        final ProgressDialog progressDialog = ProgressDialog.show(this, null,
                getString(R.string.progress_dialog_message), true);
        AsyncTask<Void, Void, Boolean> asyncTask = new AsyncTask<Void, Void, Boolean>() {

            @Override
            protected Boolean doInBackground(Void... params) {
                return fileExport.export();
            }

            @Override
            protected void onPreExecute() {
                progressDialog.show();
            }

            @Override
            protected void onPostExecute(Boolean success) {
                progressDialog.dismiss();
                if (!success)
                    Toast.makeText(MainActivity.this, R.string.export_error, Toast.LENGTH_LONG).show();
            }
        };
        asyncTask.execute();
    }

    /**
     * Called when the current team was changed. Update our cache of the current team and update the ui (menu items, action bar title).
     */
    private void onTeamChanged() {
        AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... arg0) {
                mTeam = mTeams.getCurrentTeam();
                // If for some reason we have no current team, select any available team
                // Should not really happen, so perhaps this check should be removed?
                if (mTeam == null) {
                    mTeams.selectFirstTeam();
                }
                mTeamCount = mTeams.getTeamCount();
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                // If the user has renamed the default team or added other teams, show the current team name in the title
                if (mTeamCount > 1 || (mTeam != null && !mTeam.teamName.equals(Constants.DEFAULT_TEAM_NAME)))
                    getSupportActionBar().setTitle(mTeam.teamName);
                // otherwise the user doesn't care about team management: just show the app title.
                else
                    getSupportActionBar().setTitle(R.string.app_name);
                supportInvalidateOptionsMenu();
            }
        };
        task.execute();
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    private class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a DummySectionFragment (defined as a static inner class
            // below) with the page number as its lone argument.
            Fragment fragment = null;
            if (position == 1)
                fragment = new MembersListFragment();
            else
                fragment = new MeetingsListFragment();
            return fragment;
        }

        @Override
        public int getCount() {
            // Show 2 total pages.
            return 2;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();
            switch (position) {
            case 0:
                return getString(R.string.title_section_meetings).toUpperCase(l);
            case 1:
                return getString(R.string.title_section_team).toUpperCase(l);
            }
            return null;
        }
    }

    private ContentObserver mContentObserver = new ContentObserver(null) {
        @Override
        public void onChange(boolean selfChange) {
            onTeamChanged();
        }
    };

    private OnSharedPreferenceChangeListener mSharedPrefsListener = new OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            onTeamChanged();
        }
    };

}