Build a Fully Functioning Flutter Chat App with Firebase Part 1/4

Sanskar Tiwari
Flutter Community
Published in
8 min readMay 16, 2020

In this series you will learn how to create a fully functioning chat app with flutter & Firebase, we will be using Firebase Auth, Firebase Firestore, Shared Preference to keep the user logged in, and much more.

Chat is something many apps now require if not even creating a stand-alone chat app, If you like to learn via video then you can watch it on Youtube

🎬 Full PlayList: https://bit.ly/chatappwithflutter

📕 Things covered in this Series:

  • Firebase Auth: Sign in, Sign up and Sign out
  • Firebase Firestore: Upload & Retrieve data stored in Cloud Firestore
  • Perform simple and compound queries in Cloud Firestore
  • Building Complexe UI
  • Shared Preference to keep the user logged in, Create chat room ( with username) & Send message ( by username)
  • Using Stream & Stream builder

Prerequisites :

Make Sure :

  • I have also linked to a specific time in Youtube for steps and linked so if you face any problem you can always watch that part in the video

Live Example: https://flutterdevconnect.web.app/ ( with some additional features), Watch App Demo on Youtube here

So let’s get started coding,

Step 1: Create a flutter project, I am going to do it with Android studio you can user terminal/cmd or VS code there will be no difference.

Step 2: We will start by getting rid of all the comments in the main.dart and getting rid of MyHomePage() stateful widget

Step 3: Create a folder/package inside the lib we will create all the screens in this folder so I am going to name this views.

then create a file for every screen

  • signin.dart
  • signup.dart
  • forgetpassword.dart
  • chatroomscreen.dart

Step 4: First we will create a widget called SignIn inside signin.dart where we will use scaffold, appBar, body and floating action button

so since the appBar is going to be very similar for most of the screen I am going to create it in a separate file so that it can be used in other screens as well

So I will create a new folder/package name widgets and create widgets.dart inside it. and will create appBar

import 'package:flutter/material.dart';Widget appBarMain(BuildContext context) {
return AppBar(
title: Image.asset(
"assets/images/logo.png",
height: 40,
),
elevation: 0.0,
centerTitle: false,
);
}

as you can see for the title we are using an image asset which you can get from here download it ( image may not be visible being white, with GitHub white background)

then create an assets folder inside the main directory also create image folder inside of it then to use add this to pubspec.yaml

assets:    
- assets/images/

after adding this click on packages get for android studio, save for VS code

now according to the design we have a dark background for this just go to main.dart and inside themedata add

scaffoldBackgroundColor: Color(0xff1F1F1F),

Step 5: Creating the UI of SignIn & SignUp Screen

UI in flutter is about understanding the arrangement of widgets by widgets I mean everything, it can be text, image, button …

We use column and row to structure widgets in vertical and horizontal manner respectively

Creating a text input box we use TextField and for the button, I am creating that Using container

here is how it looks.

It will show a bunch of errors let’s fix them

  • appBarMain() : we need to import this so just select it and click on bulb and import.
  • simpleTextStyle() : Since the text style for text field is same and it will be use more than 5 times 2 times in sign in 3 times in signup i will be creating it in widgets.dart
TextStyle simpleTextStyle() {  
return TextStyle(color: Colors.white, fontSize: 16);
}
  • textFieldInputDecoration() : Similar to simpleTextStyle create this inside widgets.dart
  • biggerTextStyle() : Similar to simpleTextStyle just to have bigger font size
TextStyle biggerTextStyle() {  
return TextStyle(color: Colors.white, fontSize: 17);
}
  • CustomTheme.textColor : I created a helper folder/package and then theme.dart and there i added the textColor and ColorAccent

SignUp can be created just by pasting same code with one textfield extra for username and changing the text from SignIn to SignUp and also import the styles which we created before

Step 6 : Connecting Flutter app with Firebase

  1. Login to the Firebase ( or signup with google account)

create a project and then > Project Overview then enter the “Package Name” for this project it is com.theindianappguy.chat_app_tutorial

to get the package name of your project open android > app > build.gradle inside theme scroll down and you will find

defaultConfig {
....
applicationId "com.example.chatapp"
....
}

2. Download google-services.json and move the google-services,json file you just downloaded into your Android app module root directory (app folder)

3. Add google-services dependencies in Project-level build.gradle

dependencies {  
...
classpath 'com.google.gms:google-services:4.3.3'
...
}

That’s it 🙂 Connecting android app to firebase is done

  1. Right-click on ios folder and “click open with Xcode” [Only for Mac blame apple 😕]

then there click on main Runner(blue document) then copy the ios Bundle identifier

2. In Firebase console click on ios icon then submit iOS bundle ID and click “Register app”

3. Download GoogleService-Info.plist and then move the GoogleService-Info.plist file you just downloaded into the root of your Xcode project and it to all targets

That’s it 🙂 Connecting iOS app to firebase is done

Okay so let’s continue to next steps, So far we have built a beautiful sign in screen with flutter now its time to make functioning

Now to implement Firebase Auth first we will work on SignUp screen and then SignIn Screen. also rather than calling SignIn() from main.dart call SignUp() in home.

Step 7 : Create TextEditingController

why? we have actually created the textfield which will accept user input but to get userinput of what he have written we can use onchanged property which updates everytime (every time) he (user) write or we can just use a texteditting controller

TextEditingController emailEditingController = new TextEditingController();TextEditingController passwordEditingController = new TextEditingController();TextEditingController usernameEditingController = new TextEditingController();

then assign these controller to the textfields like this for username, email & password

TextFormField(
...
controller: emailEditingController,
...
),

If it feel confusing check out the final signup.dart

Step 8: Creating Functions for Sign In, SignUp, LogOut Flutter Firebase

since we want to use firebase auth, go to Firebase and click on “Authentication” the click on set up sign-in method and then enable Email/Password

  1. Add firebase_auth to pubspec.yaml
firebase_auth: ^0.16.0

2. Create auth.dart

create a folder called services inside lib and then create auth.dart file inside it

[learn how we create these function through video here]

  • Create AuthService class
class AuthService {}
  • Instantiate FirebaseAuth
final FirebaseAuth _auth = FirebaseAuth.instance;
  • Create signInWithEmailAndPassword() function
Future signUpWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
  • create signUpWithEmailAndPassword() function
Future signUpWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
  • create resetPass() function
Future resetPass(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
return null;
}
}
  • create signOut() function
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}

find full code here

Step 9 : Implement Sign In Functionality

so when user inputs the info we will call the function and sign him up but lets say he did not enter anything 🤔 then we don’t want to call the function that’s just not required server calls

So first we will implement validation basically we will be testing the user input like is it empty for username, is it email and for password is it less than 6 character

for this we need to use TextFormField so just add update TextField to TextFormField and then

Wrap all the TextFormField in a column and that column will be wrapped in Form like this (… represents something)

Form(
child : Column(
children:[
TextFormField(
...
),
TextFormField(
...
),
TextFormField(
...
),
])
)

now to validate we need formkey so let’s create that

final formKey = GlobalKey<FormState>();

Now let’s add validation in TextFormField

  • for username

so we created a function which accepts val as argument which is what user inputs now when check if val is empty and accordingly we run conditional statement which works like this

CONDITION ? TRUE (DO THIS): FALSE (DO THIS)

TextFormField(
validator: (val){
return val.isEmpty || val.length < 3 ? "Enter Username 3+ characters" : null;
},

),
  • for email

for email its little complex to see for first time

this is called regular expression we check if the provided string is like email or not if true then we return null if false it will show error.

TextFormField(
validator: (val){
return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a- zA-Z0-9]+\.[a-zA-Z]+").hasMatch(val) ? null : "Enter correct email";
},

),
  • for password

for password we just want to make sure it is more than 6 characters and also add obscrure text so that the password will be hidden

TextFormField(
obscureText: true,
validator: (val){
return val.length < 6 ? "Enter Password 6+ characters" : null;
},

),

okay so now we want that when user will click on the Sign Up button first we should show user something is happening like a circular progress bar

then we will call the function we created in the auth.dart file and provide the username, emaill and password to signup and then send the user to the home screen.

So lets do that, first create a bool (boolean value true/false) called isLoading which will be initially false

bool isLoading = false;

also add this to call functions in auth.dart

AuthService authService = new AuthService();

now lets create the signUp function inside signup.dart

😨 too much code…

let’s understand what happened, first we did a if condition so that the upcoming statement will only run if its true

formKey.currentState.Validate() runs all the onvalidate and if they all are null then returns true or else false and TextFormField will show error

then we are setting isLoading = true;

what is setSatate((){})?

well when update some value and we want that to change the UI then calling setstate() recreates the whole ui with updates data

then we are calling the function in auth.dart to signup the user, which will return the userid, so we will check if the result is null or not

if result != null then we will send the user to the ChatRoom() screen,

Now to show loading according to isLoading bool we need to update some code

body : isLoading ? Container(child: Center(child: CircularProgressIndicator(),),) : Container(
...all code....
)

so what now, now to call this signUp() function when user click on the signup button we will wrap the button with GestureDetector and call signUp() onTap:, like this

GestureDetector(
onTap: (){
singUp();
},
child: Container(
...sign up button...
)
)

I think that’s enough for the Part 1 we will continue with Part 2

☑️ Repository:

Here’s GitHub repo which is complete Chat app made with Flutter and Firebase : https://github.com/theindianappguy/FlutterChatAppTutorial

If you found this project useful, then please consider giving it a ⭐️ on GitHub and sharing it with your friends via social media.

https://www.twitter.com/FlutterComm

--

--