Java tutorial
// @formatter:off /* * MainActivity.java - main UI for MOCA * Copyright (C) 2012 Matteo Panella <morpheus@level28.org> * * 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // @formatter:on package org.level28.android.moca.ui; import org.level28.android.moca.BuildConfig; import org.level28.android.moca.R; import org.level28.android.moca.bitmaps.NetworkAvatarLoader; import org.level28.android.moca.bitmaps.SimpleBitmapLoader; import org.level28.android.moca.sync.MocaAuthenticator; import org.level28.android.moca.ui.map.MocaMap; import org.level28.android.moca.ui.schedule.ScheduleActivity; import android.accounts.AccountManager; import android.annotation.TargetApi; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.StrictMode; import android.os.StrictMode.ThreadPolicy; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.bugsense.trace.BugSenseHandler; import com.viewpagerindicator.TitlePageIndicator; /** * Main Activity for MOCA app. * * @author Matteo Panella */ public class MainActivity extends SherlockFragmentActivity implements OnItemClickListener { private static final String STATE_ACTIVE_POSITION = "active_position"; private static final String LOG_TAG = "MainActivity"; private boolean mDualPane; private NetworkAvatarLoader mAvatarLoader; private SimpleBitmapLoader mBannerLoader; private MocaFragmentAdapter mFragmentAdapter; private FragmentListAdapter mFragmentListAdapter; private ListView mFragmentList; private ViewPager mPager; private int mActivePosition = ListView.INVALID_POSITION; private String[] mTrailers; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (BuildConfig.DEBUG) { Log.v(LOG_TAG, "MainActivity awakening"); // Debug build - enable StrictMode assertions if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { setupStrictMode(); } } else { // Production/testing build - enable BugSense setupBugSense(); } setContentView(R.layout.main); // Ensure we don't have the ActionBar Home button enabled getSupportActionBar().setHomeButtonEnabled(false); // Create a new loader for avatars mAvatarLoader = new NetworkAvatarLoader(this); // and a new loader for banners mBannerLoader = new SimpleBitmapLoader(this); // Instantiate a new FragmentPagerAdapter mFragmentAdapter = new MocaFragmentAdapter(getSupportFragmentManager(), getResources()); /* * Both layouts use a ViewPager to host fragments (it's less hacky). The * difference between the two is an implementation detail we're not * interested in here. */ mPager = (ViewPager) findViewById(R.id.pager); mPager.setAdapter(mFragmentAdapter); // Check if we're running in dual-pane mode mDualPane = getResources().getBoolean(R.bool.dualPaned); if (mDualPane) { // We do - use a list to select the currently active fragment mFragmentList = (ListView) findViewById(R.id.fragmentList); // Setup the list adapter mFragmentListAdapter = new FragmentListAdapter(this, mPager); mFragmentList.setAdapter(mFragmentListAdapter); mFragmentList.setChoiceMode(ListView.CHOICE_MODE_SINGLE); if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVE_POSITION)) { // Restore active position int position = savedInstanceState.getInt(STATE_ACTIVE_POSITION); if (position == ListView.INVALID_POSITION) { // Reset position to ground state mFragmentList.setItemChecked(mActivePosition, false); position = 0; } mFragmentList.setItemChecked(position, true); mPager.setCurrentItem(position, false); mActivePosition = position; } else { // Start from position 0 mActivePosition = 0; mFragmentList.setItemChecked(mActivePosition, true); } } else { // We don't, fall back to the less-challenging phone UI :-) final TitlePageIndicator indicator = (TitlePageIndicator) findViewById(R.id.indicator); indicator.setViewPager(mPager); // Synchronize current page with the dual-pane layout if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVE_POSITION)) { final int position = savedInstanceState.getInt(STATE_ACTIVE_POSITION); if (position != ListView.INVALID_POSITION) { // Position updates *MUST* go through the ViewPagerIndicator indicator.setCurrentItem(position); } } } // Obtain the array of URLs for MOCA 2012 trailers mTrailers = getResources().getStringArray(R.array.trailer_urls); // Check if we need to create the dummy account AccountManager am = AccountManager.get(this); if (!MocaAuthenticator.dummyAccountExists(am)) { MocaAuthenticator.addDummyAccount(am); } if (BuildConfig.DEBUG) { Log.v(LOG_TAG, "MainActivity awakened, have fun ;-)"); } } @Override protected void onStart() { super.onStart(); if (mDualPane) { mFragmentList.setOnItemClickListener(this); } } @Override protected void onStop() { if (mDualPane) { mFragmentList.setOnItemClickListener(null); } super.onStop(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mDualPane) { if (mActivePosition != ListView.INVALID_POSITION) { outState.putInt(STATE_ACTIVE_POSITION, mActivePosition); } } else { outState.putInt(STATE_ACTIVE_POSITION, mPager.getCurrentItem()); } } @Override protected void onDestroy() { mAvatarLoader.release(true); super.onDestroy(); } public NetworkAvatarLoader avatarLoader() { return mAvatarLoader; } public SimpleBitmapLoader bannerLoader() { return mBannerLoader; } @Override public boolean onCreateOptionsMenu(Menu menu) { final MenuInflater inflater = getSupportMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { final int menuItemId = item.getItemId(); switch (menuItemId) { case R.id.menu_map: startActivity(new Intent(this, MocaMap.class)); return true; case R.id.menu_support_mx: { final Uri mxUri = Uri.parse(getResources().getString(R.string.support_mx_url)); startActivity(createBrowserIntent(mxUri)); return true; } case R.id.menu_license: displayLicenseDialog(); return true; case R.id.menu_about: displayAboutDialog(); return true; case R.id.menu_teaser_one: case R.id.menu_teaser_two: case R.id.menu_subliminal: startActivity(getIntentForTrailer(menuItemId)); return true; case R.id.menu_schedule: startActivity(new Intent(this, ScheduleActivity.class)); return true; default: return false; } } @Override public void onItemClick(AdapterView<?> list, View view, int position, long id) { mActivePosition = position; // Since this method is used only in two-pane mode, we have to update // the ViewPager directly mPager.setCurrentItem(position, true); } /** * Setup {@link StrictMode} assertions in debug builds. */ @TargetApi(Build.VERSION_CODES.GINGERBREAD) private void setupStrictMode() { final ThreadPolicy.Builder threadPolicyBuilder = new ThreadPolicy.Builder(); // StrictMode thread policy: threadPolicyBuilder.detectNetwork() // No network activity in UI thread .penaltyLog() // Log violations .penaltyDeath(); // Kill the process on violation StrictMode.setThreadPolicy(threadPolicyBuilder.build()); /* * NOTE: we don't define a StrictMode VmPolicy because the Google Maps * API misbehaves *BADLY* and it will pollute the logs with heaps of * messages we can't do anything about. -morph */ Log.i(LOG_TAG, "StrictMode enabled - Everyone, please observe that the \"fasten your seatbelt\" and \"no smoking\" signs have been turned on. Sit back and enjoy your flight."); } /** * Setup integration with BugSense (only for production builds). */ private void setupBugSense() { final String key = getResources().getString(R.string.bugsense_key); if ("invalid-key".equals(key)) { Log.i(LOG_TAG, "Skipping BugSense setup"); } BugSenseHandler.setup(this, key); Log.i(LOG_TAG, "BugSense handler installed and ready"); } /** * Create an intent suitable for opening a web page. */ private static Intent createBrowserIntent(final Uri uri) { return new Intent(Intent.ACTION_VIEW, uri); } /** * Instantiate and display the license dialog. */ private void displayLicenseDialog() { LicenseDialogFragment frag = new LicenseDialogFragment(); frag.show(getSupportFragmentManager(), "dialog"); } /** * Instantiate and display the about dialog. */ private void displayAboutDialog() { AboutDialogFragment frag = new AboutDialogFragment(); frag.show(getSupportFragmentManager(), "dialog"); } /** * Resolve a menu id into a trailer URL and return an intent for it. */ private Intent getIntentForTrailer(final int menuItemId) { final int urlOffset; switch (menuItemId) { case R.id.menu_teaser_one: urlOffset = 0; break; case R.id.menu_teaser_two: urlOffset = 1; break; case R.id.menu_subliminal: urlOffset = 2; break; default: throw new IllegalArgumentException("Unknown menu id " + menuItemId + " for trailer intent resolution"); } return new Intent(Intent.ACTION_VIEW, Uri.parse(mTrailers[urlOffset])); } }