Java tutorial
/* * Copyright 2014 WNCOutdoors.info * portions Copyright 2014 The Android Open Source 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. * * MainActivity.java * Activity which checks a few requirements for the app to run, and * displays a dashboard of things for the user to do. */ package info.wncwaterfalls.app; import android.app.Activity; import android.app.Dialog; import android.content.ContentValues; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.widget.Button; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import info.wncwaterfalls.app.R; import info.wncwaterfalls.app.ExpansionDownloaderDialogFragment.ExpansionDownloadDialogListener; import org.json.JSONArray; import org.json.JSONException; public class MainActivity extends ActionBarActivity implements ExpansionDownloadDialogListener, OnCancelListener { private static final String TAG = "MainActivity"; private static final String PREFS_NAME = "AppSettingsPreferences"; private static final String USER_PREF_SHARED_WF = "SharedWaterfalls"; private static final String USER_PREF_PAUSE_DOWNLOAD = "UserPrefPauseDownload"; private static final String USER_PREF_SKIP_PLAY_SERVICES = "UserPrefSkipPlayServices"; private static final String APP_PREF_LAST_KNOWN_DB_VERSION = "LastKnownDBVersion"; private static AttrDatabase mDb = null; private ActionBar actionBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(false); mDb = new AttrDatabase(this); // TODO: Make sure this isn't leaky as a sieve SharedPreferences appPrefs = getApplicationContext().getSharedPreferences(PREFS_NAME, 0); int lastKnownDbVersion = appPrefs.getInt(APP_PREF_LAST_KNOWN_DB_VERSION, 0); SQLiteDatabase db = mDb.getReadableDatabase(); int actualDbVersion = db.getVersion(); // Save actual last version if (lastKnownDbVersion != actualDbVersion) { SharedPreferences.Editor editor = appPrefs.edit(); editor.putInt(APP_PREF_LAST_KNOWN_DB_VERSION, actualDbVersion); editor.commit(); } // This logic seems to simple to possibly be correct if (actualDbVersion > 1 && lastKnownDbVersion < actualDbVersion) { // We've been upgraded. Copy shared id's into db for quick searching onDatabaseUpgrade(); } // We're done with it. mDb.close(); } @Override protected void onResume() { super.onResume(); if (googlePlayServicesAvailable()) { // Determine if the expansion files have been downloaded // Do this in the else of the above check because it's irrelevant if // Play Services aren't available. SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); boolean userPrefPauseDownload = settings.getBoolean(USER_PREF_PAUSE_DOWNLOAD, false); if (!ExpansionDownloaderService.expansionFilesDownloaded(this)) { // Warn user about offline maps. if (!userPrefPauseDownload) { DialogFragment expansionDownloaderDialogFragment = new ExpansionDownloaderDialogFragment(); expansionDownloaderDialogFragment.show(getSupportFragmentManager(), "expansionDownloaderDialogFragment"); } else { // TODO: We should probably not show this repeatedly. Toast.makeText(getApplicationContext(), "Offline maps not available. Open App Info to download.", Toast.LENGTH_LONG).show(); } } } else { // Disable Search by Location button Button searchLocationButton = (Button) findViewById(R.id.main_btn_search_location); if (searchLocationButton != null) { searchLocationButton.setClickable(false); searchLocationButton.setEnabled(false); } } } // Define a request code to send to Google Play services // This code is returned in Activity.onActivityResult private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; // Define a DialogFragment that displays the error dialog generated in showErrorDialog public static class ErrorDialogFragment extends DialogFragment { // Global field to contain the error dialog private Dialog mDialog; // Default constructor. Sets the dialog field to null public ErrorDialogFragment() { super(); mDialog = null; } // Set the dialog to display public void setDialog(Dialog dialog) { mDialog = dialog; } // Return a Dialog to the DialogFragment. @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return mDialog; } } // Handle results returned to the FragmentActivity by Google Play services // error checking/correcting routine. @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Decide what to do based on the original request code switch (requestCode) { case CONNECTION_FAILURE_RESOLUTION_REQUEST: // If the result code is Activity.RESULT_OK, we should // have Play Services available. switch (resultCode) { case Activity.RESULT_OK: SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(USER_PREF_SKIP_PLAY_SERVICES, false); editor.commit(); break; } } } // GooglePlayServices errorDialog onCancel interface @Override public void onCancel(DialogInterface dialog) { // User chose not to install Play Services. This means no map tabs. // Save preference. SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(USER_PREF_SKIP_PLAY_SERVICES, true); editor.commit(); } private boolean googlePlayServicesAvailable() { // Check that Google Play services is available // Unfortunately, this has the side effect of creating an // error dialog, so it's not just a simple check. int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); // If Google Play services is available SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); if (ConnectionResult.SUCCESS == resultCode) { // In debug mode, log the status editor.putBoolean(USER_PREF_SKIP_PLAY_SERVICES, false); editor.commit(); return true; } else if (!settings.getBoolean(USER_PREF_SKIP_PLAY_SERVICES, false)) { // Google Play services was not available for some reason // Disable map fragments until this is resolved. Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, CONNECTION_FAILURE_RESOLUTION_REQUEST); editor.putBoolean(USER_PREF_SKIP_PLAY_SERVICES, true); editor.commit(); if (errorDialog != null) { // Play Services can sometimes provide a dialog with options // for the user to correct the issue. // Create a new DialogFragment for the error dialog. ErrorDialogFragment errorFragment = new ErrorDialogFragment(); // Set the dialog in the DialogFragment errorFragment.setDialog(errorDialog); // Show the error dialog in the DialogFragment errorFragment.show(getSupportFragmentManager(), "Maps"); // If I'm reading the docs correctly, then if the user opts to install // Play Services, startActivityForResult will be called when done, and // return through this activity's onActivityResult. } return false; } return false; } public void searchAll(View view) { // Create new intent Intent intent = new Intent(this, ResultsActivity.class); // Pack it with message containing blank search term (for "show all") intent.putExtra(SearchActivity.EXTRA_ONLY_SHARED, false); intent.putExtra(SearchActivity.EXTRA_SEARCH_MODE, SearchActivity.SEARCH_MODE_WATERFALL); intent.putExtra(SearchActivity.EXTRA_SEARCH_TERM, ""); // Start the Results activity startActivity(intent); } public void searchByName(View view) { Intent intent = new Intent(this, SearchActivity.class); intent.putExtra(SearchActivity.EXTRA_SEARCH_MODE, SearchActivity.SEARCH_MODE_WATERFALL); startActivity(intent); } public void searchByHike(View view) { Intent intent = new Intent(this, SearchActivity.class); intent.putExtra(SearchActivity.EXTRA_SEARCH_MODE, SearchActivity.SEARCH_MODE_HIKE); startActivity(intent); } public void searchByLocation(View view) { Intent intent = new Intent(this, SearchActivity.class); intent.putExtra(SearchActivity.EXTRA_SEARCH_MODE, SearchActivity.SEARCH_MODE_LOCATION); startActivity(intent); } public void searchByShared(View view) { Intent intent = new Intent(this, ResultsActivity.class); // Pack intent with message containing blank search term (for "show all") // and shared = true intent.putExtra(SearchActivity.EXTRA_ONLY_SHARED, true); intent.putExtra(SearchActivity.EXTRA_SEARCH_MODE, SearchActivity.SEARCH_MODE_WATERFALL); intent.putExtra(SearchActivity.EXTRA_SEARCH_TERM, ""); startActivity(intent); } public void appInfo(View view) { Intent intent = new Intent(this, AppInfoActivity.class); startActivity(intent); } private void startAppInfoActivity() { Intent intent = new Intent(this, AppInfoActivity.class); startActivity(intent); } // ExpansionDownloadDialogListener interface methods public void onExpansionDownloaderDialogPositiveClick(DialogFragment dialog) { startAppInfoActivity(); } public void onExpansionDownloaderDialogNegativeClick(DialogFragment dialog) { Toast.makeText(getApplicationContext(), "Skipped downloading offline maps.", Toast.LENGTH_LONG).show(); SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(USER_PREF_PAUSE_DOWNLOAD, true); editor.commit(); } // PlayServicesCheckDialogListener interface methods public void onPlayServicesDialogPositiveClick(DialogFragment dialog) { startAppInfoActivity(); } public void onPlayServicesDialogNegativeClick(DialogFragment dialog) { // OK. Fine. } public void onDatabaseUpgrade() { // Re-load shared waterfall preferences into the newly-created DB JSONArray sharedWfs = new JSONArray(); SharedPreferences appPrefs = getApplicationContext().getSharedPreferences(PREFS_NAME, 0); // Load existing shares. String sharedWfJson = appPrefs.getString(USER_PREF_SHARED_WF, "[]"); if (sharedWfJson != null) { try { sharedWfs = new JSONArray(sharedWfJson); } catch (JSONException e) { e.printStackTrace(); } } // Copy values back to database for quick searching. // Someone please chastise me for doing this on the main thread // in an ugly loop. for (int i = 0; i < sharedWfs.length(); i++) { String table = "waterfalls"; int waterfallId; try { waterfallId = sharedWfs.getInt(i); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); continue; } ContentValues values = new ContentValues(1); values.put("shared", 1); String whereClause = "_id = ?"; String[] whereArgs = { String.valueOf(waterfallId) }; mDb.update(table, values, whereClause, whereArgs); } } }