Null error when I want my firebase user id with currentUser() - firebase

Error
NoSuchMethodError: The method 'currentUser' was called on null.
Receiver: null
Tried calling: currentUser()
I'm interesting in know where i need to using this code:
String _uid = '';
void initState() {
super.initState();
auth.currentUser().then((userId) {
setState(() {
_uid = userId;
});
});
}
This code is from the home_page.dart (see below)
I had also tried to using:
widget.auth.current....
root_page
In bottom of the file i had tried different approach.
Instead of HomePage then _HomePageState(comments out)
class RootPage extends StatefulWidget {
RootPage({this.auth});
final BaseAuth auth;
#override
State<StatefulWidget> createState() => new _RootPageState();
}
enum AuthStatus {
notSignedIn,
signedIn
}
class _RootPageState extends State<RootPage>{
AuthStatus authStatus = AuthStatus.notSignedIn;
#override
void initState() {
super.initState();
widget.auth.currentUser().then((userId) {
setState(() {
authStatus = userId == null ? AuthStatus.notSignedIn : AuthStatus.signedIn;
});
});
}
void _signedIn(){
setState(() {
authStatus = AuthStatus.signedIn;
});
}
void _signedOut() {
setState(() {
authStatus = AuthStatus.notSignedIn;
});
}
#override
Widget build(BuildContext context) {
switch(authStatus) {
case AuthStatus.notSignedIn:
return new LoginPage(
auth: widget.auth,
onSignedIn: _signedIn,
);
case AuthStatus.signedIn:
/*
return new HomePageState(
auth: widget.auth,
onSignedOut: _signedOut,
);
*/
return new HomePage(
auth: widget.auth,
onSignedOut: _signedOut,
);
}
}
}
auth.dart
This is the class I'm using to get current user from auth.
abstract class BaseAuth{
Future<String> signInWithEmailAndPassword(String email, String password);
Future<String> createUserWithEmailAndPassword(String email, String password);
Future<String> currentUser();
Future<void> signOut();
}
class Auth implements BaseAuth{
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> signInWithEmailAndPassword(String email, String password) async {
FirebaseUser user = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
return user.uid;
}
Future<String> createUserWithEmailAndPassword(String email, String password) async {
FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: password);
return user.uid;
}
Future<String> currentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user.uid;
}
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
}
home_page.dart
I had tried different things in this file but get different errors.
class HomePage extends StatefulWidget {
HomePage({this.auth, this.onSignedOut});
final BaseAuth auth;
final VoidCallback onSignedOut;
void _signOut() async {
try {
await auth.signOut();
onSignedOut();
} catch (e) {
print(e);
}
}
#override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
/*
_HomePageState({this.auth, this.onSignedOut});
final BaseAuth auth;
final VoidCallback onSignedOut;
*/
//final BaseAuth auth;
String _uid = '';
#override
void initState() {
super.initState();
auth.currentUser().then((userId) {
setState(() {
_uid = userId;
});
});
}

_auth.currentUser() does not return the user ID, it returns a FirebaseUser object.
Change it like this :
auth.currentUser().then((user) {
if (user == null || user.isAnonymous) {
// what will you do?
return;
}
setState(() {
_uid = user.uid;
});
});
Yet, I would recommend to monitor the onAuthStateChanged stream instead. This way you will be informed when the user logs in or logs out immediately.
Check this article, it covers it in depth.

You can use like this.
someMethod() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
print(user.uid);
}

Related

Trying to login with google but always return null

hey guys i trying to login with google using firebase in flutter but its always return null in the next page
how can i get the current user in the next page after login with google
i already connect with firebase and generate sha-1 and sha-256
here's the code
login button
onPressed: () async {
setState(() {
_isSigningIn = true;
});
try {
final user = await googleSignIn.signIn();
final googleAuth = await user.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken
);
final googleAccount = await FirebaseAuth.instance.signInWithCredential(credential);
if(googleAccount != null) {
Navigator.pushReplacementNamed(context, HomeScreen.id);
}
} catch (e) {
final snackbar = SnackBar(content: Text(e.toString()));
_scaffoldKey.currentState.showSnackBar(snackbar);
} finally {
setState(() {
_isSigningIn = false;
});
}
},
home_screen.dart
class _HomeScreenState extends State<HomeScreen> {
final _auth = FirebaseAuth.instance;
User _currentUser;
void getCurrentUser() async {
try {
var currentUser = await _auth.currentUser;
if (currentUser != null) {
_currentUser = currentUser;
}
} catch(e) {
print(e);
}
}
#override
void initState() {
super.initState();
getCurrentUser();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_currentUser.email),
),
);
}
}
thank you
This line is an asynchronous function, it is for this reason that you receive null, you must add an await.
final googleAccount = await FirebaseAuth.instance.signInWithCredential(credential);
In addition to this, to access the information of the current user you must do it this way.
googleAccount.user

Google authentication problem (Flutter and Firebase)

I am flutter-newbie and I have one problem: I want to add Google authentication to my flutter app with firebase. This is my code for login screen:
import 'package:PixiCall/resources/firebase_repository.dart';
import 'package:PixiCall/screens/home_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
FirebaseRepository _repository = FirebaseRepository();
#override
Widget build(BuildContext context) {
return Scaffold(
body: loginButton(),
);
}
Widget loginButton() {
return FlatButton(
padding: EdgeInsets.all(35),
child: Text(
'Login',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w900,
letterSpacing: 1.2,
),
),
onPressed: () => performLogin,
);
}
void performLogin() {
_repository.signIn().then((User user) {
if (user != null) {
authenticateUser(user);
} else {
print('There was an error');
}
});
}
void authenticateUser(User user, BuildContext context) {
_repository.authenticateUser(user).then((isNewUser) {
if (isNewUser) {
_repository.addDataToDb(user).then((value) {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));
});
} else {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));
}
});
}
}
I have this error here:
lib/screens/login_screen.dart:39:25: Error: Too few positional arguments: 2 required, 1 given.
authenticateUser(user);
What is the other parameter which I have to add?
Also I think that I have one more mistake in other file. This is the code from other file:
import 'package:PixiCall/models/user.dart';
import 'package:PixiCall/utils/utilities.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class FirebaseMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
GoogleSignIn _googleSignIn = GoogleSignIn();
static final FirebaseFirestore firestore = FirebaseFirestore.instance;
//user class
User1 user = User1();
Future<User> getCurrentUser() async {
User currentUser;
currentUser = await _auth.currentUser;
return currentUser;
}
Future<User> signIn() async {
GoogleSignInAccount _signInAccount = await _googleSignIn.signIn();
GoogleSignInAuthentication _signInAuthentication =
await _signInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: _signInAuthentication.accessToken,
idToken: _signInAuthentication.idToken,
);
User user = await _auth.signInWithCredential(credential);
return user;
}
Future<bool> authenicateUser(User user) async {
QuerySnapshot result = await firestore
.collection('users')
.where('email', isEqualTo: user.email)
.get();
final List<DocumentSnapshot> docs = result.docs;
//if user is registered then length of list > 0 or else less than 0
return docs.length == 0 ? true : false;
}
Future<void> addDataToDb(User currentUser) async {
String username = Utils.getUsername(currentUser.email);
user = User1(
uid: currentUser.uid,
email: currentUser.email,
name: currentUser.displayName,
profilePhoto: currentUser.photoURL,
username: username);
firestore.collection('users').doc(currentUser.uid).set(user.toMap(user));
}
}
This is the mistake in console:
lib/resources/firebase_methods.dart:32:17: Error: A value of type 'UserCredential' can't be assigned to a variable of type 'User'.
Sorry if I confused you, as I said, I am newbie. If you want any other informations please ask here.
For the first mistake , you defined a function void authenticateUser(User user, BuildContext context) so when you use it, it expects 2 arguments a User type object and a BuildContext object
Then you are calling this function in
void performLogin() {
_repository.signIn().then((User user) {
if (user != null) {
authenticateUser(user);
} else {
print('There was an error');
}
});
}
You are passing only the User object, missing the BuildContext
For GoogleSingIn this was my solution:
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
//create user object based on FB json
User _userFromFirebaseUser(FirebaseUser user) {
return user != null
? User(uid: user.uid, emailVerified: user.isEmailVerified)
: null;
}
//auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
Future<User> singInUsingGoogle() async {
int age;
String email;
String name;
String lastname;
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: googleAuth.idToken, accessToken: googleAuth.accessToken);
final result = await _auth.signInWithCredential(credential);
FirebaseUser user = result.user;
print(result.user.providerData);
await DatabaseService(uid: user.uid).createUserData(
//user info
)

Firebase signOut() issue(Flutter)

I have an app using firebase, I handle sign in or log in in RootPage then it passes to my FirstPage, if I directly logout without go any route from FirstPage it is working well and leading me to my RootPage unsigned version but if I go any route from my FirstPage and go back there then try to signOut it just give below error:
D/FirebaseAuth(10720): Notifying id token listeners about a sign-out event.
D/FirebaseAuth(10720): Notifying auth state listeners about a sign-out event.
I/flutter (10720): NoSuchMethodError: The method 'call' was called on null.
I/flutter (10720): Receiver: null
I/flutter (10720): Tried calling: call()
I have a movetohome function to go back my FirstPage from any page and I think there is something missing at it, my function is below;
_moveToHome(BuildContext context) {
Route route = MaterialPageRoute(builder: (context) => MyFirstPage(auth: FirebaseAuth.instance,userId: userId,));
Navigator.push(context, route);
}
and you can find firebase related parts of my pages;
main.dart:
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
const MyApp();
#override
Widget build(BuildContext context) {
return DynamicTheme(
defaultBrightness: Brightness.light,
data: (brightness) => ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
}
),
primarySwatch: Colors.blueGrey,
accentColor: Colors.blueGrey,
fontFamily: 'AvenirNext',
brightness: brightness,
),
themedWidgetBuilder: (context, theme) {
return MaterialApp(
theme: theme,
home: new RootPage(auth: new Auth()),
routes: <String, WidgetBuilder>{
MyFirstPage.routeName: (context) => new MyFirstPage(auth: new Auth()),
DetailPage.routeName: (context) => new DetailPage(auth: new Auth()),
GenrePage.routeName: (context) => new GenrePage(auth: new Auth())
},
);
});
}
}
RootPage:
import 'package:flutter/material.dart';
import 'package:randommoviefinal/screens/login_singup_page.dart';
import 'package:randommoviefinal/services/authentication.dart';
import 'package:randommoviefinal/screens/HomePage.dart';
enum AuthStatus {
NOT_DETERMINED,
NOT_LOGGED_IN,
LOGGED_IN,
}
class RootPage extends StatefulWidget {
RootPage({this.auth});
final BaseAuth auth;
#override
State<StatefulWidget> createState() => new _RootPageState();
}
class _RootPageState extends State<RootPage> {
AuthStatus authStatus = AuthStatus.NOT_DETERMINED;
String _userId = "";
#override
void initState() {
super.initState();
widget.auth.getCurrentUser().then((user) {
setState(() {
if (user != null) {
_userId = user?.uid;
}
authStatus =
user?.uid == null ? AuthStatus.NOT_LOGGED_IN : AuthStatus.LOGGED_IN;
});
});
}
void loginCallback() {
widget.auth.getCurrentUser().then((user) {
setState(() {
_userId = user.uid.toString();
});
});
setState(() {
authStatus = AuthStatus.LOGGED_IN;
});
}
void logoutCallback() {
setState(() {
authStatus = AuthStatus.NOT_LOGGED_IN;
_userId = "";
});
}
Widget buildWaitingScreen() {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
}
#override
Widget build(BuildContext context) {
switch (authStatus) {
case AuthStatus.NOT_DETERMINED:
return buildWaitingScreen();
break;
case AuthStatus.NOT_LOGGED_IN:
return new LoginSignupPage(
auth: widget.auth,
loginCallback: loginCallback,
);
break;
case AuthStatus.LOGGED_IN:
if (_userId.length > 0 && _userId != null) {
return new MyFirstPage(
userId: _userId,
auth: widget.auth,
logoutCallback: logoutCallback,
);
} else
return buildWaitingScreen();
break;
default:
return buildWaitingScreen();
}
}
}
MyFirstPage:
class MyFirstPage extends StatefulWidget {
MyFirstPage({Key key, this.auth, this.userId, this.logoutCallback})
: super(key: key);
final auth;
final VoidCallback logoutCallback;
final String userId;
static String routeName = "/MyFirstPage";
#override
_MyFirstPageState createState() => new _MyFirstPageState();
}
class _MyFirstPageState extends State<MyFirstPage> {
String userId;
List<Movies> _moviesList;
final FirebaseDatabase _database = FirebaseDatabase.instance;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Query _moviesQuery;
StreamSubscription<Event> _onMoviesAddedSubscription;
StreamSubscription<Event> _onMoviesChangedSubscription;
#override
void initState() {
// TODO: implement initState
super.initState();
_moviesList = new List();
_moviesQuery = _database
.reference()
.child("movies")
.orderByChild("userId")
.equalTo(widget.userId);
_onMoviesAddedSubscription = _moviesQuery.onChildAdded.listen(onEntryAdded);
_onMoviesChangedSubscription =
_moviesQuery.onChildChanged.listen(onEntryChanged);
}
void dispose() {
_onMoviesAddedSubscription.cancel();
_onMoviesChangedSubscription.cancel();
super.dispose();
}
onEntryChanged(Event event) {
var oldEntry = _moviesList.singleWhere((entry) {
return entry.key == event.snapshot.key;
});
setState(() {
_moviesList[_moviesList.indexOf(oldEntry)] =
Movies.fromSnapshot(event.snapshot);
});
}
onEntryAdded(Event event) {
setState(() {
_moviesList.add(Movies.fromSnapshot(event.snapshot));
});
}
signOut() async {
try {
await widget.auth.signOut();
widget.logoutCallback();
} catch (e) {
print(e);
}
}
updateMovies(Movies movies) {
//Toggle completed
movies.watched = !movies.watched;
if (movies != null) {
_database.reference().child("movies").child(movies.key).set(movies.toJson());
}
}
deleteMovies(String moviesId, int index) {
_database.reference().child("movies").child(moviesId).remove().then((_) {
print("Delete $moviesId successful");
setState(() {
_moviesList.removeAt(index);
});
});
}
My another page for example:
class DetailPage extends StatefulWidget {
MovieDetailPage({Key key, this.title, this.auth, this.userId})
: super(key: key);
final auth;
final String userId;
static String routeName = "/MyHomePage";
final String title;
#override
_DetailPageState createState() => _DetailPageState();}
class _DetailPageState extends State<MovieDetailPage> {
String userId;
final FirebaseDatabase _database = FirebaseDatabase.instance;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
StreamSubscription<Event> _onMoviesAddedSubscription;
StreamSubscription<Event> _onMoviesChangedSubscription;
Query _moviesQuery;
List<Movies> _moviesList;
_moveToHome(BuildContext context) {
Route route = MaterialPageRoute(builder: (context) => MyFirstPage(auth: FirebaseAuth.instance,userId: userId,));
Navigator.push(context, route);}
#override
void initState() {
// TODO: implement initState
super.initState();
_moviesList = new List();
_moviesQuery = _database
.reference()
.child("movies")
.orderByChild("userId")
.equalTo(widget.userId);
_onMoviesAddedSubscription = _moviesQuery.onChildAdded.listen(onEntryAdded);
_onMoviesChangedSubscription =
_moviesQuery.onChildChanged.listen(onEntryChanged);
widget.auth.getCurrentUser().then((user) {
if (user != null) {
userId = user?.uid;
}});
}
void dispose() {
_onMoviesAddedSubscription.cancel();
_onMoviesChangedSubscription.cancel();
super.dispose();
}
onEntryChanged(Event event) {
var oldEntry = _moviesList.singleWhere((entry) {
return entry.key == event.snapshot.key;
});
setState(() {
_moviesList[_moviesList.indexOf(oldEntry)] =
Movies.fromSnapshot(event.snapshot);
});
}
onEntryAdded(Event event) {
setState(() {
_moviesList.add(Movies.fromSnapshot(event.snapshot));
});
}
updateMovies(Movies movies) {
//Toggle completed
movies.watched = !movies.watched;
if (movies != null) {
_database.reference().child("movies").child(movies.key).set(movies.toJson());
}
}
deleteMovies(String moviesId, int index) {
_database.reference().child("movies").child(moviesId).remove().then((_) {
print("Delete $moviesId successful");
setState(() {
_moviesList.removeAt(index);
});
});
}
...
IconButton(
icon: Icon(Icons.home),
iconSize: 35,
onPressed: () {
_moveToHome(context);
},
),
...
and authentication.dart
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
abstract class BaseAuth {
Future<String> signIn(String email, String password);
Future<String> signUp(String email, String password);
Future<FirebaseUser> getCurrentUser();
Future<void> sendEmailVerification();
Future<void> signOut();
Future<bool> isEmailVerified();
}
class Auth implements BaseAuth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> signIn(String email, String password) async {
AuthResult result = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return user.uid;
}
Future<String> signUp(String email, String password) async {
AuthResult result = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return user.uid;
}
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
Future<void> sendEmailVerification() async {
FirebaseUser user = await _firebaseAuth.currentUser();
user.sendEmailVerification();
}
Future<bool> isEmailVerified() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user.isEmailVerified;
}
}
I think FirebaseAuth is losing current user when you leave your home page try moving
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
class Auth implements BaseAuth {
//Rest of class
to right outside your class this way it has global scope just make sure it not in the abstract class that's right above it

How to access return value of a callback function present inside a Future method | Dart

auth.dart
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// Sign in with Phone Number Future<bool>
Future signInWithPhone(String phone, BuildContext context) async {
final PhoneVerificationCompleted verificationCompleted = (AuthCredential credential) async {
..
};
final PhoneVerificationFailed verificationFailed = (AuthException exception) {
// This is the return value which i want to access outside of this callback
return exception.message;
};
final PhoneCodeSent codeSent = (String verificationId, [int forceResendingToken]) {
...
};
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout = (String verificationId) {
Navigator.of(context).pop();
...
};
await _auth.verifyPhoneNumber(
phoneNumber: phone,
timeout: Duration(seconds: 10),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout
);
// Trying to access the callback value
print(verificationFailed);
}
}
login.dart
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
#override
Widget build(BuildContext context) {
return Container(
// here i am calling the phonesign in method
await _auth.signInWithPhone(phoneNumber, context);
// and here i want to show the message
);
}
}
What is the Problem?
The problem is i want to access the value of any callback of the verifyPhoneNumber , For example verificationFailed which returns an exception message and i want to access it outside so that i can use that in other widgets.
What i have tried so far?
1) I have tried printing it and it returns AuthException Closure: () => String I Don't know how to access the value.
2) I have tried using setState but as my class is not inside a statefulWidget i can't assign that value to a variable
*Why i need it? *
Look i have two pages one is called login.dart and 2nd is called auth.dart .In my auth page i mostly place the classes and code thats related to backend (to properly organize the code) and in the login page i have a stateful widget, consising of a phone textfield and on submit i call the method signInWithPhone .Everything works but if any error appears such as wrong user phone number format then the verificationFailed callback is triggered and thus i want to access the return value outside(bcz we cant directly get the return value) so that i can show it from where i called it.
Can anybody please help me so that i can continue my code.
It's clear now what you're trying to do. Using Provider is one way to do it. Another way is to pass a callback to Login Page:
class LoginPage extends StatefulWidget {
final Function(String) verificationMessage;
const LoginPage({Key key, this.verificationMessage}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
…
…
final PhoneVerificationFailed verificationFailed = (AuthException exception) {
widget.verificationMessage(exception.message);’
};
}
Now you just pass a callback function whenever you call LoginPage
LoginPage(verificationMessage: (String message) => {
setState(() {
// Do what you want with the message
})
})
In your case:
auth.dart
class AuthService {
**final Function(String) verificationMessage;**
**AuthService({#required this.verificationMessage});**
final FirebaseAuth _auth = FirebaseAuth.instance;
// Sign in with Phone Number Future<bool>
Future signInWithPhone(String phone, BuildContext context) async {
final PhoneVerificationCompleted verificationCompleted = (AuthCredential credential) async {
..
};
final PhoneVerificationFailed verificationFailed = (AuthException exception) {
// This is the return value which i want to access outside of this callback
**verificationMessage(exception.message);**
};
final PhoneCodeSent codeSent = (String verificationId, [int forceResendingToken]) {
...
};
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout = (String verificationId) {
Navigator.of(context).pop();
...
};
await _auth.verifyPhoneNumber(
phoneNumber: phone,
timeout: Duration(seconds: 10),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout
);
// Trying to access the callback value
print(verificationFailed);
}
}
login.dart
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
String message = "";
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Text(message),
Flatbutton(
....
onPressed: (){
AuthService(verificationMessage: (String newMessage) => {
setState(() {
message = newMessage
})
})
}
)
]
)
);
}
}
I suggest you make your widget stateful, then you can do this:
final PhoneVerificationFailed verifiFailed = (AuthException exception) {
setState(() {
errorMessage = exception.message;
});
print('${exception.message}');
};
It's very easy to switch your widget to be stateful:
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
#override
Widget build(BuildContext context) {
return Column(children: [
...
errorMessage == null ? SizedBox() : Text( errorMessage),
...
]);
}
}
When errorMessage is updated inside the setState the error message will be present.
You can also use Provider; here are a few links for you to look them up:
https://medium.com/flutter-community/flutter-firebase-login-using-provider-package-54ee4e5083c7
https://www.youtube.com/watch?v=MjY1_LaXyd8
https://medium.com/#JigneshPatel23/how-to-implement-an-authentication-feature-using-a-provider-in-flutter-1f351447d09d

Failed to return to login page/screen after signing out (Not sure if sign out is successful or not)

I'm new in flutter and dealing with backend. I faced problem in signing out and I don't know how to fix it due to lack of experience. When I sign out, it would not return to the login screen (Authenticate). I'm not quite sure if the problem lies at the function I wrote at the wrapper or somewhere in auth.
The wrapper widget will be executed everytime the app runs:
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: new MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.redAccent,
),
home: Wrapper(),
),
);
}
}
The wrapper code is as below:
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
print(user);
if (user == null) {
return Authenticate();
} else {
return MyBottomNavigationBar();
}
}
}
Sign out button function:
onPressed: () async {
await _auth.signOut();
print('signing out');
},
Auth code:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:mudah_replica/models/user.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
//Create user object based on FirebaseUser
User _userFromFirebaseUser(FirebaseUser user){
return user != null ? User(uid: user.uid) : null;
}
//Auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged
//.map((FirebaseUser user) => _userFromFirebaseUser(user));
.map(_userFromFirebaseUser);
}
//Sign in anonymously
Future signInAnon() async {
try {
AuthResult result = await _auth.signInAnonymously();
FirebaseUser user = result.user;
return user;
} catch(e) {
print(e.toString());
return null;
}
}
//Sign in with Email & Password
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch(e){
print(e.toString());
return null;
}
}
//Register with Email & Password
Future registerWithEmailAndPassword(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;
}
}
//Sign out
Future signOut() async {
try{
return await _auth.signOut();
} catch(e){
print('Fail to sign out');
print(e.toString());
return null;
}
}
}
in your wrapper class, you are returning auth widget instead of navigate to the right screen, so it doesn't route. Instead, you might wanna navigate to the Auth screen. Do something like this:
onPressed: () async {
await _auth.signOut();
Navigator.push(context,
MaterialPageRoute(builder: (context) => Authenticate())
},

Resources