For the easy use of the SDKs and in-built UI libraries to authenticate the user in the application, the backend services are facilitated by the Firebase Authentication. Nowadays, many apps need the identity of the user. This information of the users is saved securely in the cloud by the app. Thus, a secure authentication system is built. We can authenticate the log-in of Google, Facebook, GitHub, Twitter, and more, by using the Firebase Authentication. Here, we are using the Google and Firebase APIs to integrate the Firebase Authentication for Google Sign-In functionality in our Android application.
To create and configure the Android App on Google Firebase Account:
- First, create a Firebase developer account. For this visit https://firebase.google.com/.
- Click on ‘GO TO CONSOLE’.
- Now, click on the ‘Create a project’ button.
- Fill the project name.
- Accept the Firebase terms.
- Click on the ‘Continue’ button.
- Now, select the ‘Android’ platform SDK.
- Provide the required app information to Register the app.
- Then click on the ‘Register app’ button.
- To get the app certificate SHA-1 key follow the below steps:
- Open the Android project.
- Open the Gradle tab from a right-side panel.
- Double click on the ‘signingReport’.
- Get the app SHA-1 key on ‘Gradle Console’.
- To integrate the ‘google-services.json’ file into the Android application, download the file first.
- Then click on ‘Next’.
- In the .gradle files of the application, add the firebase SDK dependencies.
- Click on the ‘Sync now’ in the IDE.
- Click on ‘Next’.
build.gradle(Project):
dependencies { classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.google.gms:google-services:4.0.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } |
build.gradle (Module):
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.google.firebase:firebase-auth:16.0.3' implementation 'com.google.firebase:firebase-core:16.0.3' implementation 'com.google.android.gms:play-services-auth:16.0.0' implementation 'com.github.bumptech.glide:glide:3.7.0' } apply plugin: 'com.google.gms.google-services' |
AndroidManifest.xml:
In the AndroidManifest.xml file, we will write the code to add the Internet permission to access the network connection.
Required Permission:
<uses-permission android:name="android.permission.INTERNET" /> |
Code:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.radioapp"> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <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> |
- To verify the installation configuration run the app.
- A success message is displayed on a successful installation.
- Click on ‘Continue to console’.
- Select Authentication -gt; Sign-in method -gt; Google -gt; Enable at the console page.
- Click on ‘Save’.
Example: Android Firebase Authentication with Google Sign-In:
In the below example, we are integrating the Firebase Authentication with Google Sign-In. The Firebase Authentication is used to authenticate them after the user successfully login through Google Sign-In. The user is then redirected to the next activity (ProfileActivity) and their details are displayed. In the Android project app directory, we will paste the downloaded ‘google-services.json’ file.
activity_main.xml:
In the activity_main.xml file, we will write the code to implement the custom Google Sign-in button.
Code:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:textSize="20dp" android:text="Sign in to move to the next activity." /> <com.google.android.gms.common.SignInButton android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/sign_in_button" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_alignParentBottom="true" android:layout_marginBottom="20dp"> </com.google.android.gms.common.SignInButton> |
MainActivity.java:
In the MainActivity.java file, we will write the code to add various classes and methods. These are:
- new FirebaseAuth.AuthStateListener(){}:Used to check whether the user is sign-in or not. It is used as an authentication listener. Other firebase logics are placed if the user is successfully signed-in.
- new GoogleSignInOptions.Builder() method: Used to configure the Google Sign-in to get the user data using the requestEmail option.
- GoogleSignInApi.getSignInIntent(googleApiClient): Called on clicking on the Sign-In button. The intent is started with startActivityForResult().
- onActivityResult(): Used to get the result of Google Sign-in request.
- handleSignInResult(result): Used to return true to get Google Authentication using idToken.
- firebaseAuthWithGoogle(credential): Used for making Firebase Authentication with Google.
The user is redirected to the next activity (ProfileActivity.java) on successful Firebase authentication.
Code:
package com.example.radioapp; 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.Toast; 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.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.auth.GoogleAuthProvider; public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener { private static final String TAG = "MainActivity"; private SignInButton signInButton; private GoogleApiClient googleApiClient; private static final int RC_SIGN_IN = 1; String name, email; String idToken; private FirebaseAuth firebaseAuth; private FirebaseAuth.AuthStateListener authStateListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); firebaseAuth = com.google.firebase.auth.FirebaseAuth.getInstance(); //this is where we start the Auth state Listener to listen for whether the user is signed in or not authStateListener = new FirebaseAuth.AuthStateListener(){ @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { // Get signedIn user FirebaseUser user = firebaseAuth.getCurrentUser(); //if user is signed in, we call a helper method to save the user details to Firebase if (user != null) { // User is signed in // you could place other firebase code //logic to save the user details to Firebase Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid()); } else { // User is signed out Log.d(TAG, "onAuthStateChanged:signed_out"); } } }; GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(getString(R.string.default_web_client_id))//you can also use R.string.default_web_client_id .requestEmail() .build(); googleApiClient=new GoogleApiClient.Builder(this) .enableAutoManage(this,this) .addApi(Auth.GOOGLE_SIGN_IN_API,gso) .build(); signInButton = findViewById(R.id.sign_in_button); signInButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient); startActivityForResult(intent,RC_SIGN_IN); } }); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==RC_SIGN_IN){ GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); handleSignInResult(result); } } private void handleSignInResult(GoogleSignInResult result){ if(result.isSuccess()){ GoogleSignInAccount account = result.getSignInAccount(); idToken = account.getIdToken(); name = account.getDisplayName(); email = account.getEmail(); // you can store user data to SharedPreference AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null); firebaseAuthWithGoogle(credential); }else{ // Google Sign In failed, update UI appropriately Log.e(TAG, "Login Unsuccessful. "+result); Toast.makeText(this, "Login Unsuccessful", Toast.LENGTH_SHORT).show(); } } private void firebaseAuthWithGoogle(AuthCredential credential){ firebaseAuth.signInWithCredential(credential) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful()); if(task.isSuccessful()){ Toast.makeText(MainActivity.this, "Login successful", Toast.LENGTH_SHORT).show(); gotoProfile(); }else{ Log.w(TAG, "signInWithCredential" + task.getException().getMessage()); task.getException().printStackTrace(); Toast.makeText(MainActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show(); } } }); } private void gotoProfile(){ Intent intent = new Intent(MainActivity.this, ProfileActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); finish(); } @Override protected void onStart() { super.onStart(); if (authStateListener != null){ FirebaseAuth.getInstance().signOut(); } firebaseAuth.addAuthStateListener(authStateListener); } @Override protected void onStop() { super.onStop(); if (authStateListener != null){ firebaseAuth.removeAuthStateListener(authStateListener); } } } |
profile_activity.xml:
In the profile_activity.xml file, we will write the code to add an ImageView to display the user profile image, a TextView for a name, email, id, and a button for log-out.
Code:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ProfileActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <ImageView android:layout_width="80dp" android:layout_height="80dp" android:id="@+id/profileImage" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/name" android:text="name" android:textSize="20dp" android:layout_marginTop="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/email" android:textSize="20dp" android:text="email" android:layout_marginTop="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/userId" android:textSize="20dp" android:text="id" android:layout_marginTop="20dp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/logoutBtn" android:text="Sign Out" android:layout_marginTop="30dp"/> </LinearLayout> </RelativeLayout> |
ProfileActivity.java:
In the ProfileActivity.java file, we will write the code to get the user information and to display them. The final result of invoking an API method of Google Play Services is represented by the Result interface implemented by the GoogleSignInResult class. The required information of the user is kept by the GoogleSignInAccount class.
Code:
package com.example.radioapp; import android.content.Intent; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; 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.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 com.google.firebase.auth.FirebaseAuth; public class ProfileActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener { Button logoutBtn; TextView userName,userEmail,userId; ImageView profileImage; private GoogleApiClient googleApiClient; private GoogleSignInOptions gso; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.profile_activity); logoutBtn = findViewById(R.id.logoutBtn); userName = findViewById(R.id.name); userEmail = findViewById(R.id.email); userId = findViewById(R.id.userId); profileImage = findViewById(R.id.profileImage); gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestEmail() .build(); googleApiClient=new GoogleApiClient.Builder(this) .enableAutoManage(this,this) .addApi(Auth.GOOGLE_SIGN_IN_API,gso) .build(); logoutBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FirebaseAuth.getInstance().signOut(); Auth.GoogleSignInApi.signOut(googleApiClient).setResultCallback( new ResultCallback<Status>() { @Override public void onResult(Status status) { if (status.isSuccess()){ gotoMainActivity(); }else{ Toast.makeText(getApplicationContext(),"Session not close",Toast.LENGTH_LONG).show(); } } }); } }); } @Override protected void onStart() { super.onStart(); OptionalPendingResult<GoogleSignInResult> opr= Auth.GoogleSignInApi.silentSignIn(googleApiClient); if(opr.isDone()){ GoogleSignInResult result=opr.get(); handleSignInResult(result); }else{ opr.setResultCallback(new ResultCallback<GoogleSignInResult>() { @Override public void onResult(@NonNull GoogleSignInResult googleSignInResult) { handleSignInResult(googleSignInResult); } }); } } private void handleSignInResult(GoogleSignInResult result){ if(result.isSuccess()){ GoogleSignInAccount account=result.getSignInAccount(); userName.setText(account.getDisplayName()); userEmail.setText(account.getEmail()); userId.setText(account.getId()); try{ Glide.with(this).load(account.getPhotoUrl()).into(profileImage); }catch (NullPointerException e){ Toast.makeText(getApplicationContext(),"image not found",Toast.LENGTH_LONG).show(); } }else{ gotoMainActivity(); } } private void gotoMainActivity(){ Intent intent=new Intent(this,MainActivity.class); startActivity(intent); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } } |