32

I’m developing an application on Android and I want to allow users to log in with their Google account. How can I achieve this?

TRiG
  • 9,249
  • 6
  • 50
  • 101
Androbito
  • 331
  • 1
  • 4
  • 7

8 Answers8

51

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

Balaji
  • 1,609
  • 15
  • 19
  • I have try above scope to get given_name,family_name as describe in your answer ,but i got only below response { "id": "105024889100906846764", "email": "ipad3.cygnet@gmail.com", "verified_email": true, "locale": "en" } – Herry Jul 26 '13 at 13:57
  • @Herry no idea why it is not returning `given_name` and `family_name` for you, but i am sure i got those details when running sample from google, better try with another email. – Balaji Jul 29 '13 at 10:36
  • Thank you, this is so helpful for me. – Mahmudur Rahman Jul 21 '16 at 09:08
3

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.

  • i'm getting the error: java.lang.NullPointerException: Appropriate Api was not requested. on Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); – Miguel Silva Feb 24 '21 at 17:05
2

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)

fwal
  • 67
  • 7
2

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) {

    }
}
Parsania Hardik
  • 4,325
  • 1
  • 29
  • 33
1
    **Dependency**
    **Need Internet Permission** 

**Working Code   see Link on  play Store**
https://play.google.com/store/search?q=com.codecube.airbucks

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


    <?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">


        <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>

    package com.keshav.geofencing;

    import android.Manifest;
    import android.annotation.TargetApi;
    import android.app.ProgressDialog;
    import android.content.BroadcastReceiver;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.support.v4.content.LocalBroadcastManager;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.TextView;

    import com.facebook.CallbackManager;
    import com.facebook.FacebookCallback;
    import com.facebook.FacebookException;
    import com.facebook.FacebookSdk;
    import com.facebook.GraphRequest;
    import com.facebook.GraphResponse;
    import com.facebook.login.LoginManager;
    import com.facebook.login.LoginResult;
    import com.google.android.gms.appindexing.Action;
    import com.google.android.gms.appindexing.AppIndex;
    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.GoogleApiAvailability;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.common.api.OptionalPendingResult;
    import com.google.android.gms.common.api.ResultCallback;
    import com.google.android.gms.common.api.Status;

    import org.json.JSONException;
    import org.json.JSONObject;

    import java.util.Arrays;

    import utilities.CommonMethod;
    import utilities.LoginPreferences;


    public class LoginWithGmail extends AppCompatActivity
            implements GoogleApiClient.OnConnectionFailedListener {

        private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
        private static final String TAG = "LoginActivity";
        private static final int RC_SIGN_IN = 9001;
        Button loginSub;
        LinearLayout signInButton;


        String gmailId;
        String gmailName;
        String gmailUserEmailId;
        Uri gmailUserPhoto;
        String savePassword;
        LinearLayout btnlogin;
        TextView btnsigning;
        ProgressDialog prgDialog;

        private CallbackManager callbackManager;

        private BroadcastReceiver mRegistrationBroadcastReceiver;
        private LinearLayout fbloginButton;
    //    private CallbackManager callbackManager;
        private ProgressDialog mProgressDialog;
        private GoogleApiClient mGoogleApiClient;

        EditText edtEmail;

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

            checkPermission();

            GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();

            mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .addApi(AppIndex.API).build();


            // Google Sign up Button
            signInButton = (LinearLayout) findViewById(R.id.sign_in_button);

            signInButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        int permissionCheck = ContextCompat.checkSelfPermission(LoginWithGmail.this, Manifest.permission.CAMERA);
                        if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                            //showing dialog to select image

                            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                            signInIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                            startActivityForResult(signInIntent, RC_SIGN_IN);
                            Log.e("permission", "granted");
                        } else {
                            ActivityCompat.requestPermissions(LoginWithGmail.this,
                                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
                                            Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
                        }
                    } else {
                        Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                        signInIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                        startActivityForResult(signInIntent, RC_SIGN_IN);
                    }

                }
            });

        }

        public void checkPermission() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                int permissionCheck = ContextCompat.checkSelfPermission(LoginWithGmail.this,
                        Manifest.permission.CAMERA);

                if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                    //showing dialog to select image
                    if (CommonMethod.isNetworkAvailable(LoginWithGmail.this)) {
                        Log.e("keshav", "Permission if part marsh");
                    } else {
                        CommonMethod.showAlert("Internet Connectivity Failure", LoginWithGmail.this);
                    }

                    Log.e("keshav", "permission granted");
                } else {
                    ActivityCompat.requestPermissions(LoginWithGmail.this,
                            new String[]{Manifest.permission.CAMERA,
                                    Manifest.permission.ACCESS_FINE_LOCATION,
                                    Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
                }
            }
        }

        @Override
        protected void onResume() {
            super.onResume();
    //        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
    //                new IntentFilter(QuickstartPreferences.REGISTRATION_COMPLETE));
        }

        @Override
        protected void onPause() {
            LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
            super.onPause();
        }


        @Override
        public void onBackPressed() {
            super.onBackPressed();

        }

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

            if (requestCode == RC_SIGN_IN) {
                GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
                handleSignInResult(result);
            }
        }

        // TODO ADD ME

        @Override
        public void onStart() {
            super.onStart();

            OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
            if (opr.isDone()) {
                // If the user's cached credentials are valid, the OptionalPendingResult will be "done"
                // and the GoogleSignInResult will be available instantly.
                Log.e(TAG, "Got cached sign-in");
                GoogleSignInResult result = opr.get();
                handleSignInResult(result);
            } else {
                // If the user has not previously signed in on this device or the sign-in has expired,
                // this asynchronous branch will attempt to sign in the user silently.  Cross-device
                // single sign-on will occur in this branch.
                showProgressDialog();
                opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
                    @Override
                    public void onResult(GoogleSignInResult googleSignInResult) {
                        hideProgressDialog();
                        handleSignInResult(googleSignInResult);
                    }
                });
            }
        }

        // [START signOut]
        private void signOut() {
            Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                    new ResultCallback<Status>() {
                        @Override
                        public void onResult(Status status) {
                            // [START_EXCLUDE]
    //                        updateUI(false);
                            // [END_EXCLUDE]
                        }
                    });
        }
        // [END signOut]

        // [START revokeAccess]
        private void revokeAccess() {
            Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
                    new ResultCallback<Status>() {
                        @Override
                        public void onResult(Status status) {
                            // [START_EXCLUDE]
    //                        updateUI(false);
                            // [END_EXCLUDE]
                        }
                    });
        }
        // [END revokeAccess]

        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            // An unresolvable error has occurred and Google APIs (including Sign-In) will not
            // be available.
            Log.e(TAG, "onConnectionFailed:" + connectionResult);
        }

        private void showProgressDialog() {
            if (mProgressDialog == null) {
                mProgressDialog = new ProgressDialog(this);
                mProgressDialog.setMessage("Loading...");
                mProgressDialog.setIndeterminate(true);
            }
            if (LoginWithGmail.this != null && mProgressDialog != null && !mProgressDialog.equals("null"))
                mProgressDialog.show();
        }

        private void hideProgressDialog() {
            if (mProgressDialog != null && mProgressDialog.isShowing()&& !mProgressDialog.equals("null")) {
                mProgressDialog.hide();
            }
        }


        // TODO ADD ME ENd


        private void handleSignInResult(GoogleSignInResult result) {
            Log.e("&&&s", "handleSignInResult:" + result.isSuccess());
            if (result.isSuccess()) {
                // Signed in successfully, show authenticated UI.
                GoogleSignInAccount acct = result.getSignInAccount();

                gmailId = acct.getId();
                gmailName = acct.getDisplayName();
                gmailUserEmailId = acct.getEmail();
                gmailUserPhoto = acct.getPhotoUrl();

                Log.e("gmailId", "is -->" + gmailId);
                Log.e("gmailName", "is -->" + gmailName);
                Log.e("gmailUserEmailId", "is -->" + gmailUserEmailId);
                Log.e("gmailUserPhoto", "is -->" + gmailUserPhoto);

                LoginPreferences.getActiveInstance(LoginWithGmail.this).setUserName(gmailName);
                LoginPreferences.getActiveInstance(LoginWithGmail.this).setProfileImage(""+gmailUserPhoto);


                Log.e("information", "using Gmail is > " + gmailId + " " + gmailName + "" + gmailUserEmailId + "" + gmailUserPhoto);

                if (CommonMethod.isNetworkAvailable(LoginWithGmail.this)) {
                    Log.e("SignUp gmail", "Hit API..........................");
                    Intent i=new Intent(LoginWithGmail.this,DrawerActivity.class);
                    LoginPreferences.getActiveInstance(LoginWithGmail.this).setIsLoggedIn(true);
                    startActivity(i);
                    finish();

                    // TODO Here Registered User in own Database call Volley Retrofit2 Api ....
                    new SignUpSocialFacebookAsyncTask().execute();
                } else {
                    CommonMethod.showAlert("Intenet Connectivity Failure", LoginWithGmail.this);
                }

            } else {

            }
            // TODO ADD ME KESHAV Google GMail Logout
            Auth.GoogleSignInApi.signOut(mGoogleApiClient);
        }

        @Override
        public void onStop() {
            super.onStop();

            // ATTENTION: This was auto-generated to implement the App Indexing API.
            // See https://g.co/AppIndexing/AndroidStudio for more information.
            Action viewAction = Action.newAction(
                    Action.TYPE_VIEW, // TODO: choose an action type.
                    "Login Page", // TODO: Define a title for the content shown.
                    // TODO: If you have web page content that matches this app activity's content,
                    // make sure this auto-generated web page URL is correct.
                    // Otherwise, set the URL to null.
                    Uri.parse("http://host/path"),
                    // TODO: Make sure this auto-generated app deep link URI is correct.
                    Uri.parse("android-app://com.keshav.geofencing/http/host/path")
            );
            AppIndex.AppIndexApi.end(mGoogleApiClient, viewAction);
            mGoogleApiClient.disconnect();
        }

        //Todo  add new method for permission
        @TargetApi(Build.VERSION_CODES.M)
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            if (requestCode == RC_SIGN_IN) {
                Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                signInIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                startActivityForResult(signInIntent, RC_SIGN_IN);

            }
        }

    }

    **Dependency**
    **Need Internet Permission** 

**Working Code   see Link on  play Store**
https://play.google.com/store/search?q=com.codecube.airbucks
Keshav Gera
  • 8,200
  • 1
  • 56
  • 43
1

Sure you might want to start with this:

Third-party websites and applications can now let visitors sign in using their Google user accounts. Federated Login, based on the OpenID standard, frees users from having to set up separate login accounts for different web sites--and frees web site developers from the task of implementing login authentication measures. OpenID achieves this goal by providing a framework in which users can establish an account with an OpenID provider, such as Google, and use that account to sign into any web site that accepts OpenIDs. This page describes how to integrate Google's Federated Login for a web site or application.

https://developers.google.com/accounts/docs/OpenID

Come back when you get stuck!

Blundell
  • 69,653
  • 29
  • 191
  • 215
  • OpenID 2.0 has been deprecated, check https://developers.google.com/accounts/docs/OAuth2Login – mjn Nov 07 '14 at 06:07
1

You can't exactly log in to an Android application using a Google account. You use a Google account to login to a website or webservice such as GMail, Calendar, etc., or a third party website if using OpenID. Since your app is not an website, this won't work. You can do either one of:

  • check if the user has registered a Google account (using AccountManager) on their phone, and only let them use the app if they have one. If an account is registered, you can be reasonably sure that they know the password (or they stole someone's phone...)
  • build your own webservice (for example using AppEngine) that your app uses, and use Google accounts to login to it
Nikolay Elenkov
  • 51,084
  • 9
  • 81
  • 82
0

Since Android Developer Manual is a bit sparse on how to implement Google Sign-in. Here's what I ended up, after 3 days of extensive research, trial and error.

with the code below, you will be able to retrieve from google the following

  • user name
  • email
  • photo URL
  • full name

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.

Go to Google Developers Console. and create a new project

  1. Once you are done with creating a project, Click on API under API and Auth section. Search for the Google+ API and select the one which I have shown in the below image.
  2. Enable the Google+ API by selecting the Enable API Button available.
  3. After enabling goto the Credentials section under the API and Create a new Client ID.
  4. Depending on the type of application you're developing you may need to create an Android Client ID or a Web Client ID (in my case a Web client ID was enough)
  5. replace below, where it has ADD_YOUR_OWN_CLIENT_ID by your ID!

Now the Code, first the helper class:

    public class GooglePlusSignInHelper {
    private final static String TAG = "GooglePlusSignInHelper";
        private final static int RC_SIGN_IN = 100;
        private static GoogleSignInOptions gso;

        private static GooglePlusSignInHelper sInstance;
        private static String webClientID;
        public GoogleApiClient googleApiClient;
        private Context context;
        private OnGoogleSignInListener loginResultCallback;
        private ResultCallback<Status> logoutResultCallback;

        public String signOutType ="";
    /**
     * This method should be called before calling any instance.
     * This is neccessary to get access token and id of user.
     * @param googleClientId
     */
    public static void setClientID(String googleClientId) {
        webClientID = googleClientId;
    }

    /**
     * Interface to listen to the Google login
     */
    public interface OnGoogleSignInListener {
        void OnGSignSuccess(GoogleSignInAccount googleSignInAccount, @Nullable Person person);

        void OnGSignError(GoogleSignInResult errorMessage);
    }

        public static GooglePlusSignInHelper getInstance() {
            if (sInstance == null) {
                sInstance = new GooglePlusSignInHelper();
            }
            return sInstance;
        }

        private GooglePlusSignInHelper() {
            // Configure sign-in to request the user's ID, email address, and basic
            // profile. ID and basic profile are included in DEFAULT_SIGN_IN.
            gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestScopes(new Scope(Scopes.PLUS_LOGIN))
                    .requestProfile() //for profile related info
                    .requestEmail() //for email
                    .requestIdToken(webClientID) //for accessToken and id
                    .build();
        }

        public void initialize(FragmentActivity activity, OnGoogleSignInListener onGoogleSignInListener)
        {
            loginResultCallback = onGoogleSignInListener;
            context = activity;
            googleApiClient = new GoogleApiClient.Builder(activity)
                    .enableAutoManage(activity /* FragmentActivity */, new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(ConnectionResult connectionResult) {
                            Log.e(TAG, "onConnectionFailed: " + connectionResult);
                        }
                    } /* OnConnectionFailedListener */)
                    .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                    .addApi(Plus.API)
                    .build();

            googleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                @Override
                public void onConnected(Bundle bundle) {
                    Log.i(TAG, "onConnected");
                }

                @Override
                public void onConnectionSuspended(int i) {
                    Log.i(TAG, "onConnectionSuspended");
                }
            });

            googleApiClient.registerConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                @Override
                public void onConnectionFailed(ConnectionResult connectionResult) {
                    Log.i(TAG, "onConnectionFailed");
                }
            });

        }

        public boolean isConnected() {
            boolean isConnected = googleApiClient.isConnected();

            Log.i(TAG, "isConnected()" + isConnected);
            return isConnected;
        }

        public void signIn(Activity activity) {

            if (googleApiClient.isConnected()) {
                if (!googleApiClient.hasConnectedApi(Auth.GOOGLE_SIGN_IN_API)) {
                    googleApiClient.clearDefaultAccountAndReconnect();
                }
                Auth.GoogleSignInApi.signOut(googleApiClient).setResultCallback(
                        new ResultCallback<Status>() {
                            @Override
                            public void onResult(Status status) {
                                if (!signOutType.equals("silent")) {
                                    Toast.makeText(activity, "Logged Out", Toast.LENGTH_SHORT).show();
                                }
                                signOutType="";
                                startActivity(activity);
                            }
                        });
            } else {
                googleApiClient.connect();
                startActivity(activity);
            }
        }

        private void startActivity(Activity activity){
            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
            activity.startActivityForResult(signInIntent, RC_SIGN_IN);
        }

        public void signOut() {
            if (!isConnected())
                return;

            Auth.GoogleSignInApi.signOut(googleApiClient).setResultCallback(
                    new ResultCallback<Status>() {
                        @Override
                        public void onResult(Status status) {
                            if (logoutResultCallback != null) {
                                logoutResultCallback.onResult(status);
                            }
                        }
                    });
        }

        private void handleSignInResult(GoogleSignInResult result) {
            Log.d(TAG, "handleSignInResult:" + result.isSuccess());
            if (result.isSuccess()) {
                Log.i(TAG, "Signed in");
                // Signed in successfully, show authenticated UI.
                final GoogleSignInAccount acct = result.getSignInAccount();

                //This code is just for getting google plus information like gender, birthday, aboutme etc
                final Person[] person = {null};
                if(acct!=null) {
                    Plus.PeopleApi.load(googleApiClient, acct.getId()).setResultCallback(new ResultCallback<People.LoadPeopleResult>() {
                        @Override
                        public void onResult(@NonNull People.LoadPeopleResult loadPeopleResult) {
                            try {
                                person[0] = loadPeopleResult.getPersonBuffer().get(0);
                                loadPeopleResult.getPersonBuffer().release();
                            } catch (Exception e){
                                if (loginResultCallback != null) {
                                    loginResultCallback.OnGSignError(result);
                                }
                            }
                            finally {
                                if (loginResultCallback != null) {
                                    loginResultCallback.OnGSignSuccess(acct, person[0]);
                                }
                            }
                        }
                    });
                }
//                If you don't want google+ related info, just comment above code, uncomment below callback
//                if (loginResultCallback != null) {
//                    //In this case, person object will always be null
//                    loginResultCallback.OnGSignSuccess(acct, null);
//                }

            } else {
                Log.i(TAG, "Signed out");

                if (loginResultCallback != null) {
                    loginResultCallback.OnGSignError(result);
                }
            }
        }

        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
            if (requestCode == RC_SIGN_IN) {
                GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
                handleSignInResult(result);
            }
        }

        public void setLogoutResultCallback(ResultCallback<Status> callback) {
            logoutResultCallback = callback;
        }
}

Assuming you have a fragment loaded inside an activity. In my case, the fragment loaded is named 'FragmentCreateAccount '. Add the following to the activity class (not the fragment class):

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

        FragmentCreateAccount fragmentCreateAccount = (FragmentCreateAccount) getSupportFragmentManager().findFragmentById(R.id.frgament_settings_content_frame);
        if(fragmentCreateAccount!=null)
        {
            fragmentCreateAccount.onActivityResult(requestCode, resultCode, data);
        }
    }

Finally, on your fragment activity class, first, you need to declare the following

private ImageButton googleSignInButton;
private GooglePlusSignInHelper gSignInHelper;

ProgressBar progressBar;

Next, also inside the Fragment activity class, add the following:

   @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
       // ...

        googleSignInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                progressBar.setVisibility(View.VISIBLE);
                gSignInHelper.signOutType="silent";
                gSignInHelper.signIn(getActivity());
            }
        });

        GooglePlusSignInHelper.setClientID(ADD_YOUR_OWN_CLIENT_ID);
        gSignInHelper = GooglePlusSignInHelper.getInstance();
        gSignInHelper.initialize(getActivity(),  this);
        gSignInHelper.signOutType="silent";

// ...

    }

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    gSignInHelper.onActivityResult(requestCode, resultCode, data);
    progressBar.setVisibility(View.GONE);

}

/****************** Google Sign In *******************************************/
@Override
public void OnGSignSuccess(GoogleSignInAccount acct, Person person) {
    try {
        String GuserName = (acct.getDisplayName()==null)?"":acct.getDisplayName();
        String Gemail = acct.getEmail();

        email.setText(Gemail);
        String[] params= new String[4];
        params[0]=GuserName;
        params[1]=Gemail;
        params[2]="";
        params[3]="";

        if (person != null) {
            int gender = person.getGender();
            String sGender="";
            if (gender == 0)
                sGender = "MALE";
            else if (gender == 1)
                sGender = "FEMALE";
            else
                sGender = "OTHERS";

            String GpersonName = person.getDisplayName();
            String GpersonPhotoUrl = person.getImage().getUrl();

            Log.e(TAG, "Name: " + GpersonName + ", email: " + Gemail + ", Image: " + GpersonPhotoUrl);

            params[2]=GpersonName;
            params[3]=GpersonPhotoUrl;

            //personPhotoUrl = personPhotoUrl.substring(0, personPhotoUrl.length() - 2)  + PROFILE_PIC_SIZE;
            //new LoadProfileImage(imgProfilePic).execute(personPhotoUrl);
        } else if(SessionData.System.isDebugEnabled) {
            Toast.makeText(getActivity(), "Couldnt Get the Person Info", Toast.LENGTH_SHORT).show();
        }
        Toast.makeText(getActivity(), "You are Logged In " + GuserName,Toast.LENGTH_LONG).show();
        
        // ...
    } catch (Exception e) {
        CrashReports crashReports = new CrashReports();
        crashReports.SaveCrash(e, getActivity());
    }
}

@Override
public void OnGSignError(GoogleSignInResult errorMessage) {
    // status code 12501 : canceled by user
    if (errorMessage.getStatus().getStatusCode()==12501){
        // TODO: language translation
        Toast.makeText(getActivity(), "Google auth canceled", Toast.LENGTH_SHORT).show();
    }else{
        Toast.makeText(getActivity(), errorMessage.getStatus().zzg(), Toast.LENGTH_SHORT).show();
    }
}

You also need to add on the manifest file the following:

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

and on the build.gradle (app) file :

implementation 'com.google.android.gms:play-services-auth:19.0.0'
implementation 'com.google.android.gms:play-services-plus:17.0.0'

Final note: This code is working on Android Studio 4.2 canary 15, Gradle 4.2.0-alpha15, and SDK 29

Miguel Silva
  • 182
  • 1
  • 3
  • 13