/* Copyright (C) 2013 Haowen Ning 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.liberty.android.fantastischmemo.downloader.oauth; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.FragmentActivity; import android.util.Log; import com.google.common.base.Joiner; import org.liberty.android.fantastischmemo.common.AMPrefKeys; import org.liberty.android.fantastischmemo.R; import org.liberty.android.fantastischmemo.common.BaseActivity; import org.liberty.android.fantastischmemo.utils.AMGUIUtility; import java.io.IOException; public abstract class OauthAccountActivity extends BaseActivity { SharedPreferences settings; SharedPreferences.Editor editor; /* Authenticated! Now get the auth token */ // For oauth1, the accessTokens are accessToken and accessKey // For oauth2 the accessTokens are just acces token. protected abstract void onAuthenticated(final String[] authTokens); // Verify the accessTokens. Return true if it is valid. // For oauth1, the accessTokens are accessToken and accessKey // For oauth2 the accessTokens are just acces token. protected abstract boolean verifyAccessToken(final String[] accessTokens) throws IOException; // Get the access tokens string from the request strings // For oauth 1, the request has requestToken and requestSecret // and returns the accessToken and accessKey // For oauth 2, the request is access code // and returns the access token. protected abstract String[] getAccessTokens(final String[] requests) throws IOException; // Get the fragment that request the Oauth through a web page. protected abstract OauthAccessCodeRetrievalFragment getOauthRequestFragment(); // The preference key to save / retrieve the access token. The preference name is based // on the prefix and the package of the class. So the same package use the same keys. private final String oauthAccessTokenPrefKey = AMPrefKeys.OAUTH_ACCESS_TOKEN_KEY_PREFIX + getClass().getPackage().getName(); @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); settings = PreferenceManager.getDefaultSharedPreferences(this); editor = settings.edit(); String savedTokens = settings.getString(oauthAccessTokenPrefKey, null); // Request new one if nothing saved. if (savedTokens == null) { showGetTokenDialog(); } else { String[] tokens = savedTokens.split(","); ValidateAccessTokenAndRunCallbackTask task = new ValidateAccessTokenAndRunCallbackTask(); task.execute(tokens); } } protected void invalidateSavedToken() { editor.putString(oauthAccessTokenPrefKey, null); editor.commit(); } private OauthAccessCodeRetrievalFragment.AuthCodeReceiveListener authCodeReceiveListener = new OauthAccessCodeRetrievalFragment.AuthCodeReceiveListener() { public void onAuthCodeReceived(String... codes) { GetAccessTokenTask task = new GetAccessTokenTask(); task.execute(codes); } public void onAuthCodeError(String error) { showAuthErrorDialog(error); } public void onCancelled() { finish(); } }; private class ValidateAccessTokenAndRunCallbackTask extends AsyncTask<String, Void, Boolean> { private ProgressDialog progressDialog; private Exception backgroundTaskException = null; private String[] tokens = null; @Override public void onPreExecute() { super.onPreExecute(); progressDialog = new ProgressDialog(OauthAccountActivity.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.setTitle(getString(R.string.loading_please_wait)); progressDialog.setMessage(getString(R.string.loading_connect_net)); progressDialog.setCancelable(false); progressDialog.show(); } @Override public Boolean doInBackground(String... accessTokens) { tokens = accessTokens; try { return verifyAccessToken(accessTokens); } catch (Exception e) { backgroundTaskException = e; return false; } } @Override public void onPostExecute(Boolean isTokenValid){ progressDialog.dismiss(); if (backgroundTaskException != null) { AMGUIUtility.displayError(OauthAccountActivity.this, getString(R.string.error_text), getString(R.string.exception_text), backgroundTaskException); } if (isTokenValid) { Log.i(TAG, "Token is valid"); onAuthenticated(tokens); } else { invalidateSavedToken(); showGetTokenDialog(); } } } private class GetAccessTokenTask extends AsyncTask<String, Void, String[]> { private ProgressDialog progressDialog; private Exception backgroundTaskException = null; @Override public void onPreExecute() { super.onPreExecute(); progressDialog = new ProgressDialog(OauthAccountActivity.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.setTitle(getString(R.string.loading_please_wait)); progressDialog.setMessage(getString(R.string.loading_auth_text)); progressDialog.setCancelable(false); progressDialog.show(); } @Override public String[] doInBackground(String... requests) { try { return getAccessTokens(requests); } catch (Exception e) { backgroundTaskException = e; return null; } } @Override public void onPostExecute(String[] accessTokens){ progressDialog.dismiss(); if (backgroundTaskException != null) { AMGUIUtility.displayError(OauthAccountActivity.this, getString(R.string.error_text), getString(R.string.exception_text), backgroundTaskException); return; } editor.putString(oauthAccessTokenPrefKey, Joiner.on(",").join(accessTokens)); editor.commit(); if (accessTokens == null) { showAuthErrorDialog(null); } else { onAuthenticated(accessTokens); } } } private void showAuthErrorDialog(String error) { String errorMessage = getString(R.string.auth_error_text); if (error != null) { errorMessage += " " + error; } new AlertDialog.Builder(OauthAccountActivity.this) .setTitle(R.string.error_text) .setMessage(errorMessage) .setPositiveButton(R.string.back_menu_text, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }) .show(); } // show the diaglog ti get the token private void showGetTokenDialog() { OauthAccessCodeRetrievalFragment df = getOauthRequestFragment(); df.setAuthCodeReceiveListener(authCodeReceiveListener); df.show(((FragmentActivity)this).getSupportFragmentManager(), "OauthAccessCodeRetrievalFragment"); } }