net.zionsoft.obadiah.BookSelectionActivity.java Source code

Java tutorial

Introduction

Here is the source code for net.zionsoft.obadiah.BookSelectionActivity.java

Source

/*
 * Obadiah - Simple and Easy-to-Use Bible Reader
 * Copyright (C) 2015 ZionSoft
 * 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 net.zionsoft.obadiah;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

import net.zionsoft.obadiah.model.Bible;
import net.zionsoft.obadiah.model.ReadingProgressManager;
import net.zionsoft.obadiah.model.Settings;
import net.zionsoft.obadiah.model.analytics.Analytics;
import net.zionsoft.obadiah.model.appindexing.AppIndexingManager;
import net.zionsoft.obadiah.model.utils.AppUpdateChecker;
import net.zionsoft.obadiah.model.utils.UriHelper;
import net.zionsoft.obadiah.ui.activities.BaseActionBarActivity;
import net.zionsoft.obadiah.ui.activities.ReadingProgressActivity;
import net.zionsoft.obadiah.ui.activities.SearchActivity;
import net.zionsoft.obadiah.ui.activities.SettingsActivity;
import net.zionsoft.obadiah.ui.activities.TranslationManagementActivity;
import net.zionsoft.obadiah.ui.fragments.ChapterSelectionFragment;
import net.zionsoft.obadiah.ui.fragments.TextFragment;
import net.zionsoft.obadiah.ui.utils.AnimationHelper;
import net.zionsoft.obadiah.ui.utils.DialogHelper;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import butterknife.InjectView;

public class BookSelectionActivity extends BaseActionBarActivity
        implements ChapterSelectionFragment.Listener, TextFragment.Listener {
    private static final String KEY_MESSAGE_TYPE = "net.zionsoft.obadiah.BookSelectionActivity.KEY_MESSAGE_TYPE";
    private static final String KEY_BOOK_INDEX = "net.zionsoft.obadiah.BookSelectionActivity.KEY_BOOK_INDEX";
    private static final String KEY_CHAPTER_INDEX = "net.zionsoft.obadiah.BookSelectionActivity.KEY_CHAPTER_INDEX";
    private static final String KEY_VERSE_INDEX = "net.zionsoft.obadiah.BookSelectionActivity.KEY_VERSE_INDEX";

    public static Intent newStartReorderToTopIntent(Context context, String messageType, int book, int chapter,
            int verse) {
        return newStartReorderToTopIntent(context).putExtra(KEY_MESSAGE_TYPE, messageType)
                .putExtra(KEY_BOOK_INDEX, book).putExtra(KEY_CHAPTER_INDEX, chapter)
                .putExtra(KEY_VERSE_INDEX, verse);
    }

    public static Intent newStartReorderToTopIntent(Context context) {
        final Intent startIntent = newStartIntent(context);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            // there's some horrible issue with FLAG_ACTIVITY_REORDER_TO_FRONT for KitKat and above
            // ref. https://code.google.com/p/android/issues/detail?id=63570
            startIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        }
        return startIntent;
    }

    public static Intent newStartIntent(Context context) {
        return new Intent(context, BookSelectionActivity.class);
    }

    @Inject
    Bible mBible;

    @Inject
    ReadingProgressManager mReadingProgressManager;

    @Inject
    Settings mSettings;

    @InjectView(R.id.drawer_layout)
    DrawerLayout mDrawerLayout;

    private AppIndexingManager mAppIndexingManager;
    private SharedPreferences mPreferences;

    private String mCurrentTranslation;
    private List<String> mBookNames;
    private int mCurrentBook;
    private int mCurrentChapter;

    private ChapterSelectionFragment mChapterSelectionFragment;
    private TextFragment mTextFragment;

    private ActionBarDrawerToggle mDrawerToggle;
    private Spinner mTranslationsSpinner;
    private View mRootView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        App.get(this).getInjectionComponent().inject(this);

        mAppIndexingManager = new AppIndexingManager(this);
        mPreferences = getSharedPreferences(Constants.PREF_NAME, MODE_PRIVATE);

        initializeUi();
        checkDeepLink();
    }

    private void initializeUi() {
        setContentView(R.layout.activity_book_selection);

        mRootView = getWindow().getDecorView();

        final ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 0, 0);
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        final FragmentManager fm = getSupportFragmentManager();
        mChapterSelectionFragment = (ChapterSelectionFragment) fm.findFragmentById(R.id.left_drawer);
        mTextFragment = (TextFragment) fm.findFragmentById(R.id.text_fragment);
    }

    private void checkDeepLink() {
        final Intent startIntent = getIntent();
        final Uri uri = startIntent.getData();
        if (uri != null) {
            UriHelper.checkDeepLink(mPreferences, uri);
        } else {
            final String messageType = startIntent.getStringExtra(KEY_MESSAGE_TYPE);
            if (TextUtils.isEmpty(messageType)) {
                return;
            }
            final int bookIndex = startIntent.getIntExtra(KEY_BOOK_INDEX, -1);
            if (bookIndex < 0) {
                return;
            }
            final int chapterIndex = startIntent.getIntExtra(KEY_CHAPTER_INDEX, -1);
            if (chapterIndex < 0) {
                return;
            }
            final int verseIndex = startIntent.getIntExtra(KEY_VERSE_INDEX, -1);
            if (verseIndex < 0) {
                return;
            }

            mPreferences.edit().putInt(Constants.PREF_KEY_LAST_READ_BOOK, bookIndex)
                    .putInt(Constants.PREF_KEY_LAST_READ_CHAPTER, chapterIndex)
                    .putInt(Constants.PREF_KEY_LAST_READ_VERSE, verseIndex).apply();

            Analytics.trackNotificationEvent("notification_opened", messageType);
        }
    }

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

        mDrawerToggle.syncState();
    }

    @Override
    protected void onStart() {
        super.onStart();

        mAppIndexingManager.onStart();
        populateUi();
        showUpdateDialog();
    }

    private void showUpdateDialog() {
        if (TextUtils.isEmpty(mPreferences.getString(Constants.PREF_KEY_LAST_READ_TRANSLATION, null))) {
            // do nothing if there's no translation installed (most likely it's the 1st time use)
            return;
        }

        if (AppUpdateChecker.shouldUpdate(this)) {
            DialogHelper.showDialog(BookSelectionActivity.this, false,
                    R.string.dialog_new_version_available_message, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            try {
                                startActivity(new Intent(Intent.ACTION_VIEW).setData(Constants.GOOGLE_PLAY_URI));
                                Analytics.trackUIEvent("upgrade_app");
                            } catch (ActivityNotFoundException e) {
                                Analytics.trackException("Failed to open market for updating: " + Build.MANUFACTURER
                                        + ", " + Build.MODEL);

                                // falls back to open a link in browser
                                startActivity(new Intent(Intent.ACTION_VIEW)
                                        .setData(Uri.parse("http://www.zionsoft.net/bible-reader/")));
                            }
                        }
                    }, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Analytics.trackUIEvent("ignore_upgrade_app");
                        }
                    });
            AppUpdateChecker.markAsUpdateAsked(this);
        }
    }

    private void populateUi() {
        mSettings.refresh();
        mRootView.setKeepScreenOn(mSettings.keepScreenOn());
        mRootView.setBackgroundColor(mSettings.getBackgroundColor());

        mCurrentTranslation = mPreferences.getString(Constants.PREF_KEY_LAST_READ_TRANSLATION, null);
        if (mCurrentTranslation == null) {
            DialogHelper.showDialog(this, false, R.string.dialog_no_translation,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            AnimationHelper.slideIn(BookSelectionActivity.this,
                                    TranslationManagementActivity.newStartIntent(BookSelectionActivity.this));
                        }
                    }, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    });
            return;
        }

        mCurrentBook = mPreferences.getInt(Constants.PREF_KEY_LAST_READ_BOOK, 0);
        mCurrentChapter = mPreferences.getInt(Constants.PREF_KEY_LAST_READ_CHAPTER, 0);

        loadTranslations();
    }

    private void loadTranslations() {
        if (mTranslationsSpinner == null)
            return;

        mBible.loadDownloadedTranslations(new Bible.OnStringsLoadedListener() {
            @Override
            public void onStringsLoaded(List<String> strings) {
                if (strings == null || strings.size() == 0) {
                    if (mCurrentTranslation != null) {
                        DialogHelper.showDialog(BookSelectionActivity.this, false, R.string.dialog_retry,
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        loadTranslations();
                                    }
                                }, null);
                    }
                    return;
                }

                int selected = 0;
                boolean hasSelectedTranslation = false;
                for (String translation : strings) {
                    if (translation.equals(mCurrentTranslation)) {
                        hasSelectedTranslation = true;
                        break;
                    }
                    ++selected;
                }
                if (!hasSelectedTranslation) {
                    // the requested translation is not available
                    mCurrentTranslation = strings.get(0);
                    selected = 0;
                    mPreferences.edit().putString(Constants.PREF_KEY_LAST_READ_TRANSLATION, mCurrentTranslation)
                            .apply();
                }

                final int translationsCount = strings.size();
                final List<String> translations = new ArrayList<String>(translationsCount + 1);
                translations.addAll(strings);
                translations.add(getResources().getString(R.string.text_more_translations));
                mTranslationsSpinner.setAdapter(new ArrayAdapter<String>(getSupportActionBar().getThemedContext(),
                        R.layout.item_drop_down, translations));
                mTranslationsSpinner.setSelection(selected);
                mTranslationsSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                        if (position == translationsCount) {
                            AnimationHelper.slideIn(BookSelectionActivity.this,
                                    TranslationManagementActivity.newStartIntent(BookSelectionActivity.this));
                            return;
                        }

                        final String selected = translations.get(position);
                        if (selected.equals(mCurrentTranslation))
                            return;

                        Analytics.trackTranslationSelection(selected);
                        mCurrentTranslation = selected;
                        mPreferences.edit().putString(Constants.PREF_KEY_LAST_READ_TRANSLATION, selected)
                                .putInt(Constants.PREF_KEY_LAST_READ_VERSE, mTextFragment.getCurrentVerse())
                                .apply();

                        loadTexts();
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?> parent) {
                        // do nothing
                    }
                });

                loadTexts();
            }
        });
    }

    private void loadTexts() {
        mBible.loadBookNames(mCurrentTranslation, new Bible.OnStringsLoadedListener() {
            @Override
            public void onStringsLoaded(List<String> strings) {
                if (strings == null || strings.size() == 0) {
                    if (mCurrentTranslation != null) {
                        DialogHelper.showDialog(BookSelectionActivity.this, false, R.string.dialog_retry,
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        loadTexts();
                                    }
                                }, null);
                    }
                    return;
                }

                mBookNames = strings;
                updateTitle();
            }
        });

        mChapterSelectionFragment.setSelected(mCurrentTranslation, mCurrentBook, mCurrentChapter);

        mTextFragment.setSelected(mCurrentTranslation, mCurrentBook, mCurrentChapter,
                mPreferences.getInt(Constants.PREF_KEY_LAST_READ_VERSE, 0));
    }

    private void updateTitle() {
        final String bookName = mBookNames.get(mCurrentBook);
        setTitle(String.format("%s, %d", bookName, mCurrentChapter + 1));
        mAppIndexingManager.onView(mCurrentTranslation, bookName, mCurrentBook, mCurrentChapter);

        // TODO get an improved tracking algorithm, e.g. only consider as "read" if the user stays for a while
        mReadingProgressManager.trackChapterReading(mCurrentBook, mCurrentChapter);
    }

    @Override
    protected void onStop() {
        mPreferences.edit().putInt(Constants.PREF_KEY_LAST_READ_BOOK, mCurrentBook)
                .putInt(Constants.PREF_KEY_LAST_READ_CHAPTER, mCurrentChapter)
                .putInt(Constants.PREF_KEY_LAST_READ_VERSE, mTextFragment.getCurrentVerse()).apply();
        mAppIndexingManager.onStop();

        super.onStop();
    }

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

        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_bookselection, menu);

        mTranslationsSpinner = (Spinner) MenuItemCompat.getActionView(menu.findItem(R.id.action_translations));
        loadTranslations();

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mDrawerToggle.onOptionsItemSelected(item))
            return true;

        switch (item.getItemId()) {
        case R.id.action_search:
            AnimationHelper.slideIn(this, SearchActivity.newStartReorderToTopIntent(this));
            return true;
        case R.id.action_reading_progress:
            AnimationHelper.slideIn(this, ReadingProgressActivity.newStartIntent(this));
            return true;
        case R.id.action_settings:
            AnimationHelper.slideIn(this, SettingsActivity.newStartIntent(this));
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onChapterSelected(int bookIndex, int chapterIndex) {
        if (mCurrentBook == bookIndex && mCurrentChapter == chapterIndex)
            return;
        mCurrentBook = bookIndex;
        mCurrentChapter = chapterIndex;

        mDrawerLayout.closeDrawers();
        mTextFragment.setSelected(bookIndex, chapterIndex, 0);
        updateTitle();
    }

    @Override
    public void onChapterSelected(int chapterIndex) {
        if (mCurrentChapter == chapterIndex)
            return;
        mCurrentChapter = chapterIndex;

        mChapterSelectionFragment.setSelected(mCurrentBook, mCurrentChapter);
        updateTitle();
    }
}