online software programming courses

Flutter Firebase Firestore App | Getx

Firebase app for beginners to advanced.

In this tutorial we will learn how to build Flutter Firebase App. It would be an app for beginners to advanced learners. We will cover flutter sign in and login ui. Flutter firebase authentication using Getx.

In the upcoming tutorial we will also cover flutter firebase crud operation. We will also build Auth controller using Getx to learn more about authentication

Check out the video tutorial

Download the assets for the tutorials

Firebase App Assets

Download the assets for the tutorials

Settings

For android get bundle identifier like below In Android the package name is in the AndroidManifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    package="com.example.appname">

You can change the package name here. It would be the bundle identifier name.

 

For firebase app, we need several settings. Let's start with Android settings. Go and find android/app/build.gradle file.

In this file we need to add 4 lines here. In the above folder we also add our android setting json file which we get from firebase. It's google-services.json

apply plugin: 'com.google.gms.google-services'

applicationId "com.db.dbestech.flutterFirebaseApp"

MultiDexEnable true

implementation 'com.android.support:multidex:1.0.3'

For the first line add like below

 

Now add the second and third line

If you get error after setting multidex, you remove it. Some sdk throws error after setting this.

Now add the fourth line

 

Now we need to add one more line for android setting. That's in android/build.gradle file

 

Add a line there like below

classpath ‘com.google.gms:google-services:4.3.3’

 

Getx Authentication

 

AuthController

We want our AuthController to be availabe thoughout the app. So we will create an AuthController instance that would be accessible from anywhere.

We will create a static instance of the controller

class AuthController extends GetxController{
  //with instance AuthController would be able to the app everywhere
  static AuthController instance = Get.find();
  late Rx<User?> _user;
  FirebaseAuth auth = FirebaseAuth.instance;
  ......................
}

We created an instance using Get.find() inside the controller, so It will be able everywhere in the app using AuthController.instance

 

You can initialize your user from firebase and bindStrem with the user, so any changes happen to user, our firebase use would be notified.

@override
void onReady(){
 super.onReady();
 _user = Rx<User?>(auth.currentUser);
 _user.bindStream(auth.userChanges());
}

 

You also need to bind _user with our app lifecycle. So that, any time user logs in or log out or navigate to a different page, app would know it. This is the actualy auth controller.

For this we will use ever worker function in Getx. This function ever() takes a listener and a callback.  Before you call ever() worker function, you need to call _user.bindStream(auth.userChanges());

@override
void onReady(){
 super.onReady();
 _user = Rx<User?>(auth.currentUser);
 _user.bindStream(auth.userChanges());
//worker function
ever(_user, initialScreen);
}

Getx worker function ever()

With this auth controller would be able to listen to any changes, 

Sign in and Sign out Method

Since we have an access to FirebaseAuth instance, we would be able to call the FirebaseAuth properties and fields. We will use 

//Sign up or register method
await  auth.createUserWithEmailAndPassword(email: email, password: password);

//Sign in or login method
await  auth.signInWithEmailAndPassword(email: email, password: password);

Here await and async keywords are quiet important. Otherwise you will get error. See the complete controller

import 'package:firebase_app/login_page.dart';
import 'package:firebase_app/welcome_page.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class AuthController extends GetxController{
  //AuthController.intsance..
   static AuthController instance = Get.find();
   //email, password, name...
   late Rx<User?> _user;
   FirebaseAuth auth = FirebaseAuth.instance;

   @override
  void onReady(){
     super.onReady();
     _user = Rx<User?>(auth.currentUser);
     //our user would be notified
     _user.bindStream(auth.userChanges());
     ever(_user, _initialScreen);
   }

   _initialScreen(User? user){
     if(user==null){
       print("login page");
       Get.offAll(()=>LoginPage());
     }else{
       Get.offAll(()=>WelcomePage(email:user.email!));
     }
   }

   void register(String email, password)async{
     try{
     await  auth.createUserWithEmailAndPassword(email: email, password: password);
     }catch(e){
        Get.snackbar("About User", "User message",
        backgroundColor: Colors.redAccent,
        snackPosition: SnackPosition.BOTTOM,
          titleText: Text(
            "Account creation failed",
            style: TextStyle(
              color: Colors.white
            ),
          ),
          messageText: Text(
            e.toString(),
              style: TextStyle(
                  color: Colors.white
              )
          )
        );
     }
   }
   void login(String email, password)async{
     try{
       await  auth.signInWithEmailAndPassword(email: email, password: password);
     }catch(e){
       Get.snackbar("About Login", "Login message",
           backgroundColor: Colors.redAccent,
           snackPosition: SnackPosition.BOTTOM,
           titleText: Text(
             "Login failed",
             style: TextStyle(
                 color: Colors.white
             ),
           ),
           messageText: Text(
               e.toString(),
               style: TextStyle(
                   color: Colors.white
               )
           )
       );
     }
   }
   void logOut()async{
     await auth.signOut();
   }
}

 

Injecting Dependencies

You need to inject this AuthController to the app, as we talked early, because this is a dependency for our app. Our app needs some initialization. First we will wait for firebase to be initialized and then we will inject the auth controller. This happens within the main function of our app.

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp().then((value) => Get.put(AuthController()));
  runApp(MyApp());
}

Here we inject AuthController using Get.put() . Now auth controller would be available to the app.

 

View

Now it's time to call register and login method from our view

 GestureDetector(
            onTap: (){
              AuthController.instance.register(emailController.text.trim(), passwordController.text.trim());
}
GestureDetector(
            onTap: (){
              AuthController.instance.login(emailController.text.trim(), passwordController.text.trim());
}