Using Google account to log in to an Android Application

Solution 1:

You might want to authenticate the user using one of the google account already configured in your device like some of the apps do, for that follow the below link -

"Authenticating to OAuth2 Services" - http://developer.android.com/training/id-auth/authenticate.html

Download Sample from Google - Android SDK Manager/Extras/Google Play Services

In simple steps it does

  1. Shows list of accounts in your mobile
  2. Generates access token from selected accounts
  3. Gets the Account name from access token by contacting google services(seperate call) to just tell that it has authenticated.

This is another link which is good in explaining the process - http://android-developers.blogspot.in/2013/01/verifying-back-end-calls-from-android.html

you can follow below steps for Login in your app

  1. you will send the generated access token to your Back-end server
  2. Back-end server checks that access token is valid or not by contacting google services by this url "https://www.googleapis.com/oauth2/v1/userinfo?access_token=ACCESS_TOKEN"
  3. Next Back-end server responds to app whether to make the user login or not.

Below is response format of above "userinfo" call

{
 "id": "ID",
 "name": "NAME",
 "given_name": "GiVEN NAME",
 "family_name": "FAMILY_NAME",
 "link": "https://plus.google.com/ID",
 "picture": "https://PHOTO.jpg",
 "gender": "GENDER",
 "locale": "LOCALE"
}

If you want Email id along with that response you have to modify

SCOPE = "oauth2:https://www.googleapis.com/auth/userinfo.profile";

to

SCOPE = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email";

in that sample

Solution 2:

First insert the below line in your build.gradle dependencies

compile 'com.google.android.gms:play-services:7.5.0'

Now we need SHA-1 fingerprint which we have to give in Google Developers Console.

Java keytool is used to generate SHA-1 fingerprint. Open your command prompt [Open C:\Program Files\Java\jdk\bin then press Shift+Right Click] and execute the following command to generate SHA-1 fingerprint and for password enter android if prompted.

keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android

To authenticate and communicate with the Google+ APIs, you must create a Google Developers Console project where you have to enable the Google+ API and create an OAuth 2.0 Client ID.

  1. Goto Google Developers Console. and create a new project
  2. Once you are done with creating a project, Click on API’s under API’s and Auth section. Search for the Google+ API and select the one which i have shown in the below image.
  3. Enable the Google+ API by selecting the Enable API Button available.
  4. After enabling goto the Credentials section under the API and Create a new Client ID.
  5. Select the Installed Application as the type and configure consent screen
  6. Now Fill out the package name of your project, paste the SHA1 finger print, enable the Deep Linking option to activate interactive posts and all the other parameters as shown in the image below .

Now it’s time to declare permissions to your mainfest file. This is how your manifest file will look like after adding meta-data and all the permissions.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androstock.loginwithgoogle" >

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

Now we are heading towards our MainActivity.java class where we are going to do all our stuff for Google+ Login.

package com.androstock.loginwithgoogle;

import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
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;

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.OnConnectionFailedListener;
import com.google.android.gms.plus.Plus;
import com.google.android.gms.plus.model.people.Person;

import java.io.InputStream;


// A project by Ferdousur Rahman Shajib
// www.androstock.com

public class MainActivity extends AppCompatActivity implements OnClickListener,
    GoogleApiClient.ConnectionCallbacks, OnConnectionFailedListener {

    // Profile pic 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;

private boolean mShouldResolve;

private ConnectionResult connectionResult;

private SignInButton signInButton;
private Button signOutButton;
private TextView tvName, tvMail, tvNotSignedIn;
private ImageView imgProfilePic;
private LinearLayout viewContainer;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    imgProfilePic = (ImageView) findViewById(R.id.imgProfilePic);
    signInButton = (SignInButton) findViewById(R.id.sign_in_button);
    signOutButton = (Button) findViewById(R.id.sign_out_button);
    tvName = (TextView) findViewById(R.id.tvName);
    tvMail = (TextView) findViewById(R.id.tvMail);
    tvNotSignedIn = (TextView) findViewById(R.id.notSignedIn_tv);
    viewContainer = (LinearLayout) findViewById(R.id.text_view_container);



    signInButton.setOnClickListener(this);
    signOutButton.setOnClickListener(this);

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(Plus.API)
            .addScope(Plus.SCOPE_PLUS_LOGIN)
            .build();

}

protected void onStart() {
    super.onStart();
    mGoogleApiClient.connect();
}

protected void onStop() {
    super.onStop();
    if (mGoogleApiClient.isConnected()) {
        mGoogleApiClient.disconnect();
    }
}


private void resolveSignInError() {
    if (connectionResult.hasResolution()) {
        try {
            mIntentInProgress = true;
            connectionResult.startResolutionForResult(this, RC_SIGN_IN);
        } catch (SendIntentException e) {
            mIntentInProgress = false;
            mGoogleApiClient.connect();
        }
    }
}

/*
When the GoogleApiClient object is unable to establish a connection onConnectionFailed() is called
 */
@Override
public void onConnectionFailed(ConnectionResult result) {
    if (!result.hasResolution()) {
        GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this,
                0).show();
        return;
    }

    if (!mIntentInProgress) {

        connectionResult = result;

        if (mShouldResolve) {

            resolveSignInError();
        }
    }

}

/*
onConnectionFailed() was started with startIntentSenderForResult and the code RC_SIGN_IN,
we can capture the result inside Activity.onActivityResult.
 */
@Override
protected void onActivityResult(int requestCode, int responseCode,
                                Intent intent) {
    if (requestCode == RC_SIGN_IN) {
        if (responseCode != RESULT_OK) {
            mShouldResolve = false;
        }

        mIntentInProgress = false;

        if (!mGoogleApiClient.isConnecting()) {
            mGoogleApiClient.connect();
        }
    }
}

@Override
public void onConnected(Bundle arg0) {
    mShouldResolve = false;
    try {
        if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) {
            Person person = Plus.PeopleApi
                    .getCurrentPerson(mGoogleApiClient);
            String personName = person.getDisplayName();
            String personPhotoUrl = person.getImage().getUrl();
            String email = Plus.AccountApi.getAccountName(mGoogleApiClient);

            tvName.setText(personName);
            tvMail.setText(email);

            personPhotoUrl = personPhotoUrl.substring(0,
                    personPhotoUrl.length() - 2)
                    + PROFILE_PIC_SIZE;

            new LoadProfileImage(imgProfilePic).execute(personPhotoUrl);

            Toast.makeText(getApplicationContext(),
                    "You are Logged In " + personName,             Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(getApplicationContext(),
                    "Couldnt Get the Person Info", Toast.LENGTH_SHORT).show();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    signOutUI();

}

private void signOutUI() {
    signInButton.setVisibility(View.GONE);
    tvNotSignedIn.setVisibility(View.GONE);
    signOutButton.setVisibility(View.VISIBLE);
    viewContainer.setVisibility(View.VISIBLE);
}

private void signInUI() {
    signInButton.setVisibility(View.VISIBLE);
    tvNotSignedIn.setVisibility(View.VISIBLE);
    signOutButton.setVisibility(View.GONE);
    viewContainer.setVisibility(View.GONE);
}

/**
 * Fetching user's information name, email, profile pic
 */
private void getProfileInformation() {

}

@Override
public void onConnectionSuspended(int arg0) {
    mGoogleApiClient.connect();
    signInUI();
}



@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.sign_in_button:
            onSignInClicked();
            break;
        case R.id.sign_out_button:
            onSignOutClicked();
            break;
    }
}


private void onSignInClicked() {
    if (!mGoogleApiClient.isConnecting()) {
        mShouldResolve = true;
        resolveSignInError();
    }
}


private void onSignOutClicked() {
    if (mGoogleApiClient.isConnected()) {
        Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
        mGoogleApiClient.disconnect();
        signInUI();
    }
}





/**
 * Background Async task to load user profile picture from url
 * */
private class LoadProfileImage extends AsyncTask<String, Void, Bitmap> {
    ImageView bmImage;

    public LoadProfileImage(ImageView bmImage) {
        this.bmImage = bmImage;
    }

    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 e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mIcon11;
    }

    protected void onPostExecute(Bitmap result) {
        bmImage.setImageBitmap(result);
    }
}



}

Create activity_main.xml which will contain our login and logout layout .

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">

<LinearLayout
    android:id="@+id/text_view_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:visibility="gone"
    android:gravity="center">

    <ImageView
        android:id="@+id/imgProfilePic"
        android:layout_width="80dp"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tvName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textSize="20dp" />

    <TextView
        android:id="@+id/tvMail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textSize="18dp" />

</LinearLayout>

<Button
    android:id="@+id/sign_out_button"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="10dp"
    android:background="@android:color/holo_red_light"
    android:layout_marginLeft="19dp"
    android:layout_marginRight="19dp"
    android:text="LOGOUT"
    android:textColor="#fff"
    android:textStyle="bold"
    android:visibility="gone" />

<TextView
    android:id="@+id/notSignedIn_tv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginBottom="30dp"
    android:text="You are not Signed In"
    android:textSize="20sp" />

<com.google.android.gms.common.SignInButton
    android:id="@+id/sign_in_button"
    android:layout_width="220dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal" />

</LinearLayout>

Thats it folks. You are done with Google+ Login. For more details you can visit here.

Solution 3:

Take a look at http://developer.android.com/training/id-auth/index.html There you'll find a tutorial on how to use the Account Manager. (More specifically http://developer.android.com/reference/android/accounts/AccountManager.html)

Solution 4:

Here is how I integrate google login with latest and smoothest way.

From this reference : google login android studio

first create app in google developer console and download configuration file and copy in app folder.

then add following in build.gradle(Project: project_name)

classpath 'com.google.gms:google-services:1.5.0-beta2'
 maven { url 'https://jitpack.io' }
allprojects {
    repositories {
 }
}

add code in build.gradle(Module:app)

compile 'com.google.android.gms:play-services-auth:9.0.2'
    compile 'com.google.android.gms:play-services:9.0.2'
    compile 'com.github.androidquery:androidquery:0.26.9'

add following in activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.exampledemo.parsaniahardik.google_login_demonuts.MainActivity">

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="fitXY"
        android:layout_marginTop="20dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/iv"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/text"
        android:textColor="#000"
        android:layout_marginTop="20dp"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <com.google.android.gms.common.SignInButton
        android:id="@+id/sign_in_button"
        android:layout_width="200dp"
        android:layout_marginTop="20dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />
    <Button
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_gravity="center_horizontal"
        android:text="Logout"
        android:id="@+id/btn"/>
</LinearLayout>

add below in MainActivity.java

import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.androidquery.AQuery;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.plus.People;
import com.google.android.gms.plus.Plus;
import com.google.android.gms.plus.model.people.Person;

public class MainActivity extends AppCompatActivity implements  GoogleApiClient.OnConnectionFailedListener{

    private SignInButton signInButton;
    private GoogleSignInOptions gso;
    private GoogleApiClient mGoogleApiClient;
    private int SIGN_IN = 30;
    private TextView tv;
    private ImageView iv;
    private AQuery aQuery;
    private Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();
        signInButton = (SignInButton) findViewById(R.id.sign_in_button);
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .addApi(Plus.API)
                .build();

        signInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                startActivityForResult(signInIntent, SIGN_IN);
            }
        });

        tv = (TextView) findViewById(R.id.text);
        iv = (ImageView) findViewById(R.id.iv);
        btn = (Button) findViewById(R.id.btn);
        aQuery = new AQuery(this);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                        new ResultCallback<Status>() {
                            @Override
                            public void onResult(Status status) {
                                Toast.makeText(MainActivity.this, "Logout Successfully!", Toast.LENGTH_SHORT).show();
                            }
                        });
            }
        });
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //If signin
        if (requestCode == SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            //Calling a new function to handle signin
            handleSignInResult(result);
        }
    }

    private void handleSignInResult(GoogleSignInResult result) {
        //If the login succeed
        if (result.isSuccess()) {
            //Getting google account
            final GoogleSignInAccount acct = result.getSignInAccount();

            //Displaying name and email
            String name = acct.getDisplayName();
            final String mail = acct.getEmail();
            // String photourl = acct.getPhotoUrl().toString();

            final String givenname="",familyname="",displayname="",birthday="";

            Plus.PeopleApi.load(mGoogleApiClient, acct.getId()).setResultCallback(new ResultCallback<People.LoadPeopleResult>() {
                @Override
                public void onResult(@NonNull People.LoadPeopleResult loadPeopleResult) {
                    Person person = loadPeopleResult.getPersonBuffer().get(0);

                    Log.d("GivenName ", person.getName().getGivenName());
                    Log.d("FamilyName ",person.getName().getFamilyName());
                    Log.d("DisplayName ",person.getDisplayName());
                    Log.d("gender ", String.valueOf(person.getGender())); //0 = male 1 = female
                    String gender="";
                    if(person.getGender() == 0){
                        gender = "Male";
                    }else {
                        gender = "Female";
                    }

                    if(person.hasBirthday()){
                        tv.setText(person.getName().getGivenName()+" \n"+person.getName().getFamilyName()+" \n"+gender+"\n"+person.getBirthday());
                    }else {
                        tv.setText(person.getName().getGivenName()+" \n"+person.getName().getFamilyName()+" \n"+gender);

                    }
                    aQuery.id(iv).image(acct.getPhotoUrl().toString());
                   Log.d("Uriddd",acct.getPhotoUrl().toString());
                  /*   Log.d(TAG,"CurrentLocation "+person.getCurrentLocation());
                    Log.d(TAG,"AboutMe "+person.getAboutMe());*/
                    // Log.d("Birthday ",person.getBirthday());
                    // Log.d(TAG,"Image "+person.getImage());
                }
            });
        } else {
            //If login fails
            Toast.makeText(this, "Login Failed", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }
}