org.centum.android.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.centum.android.MainActivity.java

Source

/**
 Stacks Flashcards - A flashcards application for Android devices 4.0+
 Copyright (C) 2014  Phani Gaddipati
    
 This program 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 3 of the License, or
 (at your option) any later version.
    
 This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.centum.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.widget.SlidingPaneLayout;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;

import com.google.analytics.tracking.android.EasyTracker;
import com.google.analytics.tracking.android.ExceptionReporter;
import com.google.analytics.tracking.android.GAServiceManager;
import com.google.analytics.tracking.android.StandardExceptionParser;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;

import org.centum.android.card.CardFragment;
import org.centum.android.model.Stack;
import org.centum.android.model.StackManager;
import org.centum.android.settings.SettingsActivity;
import org.centum.android.settings.Themes;
import org.centum.android.sql.StacksDatabaseHelper;
import org.centum.android.sql.StacksDatabaseSyncWatcher;
import org.centum.android.stack.R;
import org.centum.android.stack.StackFragment;
import org.centum.android.utils.KEYS;
import org.centum.android.utils.LoadedData;
import org.centum.android.utils.SampleStack;
import org.centum.android.utils.Serializer;

import java.util.List;

/**
 * The base Activity, this loads data on start up, displays relevent
 * start-up messages, and holds StackFragment and CardFragment.
 * <p/>
 * Created by Phani on 1/5/14.
 */
public class MainActivity extends Activity implements SlidingPaneLayout.PanelSlideListener {

    /**
     * Preference Constants
     */
    private static final int VERSION = 2;
    private static final long RATE_TIME_TO_WAIT = 1209600000; //2 weeks
    private static final long UPGRADE_TIME_TO_WAIT = 1814400000; // 2 weeks
    private static final int STATE_NO_PREF_RATE = 0;
    private static final int STATE_NO_RATE = 1;
    private static final int STATE_NO_PREF_UPGRADE = 0;
    private static final int STATE_NO_UPGRADE = 1;
    /**
     * Views amd fragments
     */
    private SlidingPaneLayout slidingPane;
    private FrameLayout adFrameLayout;
    private AdView adView;
    private StackFragment stackFragment;
    private CardFragment cardFragment;
    /**
     * Store whether data has already been loaded, to avoid re-load on rotates
     */
    private boolean dataLoaded = false;
    /**
     * DB classes
     */
    private StacksDatabaseHelper sqlHelper;
    private StacksDatabaseSyncWatcher syncWatcher;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
        setTheme(Themes.get(this).getCurrentTheme());
        sqlHelper = StacksDatabaseHelper.get(this);
        setContentView(R.layout.main_activity);

        adFrameLayout = (FrameLayout) findViewById(R.id.ad_frameLayout);

        if (!isProVersion()) {
            adView = new AdView(this);
            adView.setAdSize(AdSize.SMART_BANNER);
            adView.setAdUnitId(KEYS.AD_UNIT_ID);
            adFrameLayout.addView(adView);
            AdRequest adRequest = new AdRequest.Builder().addTestDevice(KEYS.TEST_DEVICE).build();
            adView.loadAd(adRequest);
            adView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    adView.setAdListener(new AdListener() {
                        @Override
                        public void onAdLoaded() {
                            super.onAdLoaded();
                            adView.setVisibility(View.VISIBLE);
                        }
                    });
                    adView.setVisibility(View.GONE);
                }
            });
        } else {
            adView = null;
            adFrameLayout.setVisibility(View.GONE);
        }

        slidingPane = (SlidingPaneLayout) findViewById(R.id.slidingPane);
        slidingPane.setCoveredFadeColor(getResources().getColor(android.R.color.transparent));
        slidingPane.setSliderFadeColor(getResources().getColor(android.R.color.transparent));
        slidingPane.setPanelSlideListener(this);

        stackFragment = (StackFragment) getFragmentManager().findFragmentById(R.id.stackFragment);
        cardFragment = (CardFragment) getFragmentManager().findFragmentById(R.id.cardFragment);

        setupUncaughtExceptionHandler();

        if (savedInstanceState != null) {
            dataLoaded = savedInstanceState.getBoolean("dataLoaded", false);

            if (savedInstanceState.containsKey("stack")
                    && StackManager.get().getStack(savedInstanceState.getString("stack")) != null) {
                cardFragment.setStack(StackManager.get().getStack(savedInstanceState.getString("stack")));
            }

            if (savedInstanceState.getBoolean("stacksOpened")) {
                showStacks();
                onPanelOpened(null);
            } else {
                showCards();
                onPanelClosed(null);
            }
        } else {
            showStacks();
            onPanelOpened(null);
        }

        if (!dataLoaded || (StackManager.get().getArchivedStackList().size() == 0
                && StackManager.get().getStackList().size() == 0)) {
            loadData();
        }

        getSharedPreferences("properties", MODE_PRIVATE).edit().putInt("version", VERSION).apply();
    }

    /**
     * Check whether this is the Pro version
     *
     * @return
     */
    private boolean isProVersion() {
        //REMOVED
        return false;
    }

    /**
     * Load the stk data if the user is coming from an old version,
     * or load from the SQL db
     */
    private void loadData() {
        if (getSharedPreferences("properties", MODE_PRIVATE).getInt("version", 1) >= 2) {
            loadSQLData();
        } else {
            loadStkData();
        }
    }

    /**
     * Report uncaught exceptions (crashes) to Analytics
     */
    private void setupUncaughtExceptionHandler() {
        ExceptionReporter myHandler = new ExceptionReporter(EasyTracker.getInstance(this),
                GAServiceManager.getInstance(), Thread.getDefaultUncaughtExceptionHandler(), this);

        StandardExceptionParser exceptionParser = new StandardExceptionParser(getApplicationContext(), null) {
            @Override
            public String getDescription(String threadName, Throwable t) {
                return "{" + threadName + "} " + "{" + Build.MODEL + "} " + "{" + Build.VERSION.SDK_INT + "} "
                        + Log.getStackTraceString(t);
            }
        };

        myHandler.setExceptionParser(exceptionParser);
        Thread.setDefaultUncaughtExceptionHandler(myHandler);
    }

    /**
     * Load data from stacks.stk - the default save file in old version
     */
    private void loadStkData() {
        new AsyncTask<Void, Void, Void>() {
            ProgressDialog progressDialog;
            LoadedData loadedData;

            @Override
            protected void onPreExecute() {
                progressDialog = new ProgressDialog(MainActivity.this);
                progressDialog.setTitle("Upgrading Data");
                progressDialog.setMessage("Please wait");
                progressDialog.setIndeterminate(true);
                progressDialog.setCancelable(false);
                progressDialog.show();
                syncWatcher = new StacksDatabaseSyncWatcher(sqlHelper);
            }

            @Override
            protected Void doInBackground(Void... params) {
                loadedData = Serializer.getInstance(MainActivity.this).loadData("stacks.stk");
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                List<Stack> archivedStacks = loadedData.getLoadedArchivedStacks();
                List<Stack> stacks = loadedData.getLoadedStacks();

                for (Stack stack : stacks) {
                    StackManager.get().addStack(stack);
                }
                for (Stack stack : archivedStacks) {
                    StackManager.get().addArchiveStack(stack);
                }

                stackFragment.updateEmptyViews();
                progressDialog.dismiss();
                dataLoaded = true;

                showTimedMessages();
            }
        }.execute();
    }

    /**
     * Load the SQL db and add it into the working model
     */
    private void loadSQLData() {
        new AsyncTask<Void, Void, Void>() {
            ProgressDialog progressDialog;
            LoadedData loadedData;

            @Override
            protected void onPreExecute() {
                progressDialog = new ProgressDialog(MainActivity.this);
                progressDialog.setTitle("Loading Data");
                progressDialog.setMessage("Please wait");
                progressDialog.setIndeterminate(true);
                progressDialog.setCancelable(false);
                progressDialog.show();
            }

            @Override
            protected Void doInBackground(Void... params) {
                loadedData = sqlHelper.loadStacks();
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                List<Stack> archivedStacks = loadedData.getLoadedArchivedStacks();
                List<Stack> stacks = loadedData.getLoadedStacks();

                for (Stack stack : stacks) {
                    StackManager.get().addStack(stack);
                }
                for (Stack stack : archivedStacks) {
                    StackManager.get().addArchiveStack(stack);
                }

                stackFragment.updateEmptyViews();
                progressDialog.dismiss();
                dataLoaded = true;
                syncWatcher = new StacksDatabaseSyncWatcher(sqlHelper);
                showTimedMessages();
            }
        }.execute();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("dataLoaded", dataLoaded);
        outState.putBoolean("stacksOpened", isStacksShowing());
        if (cardFragment.getStack() != null)
            outState.putString("stack", cardFragment.getStack().getName());
    }

    /**
     * Ask the user to rate the app or upgrade after a certain time,
     * and mark it so the message is never shown again
     */
    private void showTimedMessages() {
        if (getSharedPreferences("first_run", 0).getLong("first_date", 0) < 1) {
            getSharedPreferences("first_run", 0).edit().putLong("first_date", System.currentTimeMillis()).apply();
            onFirstRun();
        } else {
            long first_run = getSharedPreferences("first_run", 0).getLong("first_date", 0);
            int askStateRate = getSharedPreferences("first_run", 0).getInt("askState", STATE_NO_PREF_RATE);
            int askStateUpgrade = getSharedPreferences("first_run", 0).getInt("askStateUpgrade",
                    STATE_NO_PREF_UPGRADE);

            if (askStateRate == STATE_NO_PREF_RATE) {
                if (System.currentTimeMillis() - first_run > RATE_TIME_TO_WAIT) {
                    new AlertDialog.Builder(this).setTitle("Rate").setMessage("Please rate/review this app!")
                            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    getSharedPreferences("first_run", 0).edit().putInt("askState", STATE_NO_RATE)
                                            .apply();
                                    final Uri uri = Uri.parse(
                                            "market://details?id=" + getApplicationContext().getPackageName());
                                    final Intent rateAppIntent = new Intent(Intent.ACTION_VIEW, uri);
                                    if (getPackageManager().queryIntentActivities(rateAppIntent, 0).size() > 0) {
                                        startActivity(rateAppIntent);
                                    }
                                    dialogInterface.dismiss();
                                }
                            }).setNegativeButton("Never", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    getSharedPreferences("first_run", 0).edit().putInt("askState", STATE_NO_RATE)
                                            .apply();
                                    dialogInterface.dismiss();
                                }
                            }).show();

                }
            }
            if (askStateUpgrade == STATE_NO_PREF_UPGRADE) {
                if (System.currentTimeMillis() - first_run > UPGRADE_TIME_TO_WAIT) {
                    new AlertDialog.Builder(this).setTitle("Upgrade")
                            .setMessage("Do you want to upgrade to remove all ads and support development?")
                            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    getSharedPreferences("first_run", 0).edit()
                                            .putInt("askStateUpgrade", STATE_NO_UPGRADE).apply();
                                    final Uri uri = Uri.parse("market://details?id=org.centum.android.stack.pro");
                                    final Intent upgradeAppIntent = new Intent(Intent.ACTION_VIEW, uri);
                                    if (getPackageManager().queryIntentActivities(upgradeAppIntent, 0).size() > 0) {
                                        startActivity(upgradeAppIntent);
                                    }
                                    dialogInterface.dismiss();
                                }
                            }).setNegativeButton("Never", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    getSharedPreferences("first_run", 0).edit()
                                            .putInt("askStateUpgrade", STATE_NO_UPGRADE).apply();
                                    dialogInterface.dismiss();
                                }
                            }).show();

                }
            }
        }
    }

    /**
     * Called if this app is run for the first time
     */
    private void onFirstRun() {
        if (StackManager.get().getNumberOfStacks() == 0) {
            addSampleStack();
            cardFragment.setStack(StackManager.get().getStack(0));
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if (!PreferenceManager.getDefaultSharedPreferences(this)
                .getBoolean(SettingsActivity.KEY_PREF_ANALYTICS_OPTOUT, false))
            EasyTracker.getInstance(this).activityStart(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        if (!PreferenceManager.getDefaultSharedPreferences(this)
                .getBoolean(SettingsActivity.KEY_PREF_ANALYTICS_OPTOUT, false))
            EasyTracker.getInstance(this).activityStop(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (adView != null) {
            adView.pause();
        }
        //Debug.stopMethodTracing();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (adView != null) {
            adView.setVisibility(View.VISIBLE);
            adView.resume();
        }
        backupData();
        stackFragment.updateEmptyViews();
        //Debug.startMethodTracing("app");
    }

    /**
     * Check whether if the settings indicates whether data should be backed up,
     * and backs up if enough time has passed
     */
    private void backupData() {
        String backupTimeS = PreferenceManager.getDefaultSharedPreferences(this)
                .getString(SettingsActivity.KEY_PREF_BACKUP_TIME, "12");
        long backupTime;
        try {
            if (Double.parseDouble(backupTimeS) < 0) {
                backupTime = Long.MAX_VALUE;
            } else if (Double.parseDouble(backupTimeS) < 1) {
                backupTime = 3600000;
                PreferenceManager.getDefaultSharedPreferences(this).edit()
                        .putString(SettingsActivity.KEY_PREF_BACKUP_TIME, "1").commit();
            } else {
                backupTime = (long) (Double.parseDouble(backupTimeS) * 3600000); //hours to ms
            }
        } catch (NumberFormatException ex) {
            backupTime = 12 * 3600000;
            PreferenceManager.getDefaultSharedPreferences(this).edit()
                    .putString(SettingsActivity.KEY_PREF_BACKUP_TIME, "12").commit();
        }
        if ((System.currentTimeMillis()
                - getSharedPreferences("backup", 0).getLong("lastBackup", 0)) > backupTime) {
            new AsyncTask<Void, Void, Void>() {
                private ProgressDialog progressDialog;

                @Override
                protected void onPreExecute() {
                    progressDialog = new ProgressDialog(MainActivity.this);
                    progressDialog.setTitle("Backing up");
                    progressDialog.setMessage("Change the backup frequency in Settings");
                    progressDialog.setIndeterminate(true);
                    progressDialog.show();
                }

                @Override
                protected void onPostExecute(Void result) {
                    progressDialog.dismiss();
                    Log.d("MainActivity", "Backed data up");
                    getSharedPreferences("backup", 0).edit().putLong("lastBackup", System.currentTimeMillis())
                            .commit();
                }

                @Override
                protected Void doInBackground(Void... params) {
                    Serializer.getInstance(MainActivity.this).backup();
                    return null;
                }
            }.execute();
        }
    }

    @Override
    public void onDestroy() {
        if (adView != null) {
            adView.destroy();
        }
        super.onDestroy();
    }

    public void addSampleStack() {
        if (!StackManager.get().containsStack("Organic Chemistry")
                && StackManager.get().getNumberOfArchivedStacks() == 0) {
            Stack chemStack = SampleStack.getSampleStack();
            StackManager.get().addStack(chemStack);
        }
    }

    @Override
    public void onPanelSlide(View view, float v) {
        cardFragment.updateColumns();
    }

    @Override
    public void onPanelOpened(View view) {
        stackFragment.setHasOptionsMenu(true);
        cardFragment.setHasOptionsMenu(false);
        getActionBar().setDisplayHomeAsUpEnabled(false);
        stackFragment.updateEmptyViews();
        setTitle("Stacks");
        //if (adView != null)
        //    adView.setVisibility(View.VISIBLE);
    }

    @Override
    public void onPanelClosed(View view) {
        stackFragment.setHasOptionsMenu(false);
        cardFragment.setHasOptionsMenu(true);
        if (cardFragment.getStack() != null) {
            setTitle(cardFragment.getStack().getName());
        }
        cardFragment.updateColumns();
        stackFragment.updateEmptyViews();
        getActionBar().setDisplayHomeAsUpEnabled(true);
        //if (adView != null)
        //    adView.setVisibility(View.VISIBLE);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            showStacks();
            return true;
        }
        return false;
    }

    public void showStacks() {
        slidingPane.openPane();
    }

    public void showCards() {
        slidingPane.closePane();
    }

    public boolean isCardsShowing() {
        return !slidingPane.isOpen();
    }

    public boolean isStacksShowing() {
        return slidingPane.isOpen();
    }

    public StackFragment getStackFragment() {
        return stackFragment;
    }

    public CardFragment getCardFragment() {
        return cardFragment;
    }

    @Override
    public void onBackPressed() {
        if (isCardsShowing()) {
            showStacks();
        } else {
            super.onBackPressed();
        }
    }
}