Flutter : phone verification firebase_auth get error when submit wrong Code - flutter

why i'm getting error and stuck when i type wrong code in textfield?
void _signInWithPhoneNumber(String smsCodes) async {
final AuthCredential credential = PhoneAuthProvider.getCredential(
verificationId: verificationId,
smsCode: smsCodes,
);
FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseUser user =
await _auth.signInWithCredential(credential).then((user) {
Navigator.of(context).pop();
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => SuksesPhone()));
}).catchError((e) {
print(e);
Navigator.of(context).pop();
setState(() {
canClick = true;
});
});
}
but when i type correct code, no error.
the error is like this.

Not 100% sure, but I think it should be like this. When using await, you shouldn't use then.
void _signInWithPhoneNumber(String smsCodes) async {
final AuthCredential credential = PhoneAuthProvider.getCredential(
verificationId: verificationId,
smsCode: smsCodes,
);
FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseUser user =
await _auth.signInWithCredential(credential).catchError((onError{
//do something
}));
//check user
if(user){
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => SuksesPhone()));
}
}

Related

firebase not creating data when user signs for first time

when new user signIn, In firebase Authentication tab it is showing users details.
but not adding the function to firestore.
google signIn code:
Future<UserCredential> signInWithGoogle() async {
showDialog(
context: context,
builder: (context) {
return const Center(child: CircularProgressIndicator());
});
final _auth = FirebaseAuth.instance;
// 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 credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
final UserCredential authResult =
await _auth.signInWithCredential(credential);
final user = authResult.user;
if (authResult.additionalUserInfo!.isNewUser) {
if (user != null) {
await DbServices().addNewUser(FirebaseAuth.instance.currentUser!.uid);
}
}
removeLoading();
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
}
removeLoading() {
return Navigator.of(context).pop();
}
}
**this is addNewUser function:**
Future addNewUser(useruid) async {
int heartid = await updateHeartId();
print('updated Heart Id $heartid....................');
await usersCollection.doc(useruid).set({
'user name': FirebaseAuth.instance.currentUser!.displayName,
'uid': useruid,
'heartId': heartid,
'total hearts': 0,
'ringed': false,
'Timestamp': FieldValue.serverTimestamp(),
'profile pic': '',
'todayRinged': false,
'ringedDay': DateTime.now().day,
});
}
when I looked into it, firebase isn't adding the function addNewUser in firestore.
I don't understand what's happening here.
when I signIn for first time the app crashes saying :
> StateError(Bad state: cannot get a field on a DocumentSnapshotPlatform
> which does not exist)
why is the addNewUser function not adding to firestore?

Flutter Google Sign In error after canceling Choose an account pop-up

After clicking sign in, choose an account pop comes up but if the user pressed back or outside of the pop-up it throws an error.
Error -
Sign in class -
class GoogleSignInProvider extends ChangeNotifier {
final googleSignIn = GoogleSignIn();
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
Future googleLogin() async {
await googleSignIn.signOut();
final googleUser = await googleSignIn.signIn();
if (googleUser == null) return;
_user = googleUser;
final googleAuth = await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken, idToken: googleAuth.idToken);
await FirebaseAuth.instance.signInWithCredential(credential);
notifyListeners();
}
}
Sign out button -
TextButton(
onPressed: () async {
final googleCurrentUser = GoogleSignIn().currentUser;
if (googleCurrentUser != null) {
await GoogleSignIn().disconnect();
}
FirebaseAuth.instance.signOut();
Navigator.pop(context);
},
child: const Text(
'Yes',
style: TextStyle(color: primaryColor),
))
Instead of if (googleUser == null) return; try using if (googleUser == null) return null;.
Here is my sign in method;
Future<UserCredential?> signInWithGoogle() async {
final _googleSignIn = GoogleSignIn();
await _googleSignIn.disconnect().catchError((e, stack) {
print(e);
});
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
// handling the exception when cancel sign in
if (googleUser == null) return null;
// Obtain the auth details from the request
final GoogleSignInAuthentication? googleAuth =
await googleUser.authentication;
// Create a new credential
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
return await FirebaseAuth.instance.signInWithCredential(credential);
}
The sign out method;
Future signOut() async {
var result = await FirebaseAuth.instance.signOut();
return result;
}
This only happens in debugging, in release this won't be an issue.

Getting NoSuchMethodError: The getter 'uid' was called on null flutter

I'm pretty new to flutter firebase and I am getting this error NoSuchMethodError: The getter 'uid' was called on null flutter. I have searched and looked very carefully but left scratching my head only where is the error. Over on my condition I'm checking if user is not equal to null then save it but its not happening.
Here's my phone authentication file code which should save the user as well but its not doing it right now because of the null issue
class PhoneAuthService {
FirebaseAuth auth = FirebaseAuth.instance;
User user = FirebaseAuth.instance.currentUser;
CollectionReference users = FirebaseFirestore.instance.collection('users');
Future<void> addUser(context, uid) async {
final QuerySnapshot result = await users.where('uid', isEqualTo: uid).get();
List<DocumentSnapshot> document = result.docs;
if (document.length > 0) {
Navigator.pushReplacementNamed(context, LocationScreen.id);
} else {
return users.doc(user.uid).set({
'uid': user.uid,
'mobile': user.phoneNumber,
'email': user.email,
}).then((value) {
Navigator.pushReplacementNamed(context, LocationScreen.id);
}).catchError((error) => print("Failed to add user: $error"));
}
}
Future<void> verifyPhonenumber(BuildContext context, number) async {
final PhoneVerificationCompleted verificationCompleted =
(PhoneAuthCredential credential) async {
await auth.signInWithCredential(credential);
};
final PhoneVerificationFailed verificationFailed =
(FirebaseAuthException e) {
if (e.code == 'invalid-phone-number') {
print('The phone number is not valid');
}
print("The error is ${e.code}");
};
final PhoneCodeSent codeSent = (String verId, int resendToken) async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OTPScreen(
number: number,
verId: verId,
)));
};
try {
auth.verifyPhoneNumber(
phoneNumber: number,
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
timeout: const Duration(seconds: 60),
codeAutoRetrievalTimeout: (String verificationId) {
print(verificationId);
});
} catch (e) {
print("Error ${e.toString()}");
}
}
}
This is where I'm getting the user otp and proceeding it further
Future<void> phoneCredential(BuildContext context, String otp) async {
FirebaseAuth _auth = FirebaseAuth.instance;
try {
PhoneAuthCredential credential = PhoneAuthProvider.credential(
verificationId: widget.verId, smsCode: otp);
final User user = (await _auth.signInWithCredential(credential)).user;
if (user != null) {
_services.addUser(context, user.uid);
Navigator.pushReplacementNamed(context, LocationScreen.id);
} else {
print("Login Process Failed ");
if (mounted) {
setState(() {
error = 'Login Failed';
});
}
}
} catch (e) {
print(e.toString());
if (mounted) {
setState(() {
error = 'Invalid OTP';
});
}
}
}
If anyone understood where I'm doing wrong please help I'm stuck for 3 days on it now.

Flutter - Google Sign In uses previously signed in account (user) even after signing out and signing in with another account

When I hit "Sign in with Google", it does let me choose the account although somehow, the previous user gets loaded.
class GoogleSignInProvider extends ChangeNotifier {
GoogleSignIn? _googleSignIn;
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
bool _isGoogleLogin = false;
final _auth = FirebaseAuth.instance;
Future signInWithGoogle(context) async {
try {
_googleSignIn = GoogleSignIn();
final googleUser = await _googleSignIn!.signIn();
if (googleUser == null) {
return;
}
_user = googleUser;
final googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
var authCredential = await _auth.signInWithCredential(credential);
_isGoogleLogin = true;
if (authCredential.user != null) {
final snapshot = await FirebaseFirestore.instance
.collection('users')
.doc(authCredential.user!.uid)
.get();
if (!snapshot.exists) {
var userId = authCredential.user!.uid;
FirebaseFirestore.instance.collection('users').doc(userId).set({
"email": googleUser.email,
"workoutsCount": 0,
"lastWorkoutDate": null
});
}
}
notifyListeners();
Navigator.of(context).pushNamed('/dashboard');
} on FirebaseAuthException catch (e) {
showSnackBar(context, e);
} catch (e) {
print('ERROR = ');
print(e);
}
}
Future<void> signOut(context) async {
try {
if (_isGoogleLogin) {
final googleCurrentUser =
GoogleSignIn().currentUser ?? await GoogleSignIn().signIn();
if (googleCurrentUser != null) {
await GoogleSignIn().disconnect().catchError((e, stack) {
FirebaseCrashlytics.instance.recordError(e, stack);
});
}
}
await _auth.signOut();
} catch (e) {
showSnackBar(context, e);
} finally {
_isGoogleLogin = false;
Navigator.of(context).pushNamedAndRemoveUntil(
'/register_login', (Route<dynamic> route) => false);
}
}
Is there something wrong with this code??
Can you try to disconnect the account before signing out:
GoogleSignIn _googleSignIn = GoogleSignIn();
await _googleSignIn.disconnect();
await FirebaseAuth.instance.signOut();
You are using firebase auth then please use thsi for signout user :
How to Signout a user in Flutter with Firebase authentication
Remove if (_isGoogleLogin) from your signOut function. googleCurrentUser will check the consitionn and responses based on the result.
First Create a Global variable
FirebaseAuth firebaseAuth = FirebaseAuth.instance;
GoogleSignIn googleSignIn = GoogleSignIn();
Make sure you are using the above variable for login and logout
final googleCurrentUser = firebaseAuth.currentUser;
if (googleCurrentUser != null) {
googleSignIn.signOut();
await firebaseAuth.signOut();
}
User above code for signout user

Using FirebaseAuth verifyPhoneNumber in flutter?

Hey I am trying to use Firebase Auth verifyPhoneNumber in Flutter.
I am constantly getting my msg in onTap function as null. I tried declaring a variable in registerToFb function but I am not able to update its value. How do I solve it?
Following is the function from where I am calling the firebaseAuth.verifyPhoneNymber() method.
onTap: () async {
setState(() => isLoading = true);
String msg = await _auth.registerToFb(
"+91$truephoneNumber", context);
print(msg);
},
Following is where I am defining my function.
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
AuthenticationService(this._firebaseAuth);
Future registerToFb(String phoneNumber, BuildContext context) async {
String result = " ";
await _firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: const Duration(seconds: 30),
verificationCompleted: (PhoneAuthCredential credential) async {
UserCredential authresult =
await _firebaseAuth.signInWithCredential(credential);
User user = authresult.user;
_getUserFromFirebase(user);
result = "signedUp";
},
verificationFailed: (FirebaseAuthException e) {
String error = e.code == 'invalid-phone-number'
? "Invalid number. Enter again."
: "Can Not Login Now. Please try again.";
result = error;
},
codeSent: (String verificationId, int resendToken) {
result = "verified";
},
codeAutoRetrievalTimeout: (String verificationId) {},
);
}
return result;
}
Help me, please. Thanks
The problem is that you aren't returning anything in your function. And even when you try to save a value from inside the callbacks, the future from verifyPhoneNumber resolves before those callbacks get called.
You need to be awaiting the right thing. You shouldn't await the future returned from verifyPhoneNumber. You should await a new future that doesn't resolve until you get a result from one of the callbacks. This means you need to create your own Future which you can manually resolve specifically when you need it to. You can do this with a Completer:
Future<String> registerToFb(String phoneNumber, BuildContext context) {
final completer = Completer<String>();
_firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: const Duration(seconds: 30),
verificationCompleted: (PhoneAuthCredential credential) async {
UserCredential authresult =
await _firebaseAuth.signInWithCredential(credential);
User user = authresult.user;
_getUserFromFirebase(user);
completer.complete("signedUp");
},
verificationFailed: (FirebaseAuthException e) {
String error = e.code == 'invalid-phone-number'
? "Invalid number. Enter again."
: "Can Not Login Now. Please try again.";
completer.complete(error);
},
codeSent: (String verificationId, int resendToken) {
completer.complete("verified");
},
codeAutoRetrievalTimeout: (String verificationId) {
completer.complete("timeout");
},
);
return completer.future;
}