1. Creating project on Firebase

Following this video to connect your flutter app to Firebase.

Note:

First, if you would like to use Google sign-in, need to do this step (only for Android — the video above won’t do it since he doesn’t use sign-in method) to get SHA-1 key (get the debug certificate is enough).

https://developers.google.com/android/guides/client-auth

Remember that the keytool only accepts one parameter, but two “-exportcert -list” are suggested. The “-exportcert” parameter is redundant and can be omitted from the commands listed on that page.

Second, add this line #import <Firebase/Firebase.h> to AppDelegate.h

Start the Cloud Firestore and Storage

Then enable sign-in method with Google

Now you’re done this step, don’t need to add or init any data manually at Firebase.

Rules at Storage:

Use this mode for storage to accept only image file type

The rule check image file type only works for Android (iOS always not match this condition even you upload the image). Because the image upload at Android is image/jpeg or image.png… but on iOS is just application/octet-stream no matter what the file type is.

So you can temporarily remove the second condition or change it to

if true && (request.resource.contentType.matches('image/.*') || request.resource.contentType.matches('application/octet-stream'));

to pass iOS file type.

If anyone finds a better solution, please tell me.

Rules at Database:

And this mode for database

2. Installing plugins

Following these instructions to add firebase_auth , google_sign_in , cloud_firestore , firebase_storage to your project.

These plugins help login app by Google account, get user info, real-time database for chatting and upload image.

And the others will help us show toast, cache data local, pick images from gallery, cache network image and parse date time.

3. Layout the login screen

When user login success, the return variable firebaseUser contains some user information, like displayName, photoUrl…

then we’ll check if the user is new or not (by query to the server does this ID exist). If they’re a new user, write it to the database.

The other things we need to do here are writing user info to local storage (to use in other screens, mention later) and navigate to the main screen when login successful.

For more details, please check out the source code at the end of this article, in the path lib/login.dart

4. Layout the main screen

This screen contains list all users in our database, we’ll show all the info we got like avatar, nickname and about me. If you would like to design user has more field than that, create a detail screen to see all particular user info is a good idea.

Note: You should use two accounts for login (A and B). So when you log in account A, you can see B and vice versa.

Get list user quite simply by using StreamBuilder like below:

And about catching event when user touch back button at this screen, will exit the app, but we should show dialog confirm at first, like this

To catch back event, use WillPopScope widget, it gives an attribute name onWillPop , when user touch on soft or hard back button, it goes to this function first, and at this function, we open the dialog.

One more thing we have to do at this screen is to create a option menu to go to Settings screen or Log out. Our option menu is like this

About how to create option menu and dialog, please check my source code in the path lib/home.dart

5. Layout the settings screen

At here, the user can change some info like their avatar, nickname and about me. You can add more field than that if you want.

At first, we load current user info from disk (the data we wrote when they log in) to show on UI.

If user change avatar, we need to upload that file to Firebase Storage, then get file’s URL.

After that, update user info to Cloud FireStore with new photoUrl we just set.

Notice that a user just need an avatar, so we set file name is userID, if user uploads a new file, Firebase will replace the old with the new one.

More details, please check my source code in the path lib/settings.dart

6. Layout the chat screen

This is a score screen so we have many things to do on this screen.

First, we need to layout the UI, root widgets are like this

The root is WillPopScope because we need to handle the back press, if sticker or keyboard is shown, we need to hide it instead of back to the previous screen.

Second is handle sticker and keyboard appearance, if keyboard being shown, the sticker will dismiss and vice versa.

Keyboard show, sticker hide and vice versa

We need a variable isShowSticker to detect should show sticker or not, focusNode help us control should focus on text input or not, if focusing, the keyboard will appear.

Third is load previous message and listening for new income message, we’ll use StreamBuilder

Notice that when user A (current user) chat with user B (peer user), the problem is which groupChatId we’ll use to read and write data chat to the server since conversation of A & B need to save at the same node? So my idea is hashing the A’ uid and B’ uid, then creates a string like this:

Then at user A or B, they both read and write data at the same Cloud Firestore node.

At the time of this article is published, I found no way to scroll item to bottom list programmatically when receive a new message, so my idea is reverse array message (set attribute .orderBy when query data from the server), then set reverse attribute in ListView to true. Then list message will have a good UX like other apps chat.

Fourth is handle sending messages, if user sends an image, we need to upload this image and get URL, then we just add the content of the message is this URL, and stickers (are saved at the local project) just need the name of the file is enough.

When receiving a new message, we’ll check type first, if the type is image, we load this image from network, if the type is sticker, show it from the local file.