org.gdg.frisbee.android.chapter.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.gdg.frisbee.android.chapter.MainActivity.java

Source

/*
 * Copyright 2013-2015 The GDG Frisbee Project
 *
 * 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 org.gdg.frisbee.android.chapter;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Spinner;

import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AndroidAppUri;
import com.google.android.gms.appinvite.AppInviteReferral;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;

import org.gdg.frisbee.android.BuildConfig;
import org.gdg.frisbee.android.Const;
import org.gdg.frisbee.android.R;
import org.gdg.frisbee.android.activity.AppInviteDeepLinkActivity;
import org.gdg.frisbee.android.api.Callback;
import org.gdg.frisbee.android.api.model.Chapter;
import org.gdg.frisbee.android.api.model.Directory;
import org.gdg.frisbee.android.app.App;
import org.gdg.frisbee.android.app.OrganizerChecker;
import org.gdg.frisbee.android.arrow.AppStateMigrationHelper;
import org.gdg.frisbee.android.cache.ModelCache;
import org.gdg.frisbee.android.common.GdgNavDrawerActivity;
import org.gdg.frisbee.android.eventseries.GdgEventListFragment;
import org.gdg.frisbee.android.onboarding.FirstStartActivity;
import org.gdg.frisbee.android.utils.PrefUtils;
import org.gdg.frisbee.android.utils.Utils;
import org.joda.time.DateTime;

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

import butterknife.Bind;
import timber.log.Timber;

public class MainActivity extends GdgNavDrawerActivity {

    private static final String SECTION_EVENTS = "events";
    private static final String ARG_SELECTED_CHAPTER = "selected_chapter";
    private static final String ARG_CHAPTERS = "chapters";

    private static final int[] PAGES = { R.string.news, R.string.info, R.string.events };
    private static final int[] ORGANIZER_PAGES = { R.string.news, R.string.info, R.string.events,
            R.string.for_leads };

    private static final int REQUEST_FIRST_START_WIZARD = 100;
    private static final int PLAY_SERVICE_DIALOG_REQUEST_CODE = 200;
    private static final Uri APP_URI = AndroidAppUri
            .newAndroidAppUri(BuildConfig.APPLICATION_ID, Uri.parse(Const.URL_GDGROUPS_ORG)).toUri();
    public static final String TITLE_GOOGLE_DEVELOPER_GROUPS = "Google Developer Groups";

    @Bind(R.id.pager)
    ViewPager mViewPager;
    @Bind(R.id.tabs)
    TabLayout mTabLayout;

    private Handler mHandler = new Handler();
    private ChapterAdapter mChapterAdapter;
    private ChapterFragmentPagerAdapter mViewPagerAdapter;

    private boolean mFirstStart = false;

    private ChapterComparator mLocationComparator;
    private Spinner mSpinner;
    private String selectedChapterId;

    // Local Broadcast receiver for receiving invites
    private BroadcastReceiver mDeepLinkReceiver = null;

    /**
     * Called when the activity is first created.
     *
     * @param savedInstanceState If the activity is being re-initialized after
     *                           previously being shut down then this Bundle contains the data it most
     *                           recently supplied in onSaveInstanceState(Bundle). <b>Note: Otherwise it is null.</b>
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mLocationComparator = new ChapterComparator(PrefUtils.getHomeChapterIdNotNull(this),
                App.getInstance().getLastLocation());

        mChapterAdapter = new ChapterAdapter(MainActivity.this, R.layout.spinner_item_actionbar);
        mChapterAdapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
        initSpinner();

        ArrayList<Chapter> chapters = null;

        if (savedInstanceState != null) {
            chapters = savedInstanceState.getParcelableArrayList(ARG_CHAPTERS);
            selectedChapterId = savedInstanceState.getString(ARG_SELECTED_CHAPTER);
        } else {
            Intent intent = getIntent();

            if (FirstStartActivity.ACTION_FIRST_START.equals(intent.getAction())) {
                Timber.d("Completed FirstStartWizard");

                if (PrefUtils.isSignedIn(this)) {
                    mFirstStart = true;
                }
            }

            selectedChapterId = getChapterIdFromIntent(intent);

            if (AppInviteReferral.hasReferral(intent)) {
                // In this case the referral data is in the intent launching the MainActivity,
                // which means this user already had the app installed. We do not have to
                // register the Broadcast Receiver to listen for Play Store Install information
                launchAppInviteActivity(intent);
            }
        }

        if (selectedChapterId == null) {
            selectedChapterId = PrefUtils.getHomeChapterIdNotNull(this);
        }

        if (chapters != null) {
            initChapters(chapters);
        } else {
            App.getInstance().getModelCache().getAsync(Const.CACHE_KEY_CHAPTER_LIST_HUB,
                    new ModelCache.CacheListener() {
                        @Override
                        public void onGet(Object item) {
                            Directory directory = (Directory) item;
                            initChapters(directory.getGroups());
                        }

                        @Override
                        public void onNotFound(String key) {
                            if (Utils.isOnline(MainActivity.this)) {
                                fetchChapters();
                            } else {
                                showError(R.string.offline_alert);
                            }
                        }
                    });
        }

        if (PrefUtils.shouldShowSeasonsGreetings(this)) {
            SeasonsGreetingsFragment seasonsGreetings = new SeasonsGreetingsFragment();
            seasonsGreetings.show(getSupportFragmentManager(), "dialog");
        }

        if (PrefUtils.isSignedIn(this)) {
            checkAchievements();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        int playServiceStatus = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (ConnectionResult.SUCCESS != playServiceStatus) {
            GooglePlayServicesUtil.getErrorDialog(playServiceStatus, this, PLAY_SERVICE_DIALOG_REQUEST_CODE).show();
        }
        checkHomeChapterValid();
        updateChapterPages();
    }

    @Override
    public void onConnected(Bundle bundle) {
        super.onConnected(bundle);
        updateChapterPages();

        AppStateMigrationHelper.checkSnapshotUpgrade(this, getGoogleApiClient(), getString(R.string.arrow_tagged));
    }

    private void updateChapterPages() {
        final boolean wasOrganizer = mViewPagerAdapter != null
                && mViewPagerAdapter.getCount() == ORGANIZER_PAGES.length;
        App.getInstance().checkOrganizer(getGoogleApiClient(), new OrganizerChecker.Callbacks() {
            @Override
            public void onOrganizerResponse(boolean isOrganizer) {
                if (mViewPagerAdapter != null && wasOrganizer != isOrganizer) {
                    mViewPagerAdapter.notifyDataSetChanged(false /* forceUpdate */);
                    mTabLayout.setTabsFromPagerAdapter(mViewPagerAdapter);
                }
            }

            @Override
            public void onErrorResponse() {
            }
        });
    }

    private void checkHomeChapterValid() {
        String homeChapterId = getCurrentHomeChapterId();
        if (isHomeChapterOutdated(homeChapterId) && isShowingStoredHomeChapter()) {
            int position = mChapterAdapter.getPosition(homeChapterId);
            if (position != -1) {
                updateSelectionfor(homeChapterId);
            }
        }
    }

    private boolean isShowingStoredHomeChapter() {
        return selectedChapterId.equals(mStoredHomeChapterId);
    }

    private String getChapterIdFromIntent(final Intent intent) {
        if (intent.hasExtra(Const.EXTRA_CHAPTER_ID)) {
            return intent.getStringExtra(Const.EXTRA_CHAPTER_ID);
        } else if (intent.getData() != null && intent.getData().getScheme() != null
                && intent.getData().getScheme().equals("https")) {
            return intent.getData().getLastPathSegment();
        }
        return null;
    }

    private void fetchChapters() {
        App.getInstance().getGdgXHub().getDirectory().enqueue(new Callback<Directory>() {
            @Override
            public void success(final Directory directory) {

                App.getInstance().getModelCache().putAsync(Const.CACHE_KEY_CHAPTER_LIST_HUB, directory,
                        DateTime.now().plusDays(1), new ModelCache.CachePutListener() {
                            @Override
                            public void onPutIntoCache() {
                                ArrayList<Chapter> chapters = directory.getGroups();
                                initChapters(chapters);
                            }
                        });
            }

            @Override
            public void failure(Throwable error) {
                showError(R.string.fetch_chapters_failed);
            }

            @Override
            public void networkFailure(Throwable error) {
                showError(R.string.offline_alert);
            }
        });
    }

    /**
     * Initializes ViewPager, TabLayout, and Spinner Navigation.
     *
     * @param chapters Chapter array to be initialized, never null.
     */
    private void initChapters(@NonNull ArrayList<Chapter> chapters) {
        addChapters(chapters);

        mViewPagerAdapter = new ChapterFragmentPagerAdapter(this, getSupportFragmentManager(), selectedChapterId);
        mViewPager.setAdapter(mViewPagerAdapter);
        mViewPager.setOffscreenPageLimit(3);
        updateSelectionfor(selectedChapterId);

        recordStartPageView();

        mTabLayout.setupWithViewPager(mViewPager);
        if (SECTION_EVENTS.equals(getIntent().getStringExtra(Const.EXTRA_SECTION))) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mViewPager.setCurrentItem(2, true);
                }
            }, 500);
        }
    }

    private void recordStartPageView() {
        Action viewAction = Action.newAction(Action.TYPE_VIEW, TITLE_GOOGLE_DEVELOPER_GROUPS, APP_URI);
        recordStartPageView(viewAction);
    }

    private void recordEndPageView() {
        Action viewAction = Action.newAction(Action.TYPE_VIEW, TITLE_GOOGLE_DEVELOPER_GROUPS, APP_URI);
        recordEndPageView(viewAction);
    }

    protected String getTrackedViewName() {
        if (mViewPager == null || mViewPagerAdapter == null) {
            return "Main";
        }
        final String[] pagesNames = { "News", "Info", "Events" };
        String pageName;
        try {
            pageName = pagesNames[getCurrentPage()];
        } catch (IndexOutOfBoundsException e) {
            pageName = "";
        }
        Chapter chapter = mChapterAdapter.findById(selectedChapterId);
        return "Main/" + (chapter != null ? chapter.getName().replaceAll(" ", "-") : "") + "/" + pageName;
    }

    @Override
    protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
        super.onActivityResult(requestCode, responseCode, intent);
    }

    private void checkAchievements() {
        if (mFirstStart) {
            getAchievementActionHandler().handleSignIn();
        }
        getAchievementActionHandler().handleAppStarted();
        if (PrefUtils.isWidgetAdded(this)) {
            getAchievementActionHandler().handlePowerUser();
        }
    }

    private void addChapters(List<Chapter> chapterList) {
        Collections.sort(chapterList, mLocationComparator);
        mChapterAdapter.clear();
        mChapterAdapter.addAll(chapterList);
    }

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

        if (PrefUtils.isFirstStart(this)) {
            startActivityForResult(new Intent(this, FirstStartActivity.class), REQUEST_FIRST_START_WIZARD);
        }
        registerDeepLinkReceiver();
    }

    @Override
    protected void onStop() {
        recordEndPageView();
        unregisterDeepLinkReceiver();
        super.onStop();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        if (mChapterAdapter.getCount() > 0) {
            outState.putParcelableArrayList(ARG_CHAPTERS, mChapterAdapter.getAll());
        }
        if (mViewPagerAdapter != null) {
            outState.putString(ARG_SELECTED_CHAPTER, mViewPagerAdapter.getSelectedChapter());
        }
    }

    private void initSpinner() {
        Toolbar toolbar = getActionBarToolbar();
        View spinnerContainer = LayoutInflater.from(this).inflate(R.layout.actionbar_spinner, toolbar, false);
        ActionBar.LayoutParams lp = new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        toolbar.addView(spinnerContainer, lp);

        mSpinner = (Spinner) spinnerContainer.findViewById(R.id.actionbar_spinner);

        mSpinner.setAdapter(mChapterAdapter);
        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(final AdapterView<?> parent, final View view, final int position,
                    final long id) {

                Chapter selectedChapter = mChapterAdapter.getItem(position);
                updateSelectionfor(selectedChapter.getGplusId());
            }

            @Override
            public void onNothingSelected(final AdapterView<?> parent) {
                // Nothing to do.
            }
        });
    }

    private void updateSelectionfor(final String newChapterId) {
        mViewPagerAdapter.setSelectedChapter(newChapterId);
        mSpinner.setSelection(mChapterAdapter.getPosition(newChapterId));
        if (!selectedChapterId.equals(newChapterId)) {
            Timber.d("Switching newChapterId!");
            selectedChapterId = newChapterId;
            mViewPagerAdapter.notifyDataSetChanged(true /* forceUpdate */);
        }
    }

    public class ChapterFragmentPagerAdapter extends FragmentStatePagerAdapter {

        private int[] mPages;
        private Context mContext;
        @NonNull
        private String mSelectedChapterId;
        private boolean forceUpdate = false;

        public ChapterFragmentPagerAdapter(Context ctx, FragmentManager fm, @NonNull String selectedChapterId) {
            super(fm);
            mContext = ctx;
            mSelectedChapterId = selectedChapterId;
            mPages = App.getInstance().isOrganizer() ? ORGANIZER_PAGES : PAGES;
        }

        public void notifyDataSetChanged(boolean forceUpdate) {
            this.forceUpdate = forceUpdate;
            notifyDataSetChanged();
        }

        @Override
        public void notifyDataSetChanged() {
            mPages = App.getInstance().isOrganizer() ? ORGANIZER_PAGES : PAGES;
            super.notifyDataSetChanged();
        }

        @Override
        public int getItemPosition(Object object) {
            if (forceUpdate) {
                return POSITION_NONE;
            }
            return super.getItemPosition(object);
        }

        @Override
        public int getCount() {
            return mPages.length;
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
            case 0:
                return NewsFragment.newInstance(mSelectedChapterId);
            case 1:
                return InfoFragment.newInstance(mSelectedChapterId);
            case 2:
                return GdgEventListFragment.newInstance(mSelectedChapterId);
            case 3:
                return LeadFragment.newInstance(mSelectedChapterId);
            }
            return null;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            if (0 <= position && position < mPages.length) {
                return mContext.getString(mPages[position]);
            } else {
                return "";
            }
        }

        @NonNull
        public String getSelectedChapter() {
            return mSelectedChapterId;
        }

        public void setSelectedChapter(@NonNull String chapterId) {
            trackView();
            mSelectedChapterId = chapterId;
        }
    }

    private void registerDeepLinkReceiver() {
        // Create local Broadcast receiver that starts AppInviteDeepLinkActivity when a deep link
        // is found
        mDeepLinkReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (AppInviteReferral.hasReferral(intent)) {
                    launchAppInviteActivity(intent);
                }
            }
        };

        IntentFilter intentFilter = new IntentFilter(getString(R.string.action_deep_link));
        LocalBroadcastManager.getInstance(this).registerReceiver(mDeepLinkReceiver, intentFilter);
    }

    private void unregisterDeepLinkReceiver() {
        if (mDeepLinkReceiver != null) {
            LocalBroadcastManager.getInstance(this).unregisterReceiver(mDeepLinkReceiver);
        }
    }

    /**
     * Launch AppInviteActivity with an intent containing App Invite information
     */
    private void launchAppInviteActivity(Intent intent) {
        Timber.d("launchAppInviteActivity:" + intent);
        Intent newIntent = new Intent(intent).setClass(this, AppInviteDeepLinkActivity.class);
        startActivity(newIntent);
    }
}