Java tutorial
/* * Copyright (C) 2014 Nafundi * * 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 cd.education.data.collector.android.preferences; import android.accounts.Account; import android.accounts.AccountManager; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.net.Uri; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; import android.preference.PreferenceCategory; import android.preference.PreferenceManager; import com.google.android.gms.auth.GoogleAuthException; import com.google.android.gms.auth.GoogleAuthUtil; import com.google.android.gms.auth.GooglePlayServicesAvailabilityException; import com.google.android.gms.auth.UserRecoverableAuthException; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; import cd.education.data.collector.android.R; import cd.education.data.collector.android.application.Collect; import cd.education.data.collector.android.listeners.InstanceUploaderListener; import cd.education.data.collector.android.tasks.GoogleMapsEngineTask; import cd.education.data.collector.android.views.DynamicListPreference; /** * Handles GME specific preferences. * * @author Carl Hartung (chartung@nafundi.com) */ public class GMEPreferencesActivity extends PreferenceActivity implements InstanceUploaderListener { private DynamicListPreference mGMEProjectIDPreference; private static String GME_ERROR = "gme_error"; private boolean partnerListDialogShowing; private final static int PROGRESS_DIALOG = 1; private final static int GOOGLE_USER_DIALOG = 3; private static final String ALERT_MSG = "alertmsg"; private static final String ALERT_SHOWING = "alertshowing"; private ProgressDialog mProgressDialog; private AlertDialog mAlertDialog; private String mAlertMsg; private boolean mAlertShowing; private GetProjectIDTask mUlTask; private ListPreference mSelectedGoogleAccountPreference; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.gme_preferences); // default initializers mAlertMsg = getString(R.string.please_wait); mAlertShowing = false; boolean adminMode = getIntent().getBooleanExtra(PreferencesActivity.INTENT_KEY_ADMIN_MODE, false); SharedPreferences adminPreferences = getSharedPreferences(AdminPreferencesActivity.ADMIN_PREFERENCES, 0); // determine if the partners list should be showing or not if (savedInstanceState != null && savedInstanceState.containsKey("partner_dialog")) { partnerListDialogShowing = savedInstanceState.getBoolean("partner_dialog"); } else { partnerListDialogShowing = false; if (savedInstanceState != null && savedInstanceState.containsKey(ALERT_MSG)) { mAlertMsg = savedInstanceState.getString(ALERT_MSG); } if (savedInstanceState != null && savedInstanceState.containsKey(ALERT_SHOWING)) { mAlertShowing = savedInstanceState.getBoolean(ALERT_SHOWING, false); } } mGMEProjectIDPreference = (DynamicListPreference) findPreference(PreferencesActivity.KEY_GME_PROJECT_ID); mGMEProjectIDPreference.setShowDialog(partnerListDialogShowing); mGMEProjectIDPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { mGMEProjectIDPreference.setValue((String) newValue); mGMEProjectIDPreference.setSummary(mGMEProjectIDPreference.getEntry()); mGMEProjectIDPreference.setShowDialog(false); return false; } }); mSelectedGoogleAccountPreference = (ListPreference) findPreference( PreferencesActivity.KEY_SELECTED_GOOGLE_ACCOUNT); PreferenceCategory gmePreferences = (PreferenceCategory) findPreference( getString(R.string.gme_preferences)); mGMEProjectIDPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { // mUlTask.setUserName(googleUsername); // ensure we have a google account selected SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(GMEPreferencesActivity.this); String googleUsername = prefs.getString(PreferencesActivity.KEY_SELECTED_GOOGLE_ACCOUNT, null); if (googleUsername == null || googleUsername.equals("")) { showDialog(GOOGLE_USER_DIALOG); return true; } //TODO: CHECK FOR NETWORK CONNECTIVITY. // setup dialog and upload task showDialog(PROGRESS_DIALOG); mUlTask = new GetProjectIDTask(); mUlTask.setUserName(googleUsername); mUlTask.setUploaderListener(GMEPreferencesActivity.this); mUlTask.execute(); return true; } }); SharedPreferences appSharedPrefs = PreferenceManager .getDefaultSharedPreferences(this.getApplicationContext()); // Editor prefsEditor = appSharedPrefs.edit(); Gson gson = new Gson(); String json = appSharedPrefs.getString(PreferencesActivity.KEY_GME_ID_HASHMAP, ""); HashMap<String, String> idhashmap = gson.fromJson(json, HashMap.class); if (idhashmap != null) { String[] entries = new String[idhashmap.size()]; String[] values = new String[idhashmap.size()]; Iterator<String> iterator = idhashmap.keySet().iterator(); int it = 0; while (iterator.hasNext()) { String key = iterator.next(); entries[it] = key; values[it] = idhashmap.get(key); it++; } mGMEProjectIDPreference.setEntries(entries); mGMEProjectIDPreference.setEntryValues(values); mGMEProjectIDPreference.setSummary(mGMEProjectIDPreference.getEntry()); } // get list of google accounts final Account[] accounts = AccountManager.get(getApplicationContext()).getAccountsByType("com.google"); ArrayList<String> accountEntries = new ArrayList<String>(); ArrayList<String> accountValues = new ArrayList<String>(); for (int i = 0; i < accounts.length; i++) { accountEntries.add(accounts[i].name); accountValues.add(accounts[i].name); } accountEntries.add(getString(R.string.no_account)); accountValues.add(""); mSelectedGoogleAccountPreference.setEntries(accountEntries.toArray(new String[accountEntries.size()])); mSelectedGoogleAccountPreference.setEntryValues(accountValues.toArray(new String[accountValues.size()])); mSelectedGoogleAccountPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { int index = ((ListPreference) preference).findIndexOfValue(newValue.toString()); String value = (String) ((ListPreference) preference).getEntryValues()[index]; ((ListPreference) preference).setSummary(value); return true; } }); mSelectedGoogleAccountPreference.setSummary(mSelectedGoogleAccountPreference.getValue()); boolean googleAccountAvailable = adminPreferences .getBoolean(AdminPreferencesActivity.KEY_CHANGE_GOOGLE_ACCOUNT, true); if (!(googleAccountAvailable || adminMode)) { gmePreferences.removePreference(mSelectedGoogleAccountPreference); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean("partner_dialog", mGMEProjectIDPreference.shouldShow()); outState.putString(ALERT_MSG, mAlertMsg); outState.putBoolean(ALERT_SHOWING, mAlertShowing); } @Override protected void onResume() { super.onResume(); if (mAlertShowing) { createAlertDialog(mAlertMsg); } } @Override protected void onPause() { super.onPause(); if (mAlertDialog != null && mAlertDialog.isShowing()) { mAlertDialog.dismiss(); } } private class GetProjectIDTask extends GoogleMapsEngineTask<Void, Void, HashMap<String, String>> { private InstanceUploaderListener mStateListener; private String mGoogleUserName; @Override protected HashMap<String, String> doInBackground(Void... values) { HashMap<String, String> projectList = new HashMap<String, String>(); String token = null; try { token = authenticate(GMEPreferencesActivity.this, mGoogleUserName); } catch (IOException e) { // network or server error, the call is expected to succeed if // you try again later. Don't attempt to call again immediately // - the request is likely to fail, you'll hit quotas or // back-off. e.printStackTrace(); return null; } catch (GooglePlayServicesAvailabilityException playEx) { Dialog alert = GooglePlayServicesUtil.getErrorDialog(playEx.getConnectionStatusCode(), GMEPreferencesActivity.this, PLAYSTORE_REQUEST_CODE); alert.show(); return null; } catch (UserRecoverableAuthException e) { GMEPreferencesActivity.this.startActivityForResult(e.getIntent(), USER_RECOVERABLE_REQUEST_CODE); e.printStackTrace(); return null; } catch (GoogleAuthException e) { // Failure. The call is not expected to ever succeed so it // should not be retried. e.printStackTrace(); return null; } if (token == null) { // if token is null, return null; } HttpURLConnection conn = null; int status = -1; try { URL url = new URL("https://www.googleapis.com/mapsengine/v1/projects/"); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.addRequestProperty("Authorization", "OAuth " + token); conn.connect(); // try { if (conn.getResponseCode() / 100 == 2) { BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); ProjectsListResponse projects = gson.fromJson(br, ProjectsListResponse.class); for (int i = 0; i < projects.projects.length; i++) { Project p = projects.projects[i]; projectList.put(p.name, p.id); } } else { String errorMessage = getErrorMesssage(conn.getErrorStream()); if (status == 400) { } else if (status == 403 || status == 401) { GoogleAuthUtil.invalidateToken(GMEPreferencesActivity.this, token); } projectList.put(GME_ERROR, errorMessage); return projectList; } } catch (Exception e) { e.printStackTrace(); GoogleAuthUtil.invalidateToken(GMEPreferencesActivity.this, token); String errorMessage = getErrorMesssage(conn.getErrorStream()); projectList.put(GME_ERROR, errorMessage); return projectList; } finally { if (conn != null) { conn.disconnect(); } } return projectList; } public void setUserName(String username) { mGoogleUserName = username; } @Override protected void onPostExecute(HashMap<String, String> results) { synchronized (this) { if (mStateListener != null) { mStateListener.uploadingComplete(results); } } } public void setUploaderListener(InstanceUploaderListener sl) { synchronized (this) { mStateListener = sl; } } } @Override public void uploadingComplete(HashMap<String, String> result) { try { dismissDialog(PROGRESS_DIALOG); } catch (Exception e) { // tried to close a dialog not open. don't care. } if (result == null) { // If result is null, then we needed to authorize the user return; } else { if (result.containsKey(GME_ERROR)) { // something went wrong, show the user String error = result.get(GME_ERROR); createAlertDialog("GME Error:" + error); return; } else { // everything is fine String[] entries = new String[result.size()]; String[] values = new String[result.size()]; // creates an ordered map Map<String, Object> copy = new TreeMap<String, Object>(result); Iterator<String> iterator = copy.keySet().iterator(); int i = 0; while (iterator.hasNext()) { String key = iterator.next(); entries[i] = key; values[i] = result.get(key); i++; } mGMEProjectIDPreference.setEntries(entries); mGMEProjectIDPreference.setEntryValues(values); SharedPreferences appSharedPrefs = PreferenceManager .getDefaultSharedPreferences(this.getApplicationContext()); Editor prefsEditor = appSharedPrefs.edit(); Gson gson = new Gson(); String json = gson.toJson(result); prefsEditor.putString(PreferencesActivity.KEY_GME_ID_HASHMAP, json); prefsEditor.commit(); mGMEProjectIDPreference.setShowDialog(true); mGMEProjectIDPreference.show(); } } } @Override public void progressUpdate(int progress, int total) { } @Override public void authRequest(Uri url, HashMap<String, String> doneSoFar) { } @Override protected Dialog onCreateDialog(int id) { switch (id) { case PROGRESS_DIALOG: Collect.getInstance().getActivityLogger().logAction(this, "onCreateDialog.PROGRESS_DIALOG", "show"); mProgressDialog = new ProgressDialog(this); DialogInterface.OnClickListener loadingButtonListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Collect.getInstance().getActivityLogger().logAction(this, "onCreateDialog.PROGRESS_DIALOG", "cancel"); dialog.dismiss(); mUlTask.cancel(true); mUlTask.setUploaderListener(null); finish(); } }; mProgressDialog.setTitle(R.string.get_project_IDs); mProgressDialog.setMessage(mAlertMsg); mProgressDialog.setIndeterminate(true); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); mProgressDialog.setCancelable(false); mProgressDialog.setButton(getString(R.string.cancel), loadingButtonListener); return mProgressDialog; case GOOGLE_USER_DIALOG: AlertDialog.Builder gudBuilder = new AlertDialog.Builder(this); gudBuilder.setTitle(R.string.no_google_account); gudBuilder.setMessage(R.string.select_maps_account); gudBuilder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); gudBuilder.setCancelable(false); return gudBuilder.create(); } return null; } private void createAlertDialog(String message) { Collect.getInstance().getActivityLogger().logAction(this, "createAlertDialog", "show"); mAlertDialog = new AlertDialog.Builder(this).create(); mAlertDialog.setTitle(getString(R.string.upload_results)); mAlertDialog.setMessage(message); DialogInterface.OnClickListener quitListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int i) { switch (i) { case DialogInterface.BUTTON1: // ok Collect.getInstance().getActivityLogger().logAction(this, "createAlertDialog", "OK"); // always exit this activity since it has no interface mAlertShowing = false; finish(); break; } } }; mAlertDialog.setCancelable(false); mAlertDialog.setButton(getString(R.string.ok), quitListener); mAlertDialog.setIcon(android.R.drawable.ic_dialog_info); mAlertShowing = true; mAlertMsg = message; mAlertDialog.show(); } // JSON public static class Project { public String id; public String name; } public static class ProjectsListResponse { public Project[] projects; } }