Social SignIn [Part - 1] - Integrate Google plus in Android App

Signup with different social sites are now common. I think almost 50% applications now have options to login with different social sites like Google Plus, Facebook, Twitter etc. And one more thing makes this things required or integrated in so much apps are Rest Api or SDK provided by such platforms is very handy and easy to integrate. They even now handle sessions by them self so now you don't have to worry about user session.

androprogrammer.com


Pr-requisite
1. Project setup in Google Developer console. more details
2. Enable Google plus Api for your project. more details


So Let's start project, i hope you have already setup project which is going to use Google plus(Google Account) login. So add below code in your app/build.gradle file. you only require this part of Google play service in dependency tag so just add this only. Google play service is huge library so if you are adding full library, make sure you require all those things in your app. if not just add parts of it which is required.

app/build.gradle
compile 'com.google.android.gms:play-services-auth:8.3.0'
That's it. In Google Play Service 8.3 they have added this part which is for just google login and getting basic user data. before Google Play Service 8.3 you have to use Google plus part of play service to login and get user data but now it is separated from it. so if you want user data like cover photo, user dob, user friend circle etc then you have to add compile 'com.google.android.gms:play-services-plus:8.3.0' also in build file.

To Login with Google and get user data i have create a helper class which actually do all the staff for me and return user data or error if any by SocialConnectListener interface. go through below code and you will see how you can write less code in your activity class and get desired result.

GooglePlusLoginHelper.java
package com.androprogrammer.socialsignin.util.helpers;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.androprogrammer.socialsignin.listeners.SocialConnectListener;
import com.androprogrammer.socialsignin.model.UserLoginDetails;
import com.androprogrammer.socialsignin.util.Utility;
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.Scopes;
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.Scope;



/**
 * Created by Wasim on 06-Dec-15.
 */
public class GooglePlusLoginHelper implements GoogleApiClient.OnConnectionFailedListener {


 private AppCompatActivity activity;
 private UserLoginDetails userData;

 private SocialConnectListener userCallbackListener;

 /* Client for accessing Google APIs */
 private static GoogleApiClient mGoogleApiClient;

 private int requestIdentifier = 0;

 private static final String TAG = "GooglePlusLoginHelper";

 public void createConnection(AppCompatActivity mActivity)
 {

  this.activity = mActivity;
  userData = new UserLoginDetails();

  if (Utility.checkPlayServices(mActivity)) {

   GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
     .requestScopes(new Scope(Scopes.PROFILE))
     .requestScopes(new Scope(Scopes.PLUS_LOGIN))
     .requestProfile()
     .requestEmail()
     .build();

   if (mGoogleApiClient == null) {
    // START create_google_api_client
    // Build GoogleApiClient with access to basic profile
    mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
      .enableAutoManage(mActivity,this)
      .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
      .build();
   }
  }
 }

 public void onActivityResult(int resultCode,Intent data)
 {

  GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
  handleSignInResult(result);

 }

 // START signIn
 public void signIn(int identifier) {
  requestIdentifier = identifier;
  Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
  activity.startActivityForResult(signInIntent, requestIdentifier);
 }
 

 // Sign out
 public void signOut() {
  if (mGoogleApiClient != null) {

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

   mGoogleApiClient.disconnect();

   Utility.showToast(activity, "You are logged out successfully");
  }
 }

 public SocialConnectListener getUserCallbackListener() {
  return userCallbackListener;
 }

 public void setUserCallbackListener(SocialConnectListener userCallbackListener) {
  this.userCallbackListener = userCallbackListener;
 }


 public void handleSignInResult(GoogleSignInResult result) {

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

   if (acct != null) {
    userData.setFullName(acct.getDisplayName());

    userData.setGoogleID(acct.getId());
    userData.setEmail(acct.getEmail());
    if (acct.getPhotoUrl() != null) {
     userData.setUserImageUri(acct.getPhotoUrl().toString());
    }

    userData.setIsGplusLogin(true);
    userData.setIsSocial(true);

    if (userCallbackListener != null) {
     userCallbackListener.onUserConnected(requestIdentifier,userData);
    }

   }
  }
 }

 @Override
 public void onConnectionFailed(ConnectionResult connectionResult) {

  Log.d(TAG, "onConnectionFailed:" + connectionResult);

  if (userCallbackListener != null)
  {
   userCallbackListener.onConnectionError(requestIdentifier,connectionResult.getErrorMessage());
  }
 }
}


In above code i have passed activity object in place of context but when you call connect method you will get response in onActivityResult for which you have to cast context to activity. check below code for LoginActivty in which i require user data. which actually initiate login request.

LoginActivity.java
package com.androprogrammer.socialsignin.activities;

import android.content.Intent;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

import com.androprogrammer.socialsignin.R;
import com.androprogrammer.socialsignin.listeners.SocialConnectListener;
import com.androprogrammer.socialsignin.model.UserLoginDetails;
import com.androprogrammer.socialsignin.util.PreferenceManager;
import com.androprogrammer.socialsignin.util.Utility;
import com.androprogrammer.socialsignin.util.helpers.GooglePlusLoginHelper;

import java.util.ArrayList;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class LoginActivity extends AppCompatActivity implements SocialConnectListener {

 // Google Plus Login
 @Bind(R.id.layout_gplustext) LinearLayout layout_gplus;
 @Bind(R.id.layout_full_gplus) LinearLayout layout_full_gplus;
 @Bind(R.id.pb_gplusloading) ProgressBar pb_gpLoader;

 /* RequestCode for sign-in */
 private static final int GPLUS_SIGN_IN = 1001;

 private GooglePlusLoginHelper gplusHelper;


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

  getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_FULLSCREEN,
    WindowManager.LayoutParams.FLAG_FULLSCREEN);

  setContentView(R.layout.activity_login);
  ButterKnife.bind(this);

  gplusHelper = new GooglePlusLoginHelper();
  gplusHelper.setUserCallbackListener(this);

  pb_gpLoader.getIndeterminateDrawable().setColorFilter(getResources().getColor(R.color.colorPrimary),
    PorterDuff.Mode.SRC_IN);

 }


 @OnClick(R.id.layout_full_gplus) void clicked() {

  // clicked on google plus login
  if (Utility.isConnectivityAvailable(LoginActivity.this)) {
   runOnUiThread(new Runnable() {
    @Override
    public void run() {
     layout_full_gplus.setBackgroundColor(getResources().getColor(R.color.view_disable));
     layout_full_gplus.setEnabled(false);
     layout_gplus.setVisibility(View.GONE);
     pb_gpLoader.setVisibility(View.VISIBLE);
    }
   });

   gplusHelper.createConnection(LoginActivity.this);
   gplusHelper.signIn(GPLUS_SIGN_IN);

  } else {
   Utility.showToast(LoginActivity.this,"No internet connection available...");
  }
 }


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

  if (requestCode == GPLUS_SIGN_IN) {
  
   gplusHelper.onActivityResult(resultCode, data);
  }
 }

 @Override
 public void onUserConnected(int requestIdentifier,UserLoginDetails userData) {

  if (requestIdentifier == GPLUS_SIGN_IN) {
   runOnUiThread(new Runnable() {
    @Override
    public void run() {
     layout_full_gplus.setBackgroundColor(getResources().getColor(R.color.bg_gplus));
     layout_full_gplus.setEnabled(true);
     layout_gplus.setVisibility(View.VISIBLE);
     pb_gpLoader.setVisibility(View.GONE);

     // For sign out 
     PreferenceManager.preferencePutInteger(getResources().getString(R.string.pref_login_identifier),
       GPLUS_SIGN_IN);
    }
   });
  }

  Utility.showToast(LoginActivity.this, "connected");
  PreferenceManager.preferencePutBoolean(getResources().getString(R.string.pref_is_loggedin),true);

  Intent MainScreen = new Intent(LoginActivity.this,MainActivity.class);

  Bundle b = new Bundle();
  b.putSerializable(getResources().getString(R.string.key_userModel),userData);

  MainScreen.putExtra(getResources().getString(R.string.key_userBundle), b);

  startActivity(MainScreen);
  overridePendingTransition(R.anim.right_slide_in, 0);
 }

 @Override
 public void onConnectionError(int requestIdentifier,String message) {
  Utility.showToast(LoginActivity.this, message);

  if (requestIdentifier == GPLUS_SIGN_IN) {
   runOnUiThread(new Runnable() {
    @Override
    public void run() {
     layout_full_gplus.setBackgroundColor(getResources().getColor(R.color.bg_gplus));
     layout_full_gplus.setEnabled(true);
     layout_gplus.setVisibility(View.VISIBLE);
     pb_gpLoader.setVisibility(View.GONE);
    }
   });
  }
 }


 @Override
 public void onCancelled(int requestIdentifier,String message) {
  Utility.showToast(LoginActivity.this, message);
 }
}



I hope this is how social connect libraries works on mobile platform. they allow us to implement some interface and they pass data through it. so you can even now create own library or framework if your using more then one platform. if you want other social connect tutorials also please subscribe to our news latter because my new article will be on facebook or twitter. so i hope you can find latest code in your inbox.

From coding point of view it is done but still you have to add Get Account permission in your manifest. and if you want your app works on Android new version Marshmallow you have to ask for permission runtime. because GET_ACCOUNTS permission is in danger permissions list. 

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

I have created this project in Kotlin language also so if you want please check out here.

Source Code

Keep coding... :)

0 comments :

Post a Comment