Check if phone exists before signup/signin - Flutter Phone Authentication [duplicate] - firebase

This question already exists:
Firebase Authentication using Phone number (Error: Missing Session Info)
Closed 2 years ago.
I want to check if phone exists before signing in or signing up a user. With email registration, I used the following and I was able to tell if an email exists or not.
final url =
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/$verifyPassword?key={API_KEY}';
Similarly, for phone numbers, I used the following:
final url ='https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPhoneNumber?key={API_KEY}';
final response = await http.post(
url,
body: json.encode(
{
'phoneNumber': number
},
),
);
However, I am getting the following error message:
Extracted data is {error: {code: 400, message: MISSING_SESSION_INFO, errors: [{message: MISSING_SESSION_INFO, domain: global, reason: invalid}]}}
I want to know why does it work for email but not for phone registration?
Also, is this the right way to check if a phone exists?
Here's my full code:
enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }
class AuthProvider with ChangeNotifier {
FirebaseAuth _auth = FirebaseAuth.instance;
User _user;
Status _status = Status.Uninitialized;
TextEditingController phoneNo;
String smsOTP;
String verificationId;
String errorMessage = '';
bool logedIn = false;
bool loading = false;
Status get status => _status;
TextEditingController address = TextEditingController();
AuthProvider.initialize() {
readPrefs();
}
Future signOut() async {
_auth.signOut();
_status = Status.Unauthenticated;
notifyListeners();
return Future.delayed(Duration.zero);
}
Future<void> readPrefs() async {
await Future.delayed(Duration(seconds: 3)).then((v) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
logedIn = prefs.getBool('logedIn') ?? false;
if (!logedIn) {
print('User is not logged in');
_status = Status.Unauthenticated;
} else {
print('User is logged in');
_user = _auth.currentUser;
_status = Status.Authenticated;
}
notifyListeners();
});
}
Future<void> verifyPhone(BuildContext context, String number,String password) async {
//To be used in the verifyPhone method
final PhoneCodeSent smsOTPSent = (String verId, [int forceCodeResend]) {
this.verificationId = verId;
smsOTPDialog(context, number,password).then((value) {
_status = Status.Authenticated;
});
};
try {
await _auth.verifyPhoneNumber(
phoneNumber: number.trim(),
codeAutoRetrievalTimeout: (String verId) {
//Starts the phone number verification process for the given phone number.
//Either sends an SMS with a 6 digit code to the phone number specified, or sign's the user in and [verificationCompleted] is called.
this.verificationId = verId;
},
codeSent: smsOTPSent,
// timeout: const Duration(seconds: 20),
//If user is automatically verified (without having to type the code)
verificationCompleted: (AuthCredential credential) async {
Navigator.of(context).pop();
UserCredential result =
await _auth.signInWithCredential(credential);
User user = result.user;
if (user != null) {
//TO DO:// Here you need to save the phone and password to DB
print('Adding user to DB');
final url = 'https://mobile-12.firebaseio.com/users/$number.json';
try {
await http.post(
url,
body: json.encode({
'password': password,
'phoneNumber':user.phoneNumber,
}),
);
_status = Status.Authenticated;
} catch (error) {
print(error);
}
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(
)));
} else {
print("Error");
}
},
verificationFailed: (FirebaseAuthException exceptio) {
print('${exceptio.message} + something is wrong');
});
} catch (e) {
handleError(e, context,number,password);
errorMessage = e.toString();
notifyListeners();
}
notifyListeners();
}
Future<bool> smsOTPDialog(BuildContext context,String number,String password) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Enter SMS Code'),
content: Container(
height: 85,
child: Column(children: [
TextField(
onChanged: (value) {
this.smsOTP = value;
},
),
(errorMessage != ''
? Text(
errorMessage,
style: TextStyle(color: Colors.red),
)
: Container())
]),
),
contentPadding: EdgeInsets.all(10),
actions: <Widget>[
FlatButton(
child: Text("Confirm"),
textColor: Colors.white,
color: Colors.blue,
onPressed: () async {
final code = this.smsOTP.trim();
AuthCredential credential = PhoneAuthProvider.credential(
verificationId: verificationId, smsCode: code);
UserCredential result =
await _auth.signInWithCredential(credential);
User user = result.user;
if (user != null) {
print('user already exist');
// //TO DO:// Save the phone number and password to DB
print('Adding user to Db in the manual OTP route');
final url = 'https://mobile-12.firebaseio.com/users/$number.json';
try {
await http.post(
url,
body: json.encode({
'password': password,
'phoneNumber':user.phoneNumber,
}),
);
} catch (error) {
print('INSIDE ERROR');
print(error);
}
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("logedIn", true);
logedIn = true;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(
)));
loading = false;
notifyListeners();
} else {
print("No OTP was added");
loading = true;
notifyListeners();
Navigator.of(context).pop();
}
},
)
],
);
});
}
//Sign-In Method checks to see if a phone exists.
signIn(BuildContext context, String number, String password,AuthMode authMode) async {
try {
//Check to see if the phone number is available
final url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPhoneNumber?key=';
final response = await http.post(
url,
body: json.encode(
{
'phoneNumber': number
},
),
);
final extractedData = json.decode(response.body) as Map<String, dynamic>;
print('Extracted data is ' + extractedData.toString());
//Register and send OTP if new user
if (extractedData == null && authMode == AuthMode.Signup) {
print('Inside NULL no errors');
// //Verify phone
verifyPhone(context, number, password);
}
//If tries to login but phone not available
else if(extractedData == null && authMode == AuthMode.Login)
{
_showErrorDialog('Phone number does not exist. Please Sign Up', context);
}
else if (extractedData['error'] != null) {
_showErrorDialog('Something went wrong! Please try again!', context);
}
//If someone signup but their phone already exist
else if(extractedData != null && authMode == AuthMode.Signup)
{
_showErrorDialog('Your phone already exists. Please Login!', context);
}
//If available, proceed to homepage
else {
print('User found');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(
)));
}
} catch (e) {
handleError(e, context,number,password);
}
}
handleError(error, BuildContext context,String number,String password) {
errorMessage = error.toString();
print('ERROR IS ' + errorMessage);
notifyListeners();
}
Future<bool> _showErrorDialog(String message,BuildContext context) {
return showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('An Error Occurred!'),
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text('Okay'),
onPressed: () {
Navigator.of(ctx).pop();
},
)
],
),
);
}
}

Related

When the user trying to login, it doesn't stores their data in firestore, When I click Confirm location button it showing following error

class AuthProvider with ChangeNotifier {
FirebaseAuth _auth = FirebaseAuth.instance;
String smsOtp;
String verificationId;
String error ='';
UserServices _userServices = UserServices();
bool loading = false;
LocationProvider locationData = LocationProvider();
String screen;
double latitude;
double longitude;
String address;
Future<void> verifyPhone({BuildContext context, String number}) async {
this.loading=true;
notifyListeners();
final PhoneVerificationCompleted verificationCompleted =
(PhoneAuthCredential credential) async {
this.loading=false;
notifyListeners();
await _auth.signInWithCredential(credential);
};
final PhoneVerificationFailed verificationFailed =
(FirebaseAuthException e) {
this.loading=false;
print(e.code);
this.error=e.toString();
notifyListeners();
};
final PhoneCodeSent smsOtpSend = (String verId, int resendToken) async {
this.verificationId = verId;
};
//open dialog to enter received OTP sms
smsOtpDialog(context, number);
try {
_auth.verifyPhoneNumber(
phoneNumber: number,
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: smsOtpSend,
codeAutoRetrievalTimeout: (String verId){
this.verificationId = verId;
},
);
} catch (e) {
this.error=e.toString();
this.loading=false;
notifyListeners();
print(e);
}
}
Future<bool> smsOtpDialog(BuildContext context, String number) {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Column(
children: [
Text('Verification Code'),
SizedBox(height: 6,),
Text('Enter 6 digits OTP received via SMS',
style: TextStyle(color: Colors.grey,fontSize: 12),
),
],
),
content: Container(
height: 85,
child: TextField(
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
maxLength: 6,
onChanged: (value){
this.smsOtp = value;
},
),
),
actions: [
FlatButton(
onPressed: ()async{
try{
PhoneAuthCredential phoneAuthCredential =
PhoneAuthProvider.credential(
verificationId: verificationId, smsCode: smsOtp);
final User user = (await _auth.signInWithCredential(phoneAuthCredential)).user;
if(user!=null){
this.loading=false;
notifyListeners();
_userServices.getUserById(user.uid).then((snapShot){
if(snapShot.exists){
//user data already exists
if(this.screen=='Login'){
//need to check user data already exists in database or not
//if its login,no new data, so no need to update
Navigator.pushReplacementNamed(context, HomeScreen.id);
}else{
//need to update new selected address
print('${locationData.latitude} : ${locationData.longitude}');
updateUser(id: user.uid, number: user.phoneNumber);
Navigator.pushReplacementNamed(context, HomeScreen.id);
}
}else{
//user data doesn't exists
//will create new data in db
_createUser(id: user.uid, number: user.phoneNumber);
Navigator.pushReplacementNamed(context, HomeScreen.id);
}
});
}else
{
print('Login Failed');
}
} catch(e){
this.error = 'Invalid OTP';
notifyListeners();
print(e.toString());
Navigator.of(context).pop();
}
},
child: Text('SUBMIT',style: TextStyle(color: Theme.of(context).primaryColor),),
),
],
);
}).whenComplete(() {
this.loading=false;
notifyListeners();
});
}
void _createUser({String id, String number} ) {
_userServices.createUserData({
'id':id,
'number':number,
'latitude':this.latitude,
'longitude':this.longitude,
'address':this.address
});
this.loading=false;
notifyListeners();
}
Future <bool> updateUser({String id, String number,} ) async{
try{
_userServices.updateUserData({
'id':id,
'number':number,
'latitude':this.latitude,
'longitude':this.longitude,
'address':this.address
});
this.loading=false;
notifyListeners();
return true;
}catch(e){
print('Error $e');
return false;
}
}
}
======== Exception caught by gesture ===============================================================
The following NoSuchMethodError was thrown while handling a gesture:
The getter 'uid' was called on null.
Receiver: null
Tried calling: uid
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 _MapScreenState.build. (package:flutter_hasho_user/screens/map_screen.dart:146:44)
#2 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:993:19)
#3 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:1111:38)
#4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:183:24)
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#3d7f8
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(184.2, 647.6)
finalLocalPosition: Offset(164.2, 15.6)
button: 1
sent tap down
====================================================================================================
I am pretty sure your issue is calling .uid on a user in your else block when the user is null, which throws an error. You should make sure that the user class is initialized or something similar atleast.
else{
_createUser(id: user.uid, number: user.phoneNumber); // [user] is null
Navigator.pushReplacementNamed(context, HomeScreen.id);
}

How to show alert on firebase auth errors flutter

I want to show an alert dialog when there is an error in the firebase auth.
Firebase already prints the error in the UI but i want to show a dialog to the user.
Heres my createUser and signInUser Funtion and my signup button function
Future registerWithEmailAndPassword({String email,password,username,image,phoneNumber}) async {
try {
UserCredential userCredential = await _firebaseAuth
.createUserWithEmailAndPassword(
email: email,
password: password,
);
} 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);
}
}
Future signInWithEmailAndPassword({String email, String password}) async {
try {
UserCredential userCredential = await _firebaseAuth
.signInWithEmailAndPassword(
email: email,
password: password
);
User user = userCredential.user;
assert(user.uid != null);
email = user.email;
} 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.');
}
}
}
press: () {
if (formKey.currentState.validate()) {
formKey.currentState.save();
context
.read<Authentication>()
.signInWithEmailAndPassword(
email: emailController.text,
password: passwordController.text)
.whenComplete(() => Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
HomeScreen())));
}
},
You can set up an AlertDialog widget similar to this. The Yes/No buttons are probably overkill in your situation and if so, just convert to an ok button and then you don't have to check the return result.
Future<String> showYesNoAlertDialog({
#required BuildContext context,
#required String titleText,
#required String messageText,
}) async {
// set up the buttons
final Widget yesButton = FlatButton(
onPressed: () => Navigator.pop(context, 'yes'),
child: const Text('Yes'),
);
final Widget noButton = FlatButton(
onPressed: () => Navigator.pop(context, 'no'),
child: const Text('No'),
);
// set up the AlertDialog
final alert = AlertDialog(
title: Text(titleText),
content: Text(messageText),
actions: [
yesButton,
noButton,
],
);
// show the dialog
return showDialog(
context: context,
builder: (context) => alert,
);
}
Then where you have your print statements outputting the errors, you'd call the above widget like this
final dr = await showYesNoAlertDialog(
context: context,
titleText: 'Authentication Error',
messageText:
'There has been an error during authentication. Would you like to retry?',
);
if (dr == 'yes') {
// Yes button clicked
}
else {
// No button clicked
}

How to edit a user in flutter firestore

I have been learning how does flutter work with firestore and now I am working in user auth with password, email and username, when a user is created the email and password are saved with an uid but the username and the email(again) are saved in firestore with a different uid, by the way I have tried a lot of things to make it have the same id but I currently cant find the way. in addition to this, there is also a function that is supposed to edit the username and save those changes. The problem comes when trying to implement the edit functinality because the edit form doesnt return anything as an output except the loading screen, I think this error is happening because of the uids. How can I fix this problem?
models/user.dart
class CustomUser {
final String uid;
CustomUser({this.uid});
}
class UserData {
final String uid;
final String name;
UserData({this.uid, this.name});
}
models/username.dart
class Username {
final String name;
Username({this.name});
}
services/auth.dart
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// create user obj based on fb user
CustomUser _userFromFirebaseUser(User user) {
return user != null ? CustomUser(uid: user.uid) : null;
}
Stream<CustomUser> get user {
return _auth.authStateChanges().map(_userFromFirebaseUser);
}
//signin email password
Future signInWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
//signup
Future registerWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
//signout
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
services/database.dart
class DatabaseService {
final String uid;
DatabaseService({this.uid});
final CollectionReference userCollection = FirebaseFirestore.instance.collection('usernames');
Future updateUserData(String name) async { // this is the function that has to edit the username
return await userCollection.doc(uid).set({
'name': name,
});
}
Future uploadUserInfo(userMap) async { // this function adds username and email to firestore
return await userCollection.doc(uid).set(userMap);
}
List<Username> _usernameListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc) {
return Username(
name: doc.data()['name'] ?? '',
);
}).toList();
}
// userData from snapshot
UserData _userDataFromSnapshot(DocumentSnapshot snapshot) {
return UserData(
uid: uid,
name: snapshot.data()['name'],
);
}
Stream<List<Username>> get usernames {
return userCollection.snapshots().map(_usernameListFromSnapshot);
}
Stream<UserData> get userData {
return userCollection.doc(uid).snapshots().map(_userDataFromSnapshot);
}
}
register.dart(code that registers the user with a username)
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
dynamic result = await _auth.registerWithEmailAndPassword(email, password).then((val) {
Map<String, String> userInfoMap = {
"name": name,
"email": email,
};
databaseService.uploadUserInfo(userInfoMap);
});
if (result == null) {
setState(() {
error = 'please suply a valid email';
loading = false;
});
}
}
}),
editForm.dart
final _formKey = GlobalKey<FormState>();
String _currentName;
final user = Provider.of<CustomUser>(context);
StreamBuilder<UserData>(
stream: DatabaseService(uid: user.uid).userData,
builder: (context, snapshot) {
if (snapshot.hasData) {
UserData userData = snapshot.data;
return Form(
key: _formKey,
child: Column(
children: <Widget>[
Text('edit username!'),
SizedBox(
height: 30,
),
TextFormField(
// initialValue: userData.user gives a initial text to the input
validator: (val) => val.isEmpty ? 'Please enter a name' : null,
onChanged: (val) => setState(() => _currentName = val),
),
RaisedButton(
child: Text('Save'),
onPressed: () async {
if (_formKey.currentState.validate()) {
print('update if good');
await DatabaseService(uid: user.uid).updateUserData(
_currentName ?? userData.name,
);
}
Navigator.pop(context);
})
],
));
} else {
return Loading();
}
},
);
If you have any questions please let me know;)
In your register.dart, the registerWithEmailAndPassword method returns a User object which contains the uid internally created by FirebaseAuth however, it doesn't seem like you took used this uid to update your Firestore user document. I've implemented a sample of what should have been done below.
dynamic result = await _auth.registerWithEmailAndPassword(email, password).then((val) {
Map<String, String> userInfoMap = {
"name": name,
"email": email,
};
DatabaseService(uid: val.uid).uploadUserInfo(userInfoMap);
});
I just realized that your registerWithEmailAndPassword function returns a CustomUser instead of a Firebase User. I just modified it to make it work.
//signup
Future<User> registerWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
return result.user;
} catch (e) {
print(e.toString());
return null;
}
}
//editFrom.dart
//form validation function
Map<String, String> userMap = {'name': currentName};
await DatabaseService(uid: user.uid).uploadUserInfo(userMap);
Side note: when working with Futures, it helps if you specify the expected return type as this will help you with debugging. I've done it for the function above

i can't update my product using fire base db in flutter

Error Message
W/NetworkRequest( 5093): no auth token for request
W/StorageUtil( 5093): no auth token for request
W/NetworkRequest( 5093): no auth token for request
E/flutter ( 5093): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Failed assertion: boolean expression must not be null
Here is my Update Code
Future<bool> updateProduct(String title, String description, File image,
double price, LocationData locData) async {
_isLoading = true;
notifyListeners();
String imgUrl;
print("section one");
final StorageReference storage = FirebaseStorage.instance.ref();
//final FirebaseReference reference=FirebaseRe
final String picture1 = "1${DateTime.now().millisecondsSinceEpoch.toString()}.jpg";
StorageUploadTask task1 = storage.child(picture1).putFile(image);
StorageTaskSnapshot snapshot1 =
await task1.onComplete.then((snapshot) => snapshot);
print("section tow");
task1.onComplete.then((snapshot) async {
imgUrl = await snapshot.ref.getDownloadURL();
print("URL printed");
print(imgUrl);
final Map<String, dynamic> updateData = {
'title': title,
'description': description,
'image': imgUrl,
'price': price,
'loc_lat': locData.latitude,
'loc_lng': locData.longitude,
'loc_address': locData.address,
'userEmail': selectedProduct.userEmail,
'userId': selectedProduct.userId
};
try {
final res= await http.put(
'https://statemarket-337e3.firebaseio.com/products/${selectedProduct.id}.json?auth=${_authenticatedUser.token}',
body: json.encode(updateData));
if(res.statusCode==200){
Fluttertoast.showToast(msg: "updated");
}else{
Fluttertoast.showToast(msg: "Error Found"+res.statusCode.toString());
}
_isLoading = false;
final Product updatedProduct = Product(
id: selectedProduct.id,
title: title,
description: description,
image: imgUrl,
price: price,
location: locData,
userEmail: selectedProduct.userEmail,
userId: selectedProduct.userId);
_products[selectedProductIndex] = updatedProduct;
notifyListeners();
return true;
} catch (error) {
_isLoading = false;
notifyListeners();
return false;
}
});
}
Here Is my Product code where i am call my function
void _submitForm(
Function addProduct, Function updateProduct, Function setSelectedProduct,
[int selectedProductIndex]) {
if (!_formKey.currentState.validate() || (_formData['image'] == null && selectedProductIndex == -1)) {
return;
}
_formKey.currentState.save();
if (selectedProductIndex == -1) {
addProduct(
_titleTextController.text,
_descriptionTextController.text,
_formData['image'],
_formData['price'],
_formData['location']).then((bool success) {
if (success) {
Navigator
.pushReplacementNamed(context, '/products')
.then((_) => setSelectedProduct(null));
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Something went wrong'),
content: Text('Please try again!'),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Okay'),
)
],
);
});
}
});
} else {
updateProduct(
_titleTextController.text,
_descriptionTextController.text,
_formData['image'],
_formData['price'],
_formData['location'],
).then((_) => Navigator
.pushReplacementNamed(context, '/products')
.then((_) => setSelectedProduct(null)));
}
}
Any solution for solve this problem ?

Flutter : how to fix Lost connection to device error with firebase PhoneNumberAuth

I am implementing phoneNumberAuth signup. But there's a problem
When i clicked authbottom, terminated iOS app
code :
String smsCode, verificationId;
Future<void> verifyPhone() async {
final PhoneCodeAutoRetrievalTimeout autoRetrieve = (String verId) {
this.verificationId = verId;
};
final PhoneCodeSent smsCodeSent = (String verId, [int forceCodeResend]) {
this.verificationId = verId;
print('asd');
smsCodeDialog(context).then((value) {
print('Signed in');
});
};
final PhoneVerificationCompleted verificationCompleted = (AuthCredential credential) {
print('verified');
};
final PhoneVerificationFailed verfiFailed = (AuthException exception) {
print('${exception.message}+ddddddddddd');
};
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: this.phoneNo,
timeout: const Duration(seconds: 5),
verificationCompleted: verificationCompleted,
verificationFailed: verfiFailed,
codeSent: smsCodeSent,
codeAutoRetrievalTimeout: autoRetrieve,
);
}
Future<bool> smsCodeDialog(BuildContext context) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('SMS 코드를 입력해주세요'),
content: TextField(
onChanged: (value) {
this.smsCode = value;
},
),
contentPadding: EdgeInsets.all(10),
actions: <Widget>[
FlatButton(
child: Text('Done'),
onPressed: () {
FirebaseAuth.instance.currentUser().then((user) {
if (user != null) {
Navigator.of(context).pop();
Navigator.of(context).pushReplacementNamed('/');
} else {
Navigator.of(context).pop();
SIGNIn();
}
});
},
)
],
);
});
}
SIGNIn() async{
final AuthCredential credential = PhoneAuthProvider.getCredential(
verificationId: verificationId,
smsCode: smsCode,
);
print('진행중');
FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseUser user = (await _auth.signInWithCredential(credential)).user;
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
setState(() {
if(user != null){
print('success!');
}else{
print('sign in failed');
}
});
}
error code :
*** First throw call stack:
(
0 CoreFoundation 0x00000001169bb8db __exceptionPreprocess + 331
1 libobjc.A.dylib 0x0000000115f66ac5 objc_exception_throw + 48
2 CoreFoundation 0x00000001169d9c94 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x00000001169c0623 ___forwarding___ + 1443
4 CoreFoundation 0x00000001169c2418 _CF_forwarding_prep_0 + 120
5 Runner 0x000000010e97d966 -[FIRPhoneAuthProvider internalVerifyPhoneNumber:UIDelegate:completion:] + 118
6 Runner 0x000000010e97ccc0 __64-[FIRPhoneAuthProvider verifyPhoneNumber:UIDelegate:completion:]_block_invoke + 272
7 libdispatch.dylib 0x0000000115e16ccf _dispatch_call_block_an<…>
Lost connection to device.
How can i do fix my code ?
Until someone helped me, i trying doing fix
It's hard because there aren't many explain errors.
I'd appreciate it if someone would help me.
Somebody Help me :(
pop removes the top level widget. Not sure its a good idea to put logic after that. Better you re-arrange your code like
// Only gets SMS, no functionality
Future<String> getSmsCode(BuildContext context) {
return showDialog<String>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('SMS 코드를 입력해주세요'),
content: TextField(
onChanged: (value) {
this.smsCode = value;
},
),
contentPadding: EdgeInsets.all(10),
actions: <Widget>[
FlatButton(
child: Text('Done'),
onPressed: () {
Navigator.of(context).pop(this.smsCode);
},
)
],
);
},
);
}
SIGNIn() async {
String smsCode = await getSmsCode(context);
if (smsCode != null && !smsCode.isNotEmpty) {
print('User cancelled SMS dialog');
return;
}
final AuthCredential credential = PhoneAuthProvider.getCredential(
verificationId: verificationId,
smsCode: smsCode,
);
print('진행중');
FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseUser user = (await _auth.signInWithCredential(credential)).user;
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
setState(() {
if (user != null) {
print('success!');
} else {
print('sign in failed');
}
});
}
Now only invoke SIGNIn, it will first get SMS code then signin using that SMS code. Hope it helps.

Resources