How to platform exception error flutter 2020 - firebase

I am trying to get to get a dialog pop to indicate to the user that the email already exists, but I keep getting this error an the dialog pop doesn't show, have gone through similar solution but none seem to work any help will be appreciated
Exception has occurred.
FirebaseAuthException ([firebase_auth/email-already-in-use] The email address is already in use by another account.)
Below is my authentication code
void registerToFb() {
firebaseAuth
.createUserWithEmailAndPassword(
email: emailController.text, password: passwordController.text)
.then((result) {
dbRef.child(result.user.uid).set({
"email": emailController.text,
"age": ageController.text,
"name": nameController.text
}).then((res) {
isLoading = false;
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home(uid: result.user.uid)),
);
});
}).catchError((err) {
print(err);
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();
},
)
],
);
});
});
}

I've not checked the latest docs but I think the error codes have changed. First check by printing what's inside err.message. I read somewhere this changed to err.code!

Related

How to fix login issue? Flutter - Firebase

Here is what I'm doing in my code.
ReusableButton(
title: "Login",
color: Colors.white,
onPress: () async {
try {
final user = await _auth.signInWithEmailAndPassword(
email: myEmailController.text,
password: myPasswordController.text,
);
if (user != null) {
await Navigator.pushNamed(context, AllTasks.id);
}
} catch (e) {
String newString = e.toString().split("]").removeLast();
setState(() {
showDialog(
context: context,
builder: (value) => AlertDialog(
title: Text(
"Wrong Information",
style: kNormalTextStyle,
),
content: Text(
newString,
),
actions: [
FlatButton(
onPressed: () {
Navigator.of(value).pop();
},
child: Text(
"Close",
style: kNormalTextStyle,
))
],
));
});
}
},
),
I'm trying to login and after that pushin the page to another page. However this login part is a little bit slow so I get an error like this:
I'm assuming this is about the connection speed with firebase but is there a solution to solve this? Btw, when I reload the code, it starts working.
Here is my AllTasks code block:
https://github.com/sonelektrikci/task_manager_app_flutter/blob/main/task_management_app_flutter/lib/screens/all_tasks.dart
I'm pushing the page to here when user logs in.
This is most likely causing your issue:
.where('email', isEqualTo: loggedInUser!.email)
How are you asserting that the user is indeed logged in and promising your compiler that an email is retrievable? This is the explanation of your error.
Refactor your code, in a way to not make it into this block, unless loggedInUser is not null.

Writing to Firebase Realtime Database with Flutter

I've perused the forums, google, and youtube for info on writing data to a real-time database with flutter and haven't found a proper guide for even the most basic write.
That being said, in my app, I am currently trying to save the user's email to the database as a child of the user's new id. I am attempting to do this immediately after calling .createUserWithEmailAndPassword. This all should occur on click of a Material Button. I previously had the write inside of the then statement, but that was giving me an error.
Code:
FirebaseAuth userAuth = FirebaseAuth.instance;
void saveEmailInDb(String userId, String email) {
final userRef = FirebaseDatabase.instance.reference();
userRef.child(userId).child("Email").push().set(email);
}
//inside of the build widget
MaterialButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32),
),
color: colorPalette.chooseColor('yellow'),
child: Container(
padding: EdgeInsets.all(13),
child: Text(
'Register',
style: GoogleFonts.ubuntu(
color: colorPalette.chooseColor('darkGrey'),
fontSize: 17),
),
),
onPressed: () async {
try {
UserCredential userCredential = await userAuth
.createUserWithEmailAndPassword(
email: tecEmail.text,
password: tecPassword.text)
.then(
(value) => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoadingPage(),
),
),
);
saveEmailInDb(
userCredential.user.uid, tecEmail.text);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
},
),
I have instantiated firebase in the main widget:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
GetMaterialApp(
home: LoadingPage(),
),
);
}
Now, I know that flutter is hooked up properly to my app because an account is created in the firebase console under authentication. However, nothing is written to the database and as there are no proper guides or official documentation, I am unsure how to proceed.
Database Rules:
{
"rules": {
".read": true,
".write": true
}
}
Answer: Moving the navigation code outside of the then statement, and below the database write, was sufficient to solve this problem. Basically, the navigation was poping the widget before the database code was called. Revised code below:
MaterialButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32),
),
color: colorPalette.chooseColor('yellow'),
child: Container(
padding: EdgeInsets.all(13),
child: Text(
'Register',
style: GoogleFonts.ubuntu(
color: colorPalette.chooseColor('darkGrey'),
fontSize: 17),
),
),
onPressed: () async {
try {
UserCredential userCredential =
await userAuth.createUserWithEmailAndPassword(
email: tecEmail.text,
password: tecPassword.text);
saveEmailInDb(userCredential.user.uid, tecEmail.text);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoadingPage(),
),
);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
},
),

Flutter FirebaseAuth not sending verification code to phone

I'm trying to add a feature on my app that allows users to verify their phone number by sending a code to their phone numbers. I found that I can do that by using firebase. This is how I send verification code:
Future<void> verifyPhone() async {
void verificationCompleted(AuthCredential phoneAuthCredential) {
print('verificationCompleted $phoneAuthCredential');
_phoneAuthCredential = phoneAuthCredential;
_db.updateUserField(userUid, {
'isNumberConfirmed': true,
'linkedAccounts': FieldValue.arrayUnion(['P-$phoneAuthCredential'])
});
currentUser.isNumberConfirmed = true;
currentUser.linkedAccounts.add('P-$phoneAuthCredential');
worked = true;
}
void verificationFailed(FirebaseAuthException error) {
worked = false;
}
void codeSent(String verificationId, [int code]) {
_code = code;
_verificationId = verificationId;
print('Code: $code\t_verificationId: $_verificationId');
}
void codeAutoRetrievalTimeout(String verificationId) {
worked = false;
}
_auth.verifyPhoneNumber(
phoneNumber: '+1${currentUser.phone}',
timeout: Duration(milliseconds: 60000),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
}
but whenever this method get called, I get the following messages and no verification code is sent:
I/BiChannelGoogleApi(25924): [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzao#bafccce
W/DynamiteModule(25924): Local module descriptor class for com.google.firebase.auth not found.
I/FirebaseAuth(25924): [FirebaseAuth:] Preparing to create service connection to gms implementation
I'm not sure why it is not sending the code. Am I missing something?
I find your code hard to debug so I am sharing this :
First make sure you have enabled phone sign in method in firebase console ,
and added Firebase Authentication plugin and Firebase core plugin in pubspec.yaml
define your verify phone number button like this :
onPressed: (){
//code for sign in
final mobile = _phoneTextBoxController.text.trim();
registerUser(mobile, context);
}
Now define whole verifying process like this :
Future registerUser(String mobile, BuildContext context) async{
FirebaseAuth _auth = FirebaseAuth.instance;
_auth.verifyPhoneNumber(
phoneNumber: mobile,
timeout: Duration(seconds: 60),
verificationCompleted: (AuthCredential authCredential){
_auth.signInWithCredential(_credential).then((AuthResult result){
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => HomeScreen(result.user)
));
}).catchError((e){
print(e);
});
},
verificationFailed: (AuthException authException){
print(authException.message);
},
codeSent:(String verificationId, [int forceResendingToken]){
//show dialog to take input from the user
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text("Enter SMS Code"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
TextField(
controller: _codeController,
),
],
),
actions: <Widget>[
FlatButton(
child: Text("Done"),
textColor: Colors.white,
color: Colors.redAccent,
onPressed: () {
FirebaseAuth auth = FirebaseAuth.instance;
smsCode = _codeController.text.trim();
_credential = PhoneAuthProvider.getCredential(verificationId: verificationId, smsCode: smsCode);
auth.signInWithCredential(_credential).then((AuthResult result){
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => HomeScreen(result.user)
));
}).catchError((e){
print(e);
});
},
)
],
)
);
},
codeAutoRetrievalTimeout: (String verificationId){
verificationId = verificationId;
print(verificationId);
print("Timout");
}
);
So what above code does ? First it sends the OTP code to user and try to sign in using this code :
verificationCompleted: (AuthCredential authCredential){
_auth.signInWithCredential(_credential).then((AuthResult result){
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => HomeScreen(result.user)
));
}).catchError((e){
print(e);
});
},
and pushes user to the home screen , you can change above code accordingly to match your app home screen . If auto retrieval fails then the codeSent : shows user a showDialog to manually enter the code . For more information visit this medium article and for complete code visit this github repository

How to call a function ASA the app runs in flutter?

I have an application that do login with the help of firestore database and I want to do autologin so I made a boolean and set it to false in the database and made the login function set it to true as he or she sign in, so I want to check if the person have already signed in or not as the app runs, any ideas :) ?
here my code:
void getUserData() async {
try {
var firebaseUser = await FirebaseAuth.instance.currentUser();
firestoreInstance
.collection("Students")
.document(usernameController.text)
.get()
.then((value) {
setState(() {
email = (value.data)['email'];
password = (value.data)['password'];
gender = (value.data)['gender'];
loggedin = (value.data)['token'];
});
});
} catch (e) {
print(e.toString);
}
}
You dont have to use a boolean to check if the user is logged in or not. Firebase authentication already offers that. You can check inside the initState:
#override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((res) {
print(res);
if (res != null) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home(uid: res.uid)),
);
}
else
{
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SignUp()),
);
}
});
}
Checks if there is a current user or not and navigates to the required page.
If you have different types of users, then you have to identify them in the database. So authenticate in firebase authentication, and use a userType field in the database:
void registerToFb() {
firebaseAuth
.createUserWithEmailAndPassword(
email: emailController.text, password: passwordController.text)
.then((result) {
firestoreInstance.collection("users").document(result.user.uid).setData({
"email": emailController.text,
"name": nameController.text,
"userType" : "Students"
}).then((res) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home(uid: result.user.uid)),
);
});
}).catchError((err) {
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();
},
)
],
);
});
});
}

Flutter user registration storing data

I'm new to flutter. I need some help with Registering users with my app. I'm using Firebase authentication just to get the email and I need to save the details of the users in a database. I'm trying with cloud firestore, but I'm feeling like its not the best ideal option. And when login I want verify if the user is registered or not
you can use this code for registration user in Cloud Firestore
final FirebaseAuth _auth = FirebaseAuth.instance;
_auth
.createUserWithEmailAndPassword(
email: _myEmail, password: _myPassword)
.catchError((e) {
showDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: Text('Error Occured'),
content: Text(e.toString()),
actions: <Widget>[
CupertinoButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop())
],
);
});
FirebaseAuth.instance
.signInWithEmailAndPassword(email: _myEmail, password: _myPassword)
.catchError((e) {
showDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: Text('Error Occured'),
content: Text(e.toString()),
actions: <Widget>[
CupertinoButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop())
],
);
});

Resources