Android Login with Google Plus Account

    Rating: ★★★★☆
    View: 277
    Download: 228
    Từ khóa:

    The major advantage of integrating G+ login is, you can drive more users to your app by providing quicker & easiest way of registration process.

    So let’s start by doing required setup.

    1. Installing / updating Google Play Services

    Google plus is a part of Google Play Services API. So first we need to download the google play services in Android SDK manager. If you have already installed play services, it it very important to update it to latest version. Open the SDK manager and install or update the play services under Extras section.

    2. Enabling G+ API on google console

    In order to consume google plus services, first we need to enable the Google Plus API on google console and we need to register our digitally signed .apk file’s public certificate in the Google APIs Console.

    2.1) Java keytool can be used to generate SHA-1 fingerprint. Open your terminal and execute the following command to generate SHA-1 fingerprint. If it ask for password, type android and press enter.

    On windows

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

    On Linux or Mac OS

    keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

    In the output you can notice SHA1 fingerprint.

    2.2) Open Google APIs console

    2.3) On the left, under APIs & auth section, click on APIs and on the right enable Google+ API service.

    2.4) Now again on the left, click on Credentials and on the right, click on CREATE NEW CLIENT IDbutton. It will open a popup to configure a new client id.

    2.5) In the popup, select Installed application as Application type.

    2.6) Under Installed application type section select Android and give your project package name. This package name should be equal to your android project. I gave my package name asinfo.androidhive.gpluslogin

    2.7) Enter your SHA1 fingerprint in Signing certificate fingerprint (SHA1) field.

    2.8) Enable Deep Linking and click on Create Client ID button. Now you should see a new client created for your android application.

    3. Importing Play Services Library to Eclipse

    Before creating a new project, we need to import the play services library into Eclipse workspace. To import, follow below steps.

    3.1) In Eclipse goto File ⇒ Import ⇒ Android ⇒ Existing Android Code Into Workspace

    3.2) Click on Browse and select Google Play Services project from your android sdk folder. You can locate play services library project from
    android-sdk-windowsextrasgooglegoogle_play_serviceslibprojectgoogle-play-services_lib

    3.3) And check Copy projects into workspace option as shown in the below image, which places a copy of play services in eclipse workspace.

    4. Creating New Project

    Until now we are done with all the required setup, now we can create a new project for google plus login.

    4.1) In Eclipse create a new project by navigating to File ⇒ New ⇒ Android Application Project and fill required details. Set min SDK version and compile with to API 9: Android 2.3 and max SDK version to latest version.

    4.2) Now we need to use Google Play Services project as a library to our project. So right click on project and select properties. In the properties window on left side select Android. On the right you can see a Add button under library section. Click it and select google play services project which we imported previously.

    4.3) Open the AndroidManifest.xml file add required permissions. Add INTERNET,GET_ACCOUNTS and USE_CREDENTIALS. Also add the meta-data tag for google play services under application tag.

    Permissions:

    
    
    
    Meta-data:
    
    
    After adding, your manifest file should look like this.
    
    AndroidManifest.xml
    
    
     
        
     
        
        
        
     
        
            
     
            
                
                    
     
                    
                
            
        
     
    
    4.4) Open strings.xml file under res ⇒ values ⇒ strings.xml add following strings for buttons text.
    
    strings.xml
    
    
        G+ Login
        Settings
         
        
        Logout from Google
        Revoke Access
    
    4.5). Now I am designing a simple layout to display user’s profile picture, name, email and other buttons. Paste the below code in layout file of your main activity. In my case my layout file name is activity_main.xml
    
    activity_main.xml
    
     
        
     
            
     
            
     
                
     
                
            
        
     
        
     
        

    The above XML will produce following output. Even though we added other buttons too, they are currently hidden and will be shown once user successfully login with their G+ account.

    4.6) Now open your main activity class and add the basic code like implementing the class from listeners and other required variables. Also we need to initialize the GoogleApiClient which is required to communicate with Google+ APIs.

    MainActivity.java
    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;
     
    public class MainActivity extends Activity implements OnClickListener,
            ConnectionCallbacks, OnConnectionFailedListener {
     
        private static final int RC_SIGN_IN = 0;
        // Logcat tag
        private static final String TAG = "MainActivity";
     
        // Profile pic image size in pixels
        private static final int PROFILE_PIC_SIZE = 400;
     
        // Google client to interact with Google API
        private GoogleApiClient mGoogleApiClient;
     
        /**
         * A flag indicating that a PendingIntent is in progress and prevents us
         * from starting further intents.
         */
        private boolean mIntentInProgress;
     
        private boolean mSignInClicked;
     
        private ConnectionResult mConnectionResult;
     
        private SignInButton btnSignIn;
        private Button btnSignOut, btnRevokeAccess;
        private ImageView imgProfilePic;
        private TextView txtName, txtEmail;
        private LinearLayout llProfileLayout;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
     
            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.imgProfilePic);
            txtName = (TextView) findViewById(R.id.txtName);
            txtEmail = (TextView) findViewById(R.id.txtEmail);
            llProfileLayout = (LinearLayout) findViewById(R.id.llProfile);
     
            // Button click listeners
            btnSignIn.setOnClickListener(this);
            btnSignOut.setOnClickListener(this);
            btnRevokeAccess.setOnClickListener(this);
     
            // Initializing google plus api client
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this).addApi(Plus.API, null)
                    .addScope(Plus.SCOPE_PLUS_LOGIN).build();
        }
     
        protected void onStart() {
            super.onStart();
            mGoogleApiClient.connect();
        }
     
        protected void onStop() {
            super.onStop();
            if (mGoogleApiClient.isConnected()) {
                mGoogleApiClient.disconnect();
            }
        }
     
        /**
         * Button on click listener
         * */
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.btn_sign_in:
                // Signin button clicked
                signInWithGplus();
                break;
            case R.id.btn_sign_out:
                // Signout button clicked
                signOutFromGplus();
                break;
            case R.id.btn_revoke_access:
                // Revoke access button clicked
                revokeGplusAccess();
                break;
            }
        }
    }

    4.7) Also we need to add few more call back listeners which will be invoked by GoogleApiClient when the connection status changes. The methods like onConnectionFailed()onConnected(),onConnectionSuspended() has to be added.

    Also we need to add onActivityResult() method which receives some data whenstartIntentSenderForResult called. Add the following code to your main activity.

    MainActivity.java
    @Override
    public void onConnectionFailed(ConnectionResult result) {
        if (!result.hasResolution()) {
            GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this,
                    0).show();
            return;
        }
     
        if (!mIntentInProgress) {
            // Store the ConnectionResult for later usage
            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.
                resolveSignInError();
            }
        }
     
    }
     
    @Override
    protected void onActivityResult(int requestCode, int responseCode,
            Intent intent) {
        if (requestCode == RC_SIGN_IN) {
            if (responseCode != RESULT_OK) {
                mSignInClicked = false;
            }
     
            mIntentInProgress = false;
     
            if (!mGoogleApiClient.isConnecting()) {
                mGoogleApiClient.connect();
            }
        }
    }
     
    @Override
    public void onConnected(Bundle arg0) {
        mSignInClicked = false;
        Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
     
        // Get user's information
        getProfileInformation();
     
        // Update the UI after signin
        updateUI(true);
     
    }
     
    @Override
    public void onConnectionSuspended(int arg0) {
        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);
            llProfileLayout.setVisibility(View.VISIBLE);
        } else {
            btnSignIn.setVisibility(View.VISIBLE);
            btnSignOut.setVisibility(View.GONE);
            btnRevokeAccess.setVisibility(View.GONE);
            llProfileLayout.setVisibility(View.GONE);
        }
    }

    Signing in with Google Plus Account

    4.8) If you observe the code in onClick() function, I have called a method signInWithGplus() on sign in button click. Add the following code in your main activity which signs in user using google plus account.

    /**
     * Sign-in into google
     * */
    private void signInWithGplus() {
        if (!mGoogleApiClient.isConnecting()) {
            mSignInClicked = true;
            resolveSignInError();
        }
    }
     
    /**
     * Method to resolve any signin errors
     * */
    private void resolveSignInError() {
        if (mConnectionResult.hasResolution()) {
            try {
                mIntentInProgress = true;
                mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
            } catch (SendIntentException e) {
                mIntentInProgress = false;
                mGoogleApiClient.connect();
            }
        }
    }

    If user clicks on sign in button, the following popup will be shown asking user to sign-in using google plus account.

    Getting user’s profile information (name, email, profile pic etc.,)

    4.9) Add the following method to get user’s profile information once he/she logged in. This method is called in onConnected function. Also I have added an async method to get the user profile picture from an url.

    By default the Google plus client gives profile picture url of 50×50 pixel image. We can replace that values with any size that we want. You can do that by replacing last two characters of the profile pic url.

    /**
     * Fetching user's information 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 email = Plus.AccountApi.getAccountName(mGoogleApiClient);
     
                Log.e(TAG, "Name: " + personName + ", plusProfile: "
                        + personGooglePlusProfile + ", email: " + email
                        + ", Image: " + personPhotoUrl);
     
                txtName.setText(personName);
                txtEmail.setText(email);
     
                // by default the profile url gives 50x50 px image only
                // 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 e) {
            e.printStackTrace();
        }
    }
     
    /**
     * Background Async task to load user profile picture from url
     * */
    private class LoadProfileImage extends AsyncTask {
        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);
        }
    }

    After fetching the user’s profile information successfully, you can see the following screen in your application.

     

    Sign out from Google Plus

    4.10) In order to sign out user from google plus account, add the following method in your main activity. This method is called when user presses sign out button.

    **
     * Sign-out from google
     * */
    private void signOutFromGplus() {
        if (mGoogleApiClient.isConnected()) {
            Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
            mGoogleApiClient.disconnect();
            mGoogleApiClient.connect();
            updateUI(false);
        }
    }

    Revoking access from Google Plus

    4.11) Also if you want to revoke the access from google plus account completely, add the following method. The function is being called when user touches the revoke access button.

    /**
     * Revoking access from google
     * */
    private void revokeGplusAccess() {
        if (mGoogleApiClient.isConnected()) {
            Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
            Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient)
                    .setResultCallback(new ResultCallback() {
                        @Override
                        public void onResult(Status arg0) {
                            Log.e(TAG, "User access revoked!");
                            mGoogleApiClient.connect();
                            updateUI(false);
                        }
     
                    });
        }
    }

    5. Testing the app

    On Real Device:
    You can directly test this app on a real devices which is having Google Play Store installed.

    On Emulator:
    You can also test the application on an emulator which runs Android 4.2.2 or greater. Follow below link to know how to configure an emulator by installing Google Play Services.
    Configuring emulator with Google Play Services

    Complete Code

    Following is the full code of main activity class.

    MainActivity.java
    package info.androidhive.gpluslogin;
     
    import java.io.InputStream;
     
    import android.app.Activity;
    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.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.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;
     
    public class MainActivity extends Activity implements OnClickListener,
            ConnectionCallbacks, OnConnectionFailedListener {
     
        private static final int RC_SIGN_IN = 0;
        // Logcat tag
        private static final String TAG = "MainActivity";
     
        // Profile pic image size in pixels
        private static final int PROFILE_PIC_SIZE = 400;
     
        // Google client to interact with Google API
        private GoogleApiClient mGoogleApiClient;
     
        /**
         * A flag indicating that a PendingIntent is in progress and prevents us
         * from starting further intents.
         */
        private boolean mIntentInProgress;
     
        private boolean mSignInClicked;
     
        private ConnectionResult mConnectionResult;
     
        private SignInButton btnSignIn;
        private Button btnSignOut, btnRevokeAccess;
        private ImageView imgProfilePic;
        private TextView txtName, txtEmail;
        private LinearLayout llProfileLayout;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
     
            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.imgProfilePic);
            txtName = (TextView) findViewById(R.id.txtName);
            txtEmail = (TextView) findViewById(R.id.txtEmail);
            llProfileLayout = (LinearLayout) findViewById(R.id.llProfile);
     
            // Button click 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();
        }
     
        protected void onStart() {
            super.onStart();
            mGoogleApiClient.connect();
        }
     
        protected void onStop() {
            super.onStop();
            if (mGoogleApiClient.isConnected()) {
                mGoogleApiClient.disconnect();
            }
        }
     
        /**
         * Method to resolve any signin errors
         * */
        private void resolveSignInError() {
            if (mConnectionResult.hasResolution()) {
                try {
                    mIntentInProgress = true;
                    mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
                } catch (SendIntentException e) {
                    mIntentInProgress = false;
                    mGoogleApiClient.connect();
                }
            }
        }
     
        @Override
        public void onConnectionFailed(ConnectionResult result) {
            if (!result.hasResolution()) {
                GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this,
                        0).show();
                return;
            }
     
            if (!mIntentInProgress) {
                // Store the ConnectionResult for later usage
                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.
                    resolveSignInError();
                }
            }
     
        }
     
        @Override
        protected void onActivityResult(int requestCode, int responseCode,
                Intent intent) {
            if (requestCode == RC_SIGN_IN) {
                if (responseCode != RESULT_OK) {
                    mSignInClicked = false;
                }
     
                mIntentInProgress = false;
     
                if (!mGoogleApiClient.isConnecting()) {
                    mGoogleApiClient.connect();
                }
            }
        }
     
        @Override
        public void onConnected(Bundle arg0) {
            mSignInClicked = false;
            Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
     
            // Get user's information
            getProfileInformation();
     
            // Update the UI after signin
            updateUI(true);
     
        }
     
        /**
         * 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);
                llProfileLayout.setVisibility(View.VISIBLE);
            } else {
                btnSignIn.setVisibility(View.VISIBLE);
                btnSignOut.setVisibility(View.GONE);
                btnRevokeAccess.setVisibility(View.GONE);
                llProfileLayout.setVisibility(View.GONE);
            }
        }
     
        /**
         * Fetching user's information 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 email = Plus.AccountApi.getAccountName(mGoogleApiClient);
     
                    Log.e(TAG, "Name: " + personName + ", plusProfile: "
                            + personGooglePlusProfile + ", email: " + email
                            + ", Image: " + personPhotoUrl);
     
                    txtName.setText(personName);
                    txtEmail.setText(email);
     
                    // by default the profile url gives 50x50 px image only
                    // 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 e) {
                e.printStackTrace();
            }
        }
     
        @Override
        public void onConnectionSuspended(int arg0) {
            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;
        }
     
        /**
         * Button on click listener
         * */
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.btn_sign_in:
                // Signin button clicked
                signInWithGplus();
                break;
            case R.id.btn_sign_out:
                // Signout button clicked
                signOutFromGplus();
                break;
            case R.id.btn_revoke_access:
                // Revoke access button clicked
                revokeGplusAccess();
                break;
            }
        }
     
        /**
         * Sign-in into google
         * */
        private void signInWithGplus() {
            if (!mGoogleApiClient.isConnecting()) {
                mSignInClicked = true;
                resolveSignInError();
            }
        }
     
        /**
         * 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() {
                            @Override
                            public void onResult(Status arg0) {
                                Log.e(TAG, "User access revoked!");
                                mGoogleApiClient.connect();
                                updateUI(false);
                            }
     
                        });
            }
        }
     
        /**
         * Background Async task to load user profile picture from url
         * */
        private class LoadProfileImage extends AsyncTask {
            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);
            }
        }
     
    }

     

    loading Đang tải...

    template được ưa chuộng