Firebase authentication – Register with email using coroutine

Previously we have already implemented the activity_register.xml file. In this chapter of the Firebase authentication Android tutorial we are going to implement the registration using name, email and password and we gonna encapsulate the functions in Kotlin coroutines.

The user first has to provide the name, email and password. When the user clicks on the “Register” button, then some validation functions will be called, and these will check the correctness of the fields. When the texts are ok, then the process will be continued with the Firebase authentication. When the result was successful, then the user gonna be saved with the name in Firestore as well.

GitHub

If you didn’t make the previous chapters, then you can start from this chapter also by downloading/cloning the prfoject from GitHub.

GitHub – create_app_icon branch

Step 1 – Add the dependencies

Before we start the implementation of the email authentication, we gonna add some more dependencies to our project.

Previously we have added the Material design dependency.

Open the build.gradle Module:app from the left “Project” tab. There will be the implementation of the Material designe library.

implementation “com.google.android.material:material:$materialDesignVersion

We have implemented the versions in the Project build.gradle, what you can find also in the left “Project” tab.

Our task is after that is just to add this lines to the build.gradle Module:app.


Dependecies

One more thing is missing and it is the “kapt”. It means the Kotlin Annotation Process Tool.

At the beginning of the build.gradle Module:app, there are some line with “apply….”. Add this line after them:

apply plugin: ‘kotlin-kapt’

Finally click on the “Sync now” button at the top right corner and wait until Android Studio finishes syncing.

Step 2 – Add Firebase to the project

After the dependencies, we have to add Firebase to the project as well. Using Android Studio, it is super easy, because the IDE has a tool for this.

From the top menu select the “Tool” option, and from it the “Firebase” menu.

At the right side of Android Studio a new tab will be visible for us, called “Assistant”.

From this tab select the “Authentication” option, then click on the “Email and password authentication”.

In this tab you will see a step by step implementation, but here we gonna click on the two buttons, called “Connect to Firebase” and “Add Firebase Authentication to your app”.

They gonna create for us the project on Firebase also. So first click on the “Connect to Firebase” button. Here you can add a name for the project on Firebase. We use the default one. If you are done, just click on the  “Connect to Firebase” button.

In case, if you haven’t registered to Firebase, then in the browser a window will be showen, where you can create an account to using your Google account.

If the process by Android Studio is finished, then click on the “Add Firebase Authentication to your app” as well.

This will add the Firebase dependecies to our project.

Step 3 – Enable email authentication

Before we can use the email authentication in our project, we have to enable it in our Firebase project.

So open the link: Firebase

In the popup window select our project and in the left menu, click in the “Develop” part on the “Authentication” menu. In this window at the top there will be a tab navigation, where you should see the tab called “Sign-in method”.

If you move the mouse to the line of the “Email/Password”, then at the end of the line a pen gonna be visible, click on it.

Set to enabled the email authentication by clicking on the switch, as you can see on the picture above. Then click on the “Save” button.

Step 4 – Enable Firestore

Next we gonna enable Firestore for our project as well. To do that, open again in Android Studio from the left side the “Assistant” tab. Scroll down, and expand the Firestore and click on the “Read and write documents with Firestore” link.

Here we gonna need again only the first 2 steps. The first should be already done, because we have added already the Firebase authentication to our project. So just click on the second button and set the Firestore dependency. In the popup window click again on the “Add” button and wait until the process will be finished.

Add Firestore on Firebase

What we have to do more, is to enable in Firebase the Firestore as well. As a cloud data storage we can use Real Time Database or Firestore. So we have to select on Firebase the Firestore option.

Open in the browser the project in Firebase and from the left menubar select “Database”.

This part is changing time to time, so it is hard to tell you where to click now, but somewhere there should be a button with the label of “Create database” for Firestore. The next window should popup.

On this window you can see the rights of the read and write. Later on we will set it and we can read and write it. Click “Next”.

In the next window click again on the “Next”.

The third window will show us a settings, and the condition of the usage. Accept both of them, and click on the “Finish” button.

Rules

So the Firestore database is almost ready to use. The last step before we can go forward is to set the rules. On the page, after the Firestore creation, should be at the top a tab menu system. There we need the second tab, called “Rules”.

Click on it and past this code there.


Firestore rules

After the edit, above of the code a new line will be visible. There goign to be a “Publish” button.

Click on it, and we can go to the next step.

Step 5 – Sealed class to hold the result

The sealed class Result holds the result of the Firestore operation and its status (Success, Error, Canceled). It allows us to know if our operation succeed or not and get the eventual error message Firestore returns.

The Result.kt file will be in a utils” package. So on the root package of the application click with the right mouse button, “New”, then “Package”. Name in the popup window the package as “utils” and click “OK”.

Next we gonna create the Result.kt file in this “utils” folder. So click with the right mouse button on the newly created package, and create a new Kotlin file there. The name of the file will be “Result”.

Paste this source code into the Result.kt file.


Result.kt

All of the Firebase’s results gonna capsulated in this Result sealed class.

Step 6 – Coroutine from a Firebase Task

The result of a Firebase query is a Firebase Task. We need to convert this Task into a coroutine function that will wait for the answer of the query and emit a Result object with the corresponding data.

So what we gonna do is to create an extension function for the Task object, called await(), what will return:

      • Result.Success: the data if the query was successful
      • Result.Error: the error message if an error happened
      • Result.Canceled: an eventual error message if the query was canceled.

Our Task object will in the package of “extension”, so create it next to the “utils” and “ui” packages. Inside of it create a new Kotlin file called “Task”. Paste this source into it.


Task.kt

Step 7 – User model

We are going to store the data in a User data class.

More information about Kotlin data class

Data class

For the User data class we gonna create a new package called “model”. Inside of the new package create a new Kotlin file with the name of “User”.

The source code of the User class will have properties for the “id” and for the “name”.

Copy and paste the code into the User::class.


The UserRepository interface

Note that we have started these functions whit the keyword of “suspend”

Suspending functions are at the center of everything coroutines. A suspending function is simply a function that can be paused and resumed at a later time. They can execute a long running operation and wait for it to complete without blocking.

The syntax of a suspending function is similar to that of a regular function except for the addition of the suspend keyword. It can take a parameter and have a return type. However, suspending functions can only be invoked by another suspending function or within a coroutine.

Step 9 - UserRepositoryImpl

We are going to implement the UserRepository::interface in a new file, called UserRepositoryImpl.kt.
Create it inside the "implementation" package!

Override methods

Extend the UserRepositoryImpl::class with the UserRepository::interface

class UserRepositoryImpl : UserRepository
{

}

Now Android Studio will give you an error. It will tell you, that you should implement the methods, what we have created in the last step. So just move the cursor to the beginning of the class, where we have the red underline. Click on the red bulb at the beginning of this line, and implement the missing methods.

Member variables

Before we implement these method we gonna create 4 member variables.

In Firestore we gonna have always the same name for the collections. Because of this we gonna store it in a constant variable. Currently we will have only one variable. It is for the "users" collection. So jsut declare it as a member variable.

private val USER_COLLECTION_NAME = "users"

The next variable will make an instance about FirebaseFirestore.

private val firestoreInstance = FirebaseFirestore.getInstance()

The third one will be the instance of the collection.

private val userCollection = firestoreInstance.collection(USER_COLLECTION_NAME)

The last one will be an instance of the FirebaseAuth.

private val firebaseAuth: FirebaseAuth = FirebaseAuth.getInstance()

registerUserFromAuthWithEmailAndPassword

When it comes to converting Firebase calls to a suspending function, the only extra work we need to do is utilise the await() extension function provided by the library. 

Like most asynchronous operations from within Firebase SDKs, this authorisation method returns an instance of a Task. For this we have implemented the Task extension function and we can add listeners that allow us to hook into change events such as when the task completes, is successful or fails. 

Now that we have access to this coroutines-play-services library, we can wrap our registerUserFromAuthWithEmailAndPassword and await for a result within a suspending function, which could look like below.


registerUserFromAuthWithEmailAndPassword

With the above code:

      • First, registerUserFromAuthWithEmailAndPassword will trigger the authentication flow for Firebase
      • With the use of the await() extension function no more code will be executed until this operation has completed
      • Finally, we will return the current user from our firebase auth reference or throw an exception if this is null
      • In case if still we couldn't catch the exception, we will surround the whole call with a try-catch and the catch will get back the exception
createUserInFirestore

In this method we gonna implement the Firestore part of the registration process.


createUserInFirestore

With the above code:

      • First, we will send the user's data to Firestore with User object. In our case the "id" gonna be the userId from the Firebase authentication what we got back from the previous method.
        (We are going to create the User object in the next chapter in the ViewModel.)
      • We will surround again the method with try-catch.

Summary

In this chapter we have learned how to implement the Firebase email registration using Kotlin coroutines. Still we can't run the app, because we have to call these methods when the user clicked on the "Register" button.

What the user start the registration process, then from the activity the click listener of the button will call a function in the FirebaseViewModel. This ViewModel will call the functions, what we have created in this chapter.

About the ViewModels we gonna talk in the next chapter.

GitHub

The source code is availabel on GitHub

GitHub - register_with_email branch

Questions

I hope the description was understandable and clear. But if you have still questions, then leave me comments below! 😉

Have a nice a day! 🙂

 


 

Follow and like us:
Click to rate this post!
[Total: 0 Average: 0]

Leave a Reply

Your email address will not be published. Required fields are marked *