Android Open Source - compute-getting-started-android Login Activity






From Project

Back to project page compute-getting-started-android.

License

The source code is released under:

Apache License

If you think the Android project compute-getting-started-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* Copyright 2013 Google Inc. All Rights Reserved.
 */*from www  .  j a v a  2  s.  c  o  m*/
 * 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 com.google.devrel.samples.compute.android;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.api.client.repackaged.com.google.common.base.Strings;
import com.google.api.services.compute.ComputeScopes;

import java.io.IOException;

import static com.google.devrel.samples.compute.android.BuildConfig.DEBUG;

/**
 * Display a login screen to select a Google account registered with the Android device. The
 * {@code Activity} ensures the application is authorized for the required OAuth2 scopes prior to
 * forwarding to the next screen.
 *
 * This Android sample code was added to the sample project from the Android Studio examples found
 * in the "File -> New Class -> Android Activity" menu flow. It has been modified to present a login
 * experience that makes use of Google Accounts already registered with the Android device.
 *
 * @author paul.rashidi@google.com (Paul Rashidi)
 */
public class LoginActivity extends Activity {
  private final static String LOG_TAG = "LoginActivity";

  /**
   * Activity result indicating a return from the authorization approval intent.
   */
  private static final int ACTIVITY_RESULT_FROM_REQUEST_AUTH = 1111;

  /**
   * Activity result indicating a return from the Google account selection intent.
   */
  private static final int ACTIVITY_RESULT_FROM_ACCOUNT_SELECTION = 2222;

  /**
   * Tracking variable for the active {@code AsyncTask} to prevent duplicates and allow for
   * cancellation.
   */
  private AuthorizationCheckTask mAuthTask = null;

  private View mLoginFormView;
  private View mLoginStatusView;
  private TextView mLoginStatusMessageView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_login);

    // Prevent the keyboard from being visible upon startup.
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

    mLoginFormView = findViewById(R.id.login_form);
    mLoginStatusView = findViewById(R.id.login_status);
    mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message);

    // Register the select_account_button to invoke an account chooser dialog.
    findViewById(R.id.select_account_button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {

        // Check for Play Services availability.
        if (!AppUtils.checkGooglePlayServicesAvailability(LoginActivity.this)) {
          return;
        }

        TextView emailTextView = (TextView)LoginActivity.this.findViewById(R.id.email);

        // Check to see how many Google accounts are registered with the device.
        int googleAccounts = AppUtils.countGoogleAccounts(LoginActivity.this);
        if (googleAccounts == 0) {
          // No accounts present, nothing to do.
          Toast.makeText(LoginActivity.this, R.string.toast_no_google_accounts_registered,
              Toast.LENGTH_LONG).show();
        } else if (googleAccounts == 1) {
          // One account is present, select it.
          Toast.makeText(LoginActivity.this, R.string.toast_only_one_google_account_registered,
              Toast.LENGTH_LONG).show();
          AccountManager am = AccountManager.get(LoginActivity.this);
          Account[] accounts = am.getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
          if (accounts != null && accounts.length > 0) {
            // Select account and perform authorization check.
            emailTextView.setText(accounts[0].name);
            performAuthCheck();
          }
        } else {
          // More than one Google Account is present, a chooser is necessary.

          // Reset selected account.
          emailTextView.setText("");

          // Disable the verify_authorization_button.
          Button listComputeButton = (Button) LoginActivity.this.findViewById(
              R.id.verify_authorization_button);
          listComputeButton.setEnabled(false);

          // Invoke an {@code Intent} to allow the user to select a Google account.
          Intent accountSelector = AppUtils.getAccountPickerIntent();
          LoginActivity.this.startActivityForResult(accountSelector,
              LoginActivity.ACTIVITY_RESULT_FROM_ACCOUNT_SELECTION);
        }
      }
    });

    // Register a way for the user to verify the application authorization. This will typically not
    // be needed by a user since performAuthCheck() is called at various times, but there are some
    // edge cases when it might be needed (internet connectivity issues).
    findViewById(R.id.verify_authorization_button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        performAuthCheck();
      }
    });

    // Register the button that forwards to the Google Compute Engine resources list.
    findViewById(R.id.view_resources_button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        invokeResourceListIntent();
      }
    });

    // Load email account used previously.
    String storedEmail = AppUtils.getStoredAccount(this);
    ((TextView) findViewById(R.id.email)).setText(storedEmail);

    // Load project ID used previously with this email account.
    String storedProjectId = AppUtils.getStoredProjectId(this, storedEmail);
    ((TextView) findViewById(R.id.project_id)).setText(storedProjectId);

    if (!Strings.isNullOrEmpty(storedEmail)) {
      // Authorization check for users who have previously selected an account.
      performAuthCheck();
    }

  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == ACTIVITY_RESULT_FROM_REQUEST_AUTH && resultCode == RESULT_OK) {
      // This path indicates that the user successfully authorized the application OAuth2
      // request on their phone. Now we need to kick off our authorization check again.
      performAuthCheck();
    } else if (requestCode == ACTIVITY_RESULT_FROM_ACCOUNT_SELECTION && resultCode == RESULT_OK) {
      // This path indicates the account selection activity resulted in the user selecting a
      // Google account and clicking OK.

      // Set the selected account.
      String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
      TextView emailAccountTextView = (TextView)this.findViewById(R.id.email);
      emailAccountTextView.setText(accountName);

      // Enable the verify_authorization_button
      Button verifyLoginButton = (Button) findViewById(R.id.verify_authorization_button);
      verifyLoginButton.setText(R.string.button_verify_authorization);
      verifyLoginButton.setEnabled(true);

      // Fire off the authorization check for this account and OAuth2 scopes. User might be prompted
      // if they haven't been prompted prior.
      performAuthCheck();
    }
  }

  private String getEmailAccount() {
    TextView emailTextView = (TextView) this.findViewById(R.id.email);
    String emailString = "";
    if (emailTextView.getText()!=null) {
      emailString = emailTextView.getText().toString();
    }
    return Strings.emptyToNull(emailString);
  }

  private String getProjectId() {
    TextView projectIdTextView = (TextView) this.findViewById(R.id.project_id);
    String projectIdString = "";
    if (projectIdTextView.getText()!=null) {
      projectIdString = projectIdTextView.getText().toString();
    }
    return Strings.emptyToNull(projectIdString);
  }

  /**
   * Invoke the activity that will display the Google Compute Engine project details.
   */
  private void invokeResourceListIntent() {
    // Store the email account and project id for the reset of the application and so that they can
    // be restored them to the UI later.
    String configuredEmail = getEmailAccount();
    AppUtils.setStoredAccount(this, configuredEmail);
    String configuredProjectId = getProjectId();
    AppUtils.setStoredProjectId(this, configuredProjectId, configuredEmail);

    // Open Google Compute Engine resource listing.
    Intent intent = new Intent(LoginActivity.this, ItemListActivity.class);
    startActivity(intent);

    if (DEBUG) {
      Log.i(LOG_TAG, "Forwarding to resource listing.");
    }
  }

  /**
   * Schedule the authorization check in an {@code AsyncTask}.
   */
  public void performAuthCheck() {
    if (Strings.isNullOrEmpty(getEmailAccount())) {
      // Email address hasn't been selected so we have nothing to check.
      return;
    }

    // Cancel previously running tasks.
    if (mAuthTask != null) {
      try {
        mAuthTask.cancel(true);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    // Show a progress spinner.
    mLoginStatusMessageView.setText(R.string.text_authenticating);
    showProgress(true);

    // Start task to check authorization.
    mAuthTask = new AuthorizationCheckTask();
    mAuthTask.execute();
  }

  /**
   * Shows the progress UI and hides the login form.
   */
  @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
  private void showProgress(final boolean show) {
    // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
    // for very easy animations. If available, use these APIs to fade-in
    // the progress spinner.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
      int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);

      mLoginStatusView.setVisibility(View.VISIBLE);
      mLoginStatusView.animate().setDuration(shortAnimTime)
              .alpha(show ? 1 : 0)
              .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                  mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
                }
              });

      mLoginFormView.setVisibility(View.VISIBLE);
      mLoginFormView.animate().setDuration(shortAnimTime)
              .alpha(show ? 0 : 1)
              .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                  mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
                }
              });
    } else {
      // The ViewPropertyAnimator APIs are not available, so simply show
      // and hide the relevant UI components.
      mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
      mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
    }
  }

  /**
   * Verifies OAuth2 token access for the application and Google account combination with
   * the {@code AccountManager} and Play Services. If the appropriateOAuth2 access hasn't been
   * granted (to this application) then the task may fire an {@code Intent} to request that the user
   * approve such access. If the appropriate access does exist then the button that will let the
   * user proceed to the next activity is enabled.
   */
  class AuthorizationCheckTask extends AsyncTask<Object, Integer, Boolean> {
    private Intent userRecoverableIntent;
    @Override
    protected Boolean doInBackground(Object... unused) {
      Log.i(LOG_TAG, "Background task started.");

      // Ensure only one task is running at a time.
      mAuthTask = this;

      // Ensure an email was selected.
      String emailAccount = LoginActivity.this.getEmailAccount();
      if (Strings.isNullOrEmpty(emailAccount)) {
        publishProgress(R.string.toast_no_google_account_selected);
        // Failure.
        return false;
      }

      String oauth2 = AppUtils.getOAuth2ScopeString(new String[]{ComputeScopes.COMPUTE,
          ComputeScopes.DEVSTORAGE_READ_ONLY});

      if (DEBUG) {
        Log.d(LOG_TAG, "Attempting to get AuthToken for account: " + getEmailAccount());
      }

      try {
        // If the application has the appropriate access then a token will be retrieved, otherwise
        // an error will be thrown.
        GoogleAuthUtil.getToken(LoginActivity.this, getEmailAccount(), oauth2, null);

        if (DEBUG) {
          Log.d(LOG_TAG, "AuthToken retrieved");
        }

        // Success.
        return true;
      } catch (UserRecoverableAuthException userRecoverableException) {
        Log.w(LOG_TAG, "User recoverable auth exception; firing intent to resolve.",
            userRecoverableException);
        // Invoke the embedded intent to allow the user to resolve the issue causing the exception.
        // The intent is typically the acceptance of an OAuth2 authorization screen for the app.
        userRecoverableIntent =  userRecoverableException.getIntent();
        return false;
      } catch (GoogleAuthException authException) {
        Log.e(LOG_TAG, "Exception checking OAuth2 authentication.", authException);
        publishProgress(R.string.toast_exception_checking_authorization);
        return false;
      } catch (IOException ioException) {
        Log.e(LOG_TAG, "Exception checking OAuth2 authentication.", ioException);
        publishProgress(R.string.toast_exception_checking_authorization);
        return false;
      }
    }

    @Override
    protected void onPreExecute() {
      // Disable the button that can invoke this task.
      Button listComputeButton = (Button) LoginActivity.this.findViewById(
          R.id.view_resources_button);
      listComputeButton.setEnabled(false);
      mAuthTask = this;
    }

    @Override
    protected void onPostExecute(Boolean success) {
      if (success) {
        // Authorization check successful.

        // Enable button to move to the next activity to view teh resources list.
        Button listComputeButton = (Button) LoginActivity.this.findViewById(
            R.id.view_resources_button);
        listComputeButton.setEnabled(true);

        // Disable the verify credentials button since the auth task succeeded.
        Button verifyLogin = (Button) LoginActivity.this.findViewById(
            R.id.verify_authorization_button);
        verifyLogin.setEnabled(false);
        // Also change text on the button to indicate why it is disabled.
        verifyLogin.setText(R.string.button_authorization_verified);

      } else {
        // Authorization check not successful.
        if (userRecoverableIntent != null) {
          // If an intent exists fire it to resolve the issue. onActivityResult will be called once
          // the intent completes, and if the intent completed successfully we will start an
          // instance of this task again to check authorization.
          LoginActivity.this.startActivityForResult(userRecoverableIntent,
              ACTIVITY_RESULT_FROM_REQUEST_AUTH);
        }
      }

      // Stop Activity progress screen.
      showProgress(false);
      mAuthTask = null;
    }

    @Override
    protected void onCancelled() {
      // Stop Activity progress screen.
      showProgress(false);
      mAuthTask = null;
    }
  }
}




Java Source Code List

com.google.devrel.samples.compute.android.AppConstants.java
com.google.devrel.samples.compute.android.AppUtils.java
com.google.devrel.samples.compute.android.ItemDetailActivity.java
com.google.devrel.samples.compute.android.ItemDetailFragment.java
com.google.devrel.samples.compute.android.ItemListActivity.java
com.google.devrel.samples.compute.android.ItemListFragment.java
com.google.devrel.samples.compute.android.LoginActivity.java
com.google.devrel.samples.compute.android.dummy.DummyContent.java
com.google.devrel.samples.compute.android.tasks.ComputeTask.java
com.google.devrel.samples.compute.android.tasks.DownloadProjectInformationTask.java
com.google.devrel.samples.compute.android.tasks.ZoneOperationParameters.java
com.google.devrel.samples.compute.android.tasks.ZoneOperationTask.java