Java tutorial
/* Montral Just in Case Copyright (C) 2011 Mudar Noufal <mn@mudar.ca> Geographic locations of public safety services. A Montral Open Data project. This file is part of Montral Just in Case. 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 ca.mudar.mtlaucasou; import ca.mudar.mtlaucasou.provider.PlacemarkDatabase; import ca.mudar.mtlaucasou.services.SyncService; import ca.mudar.mtlaucasou.utils.ActivityHelper; import ca.mudar.mtlaucasou.utils.AppHelper; import ca.mudar.mtlaucasou.utils.Const; import ca.mudar.mtlaucasou.utils.DetachableResultReceiver; import ca.mudar.mtlaucasou.utils.EulaHelper; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.location.Location; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.view.Menu; import android.support.v4.view.MenuInflater; import android.support.v4.view.MenuItem; import android.support.v4.view.Window; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.Toast; public class MainActivity extends LocationFragmentActivity { private static final String TAG = "MainActivity"; // TODO Cleaner handling of extension (refactor into implement) // protected AppHelper mAppHelper; // protected ActivityHelper mActivityHelper; // protected SharedPreferences prefs; // protected SharedPreferences.Editor prefsEditor; private SyncStatusUpdaterFragment mSyncStatusUpdaterFragment; private static boolean hasLoadedData; private String lang; // TODO Cleanup code, order functions by overrides following activity // lifecycle @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); requestWindowFeature(Window.FEATURE_PROGRESS); /** * SharedPreferences are used to verify determine if syncService is * required for initial launch or on database upgrade. */ hasLoadedData = prefs.getBoolean(Const.PrefsNames.HAS_LOADED_DATA, false); int dbVersionPrefs = prefs.getInt(Const.PrefsNames.VERSION_DATABASE, -1); if (!hasLoadedData || PlacemarkDatabase.getDatabaseVersion() > dbVersionPrefs) { hasLoadedData = false; createServiceFragment(); } /** * Display the GPLv3 licence */ if (!EulaHelper.hasAcceptedEula(this)) { EulaHelper.showEula(false, this); } /** * Get the ActivityHelper */ mActivityHelper = ActivityHelper.createInstance(this); mAppHelper = (AppHelper) getApplicationContext(); lang = mAppHelper.getLanguage(); mAppHelper.updateUiLanguage(); setContentView(R.layout.activity_home); setProgressBarIndeterminateVisibility(Boolean.FALSE); setProgressBarVisibility(false); /** * Android ICS has support for setHomeButtonEnabled() to disable tap on * actionbar logo on dashboard. */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { getActionBar().setHomeButtonEnabled(false); } } @Override public void onResume() { super.onResume(); /** * Update the interface language */ getSupportActionBar().setTitle(R.string.app_name); if (!lang.equals(mAppHelper.getLanguage())) { lang = mAppHelper.getLanguage(); this.onConfigurationChanged(); } /** * Starting the sync service is done onResume() for * SyncStatusUpdaterFragment to be ready. Otherwise, we send an empty * receiver to the service. */ // TODO Move this to a sync service listener. if (!hasLoadedData && (mSyncStatusUpdaterFragment != null)) { Intent intent = new Intent(Intent.ACTION_SYNC, null, getApplicationContext(), SyncService.class); intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, mSyncStatusUpdaterFragment.mReceiver); startService(intent); } } @Override public boolean onCreateOptionsMenu(Menu menu) { /** * Manual detection of Android version: This is because of a * ActionBarSherlock/compatibility package issue with the MenuInflater. * Also, versions earlier than Honeycomb don't manage SHOW_AS_ACTION_* * options other than ALWAYS. */ if (Const.SUPPORTS_HONEYCOMB) { /** * Honeycomb drawables are different (white instead of grey) because * the items are in the actionbar. */ menu.add(Menu.NONE, R.id.menu_about, 1, R.string.menu_about) .setIcon(getResources().getDrawable(R.drawable.ic_actionbar_info_details)) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); menu.add(Menu.NONE, R.id.menu_preferences, 2, R.string.menu_preferences) .setIcon(getResources().getDrawable(R.drawable.ic_actionbar_preferences)) .setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); } else { MenuInflater inflater = (MenuInflater) getMenuInflater(); inflater.inflate(R.menu.menu_activity_main, menu); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { return mActivityHelper.onOptionsItemSelected(item); } /** * Update the interface language, independently from the phone's UI * language. This does not override the parent function because the Manifest * does not include configChanges. */ private void onConfigurationChanged() { View root = findViewById(android.R.id.content).getRootView(); ((Button) root.findViewById(R.id.home_btn_fire_halls)).setText(R.string.btn_fire_halls); ((Button) root.findViewById(R.id.home_btn_spvm_stations)).setText(R.string.btn_spvm_stations); ((Button) root.findViewById(R.id.home_btn_water_supplies)).setText(R.string.btn_water_supplies); ((Button) root.findViewById(R.id.home_btn_emergency_hostels)).setText(R.string.btn_emergency_hostels); invalidateOptionsMenu(); } private void createServiceFragment() { FragmentManager fm = getSupportFragmentManager(); mSyncStatusUpdaterFragment = (SyncStatusUpdaterFragment) fm .findFragmentByTag(SyncStatusUpdaterFragment.TAG); if (mSyncStatusUpdaterFragment == null) { mSyncStatusUpdaterFragment = new SyncStatusUpdaterFragment(); fm.beginTransaction().add(mSyncStatusUpdaterFragment, SyncStatusUpdaterFragment.TAG).commit(); } } public static class SyncStatusUpdaterFragment extends Fragment implements DetachableResultReceiver.Receiver { public static final String TAG = SyncStatusUpdaterFragment.class.getName(); private DetachableResultReceiver mReceiver; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); mReceiver = new DetachableResultReceiver(new Handler()); mReceiver.setReceiver(this); } /** {@inheritDoc} */ public void onReceiveResult(int resultCode, Bundle resultData) { MainActivity activity = (MainActivity) getSupportActivity(); if (activity == null) { return; } activity.setProgressBarIndeterminateVisibility(Boolean.TRUE); activity.setProgressBarVisibility(true); final ProgressBar progressHorizontal = (ProgressBar) getSupportActivity() .findViewById(R.id.progress_horizontal); progressHorizontal.setVisibility(View.VISIBLE); switch (resultCode) { case SyncService.STATUS_RUNNING: { activity.setProgressBarIndeterminateVisibility(Boolean.TRUE); progressHorizontal.incrementProgressBy(resultData.getInt(Const.KEY_BUNDLE_PROGRESS_INCREMENT, 0)); /** * Title progress is in range 0..100 */ getSupportActivity().setProgress(100 * progressHorizontal.getProgress()); break; } case SyncService.STATUS_FINISHED: { activity.setProgressBarIndeterminateVisibility(Boolean.FALSE); activity.setProgressBarVisibility(false); progressHorizontal.setVisibility(View.INVISIBLE); // TODO put this in an activity listener if (EulaHelper.hasAcceptedEula(getSupportActivity().getApplicationContext())) { Toast.makeText(activity, R.string.toast_sync_finished, Toast.LENGTH_SHORT).show(); } finalizeLoadingData(getSupportActivity().getApplicationContext()); break; } case SyncService.STATUS_ERROR: { /** * Error happened down in SyncService: hide progressbars and * show Toast error message. */ activity.setProgressBarIndeterminateVisibility(Boolean.FALSE); activity.setProgressBarVisibility(false); progressHorizontal.setVisibility(View.INVISIBLE); final String errorText = getString(R.string.toast_sync_error, resultData.getString(Intent.EXTRA_TEXT)); Toast.makeText(activity, errorText, Toast.LENGTH_LONG).show(); break; } } } } public static void finalizeLoadingData(Context context) { SharedPreferences prefs = context.getSharedPreferences(Const.APP_PREFS_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor prefsEditor = prefs.edit(); AppHelper appHelper = (AppHelper) context; prefsEditor.putBoolean(Const.PrefsNames.HAS_LOADED_DATA, true); prefsEditor.putInt(Const.PrefsNames.VERSION_DATABASE, PlacemarkDatabase.getDatabaseVersion()); prefsEditor.commit(); hasLoadedData = true; /** * Make sure the distance is updated on first load! */ Location l = appHelper.getLocation(); appHelper.initializeLocation(); appHelper.setLocation(l); } }