I have a login and register methods that don't catch the exceptions and I don't know why.
static Future<void> register(BuildContext context,
{#required String email, #required String password, #required displayName, #required gender}) async {
try {
final authResult = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password);
if (authResult.user != null) {
FirestoreInit.initDocs(authResult.user);
FirestoreInit.initUser(authResult.user, gender, displayName);
await authResult.user.updateProfile(displayName: displayName);
await authResult.user.reload();
Navigator.of(context).pushNamed(Routing.routeName, arguments: authResult.user);
}
} on FirebaseAuthException catch (exception) {
signUpFailureDialog(context, exception);
} on PlatformException catch (exception) {
signUpFailureDialog(context, exception);
} catch (uknownError) {
uknownSignUpFailureDialog(context, uknownError);
}
}
I get the following exception in vscode:
Exception has occurred. PlatformException
(PlatformException(firebase_auth,
com.google.firebase.auth.FirebaseAuthUserCollisionException: The email
address is already in use by another account., {code:
email-already-in-use, additionalData: {}, message: The email address
is already in use by another account.}, null))
I can't understand why the catch line on platform exception does not run
on PlatformException catch (exception) {
signUpFailureDialog(context, exception);
}
The code for the dialog for completion sake:
void signInFailureDialog(BuildContext context, dynamic exception) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(exception.code),
content: Text(exception.message),
backgroundColor: Colors.white,
shape: ContinuousRectangleBorder(borderRadius: BorderRadius.circular(45)),
);
},
);
}
Related
I am building a Flutter/Firebase app with reset password functionality.
For modularity, I keep my auth functions in an AuthService Class.
class AuthService{
final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
// **8** FUNCTION TO RESET PASSWORD
Future<void> resetPassword(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
}
}
// **8**
}
Then I call it in my widget like this:
final auth = Provider.of<AuthService>(context);
...
await auth.resetPassword(email);
When I add a .then method to go to a route when successful, it redirects to the new route even when there is an error. I have tried to add a .catch method but that throws an exception.
How can I go about this?
await auth.resetPassword(email).then((value) =>
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const AndroidRecoverySuccess())));
Thanks.
Return bool value after sendPasswordResetEmail, also your Future should return bool. Here is the working code:
Future<bool> resetPassword(String email) async {
try {
await _auth.sendPasswordResetEmail(email: email);
return true;
} catch (e) {
print(e.toString());
return false;
}
}
(optional) You can use FirebaseAuthException for better UX:
Future<bool> resetPassword(String email) async {
try {
await _auth.sendPasswordResetEmail(email: email);
return true;
} on FirebaseAuthException catch (e) {
if (e.code.toString() == 'invalid-email') {
// setState(() {message 'Invalid email address.';});
}
if (e.code.toString() == 'missing-email') {
//...
}
if (e.code.toString() == 'user-not-found') {
//...
}
} catch (e) {
return false;
}
}
I'm working on authentication part of my flutter project. I want to carryout out exception handling for login when the phone is not connected to internet. The app has 3 auth providers: Phone, GoogleSignIn, and email. The error message is displayed properly for phone signin and email sigin using FirebaseException, which displays the error message. But for GoogleSignIn, if the device is not connected to the internet the code fails at :
final GoogleSignInAccount? googleUser = await googleSignIn.signIn();
Since the execution fails at this point I think FirebaseAuthException doesnt work as it is not supported in googleSignIn.
For which FirebaseAuthException doesnt work, but only "Exception" works.
And i dont get the proper error message using Exception in an alert Dialog.
Code for Email SignIn with exception handling.
Future<void> signInWithEmailAndPassword(
String email,
String password,
void Function(FirebaseAuthException e) errorCallback,
) async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
Error Dialog which gets called in errorCallback(e)
void _showErrorDialog(BuildContext context, String title, Exception e) {
showDialog<void>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(
title,
style: const TextStyle(fontSize: 24),
),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'${(e as dynamic).message}',
style: const TextStyle(fontSize: 18),
),
],
),
),
actions: <Widget>[
ElevatedButton(onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK',
style: TextStyle(color: Colors.deepPurple),
),)
],
);
},
);
}
Exception handling using FirebaseAuthException for email
Exception handling using FirebaseAuthException for email
Google SignIn
Future<void> signInWithGoogle (
void Function(Exception e) errorCallback,
) async {
try{
final GoogleSignInAccount? googleUser = await googleSignIn.signIn();
final GoogleSignInAuthentication? googleAuth = await googleUser!.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth!.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
}
on Exception catch (e) {
print(e);
errorCallback(e);
}
}
Exception handling for google login using Exception instead of FirebaseAuthException
Error printed in console
I/flutter ( 4383): PlatformException(network_error,com.google.android.gms.common.api.ApiException: 7: , null, null)
P.S I just want the proper network error to be displayed in the alert dialog and not " com.google.android.gms.common.api.ApiException: 7"
Update
Since FirebaseAuthException isn't called as execution fails at GoogleSignIn, FirebaseAuthException cannot be used.
While the error printed in log is a PlatformException, we can use PlatformException instead of Exception in the try catch block and check the error code since its supported by PlatformException.
The error code can be compared with GoogleSignIn.kNetworkError and GoogleSignIn.kSignInFailedError.
Future<void> signInWithGoogle (
void Function(String errorMessage) errorCallback,
) async {
try {
final GoogleSignInAccount? googleUser = await googleSignIn.signIn();
final GoogleSignInAuthentication? googleAuth = await googleUser!.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth!.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
}
on PlatformException catch (e) {
if (e.code == GoogleSignIn.kNetworkError) {
String errorMessage = "A network error (such as timeout, interrupted connection or unreachable host) has occurred.";
errorCallback(errorMessage);
} else {
String errorMessage = "Something went wrong.";
errorCallback(errorMessage);
}
}
}
Screenshot
I have the following problem. I want the message to be the correct exception type. i can only use set state within my sign in (because my auth class is not a statlesswidget)class and pass a message there with set state(), but the same for all errors. I've been trying for 9 hours and I can't figure it out. Please help. so I just want the correct exception to be displayed.Something like „The Email adress is badly formated“.the problem is i it dont let me to set the error message be the real error message and i dont know how to fix it
Widget _buildLoginBtn() {
return Container(
padding: EdgeInsets.symmetric(vertical: 25.0),
width: double.infinity,
child: RawMaterialButton(
elevation: 5.0,
padding: EdgeInsets.all(15.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
fillColor: Colors.white,
child: Text(
'LOGIN',
style: TextStyle(
color: Color(0xFF527DAA),
letterSpacing: 1.5,
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
print('valid');
setState(() => loading = false);
dynamic result =
await _auth.signIN(email, password);
if (result == null) {
setState(() => error = 'Check your Input');
loading= false;
}
}
}),
);
}
Future<String> signIN(String email, String password) async {
try {
FirebaseUser user = (await _auth.signInWithEmailAndPassword(
email: email.trim(), password: password)).user;
} catch (e) {
return null;
}
if (user != null) {
print(user);
}
return null;
}
So after im following # Gerpea advice I Get the following error when im just trying to catch the error without the statement on FIREBASEAUTHERROR and when im trying with the statement. When im trying to update my auth and cloud and core it gets me another error.And I can really say if the he ignored the catch block because it don't starts actually when im starting I get as I said before the error in console Im using:
cupertino_icons: ^1.0.2
firebase_auth: ^0.14.0+5
cloud_firestore: ^0.12.9+4
firebase_core_web: ^0.2.1+3
provider: ^4.3.3
flutter_svg: ^0.19.2+1
flutter_spinkit: "^4.1.2"
auto_size_text: ^2.1.0
firebase_core: ^0.4.0
get_it: ^5.0.6
The error ist this:
Invalid depfile: /Users/MYUSERNAME/Desktop/project neu2/flutter_application_2/.dart_tool/flutter_build/7e96e6ced6aa40f9bcd60c2328bbea3e/kernel_snapshot.d
^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3/lib/js.dart:8:1: Error: Not found: 'dart:js'
export 'dart:js' show allowInterop, allowInteropCaptureThis;
^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3/lib/js_util.dart:8:1: Error: Not found: 'dart:js_util'
export 'dart:js_util';
^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/js_interop.dart:24:7: Error: Method not found: 'hasProperty'.
if (util.hasProperty(jsObject, 'toDateString')) {
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:39:26: Error: Method not found: 'getProperty'.
map[key] = dartify(util.getProperty(jsObject, key), customDartify);
^^^^^^^^^^^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:65:17: Error: Method not found: 'newObject'.
var jsMap = util.newObject();
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:67:7: Error: Method not found: 'setProperty'.
util.setProperty(jsMap, key, jsify(value, customJsify));
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:73:12: Error: Method not found: 'allowInterop'.
OKafter trying the second correction that #Gerpea send I get the same error so I decide to update to the newest versions go auth.
No I got some problems but I think that's maybe be easyler to correct
but don't really how maybe you know?
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core_web/firebase_core_web_interop.dart';
import 'package:flutter_application_2/models/user.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
String error;
//create user obj based on FirebasedUser
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(uid: user.uid) : null;
}
//auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
//sign in anon
Future signInAnon() async {
try {
AuthResult result = await _auth.signInAnonymously();
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
//sign in with passwort and email
Future<String> signIN(String email, String password) async {
try {
FirebaseUser user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on FirebaseAuthException catch (e) {
switch(e.code) {
case 'user-not-found': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
}
return null;
}
//register with passwort an email
Future<String> signUp(String email, String password) async {
FirebaseUser user = (await _auth.createUserWithEmailAndPassword(
email: email, password: password)) .user;
try {
await user.sendEmailVerification();
return user.uid;
} catch (e) {
print(e.toString);
return null;
}
}
//sign out
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
//resetpassword
Future<void> sendPasswordResetEmail(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
return null;
}
}
}
that's the exceptions
enter image description here
OK now it logs very good I just have 2 exceptions. Code looks like that:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_application_2/models/user.dart' as Model;
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
String error;
//create user obj based on FirebasedUser
Model.User _userFromFirebaseUser(Model.User user) {
return user != null ? Model.User(uid: user.uid) : null;
}
//auth change user stream
Stream<Model.User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
//sign in anon
Future signInAnon() async {
try {
UserCredential result = await _auth.signInAnonymously();
User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
//sign in with passwort and email
Future<String> signIN(String email, String password) async {
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on FirebaseAuthException catch (e) {
switch(e.code) {
case 'user-not-found': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
}
return null;
}
//register with passwort an email
Future<String> signUp(String email, String password) async {
User user = (await _auth.createUserWithEmailAndPassword(
email: email, password: password)) .user;
try {
await user.sendEmailVerification();
return user.uid;
} catch (e) {
print(e.toString);
return null;
}
}
//sign out
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
//resetpassword
Future<void> sendPasswordResetEmail(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
return null;
}
}
}
And EXCEptions like that:
enter image description here
#Gerpea
So here's my code
Future<String> signUp(String email, String password, String fullname,String user) async {
try {
( await _auth.createUserWithEmailAndPassword(
email: email.trim(), password: password,)).user.sendEmailVerification();
await DatbaseService(uid: user.uid).updateUserData('username', 'fullname', 'Passwort', 'Email');
} on FirebaseAuthException catch (e) {
And the method from YouTube:
Future registerWithEmailAndAPassword(String email, String,Passwort)async {
try{
AuthResult result = await.createUserWithEmailAndPassowrd(email:email,password:password);
FirebaseUser user =result.user;
await DatabaseService(uid:user.uid).updateUserData('0','new crew member',100);
return _userFromFirebaseUser(user);
}catch (e){
signInWithEmailAndPassword() method in case of error will throw a FirebaseAuthException which contain code field with error code.
The full list of errors for this method can be found here.
So you can rewrite you method a bit, to return an error message instead just null.
Future<String> signIN(String email, String password) async {
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on FirebaseAuthException catch (e) {
switch(e.code) {
case 'user-not-found': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
}
return null;
}
Now this method return null if there is no error and String if some error occurs.
Use this in onPressed callback.
onPressed: () async {
if (_formKey.currentState.validate()) {
print('valid');
String authError = await _auth.signIN(email, password);
if (authError != null) {
setState(() => error = authError);
}
setState(() => loading = false);
}
}
firebase_auth: ^0.14.0+5
This is a bit outdated and has some problems, so it will be better if you
will upgrade your dependencies.
But if you can't upgrade. This should work.
Future<String> signIN(String email, String password) async {
try {
FirebaseUser user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on AuthException catch (e) {
switch(e.code) {
case 'ERROR_USER_NOT_FOUND': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
} catch(e) {
return 'Some error that FirebaseAuth do not catch'!;
}
return null;
}
List of error codes can be found here.
I don't know how to handle this exception launched by Firebase.
Exception has occurred.
PlatformException (PlatformException(user-not-found, There is no user record corresponding `to this identifier. The user may have been deleted.,
{code: user-not-found, message: There is no user record corresponding to this identifier. The user may have been deleted.,
nativeErrorMessage: There is no user record corresponding to this identifier. The user may have been deleted., nativeErrorCode: 17011, additionalData: {}}, null)).
This is the code, it comes from "loginWithEmailAndPassword" :
Future<void> submit(
context, FirebaseAuth authF, String email, String password) async {
try {
final userCredential = await authF.signInWithEmailAndPassword(
email: email,
password: password,
);
return;
} on FirebaseException catch (e) {
if (Platform.isIOS) {
LogInCupertinoDialogue(context);
} else {
LogInAndroidDialogue(context);
}
return;
}
}
User doesn't exists, this is what I need to handle.
EDIT : For "handle" I mean that if a non registered user try to login my app crashes. I don't want it! If it should crash just launch the window dialogue.
If I correctly understand your question, the following should do the trick:
} on FirebaseException catch (e) {
if (e.code == 'user-not-found') {
// Display the error message that user doesn't exists
} else {
// Display a more global error message
}
} ...
You can detect the code from the exception details:
PlatformException (PlatformException(user-not-found, There is no user
record corresponding `to this identifier. The user may have been
deleted., {code: user-not-found,...
Note: You'll find in the doc the list of the potential error codes returned by signInWithEmailAndPassword().
you can use exception code to detect different exception then use a dialog for showing it to user here is a simple example:-
Future<User> signin(String email, String password, BuildContext context) async {
await Firebase.initializeApp();
try {
UserCredential result =
await auth.signInWithEmailAndPassword(email: email, password: email);
User user = result.user;
return Future.value(user);
} catch (e) {
print(e.code);
switch (e.code) {
case 'ERROR_INVALID_EMAIL':
showErrDialog(context, e.code);
break;
case 'ERROR_WRONG_PASSWORD':
showErrDialog(context, e.code);
break;
case 'ERROR_USER_NOT_FOUND':
showErrDialog(context, e.code);
break;
case 'ERROR_USER_DISABLED':
showErrDialog(context, e.code);
break;
case 'ERROR_TOO_MANY_REQUESTS':
showErrDialog(context, e.code);
break;
case 'ERROR_OPERATION_NOT_ALLOWED':
showErrDialog(context, e.code);
break;
}
showErrDialog(BuildContext context, String err) {
FocusScope.of(context).requestFocus(new FocusNode());
return showDialog(
context: context,
child: AlertDialog(
title: Text("Error"),
content: Text(err),
actions: <Widget>[
OutlineButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Ok"),
),
],
),
);
}
}
change the platformExeption with FirebaseException
} on FirebaseException catch (err) {
var message = "An error occurred, please check your credential";
if (err.message != null) {
message = err.message;
}
print("error message : $message");
ScaffoldMessenger.of(ctx).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Theme.of(ctx).errorColor,
),
);
I had some troubles with the SignInWithEmailAndPassword Firebase method.
When a non registered user tries to signIn (he should create a new user before) Firebase, rightly, throw an error but the problem is that this error freezes my app so I need to catch it but I don't know why also when I catch the error (or at least I think I caught it) the app freezes so I opened the documentation and found this code :
try {
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "barry.allen#example.com",
password: "SuperSecretPassword!"
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
Well I copy-pasted it to see if the error handling works fine because obviously this call will throw an error but also this freezes my app. The I tried to read the doc and I found that the "Error Handling" section is missing missing doc.
Someone told me that I "need to learn javascript" well ok maybe I'm missing something but also a common error can be hard to solve for who doesn't know it, so I will write my previous code below to show you :
Future<void> submit(
context, FirebaseAuth authF, String email, String password) async {
try {
UserCredential userCredential =
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
} else {
print(e);
}
} catch (e) {
if (Platform.isIOS) {
LogInCupertinoDialogue(context,e);
} else {
LogInAndroidDialogue(context,e);
}
}
}
This function is called by :
Future<void> _submit(Auth auth, FirebaseAuth authF) async {
//Create Artist and send it to the database
if (_validateAndSaveForm()) {
try {
//await submit(context, authF, emailF, password);
submit(context, authF, emailF, password);
//Dovrebbe andare in home page ma per ora va bene così
} catch (e) {
if (Platform.isIOS) {
LogInCupertinoDialogue(context,e);
} else {
LogInAndroidDialogue(context,e);
}
}
}
}
Just use the below code. It has following functions:-
signin()
signUp()
showErrDialog()
FirebaseAuth auth = FirebaseAuth.instance;
final googleSignIn = GoogleSignIn();
Future<User> signin(String email, String password, BuildContext context) async {
await Firebase.initializeApp();
try {
UserCredential result =
await auth.signInWithEmailAndPassword(email: email, password: email);
User user = result.user;
return Future.value(user);
} catch (e) {
print(e.code);
switch (e.code) {
case 'ERROR_INVALID_EMAIL':
showErrDialog(context, e.code);
break;
case 'ERROR_WRONG_PASSWORD':
showErrDialog(context, e.code);
break;
case 'ERROR_USER_NOT_FOUND':
showErrDialog(context, e.code);
break;
case 'ERROR_USER_DISABLED':
showErrDialog(context, e.code);
break;
case 'ERROR_TOO_MANY_REQUESTS':
showErrDialog(context, e.code);
break;
case 'ERROR_OPERATION_NOT_ALLOWED':
showErrDialog(context, e.code);
break;
}
showErrDialog(BuildContext context, String err) {
FocusScope.of(context).requestFocus(new FocusNode());
return showDialog(
context: context,
child: AlertDialog(
title: Text("Error"),
content: Text(err),
actions: <Widget>[
OutlineButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Ok"),
),
],
),
);
}
Future<User> signUp(
String email, String password, String eno, BuildContext context) async {
await Firebase.initializeApp();
try {
UserCredential result = await auth.createUserWithEmailAndPassword(
email: email, password: email);
User user = result.user;
print("user is :" + user.email + " id is :" + user.uid);
return Future.value(user);
} catch (error) {
switch (error.code) {
case 'ERROR_EMAIL_ALREADY_IN_USE':
showErrDialog(context, "Email Already Exists");
break;
case 'ERROR_INVALID_EMAIL':
showErrDialog(context, "Invalid Email Address");
break;
case 'ERROR_WEAK_PASSWORD':
showErrDialog(context, "Please Choose a stronger password");
break;
}
return Future.value(null);
}
}