Flutter Firebase Auth Email and Google Signin With Lastest Oct 2020 Update

Update: Nov 11, 2020

Added phone_login.dart for phone number authentication.


 

 

Update: Nov 2, 2020

1. Added "forgot password" to email_login.dart

2. Added forgot_password.dart

 

Update: Nov 1, 2020

1. Added "await" in email_singup.dart

2. Added "isLoading = false;" in email_login.dart

 

As of Oct 7 2020, Firebase Auth for Flutter has the new version 0.18.1+2. This Flutter Auth demo with Email and Google Sign-in is just a new update to show you how to work with the newest Firebase Auth version.


Most of the codes here are obtained from Peter Haddad's article How To Use Firebase Authentication In Flutter. Many thanks to Peter Haddad.

 

1. Create a new Flutter project. 

Open Android Studio. And create a new Flutter project named "fire_auth_demo". Then go to android/app/build.gradle. Look for "applicationId". That's your Android package name. My package name is "com.haoc.fire_auth_demo". Yours might be different. We need it to set up a Firebase project.

2. Set up a Firebase project.

Go to your Firebase console . Click to create a new project. Under the project, click the Android icon to add an Android app, with the package name "com.haoc.fire_auth_demo". Follow all the steps in the YouTube video to finish setup.

3. Add dependencies to pubspec.yaml.

dependencies:
flutter:
sdk: flutter


# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.3

firebase_core : ^0.5.0
# firebase_database: ^4.1.1
firebase_auth: ^0.18.1
google_sign_in: "^4.5.4"
flutter_signin_button: ^1.0.0

 

11. phone_login.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

TextEditingController nameController = TextEditingController();

class PhoneLogin extends StatefulWidget {
PhoneLogin(this.isRegister);
final bool isRegister;

@override
_PhoneLoginState createState() => _PhoneLoginState();
}

class _PhoneLoginState extends State<PhoneLogin> {
bool isLoading = false;
final _formKey = GlobalKey<FormState>();

TextEditingController phoneController = TextEditingController();

@override
void initState() {
super.initState();
nameController.text = '';
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.isRegister ? "Phone Number Register" : "Phone Number Login")),
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(children: <Widget>[
Container(
child: widget.isRegister
? Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: nameController,
decoration: InputDecoration(
labelText: "Enter User Name",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter User Name';
}
return null;
},
),
)
: null,
),
Padding(
padding: EdgeInsets.all(10.0),
child: ListTile(
title: Text("Enter phone number. We might send SMS to you. Fee may occur.",
style: TextStyle(color: Colors.blue)),
)),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: phoneController,
decoration: InputDecoration(
labelText: "Format: +1 555 555 5555",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter phone number';
} else if (!value.contains('+')) {
return 'Enter valid phone number';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: isLoading
? CircularProgressIndicator()
: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.blue[700])),
onPressed: () {
if (_formKey.currentState.validate()) {
setState(() {
isLoading = true;
});
registerToFb(nameController.text.trim(),
phoneController.text.trim());
}
},
child: Text('Submit'),
),
)
]))),
));
}

void registerToFb(String name, String phoneNo) async {
if (name == '' && widget.isRegister) {
name = phoneNo;
}
FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
phoneNumber: phoneNo,
timeout: const Duration(seconds: 60),
verificationCompleted: (PhoneAuthCredential credential) async {
await auth.signInWithCredential(credential);
User user = auth.currentUser;

if (user != null && widget.isRegister) {
// new method to update user profile
await user.updateProfile(displayName: name);
}
setState(() {
isLoading = false;
});

Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home()),
);
},
verificationFailed: (FirebaseAuthException e) {
var msg;
if (e.code == 'invalid-phone-number') {
msg = 'Invalid number. Enter again.';
} else {
msg = e.message;
}

setState(() {
isLoading = false;
});

showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text(msg.toString()),
actions: [
FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
},
codeSent: (String verificationId, int resendToken) {
setState(() {
isLoading = false;
});

Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EnterSMS(
verificationId, resendToken, phoneNo, widget.isRegister)),
);
},
codeAutoRetrievalTimeout: (String verificationId) {
setState(() {
isLoading = false;
});
/*showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text('Timeout. Try again later.'),
actions: [
FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});*/
},
);
}


} //phone login

class EnterSMS extends StatefulWidget {
EnterSMS(this.vId, this.tkn, this.phoneN, this.isReg);
final String vId;
final int tkn;
final String phoneN;
final bool isReg;

@override
_EnterSMSState createState() => _EnterSMSState();
}

class _EnterSMSState extends State<EnterSMS> {
final _formKey = GlobalKey<FormState>();
TextEditingController smsController = TextEditingController();
var isLoading = false;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Phone Number Register / Login")),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: ListTile(
title: Text("SMS sent. Enter the verification code:",
style: TextStyle(color: Colors.black)),
)),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: smsController,
decoration: InputDecoration(
labelText: "Code",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter code';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: isLoading
? CircularProgressIndicator()
: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.blue[700])),
onPressed: () {
if (_formKey.currentState.validate()) {
setState(() {
isLoading = true;
});
verifySMS(widget.vId, smsController.text.trim());
}
},
child: Text('Submit'),
),
),
Padding(
padding: EdgeInsets.all(10.0),
child: ListTile(
title: Text("Code not received? Send again.",
style: TextStyle(color: Colors.blue)),
onTap: () async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: widget.phoneN,
forceResendingToken: widget.tkn,
//verificationCompleted: (PhoneAuthCredential credential) {},
//verificationFailed: (FirebaseAuthException e) {},
codeSent: (String verificationId, int resendToken) {
setState(() {});
},
//codeAutoRetrievalTimeout: (String verificationId) {},
);
},
)),
]))));
}

void verifySMS(String vID, String msg) async {
// Create a PhoneAuthCredential with the code
PhoneAuthCredential phoneAuthCredential =
PhoneAuthProvider.credential(verificationId: vID, smsCode: msg);
// Sign the user in (or link) with the credential
try {
await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential);
setState(() {
isLoading = false;
});
User user = FirebaseAuth.instance.currentUser;
if (user != null && widget.isReg) {
// new method to update user profile
await user.updateProfile(displayName: nameController.text);
}
Navigator.of(context).popUntil((route) => route.isFirst);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home()),
);
} catch (err) {
setState(() {
isLoading = false;
});
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text(err.message),
actions: [
FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
} // verify sms


}


4. main.dart

import 'package:firebase_core/firebase_core.dart'; // new requirement for all Firebase projects.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';
import 'signup.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); // new for Firebase Auth
runApp(MyApp());
}

class MyApp extends StatelessWidget {
User user = FirebaseAuth.instance.currentUser;

@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HaoC Study',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: (user == null)
? SignUp()
: Home(uid: user.uid),
);
}
}

5. signup.dart

import 'package:flutter/material.dart';
import 'package:flutter_signin_button/flutter_signin_button.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

import 'email_login.dart';
import 'email_signup.dart';
import 'home.dart';
import 'phone_login.dart';

class SignUp extends StatelessWidget {
final String title = "Sign Up - HaoC Study";

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: SignInButtonBuilder(
icon: Icons.phone_outlined,
text: "Sign up with phone number",
backgroundColor: Colors.blueAccent[700],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PhoneLogin(true)));
},
)),
Padding(
padding: EdgeInsets.all(10.0),
child: SignInButton(
Buttons.Email,
text: "Sign up with Email",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EmailSignUp()),
);
},
)),
Padding(
padding: EdgeInsets.all(10.0),
child: ListTile(
title: Text("Already have an account?",
style: TextStyle(color: Colors.blue)),
)),
Padding(
padding: EdgeInsets.all(10.0),
child: SignInButtonBuilder(
icon: Icons.phone_outlined,
text: "Sign in with phone number",
backgroundColor: Colors.lightBlueAccent[700],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PhoneLogin(false)),
);
},
)),
Padding(
padding: EdgeInsets.all(10.0),
child: SignInButtonBuilder(
text: 'Sign in with Email',
icon: Icons.email,
backgroundColor: Colors.blueGrey[700],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => EmailLogIn()),
);
},
),
),
Padding(
padding: EdgeInsets.all(10.0),
child: SignInButton(
Buttons.Google,
text: "Sign in with Google",
onPressed: () async {
// sign in Google with a returning user profile
UserCredential userCredential = await signInWithGoogle();
final snapShot = await FirebaseFirestore.instance
.collection("userData").doc(userCredential.user.uid).get();
if(snapShot == null || !snapShot.exists) {
await FirebaseFirestore.instance.collection("userData")
.doc(userCredential.user.uid).set({'NoOfDecks': 0});
}
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
Home(uid: userCredential.user.uid)),
);
},
)),
]),
));
}

// standard Google sign-in code
Future<UserCredential> signInWithGoogle() async {
// Trigger the authentication flow
final GoogleSignInAccount googleUser = await GoogleSignIn().signIn();

// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;

// Create a new credential
final GoogleAuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);

// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
}

}

6. email_signup.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class EmailSignUp extends StatefulWidget {
@override
_EmailSignUpState createState() => _EmailSignUpState();
}

class _EmailSignUpState extends State<EmailSignUp> {
bool isLoading = false;
final _formKey = GlobalKey<FormState>();
//FirebaseAuth firebaseAuth = FirebaseAuth.instance;
//DatabaseReference dbRef = FirebaseDatabase.instance.reference().child("Users");
TextEditingController emailController = TextEditingController();
TextEditingController nameController = TextEditingController();
TextEditingController passwordController = TextEditingController();
TextEditingController retypePasswordController = TextEditingController();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Email Sign Up")),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: nameController,
decoration: InputDecoration(
labelText: "Enter User Name",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter User Name';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: emailController,
decoration: InputDecoration(
labelText: "Enter Email",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter an Email Address';
} else if (!value.contains('@')) {
return 'Please enter a valid email address';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
obscureText: true,
controller: passwordController,
decoration: InputDecoration(
labelText: "Enter Password",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter Password';
} else if (value.trim().length < 6) {
return 'Password must be atleast 6 characters!';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
obscureText: true,
controller: retypePasswordController,
decoration: InputDecoration(
labelText: "Re-enter Password",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Re-enter Password';
} else if (value.trim() != passwordController.text.trim()) {
return 'Passwords didn\'t match. Please re-enter password.';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: isLoading
? CircularProgressIndicator()
: RaisedButton(
color: Colors.lightBlue,
onPressed: () {
if (_formKey.currentState.validate()) {
setState(() {
isLoading = true;
});
registerToFb();
}
},
child: Text('Submit'),
),
)
]))));
}

void registerToFb() async {
try {
UserCredential userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
User user = userCredential.user;
//FirebaseAuth.instance.currentUser;
if (user != null) {
// added "await" Nov 1,2020. new method to update user profile
await user.updateProfile(displayName: nameController.text.trim());
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home(uid: user.uid)),
);
}
} catch (err) {
isLoading = false;

showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text(err.message),
actions: [
FlatButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
}

@override
void dispose() {
super.dispose();
nameController.dispose();
emailController.dispose();
passwordController.dispose();
retypePasswordController.dispose();
}

}

7. email_login.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';
import 'forgot_password.dart';

class EmailLogIn extends StatefulWidget {
@override
_EmailLogInState createState() => _EmailLogInState();
}

class _EmailLogInState extends State<EmailLogIn> {
final _formKey = GlobalKey<FormState>();
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
bool isLoading = false;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Login")),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: emailController,
decoration: InputDecoration(
labelText: "Enter Email Address",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter Email Address';
} else if (!value.contains('@')) {
return 'Please enter a valid email address!';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
obscureText: true,
controller: passwordController,
decoration: InputDecoration(
labelText: "Enter Password",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter Password';
} else if (value.length < 6) {
return 'Password must be at least 6 characters!';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(10.0),
child: ListTile(
title: Text("Forgot your password?",// added Nov 2,2020
style: TextStyle(color: Colors.blue)),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ForgotPassword(emailController.text ?? '')));
},
)),
Padding(
padding: EdgeInsets.all(20.0),
child: isLoading
? CircularProgressIndicator()
: RaisedButton(
color: Colors.lightBlue,
onPressed: () {
if (_formKey.currentState.validate()) {
setState(() {
isLoading = true;
});
logInToFb();
}
},
child: Text('Submit'),
),
)
]))));
}

void logInToFb() async {
try {
UserCredential userCredential = await FirebaseAuth.instance
.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim());
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Home(uid: userCredential.user.uid)),
);
} catch (err) {
// updated Nov 1, 2020
setState(() {
isLoading = false;
});
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text(err.message),
actions: [
FlatButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
} //finally {
//isLoading = false;
//}
}

@override
void dispose() {
super.dispose();
emailController.dispose();
passwordController.dispose();
}
}


 

7.5 forgot_password.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

class ForgotPassword extends StatefulWidget {
ForgotPassword(this.email);
final String email;

@override
_ForgotPasswordState createState() => _ForgotPasswordState();
}

class _ForgotPasswordState extends State<ForgotPassword> {
final _formKey = GlobalKey<FormState>();
TextEditingController emailController = TextEditingController();

@override
void initState() {
super.initState();
emailController.text = widget.email;
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Reset Password")),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0, bottom: 20.0),
child:
Text('To reset your password, enter your email address:'),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(
controller: emailController,
decoration: InputDecoration(
labelText: "Enter Email Address",
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
// The validator receives the text that the user has entered.
validator: (value) {
if (value.isEmpty) {
return 'Enter Email Address';
} else if (!value.contains('@')) {
return 'Please enter a valid email address!';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.all(20.0),
child: RaisedButton(
color: Colors.lightBlue,
onPressed: () {
if (_formKey.currentState.validate()) {
resetPassword();
}
},
child: Text('Submit'),
),
)
]))));
}

void resetPassword() {
bool hasError = false;
String emailAddress = emailController.text.trim();
FirebaseAuth.instance
.sendPasswordResetEmail(email: emailAddress)
.catchError((onError) {
showMessage(onError.toString());
hasError = true;
}).then((value) {
if (!hasError) {
var msg =
'Successfully sent reset email! Check your email inbox and follow the instruction.';
showMessage(msg);
}
});
}

void showMessage(String msg) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
//title: Text("Error"),
content: Text(msg),
actions: [
FlatButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}

@override
void dispose() {
super.dispose();
emailController.dispose();
}
}

8. home.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'main.dart';

class Home extends StatefulWidget {
Home({this.uid});
final String uid;
@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
final String title = "Home - HaoC Study";
var name = '';

@override
void initState() {
super.initState();
User user = FirebaseAuth.instance.currentUser;
name = user.displayName ?? '';
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(child: Text('Welcome ' + name)),
drawer: NavigateDrawer(uid: widget.uid));
}
}

class NavigateDrawer extends StatefulWidget {
final String uid;
NavigateDrawer({Key key, this.uid}) : super(key: key);
@override
_NavigateDrawerState createState() => _NavigateDrawerState();
}

class _NavigateDrawerState extends State<NavigateDrawer> {
@override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
SizedBox(
height: 50,
),
ListTile(
leading: new IconButton(
icon: new Icon(Icons.home, color: Colors.black),
onPressed: () => null,
),
title: Text('Home'),
onTap: () {
print(widget.uid);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Home(uid: widget.uid)),
);
},
),
ListTile(
leading: new IconButton(
icon: new Icon(Icons.settings, color: Colors.black),
onPressed: () => null,
),
title: Text('Settings'),
onTap: () {
print(widget.uid);
},
),
ListTile(
leading: new IconButton(
icon: new Icon(Icons.exit_to_app, color: Colors.black),
onPressed: () => null,
),
title: Text('Sign Out'),
onTap: () async {
await FirebaseAuth.instance.signOut();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
},
),
],
),
);
}
}

9. settings.gradle

include ':app'

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}

plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}


10. app/build.gradle

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

apply plugin: 'com.google.gms.google-services' //this line
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 28

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

lintOptions {
disable 'InvalidPackage'
}

defaultConfig {
// TODO: Change to your own unique Application ID!!!
applicationId "
com.haoc.fire_auth_demo"
minSdkVersion 23
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}

buildTypes {
release {

// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}

flutter {
source '../..'
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.firebase:firebase-database:19.2.1'
}


Comments

  1. Thank You Dear,but one question how to save this all information in cloud firestore in collection users

    ReplyDelete
    Replies
    1. you need to create a collection named "Users". Then save user's info to this collection.

      Delete
  2. Thank You Dear,but one question how to resend code otp

    ReplyDelete

Post a Comment

Popular posts from this blog

Android CameraX Picture And Video Capture Complete Code Tutorial

Flutter: call a method from another class / setState a page from outside that class with StreamController

How To Add AdMob To Flutter App Quick Tutorial