OK, we are now ready to start using Firebase in our app.
In main.dart , we need to import the firebase_core library and the firebase_options.dart file, that we’ll use to initialize FlutterFire:
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
Next, let’s mark the main method as async: note that all Firebase methods are asynchronous, so the methods we’ll write to interact with it will usually need to be asynchronous as well. In the build method, before calling runApp, let’s add the
WidgetsFlutterBinding.ensureInitialized();
instruction. This makes sure we can call native code before the runApp method. Next, let’s await Firebase.initilizeApp. This will initialize FlutterFire, and it’s a prerequisite before interacting with any of the Firebase features. In other words, it’s a good idea to initialize FlutterFire in your main method, so that you can use it anywhere else in your app.
We’ll also specify the options here, setting it to DefaultFirebaseOptions.currentPlatform. This is very important: what this does is taking the options from the firebaseoptions.dart file, that was automatically generated when we set up flutterfire with the CLI.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
Let’s have a quick look at this file: you can see that there are different options based on the platform you are using, in this case Android and iOS, with all the necessary keys to connect to your Firebase project.
OK, now let’s create a new file in the screens folder of our project, called authentication_screen.dart. At the top of the file, let’s import material.dart. Next, let’s also import the firebase_auth library:
import 'package:firebase_auth/firebase_auth.dart';
Here we’ll create a stateless widget using the stless shortcut: we’ll call this widget AuthenticationScreen. In the build method of the widget, we’ll return a StreamBuilder, of type User (nullable): this is a widget that rebuilds itself based on a stream: in other words, each time the streams send some data, the Streambuilder will listen to the changes and call its builder method.
In this case the stream comes from FirebaseAuth.instance.authStateChanges(). Next let’s add a builder: the method takes a BuildContext, and a snapshot.
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
return Container();
},
In the main.dart file, in the build method, for the home of MaterialApp let’s call our AuthenticationScreen. Now, before moving on, let’s run the app on an Android device.
And, well, as you can see, we have an error here. Note that the error message is telling us that we need a higher Android SDK version. This might change soon, and if your app is running fine you need to do nothing, but in case it doesn’t, in the Android folder, open the Android.localproperties file. Here just add:
flutter.minSdkVersion=21
Now in the app folder, open the build.gradle file, and search minSDK. In the minSdkVersion key, let’s set localProperties.getProperty(‘flutter.minSdkVersion’).toInteger()
minSdkVersion localProperties.getProperty('flutter.minSdkVersion').toInteger()
Let’s run the app again, and everything should work fine now. Now let’s use FlutterUI to build our login screen.
In the build method of our AuthenticationScreen widget, in the builder of the StreamBuilder, let’s check whether the snapshot has some data: if the snapshot hasdata property is true, this means that the user has already logged in, otherwise this will return false. So, when the user is NOT logged in (let’s add an exclamation mark here), we want to return a SignInScreen.
if (!snapshot.hasData) {
return SignInScreen();
}
Let’s open the quick fix option by clicking the light bulb, and choose the first option, that will import the FlutterFire_ui auth library.
This signinScreen is one of the screens that FlutterFire UI brings to your apps, again, almost with no code.
Now, we must tell the SignInScreen that we want to use the email and password provider: we can do this through the providerConfigs property: this takes a List of providers, and here just add EmailProviderConfiguration, which is the only provider we are using here.
providerConfigs: [
EmailProviderConfiguration(),
],
Now let’s also specify what happens when the user is logged in. Well, in this case we can just return our ActivitiesScreen.
// User is not logged in
if (!snapshot.hasData) {
return const SignInScreen(
providerConfigs: [
EmailProviderConfiguration(),
],
);
}
return const ActivitiesScreen();
Let’s run the app and see what happens:
As you can see you now have a fully functional sign-in screen, and you can even register as a new user when you press theRegister button!
Now, let’s register a new user.
So, let’s add an email, a super-secret password, then repeat it and press the “Register” button.
In this way, we can see that this actually works.
Let’s customize the sign in screen next!