package com.ghostflying.portalwaitinglist; import android.accounts.AccountManager; import android.app.Activity; import android.app.Dialog; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Toast; import com.ghostflying.portalwaitinglist.util.SettingUtil; 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.AccountPicker; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.SignInButton; import java.io.IOException; /** * The Activity to auth when user open this app first time. */ public class AuthActivity extends Activity { static final int REQUEST_CODE_PICK_ACCOUNT = 1000; static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1001; // The scope used, read all mails public static final String SCOPE = "oauth2:https://www.googleapis.com/auth/gmail.readonly"; String mEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_auth); ((SignInButton)findViewById(R.id.sign_in_button)).setSize(SignInButton.SIZE_WIDE); findViewById(R.id.sign_in_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getToken(); } }); } private void getToken(){ if (mEmail == null) pickUserAccount(); else new GetTokenTask(this).execute(); } /** * Show the dialog for user to select one Google Account */ private void pickUserAccount() { String[] accountTypes = new String[]{"com.google"}; Intent intent = AccountPicker.newChooseAccountIntent(null, null, accountTypes, false, null, null, null, null); startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT); } /** * Process different return status of different activities. * @param requestCode {@inheritDoc} * @param resultCode {@inheritDoc } * @param data {@inheritDoc} */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_PICK_ACCOUNT) { // Receiving a result from the AccountPicker if (resultCode == RESULT_OK) { mEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); new GetTokenTask(this).execute(); // With the account name acquired, go get the auth token } else if (resultCode == RESULT_CANCELED) { // The account picker dialog closed without selecting an account. // Notify users that they must pick an account to proceed. Toast.makeText(this, getString(R.string.alert_no_choose_account), Toast.LENGTH_SHORT).show(); } }else if ((requestCode == REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR) && resultCode == RESULT_OK){ getToken(); } } /** * This method is a hook for background threads and async tasks that need to * provide the user a response UI when an exception occurs. */ public void handleException(final Exception e) { // Because this call comes from the AsyncTask, we must ensure that the following // code instead executes on the UI thread. runOnUiThread(new Runnable() { @Override public void run() { if (e instanceof GooglePlayServicesAvailabilityException) { // The Google Play services APK is old, disabled, or not present. // Show a dialog created by Google Play services that allows // the user to update the APK int statusCode = ((GooglePlayServicesAvailabilityException)e) .getConnectionStatusCode(); Dialog dialog = GooglePlayServicesUtil.getErrorDialog(statusCode, AuthActivity.this, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR); dialog.show(); } else if (e instanceof UserRecoverableAuthException) { // Unable to authenticate, such as when the user has not yet granted // the app access to the account, but the user can fix this. // Forward the user to an activity in Google Play services. Intent intent = ((UserRecoverableAuthException)e).getIntent(); startActivityForResult(intent, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR); } } }); } /** * The main logic to get the token. */ private class GetTokenTask extends AsyncTask<Void, Void, Void> { Activity mActivity; String token; public GetTokenTask(Activity activity){ this.mActivity = activity; } @Override protected Void doInBackground(Void... params) { try{ token = fetchToken(); } catch (IOException e){ e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), R.string.network_error, Toast.LENGTH_SHORT).show(); } }); } return null; } @Override protected void onPostExecute(Void result){ if (token != null){ // return to main activity Intent mainIntent = new Intent(getApplicationContext(), MainActivity.class); // set flag to remove self. mainIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // store the auth account SettingUtil.setAccount(mEmail); startActivity(mainIntent); } } protected String fetchToken() throws IOException{ try{ return GoogleAuthUtil.getToken(mActivity, mEmail, SCOPE); } catch (UserRecoverableAuthException e){ handleException(e); } catch (GoogleAuthException e){ e.printStackTrace(); } return null; } } }