We will use Google login to authenticate users of the application. The Google Login feature allows users to safely log on with their Google account (the same account that Gmail, play, photos, and other Google services use). We can also personalize the user experience based on the personal data and identity information associated with the user's Google account. After the user logs in, we can use personal profile photos to personalize the chat message avatar.
To add support for Google Login, we will use the Google_sign_in plugin to import the appropriate packages in the Main.dart file.
Import ' Package:google_sign_in/google_sign_in.dart ';
To enable Google login, you need to open the Firebase console in your browser and select our project. Navigate to the Authentication > Login method. Enable the Google provider, as follows:
To configure Google login on iOS, you need to make sure that the generated googleservice-info.plist files are located in the runner directory of the Runner project in Xcode, so the Google login framework can determine your client ID. Add the bundle ID and reverse URL of the client ID to the main dictionary of the applied info.plist file:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole< /key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array >
<!--reverse the URL of the client ID-->
<string> Com.googleusercontent.apps.462578386393-kisbgopib3t6plf4dgv3s0n4ur3svjmo</string>
<!--bundle ID-->
<string>com.yourcompany.friendlychat</string>
</array>
</dict>
</array>
We can find the reverse URL of the client ID in the Googleservice-info.plist file, copy the value of the reversed_client_id string, and paste it to add it to cfbundleurlschemes. This URL type handles the callback when the user logs on to the application.
The first time you start an application, it may take two minutes to start. On iOS, extra time is needed to initialize cocapods repo, and on Android, maven dependencies need to be downloaded. After the next set of changes, we will be able to reload the application and the development cycle will be much faster.
Now that our applications are limited to individual users and devices, when a user sends a message, the application marks it as the value of the _name variable and displays it on the same screen, and the avatar is a simple colored circle. What we need to do now is that multiple users will be able to share messages through a live database. To help expand the application, we will personalize the avatar to differentiate the user. Since we will have the sender's Google login credentials, we can reuse the user's profile photos. We will add database support in a later step.
First, add a global variable named Googlesignin, initialize it with a new Googlesignin instance, and we'll use it to invoke the Google login API. Add the following code to the Main.dart file.
Final googlesignin = new Googlesignin ();
Now define two private methods, one for logging in and another for sending messages. Add the _ensureloggedin () method to check the CurrentUser property of the Googlesignin instance. Add the _ensureloggedin () method definition in Chatscreenstate.
Class Chatscreenstate extends state<chatscreen> with tickerproviderstatemixin {
//...
Future<null> _ensureloggedin () async {
Googlesigninaccount user = Googlesignin.currentuser;
if (user = null)
user = await googlesignin.signinsilently ();
if (user = = null) {
await googlesignin.signin ();
}
}
//...
}
The previous code fragment uses multiple wait expressions to sequentially execute the Google login method. If the value of the CurrentUser property is null, the application first executes signinsilently (), gets the result, and stores it in the user variable. The Signinsilently method attempts to authenticate the user before logging in without interaction. When this method completes, if the user value is still null, the application starts the logon process by executing the signin () method. After the user logs in, we can access the profile photos from the Googlesignin instance.
The process of submitting the message now has two steps, authentication and dispatch. We need to coordinate work to first authenticate, and if successful, then users can send messages. First, split the _handlesubmitted method from the chatscreenstate into two separate methods. Instead of performing all the committed work in _handlesubmitted (), we will use it to coordinate the tasks that other methods perform, such as verifying that the user is logged in and sending a message.
Keep _textcontroller.clear () and SetState () in _handlesubmitted () ... _iscomposing method call. Add _ensureloggedin () and _sendmessage () calls, as shown in the following code.
Class Chatscreenstate extends state<chatscreen> with tickerproviderstatemixin {
//...
Future _handlesubmitted (String text) Async {
_textcontroller.clear ();
SetState (() {
_iscomposing = false;
});
await _ensureloggedin ();
_sendmessage (Text:text);
}
//...
}
Modify the signature of the _handlesubmitted () to indicate that it is an asynchronous method that does not return any content. Before attempting to send a message, the call is added to the await _ensureloggedin () to wait for the user to authenticate successfully. Now we define _SENDMESSAGE () to add the remainder of _handlesubmitted () to the new private method. We'll make text a named parameter so that you can add more string arguments to _sendmessage later.
Class Chatscreenstate extends state<chatscreen> with tickerproviderstatemixin {
//...
void _sendmessage ({String text}) {
chatmessage message = new Chatmessage (
text:text,
Animationcontroller: New Animationcontroller (
duration:new Duration (milliseconds:300),
vsync:this
)
);
SetState (() {
_messages.insert (0, message);
});
Message.animationController.forward ();
}
//...
}
To personalize the avatar, we replace the Circleavatar control with its text control with the new Googleusercircleavatar object in the build () method of the Chatmessage class. Circleavatar can use network images, but the Googleusercircleavatar helper class can easily get the correct size profile photos from the Googlesignin instance. The Google_sign_in.dart plug-in defines this class.
Class Chatmessage extends Statelesswidget {
//...
@override
Widget Build [Buildcontext context] {return
new sizetransition/
/...
Child:new Container (
margin:const edgeinsets.symmetric (vertical:10.0),
child:new Row (
CrossAxisAlignment:CrossAxisAlignment.start,
Children: <widget>[
new Container (
margin:const Edgeinsets.only (right:16.0),
child:new Googleusercircleavatar (GOOGLESIGNIN.CURRENTUSER.PHOTOURL),
//...
]
)
)
);
}
}
The CurrentUser property is an authentication object, and we use Photourl to get the image of the new avatar. Now we need to personalize the display of the user name. Previously, we used hard coded to display the user name. Now that we have integrated the Google login, we can delete the _name global variable. Change to get the user name from the logged-on Google user. Use the DisplayName from the Googlesignin instance in the Chatmessage class to set the _name variable.
class Chatmessage extends Statelesswidget {//... @override Widget build (Buildcontext context) {return new
Sizetransition (//... child:new Container margin:const edgeinsets.symmetric (vertical:10.0),
Child:new Row (CrossAxisAlignment:CrossAxisAlignment.start, Children: <widget>[ ... new Column (CrossAxisAlignment:CrossAxisAlignment.start, Children: <wid get>[New Text (GoogleSignIn.currentUser.displayName, Style:theme.
of (context). Texttheme.subhead), New Container (Margin:const edgeinsets.only (top:5.0),
Child:new text (text))])
); }
}
Now, when we send a message, the Avatar and the sender's name match the profile information in your Google account. As we continue to make changes and optimize the application's UI, we can quickly see the results without having to restart the full application. Use the Flutter thermal reload feature to inject the updated source files into the running Dart virtual machine (Dart dummy Machine) and refresh the UI. Thermal overloading is a powerful tool for experimentation, prototyping, and iterative design.