title: Android - Google Login with Login-Screen instead of Automatic Login
body: <p>I've added a Google log-in to my Android App (steps can be found at edit 3 of this post). Everything works as it should, but I'd like to make some small adjustments. With the current code found at edit 3, you are automatically logged in every time you start the app, without the Log-in Screen. I want to disable this, since the app will be used on a tablet at work, where a different employee should Login to the app every day.</p>
  
  <p>I started by removing the <code>mGoogleApiClient.connect();</code> from the <code>onStart()</code> method, and now I have the Google Login button again. When I add <code>mGoogleApiClient.connect();</code> to the <code>signInWithGoogle()</code> I'm able to sign in with the remembered user.</p>
  
  <p>What I want right now is the default Google Login screen where you can fill in your Google-Email and Password, every time you click on the Login Button, instead of just logging-in the remembered user. (PS: Keep in mind that on my Android Device I currently only have one user at <code>Settings -&gt; Google Accounts</code>, maybe that's why it automatically logs in instead of giving the option to choose which account should be connecting.)</p>
  
  <p><strike>I will test if it makes a different when I have multiple Google Accounts on my Android Device.</strike> Ok, I've added a second Google Account to my Android Device, but my app still automatically logs in the remembered user when I click on Sign-In..</p>
  
  <hr>
  
  <p>EDIT 2:</p>
  
  <p>I haven't been able to find a solution for my problem yet. </p>
  
  <p>I did find some more tutorials with different ways to log-in to Google, like using the <code>AccountManager</code> so a user can select one of the existing Google Accounts on the device. (I've only read about this method today, so don't have any code examples for this yet. But this also isn't what I'm looking for anyway.)</p>
  
  <p>I probably already made it clear in the post above, but this is what I want explained in pictures:</p>
  
  <ol>
  <li>A User starts the app on his/her Android Device.</li>
  <li>A User puts in his Google-Account username (used e-mail) and password <img src="https://i.stack.imgur.com/9QbiX.png" alt="List item"></li>
  <li>After a user is successfully logged in, we can do other things with the app</li>
  </ol>
  
  <p>PS: Just to make sure, this Log-in screen is the one of Google itself. So it's not a Login screen created by myself. This would in theory make me able to save the entered password, which is against protocol of Google OAuth.</p>
  
  <hr>
  
  <p>EDIT 3 (The Code):</p>
  
  <p>Steps I did to make Google Services work so far are below. Now I just need to figure out how to either force the log-in screen or completely log-out which results in the log-in screen every time.</p>
  
  <p>I've followed the following tutorial: 
  <a href="http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/" rel="nofollow noreferrer">http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/</a></p>
  
  <p>With extra info used from the following tutorials/sites:</p>
  
  <ul>
  <li><a href="https://developers.google.com/+/mobile/android/getting-started" rel="nofollow noreferrer">https://developers.google.com/+/mobile/android/getting-started</a></li>
  <li><a href="https://developers.google.com/+/mobile/android/sign-in" rel="nofollow noreferrer">https://developers.google.com/+/mobile/android/sign-in</a></li>
  <li><a href="http://developer.android.com/google/play-services/setup.html#Setup" rel="nofollow noreferrer">http://developer.android.com/google/play-services/setup.html#Setup</a></li>
  </ul>
  
  <p>This generated the following code:</p>
  
  <p>AndroidManifest.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.testproject_gmaillogin"
      android:versionCode="1"
      android:versionName="1.0" &gt;
  
      &lt;uses-sdk
          android:minSdkVersion="9"
          android:targetSdkVersion="19" /&gt;
  
      &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
      &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
      &lt;uses-permission android:name="android.permission.USE_CREDENTIALS" /&gt;
  
      &lt;application
          android:allowBackup="true"
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" &gt;
  
          &lt;meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /&gt;
  
          &lt;activity
              android:name="com.example.testproject_gmaillogin.MainActivity"
              android:label="@string/app_name" &gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.MAIN" /&gt;
  
                  &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
              &lt;/intent-filter&gt;
          &lt;/activity&gt;
      &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p>strings.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;resources&gt;
  
      &lt;string name="app_name"&gt;TestProject_GmailLogin&lt;/string&gt;
      &lt;string name="action_settings"&gt;Settings&lt;/string&gt;
  
      &lt;string name="profile_pic_description"&gt;Google Profile Picture&lt;/string&gt;
      &lt;string name="btn_logout_from_google"&gt;Logout from Google&lt;/string&gt;
      &lt;string name="btn_revoke_access"&gt;Revoke Access&lt;/string&gt;
  
  &lt;/resources&gt;
  </code></pre>
  
  <p>activity_main.xml:</p>
  
  <pre><code>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:padding="16dp"
      tools:context=".MainActivity" &gt;
  
      &lt;LinearLayout
          android:id="@+id/profile_layout"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_marginBottom="20dp"
          android:orientation="horizontal"
          android:weightSum="3"
          android:visibility="gone"&gt;
  
          &lt;ImageView
              android:id="@+id/img_profile_pic"
              android:contentDescription="@string/profile_pic_description"
              android:layout_width="80dp"
              android:layout_height="wrap_content"
              android:layout_weight="1"/&gt;
  
          &lt;LinearLayout
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginLeft="10dp"
              android:orientation="vertical"
              android:layout_weight="2" &gt;
  
              &lt;TextView
                  android:id="@+id/txt_name"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:padding="5dp"
                  android:textSize="20sp" /&gt;
  
              &lt;TextView
                  android:id="@+id/txt_email"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:padding="5dp"
                  android:textSize="18sp" /&gt;
          &lt;/LinearLayout&gt;
      &lt;/LinearLayout&gt;
  
      &lt;com.google.android.gms.common.SignInButton
          android:id="@+id/btn_sign_in"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_marginBottom="20dp"/&gt;
  
      &lt;Button
          android:id="@+id/btn_sign_out"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="@string/btn_logout_from_google"
          android:visibility="gone"
          android:layout_marginBottom="10dp"/&gt;
  
      &lt;Button
          android:id="@+id/btn_revoke_access"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="@string/btn_revoke_access"
          android:visibility="gone" /&gt;
  
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p>MainActivity.java:</p>
  
  <pre><code>package com.example.testproject_gmaillogin;
  
  import com.google.android.gms.common.ConnectionResult;
  import com.google.android.gms.common.GooglePlayServicesUtil;
  import com.google.android.gms.common.SignInButton;
  import com.google.android.gms.common.api.GoogleApiClient;
  import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
  import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
  import com.google.android.gms.common.api.ResultCallback;
  import com.google.android.gms.common.api.Status;
  import com.google.android.gms.plus.Plus;
  import com.google.android.gms.plus.model.people.Person;
  
  import android.support.v7.app.ActionBarActivity;
  import android.content.Intent;
  import android.content.IntentSender.SendIntentException;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.ImageView;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  import android.widget.Toast;
  
  public class MainActivity extends ActionBarActivity implements ConnectionCallbacks, OnConnectionFailedListener, OnClickListener
  {
      // Logcat tag
      private static final String TAG = "MainActivity";
  
      // Profile pix image size in pixels
      private static final int PROFILE_PIC_SIZE = 400;
  
      // Request code used to invoke sign in user interactions
      private static final int RC_SIGN_IN = 0;
  
      // Client used to interact with Google APIs
      private GoogleApiClient mGoogleApiClient;
  
      // A flag indicating that a PendingIntent is in progress and prevents
      // us from starting further intents
      private boolean mIntentInProgress;
  
      // Track whether the sign-in button has been clicked so that we know to resolve
      // all issues preventing sign-in without waiting
      private boolean mSignInClicked;
  
      // Store the connection result from onConnectionFailed callbacks so that we can
      // resolve them when the user clicks sign-in
      private ConnectionResult mConnectionResult;
  
      // The used UI-elements
      private SignInButton btnSignIn;
      private Button btnSignOut, btnRevokeAccess;
      private ImageView imgProfilePic;
      private TextView txtName, txtEmail;
      private LinearLayout profileLayout;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          // Get the UI-elements
          btnSignIn = (SignInButton) findViewById(R.id.btn_sign_in);
          btnSignOut = (Button) findViewById(R.id.btn_sign_out);
          btnRevokeAccess = (Button) findViewById(R.id.btn_revoke_access);
          imgProfilePic = (ImageView) findViewById(R.id.img_profile_pic);
          txtName = (TextView) findViewById(R.id.txt_name);
          txtEmail = (TextView) findViewById(R.id.txt_email);
          profileLayout = (LinearLayout) findViewById(R.id.profile_layout);
  
          // Set the Button onClick-listeners
          btnSignIn.setOnClickListener(this);
          btnSignOut.setOnClickListener(this);
          btnRevokeAccess.setOnClickListener(this);
  
          mGoogleApiClient = new GoogleApiClient.Builder(this)
              .addConnectionCallbacks(this)
              .addOnConnectionFailedListener(this)
              .addApi(Plus.API, null)
              .addScope(Plus.SCOPE_PLUS_LOGIN)
              .build();
      }
  
      @Override
      protected void onStart(){
          super.onStart();
          mGoogleApiClient.connect(); // &lt;- REMOVED (EDIT 4: Added again)
      }
  
      @Override
      protected void onStop(){
          super.onStop();
  
          if(mGoogleApiClient.isConnected())
              mGoogleApiClient.disconnect();
      }
  
      @Override
      public void onClick(View view){
          switch(view.getId()){
              case R.id.btn_sign_in:
                  signInWithGPlus();
                  break;
              case R.id.btn_sign_out:
                  signOutFromGPlus();
                  break;
              case R.id.btn_revoke_access:
                  revokeGPlusAccess();
                  break;
          }
      }
  
      @Override
      public void onConnectionFailed(ConnectionResult result) {
          if(!result.hasResolution()){
              GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
              return;
          }
  
          if(!mIntentInProgress){
              // Store the ConnectionResult so that we can use it later when the user clicks 'sign-in'
              mConnectionResult = result;
  
              if(mSignInClicked)
                  // The user has already clicked 'sign-in' so we attempt to resolve all
                  // errors until the user is signed in, or they cancel
                  resolveSignInErrors();
          }
      }
  
      @Override
      protected void onActivityResult(int requestCode, int responseCode, Intent intent){
          if(requestCode == RC_SIGN_IN &amp;&amp; responseCode == RESULT_OK)
              SignInClicked = true;
  
              mIntentInProgress = false;
  
              if(!mGoogleApiClient.isConnecting())
                  mGoogleApiClient.connect();
          }
      }
  
      @Override
      public void onConnected(Bundle connectionHint) {
          mSignInClicked = false;
          Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
  
          // Get all the user's information
          getProfileInformation();
  
          // Update the UI after sign-in
          updateUI(true);
      }
  
      @Override
      public void onConnectionSuspended(int cause){
          mGoogleApiClient.connect();
          updateUI(false);
      }
  
      // Updating the UI, showing/hiding buttons and profile layout
      private void updateUI(boolean isSignedIn){
          if(isSignedIn){
              btnSignIn.setVisibility(View.GONE);
              btnSignOut.setVisibility(View.VISIBLE);
              btnRevokeAccess.setVisibility(View.VISIBLE);
              profileLayout.setVisibility(View.VISIBLE);
          }
          else{
              btnSignIn.setVisibility(View.VISIBLE);
              btnSignOut.setVisibility(View.GONE);
              btnRevokeAccess.setVisibility(View.GONE);
              profileLayout.setVisibility(View.GONE);
          }
      }
  
      // Sign-in into Google
      private void signInWithGPlus(){
          //if(!mGoogleApiClient.isConnecting()) // &lt;- ADDED (EDIT 4: Removed again)
              //mGoogleApiClient.connect(); // &lt;- ADDED (EDIT 4: Removed again)
  
          if(!mGoogleApiClient.isConnecting()){
              mSignInClicked = true;
              resolveSignInErrors();
          }
      }
  
      // Method to resolve any sign-in errors
      private void resolveSignInErrors(){
          if(mConnectionResult.hasResolution()){
              try{
                  mIntentInProgress = true;
  
                  //Toast.makeText(this, "Resolving Sign-in Errors", Toast.LENGTH_SHORT).show();
  
                  mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
              }
              catch(SendIntentException e){
                  // The intent was cancelled before it was sent. Return to the default
                  // state and attempt to connect to get an updated ConnectionResult
                  mIntentInProgress = false;
                  mGoogleApiClient.connect();
              }
          }
      }
  
      // Fetching the user's infromation name, email, profile pic
      private void getProfileInformation(){
          try{
              if(Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null){
                  Person currentPerson = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
                  String personName = currentPerson.getDisplayName();
                  String personPhotoUrl = currentPerson.getImage().getUrl();
                  String personGooglePlusProfile = currentPerson.getUrl();
                  String personEmail = Plus.AccountApi.getAccountName(mGoogleApiClient);
  
                  Log.e(TAG, "Name: " + personName + ", "
                          + "plusProfile: " + personGooglePlusProfile + ", "
                          + "email: " + personEmail + ", "
                          + "image: " + personPhotoUrl);
  
                  txtName.setText(personName);
                  txtEmail.setText(personEmail);
  
                  // by default the profile url gives 50x50 px image,
                  // but we can replace the value with whatever dimension we
                  // want by replacing sz=X
                  personPhotoUrl = personPhotoUrl.substring(0, personPhotoUrl.length() - 2)
                          + PROFILE_PIC_SIZE;
  
                  new LoadProfileImage(imgProfilePic).execute(personPhotoUrl);
              }
              else{
                  Toast.makeText(getApplicationContext(), "Person information is null", Toast.LENGTH_LONG).show();
              }
          }
          catch(Exception ex){
              ex.printStackTrace();
          }
      }
  
      // Sign-out from Google
      private void signOutFromGPlus(){
          if(mGoogleApiClient.isConnected()){
              Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
              mGoogleApiClient.disconnect();
              mGoogleApiClient.connect();
              updateUI(false);
          }
      }
  
      // Revoking access from Google
      private void revokeGPlusAccess(){
          if(mGoogleApiClient.isConnected()){
              Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
              Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient)
                  .setResultCallback(new ResultCallback&lt;Status&gt;(){
                      @Override
                      public void onResult(Status s){
                          Log.e(TAG, "User access revoked!");
                          mGoogleApiClient.connect();
                          updateUI(false);
                      }
                  });
          }
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.main, menu);
          return true;
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          // Handle action bar item clicks here. The action bar will
          // automatically handle clicks on the Home/Up button, so long
          // as you specify a parent activity in AndroidManifest.xml.
          int id = item.getItemId();
          if (id == R.id.action_settings)
              return true;
  
          return super.onOptionsItemSelected(item);
      }
  }
  </code></pre>
  
  <p>LoadProfileImage.java:</p>
  
  <pre><code>package com.example.testproject_gmaillogin;
  
  import java.io.InputStream;
  
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.os.AsyncTask;
  import android.util.Log;
  import android.widget.ImageView;
  
  /**
   * Background async task to load user profile picture from url
   **/
  public class LoadProfileImage extends AsyncTask&lt;String, Void, Bitmap&gt; {
      private ImageView bmImage;
  
      public LoadProfileImage(ImageView bmImage){
          this.bmImage = bmImage;
      }
  
      @Override
      protected Bitmap doInBackground(String... urls){
          String urlDisplay = urls[0];
          Bitmap mIcon11 = null;
          try{
              InputStream in = new java.net.URL(urlDisplay).openStream();
              mIcon11 = BitmapFactory.decodeStream(in);
          }
          catch(Exception ex){
              Log.e("Error", ex.getMessage());
              ex.printStackTrace();
          }
          return mIcon11;
      }
  
      @Override
      protected void onPostExecute(Bitmap result){
          bmImage.setImageBitmap(result);
      }
  }
  </code></pre>
  
  <p>The other steps I did were:</p>
  
  <p>At <a href="https://console.developers.google.com/project" rel="nofollow noreferrer">https://console.developers.google.com/project</a> I've created a project with:</p>
  
  <p>Google+ API on:</p>
  
  <p><img src="https://i.stack.imgur.com/MIenh.png" alt="Google+ API on"></p>
  
  <p>And a Client ID created with the correct SHA1 and exact same namespace as the project:</p>
  
  <p><img src="https://i.stack.imgur.com/LwXdx.png" alt="And a Client ID created with the correct SHA1"></p>
  
  <p>At Eclipse:</p>
  
  <p>I've installed the google-play-services library:</p>
  
  <p><img src="https://i.stack.imgur.com/UGa2d.png" alt="Google-play services installed"></p>
  
  <p>And added it to the project:</p>
  
  <p><img src="https://i.stack.imgur.com/z4ybG.png" alt="Google-play services library added (2)">
  <img src="https://i.stack.imgur.com/ZPBmR.png" alt="Google-play services library added (2)"></p>
  
  <p>I've also created an Emulator with version Google 4.4.2 (so not Android 4.4.2) and also changed the Project to Google 4.4.2 instead of Android 4.4.2:</p>
  
  <p><img src="https://i.stack.imgur.com/0suau.png" alt="Solution Error">
  <img src="https://i.stack.imgur.com/1Cl2h.png" alt="Solution Error Emulator"></p>
  
  <hr>
  
  <p>EDIT 4:</p>
  
  <p>Ok, I have a temporary solution for my own case. In my case the app I'm making should run on a Tablet which is used explicitly for my App. Because this is the case, I can remove all the Google Accounts from the Device Settings the moment someone revokes access (as log out function).</p>
  
  <p>I started by removing the previous changes (re-added the <code>.connect();</code> to the <code>onStart()</code> and removed it from the <code>signInWithGPlus()</code>)</p>
  
  <p>Then I added one line to the <code>revokeGPlusAccess</code>-method:</p>
  
  <pre><code>// Revoking access from Google
  private void revokeGPlusAccess(){
      if(mGoogleApiClient.isConnected()){
          Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
          Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient)
              .setResultCallback(new ResultCallback&lt;Status&gt;(){
                  @Override
                  public void onResult(Status s){
                      Log.e(TAG, "User access revoked!");
                      removeAllGoogleAccountsFromDevice(); // &lt;- Added
                      mGoogleApiClient.connect();
                      updateUI(false);
                  }
              });
      }
  }
  </code></pre>
  
  <p>With the following method:</p>
  
  <pre><code>// Method to remove ALL Google Accounts from the Android Device
  private void removeAllGoogleAccountsFromDevice(){
      // Ask if this really is what you want
      new AlertDialog.Builder(MainActivity.mActivity)
          .setMessage("Are you sure you want to delete all Google Accounts from this Android Device?\r\n\r\n" +
                  "WARNING: If you run this app on the Work Tablet, click YES. If you run this on your own device, it's recommended to click NO.")
          .setCancelable(false)
          .setPositiveButton("Yes, continue", new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int which) {
                  // AccountManager is final because we use it in the separate Thread below
                  final AccountManager accountManager = AccountManager.get(MainActivity.this);
                  Account[] googleAccounts = accountManager.getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
                  // Account is final because we use it in the separate Thread below
                  for(final Account a : googleAccounts){
                      // Separate Thread because AccountManager #removeAccount is an async operation
                      Thread worker = new Thread(new Runnable() {
                          @Override
                          public void run() {
                              accountManager.removeAccount(a, null, null);
                          }
                      });
                      worker.start();
                  }
              }
          })
          .setNegativeButton("No", null)
          .show();
  }
  </code></pre>
  
  <p>Still, this only works in my case. This won't work on a personal device where you obviously don't want to delete all the Device's Google Accounts. I would still like to know a solution when you don't want to delete any Device's Google Accounts.</p>