Flutter Firebase: (!snapShot.exists) is not working - firebase

I'm using a Google Auth Sign in after the user signs in a Method initalize(); runs and states wether the user is a new user or existed user. but its always detecting a user as new user and resetting the data to default.
Google Login :
Future googleLogin() async {
try {
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);
initalize(); //<--------------The problem
} catch (e) {
print(e.toString());
}
notifyListeners();
}
Initialize() method:
initalize() async {
var user = FirebaseAuth.instance.currentUser!;
final snapShot = await FirebaseFirestore.instance
.collection('expenses')
.doc(user.uid)
.get();
if (!snapShot.exists) {
print(snapShot);
await SetTransaction(
uid: user.uid,
t_name: 't_name',
t_amt: '0',
isIncome: true,
Category: 'Any');
}
else{print('Yesss siirrr');}
}
Extra code
The google login happens here:
return Scaffold(
resizeToAvoidBottomInset:false,
backgroundColor: const Color(0xffedf1f4),
body: StreamBuilder(
stream:FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot){
if(snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasData){
return LoggedInWidget();
}
else if (snapshot.hasError) {
return Center(child: Text('Something Went Wrong!'));
}else {
return SignUpWidget();
}
},
),
);
Button inside SignUpWidget(); class which helps to login:
GestureDetector(
onTap: () { //<------this happens on click of the button
print("Clicked");
final provider = Provider.of<GoogleSignInProvider>(
context,
listen: false);
provider.googleLogin();
},
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FaIcon(FontAwesomeIcons.google),
Text("Sign Up with Google")
],
),
padding: EdgeInsets.only(
left: 20, right: 20, top: 15, bottom: 15),
margin: EdgeInsets.symmetric(horizontal: 70.0),
decoration: BoxDecoration(
color: Color(0xffedf1f4),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey.shade600,
offset: Offset(5, 5),
blurRadius: 5,
spreadRadius: 1),
BoxShadow(
color: Colors.white,
offset: Offset(-5, -5),
blurRadius: 5,
spreadRadius: 1,
)
],
),
),
),

googleLogin is a future method, it needs to await
GestureDetector(
onTap: () async{
...
await provider.googleLogin();
},
More about sync-await.

Related

Flutter: No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()

[core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
Where create call Firebase.initializeApp() ?
what should I change in my code? Is there any way to do it? In case you want to see the code please let me know I will update more.
auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:quiz2/model/user.dart';
class AuthService {
FirebaseAuth _auth = FirebaseAuth.instance;
UserFire _userFromFirebase(User user){
return user != null ? UserFire(uid: user.uid):null;
}
Future signInEmailAndPass(String email, String password) async {
try {
UserCredential authResult = await _auth.signInWithEmailAndPassword(
email: email, password: password);
User firebaseUser = authResult.user;
return _userFromFirebase(firebaseUser);
} catch (e) {
print(e.toString());
}
}
Future signUpWithEmailAndPassword(String email, String password) async{
try{
UserCredential authResult = await _auth.createUserWithEmailAndPassword(email: email, password: password);
User firebaseUser = authResult.user;
return _userFromFirebase(firebaseUser);
}catch(e){
print(e.toString());
}
}
Future signOut() async{
try{
return await _auth.signOut();
}catch(e){
print(e.toString());
return null;
}
}
}
signup.dart
import 'package:flutter/material.dart';
import 'package:quiz2/database/auth.dart';
import 'package:quiz2/screens/landing.dart';
import 'package:quiz2/screens/signin.dart';
import 'package:quiz2/widgets/widget.dart';
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
final _formKey = GlobalKey<FormState>();
String email, password, name;
AuthService authService = new AuthService();
bool _isLoading = false;
signUp() async {
if (_formKey.currentState.validate()) {
setState(() {
_isLoading = true;
});
authService.signUpWithEmailAndPassword(email, password).then((val) {
if (val != null) {
setState(() {
_isLoading = false;
});
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => MyHomePage()));
}
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: appBar(context),
backgroundColor: Colors.transparent,
elevation: 0.0,
brightness: Brightness.light,
),
body: _isLoading
? Container(child: Center(child: CircularProgressIndicator()))
: Form(
key: _formKey,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 24),
child: Column(
children: [
Spacer(),
TextFormField(
validator: (val) {
return val.isEmpty ? 'Enter Name' : null;
},
decoration: InputDecoration(hintText: 'Name'),
onChanged: (val) {
name = val;
},
),
SizedBox(
height: 6,
),
TextFormField(
validator: (val) {
return val.isEmpty ? 'Enter Email' : null;
},
decoration: InputDecoration(hintText: 'Email'),
onChanged: (val) {
email = val;
},
),
SizedBox(
height: 6,
),
TextFormField(
obscureText: true,
validator: (val) {
return val.isEmpty ? 'Enter password' : null;
},
decoration: InputDecoration(hintText: 'Password'),
onChanged: (val) {
password = val;
},
),
SizedBox(
height: 24,
),
GestureDetector(
onTap: () {
signUp();
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 16),
decoration: BoxDecoration(
color: Colors.teal,
borderRadius: BorderRadius.circular(30)),
alignment: Alignment.center,
width: MediaQuery.of(context).size.width - 48,
child: Text(
"Sign Up",
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
SizedBox(
height: 18,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Alredy have an account?",
style: TextStyle(fontSize: 16),
),
GestureDetector(
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => SignIn()));
},
child: Text(" Sign In",
style: TextStyle(
fontSize: 16,
decoration: TextDecoration.underline)))
],
),
SizedBox(
height: 80,
),
],
)),
),
);
}
}
user.dart
class UserFire{
String uid;
UserFire({this.uid});
}
what should I change in my code? Is there any way to do it? In case you want to see the code please let me know I will update more.
You need initialize your firebase .Do as follows:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Did you complete all the installation steps?
if you answer is yes :
you must check this link

How can I change a Futurebuilder into an Streambuilder?

I'm using a future builder in a method and trying to switch to a Streambuilder but struggling a it with that heres my code may be anyone can help
class _MeineFreundeState extends State<MeineFreunde> {
Icon custIcon = Icon(Icons.search);
Widget cusSearchBar = Text("Meine Freunde");
Stream myVideos;
int likes = 0;
int videos = 0;
int followers;
int following;
bool dataisthere = false;
#override
void initState() {
super.initState();
getalldata();
}
getalldata() async {
var listOfIds = [];
String myID = FirebaseAuth.instance.currentUser.uid;
var idofotheruser = await FirebaseFirestore.instance
.collection('meinprofilsettings')
.doc(myID)
.collection('following')
.get();
following = idofotheruser.docs.length;
idofotheruser.docs.forEach((element) {
listOfIds.add(element.id);
});
print(listOfIds);
myVideos = FirebaseFirestore.instance
.collection('videos')
.where('uid', isEqualTo: 'Fp3unLwcl2SGVh4MbUPiRVAylYV2')
.snapshots();
var documents = await FirebaseFirestore.instance
.collection('videos')
.where('uid', isEqualTo: 'Fp3unLwcl2SGVh4MbUPiRVAylYV2')
.get();
if (!mounted) return;
setState(() {
videos = documents.docs.length;
});
for (var item in documents.docs) {
likes = item.data()['likes'].length + likes;
}
var followersdocuments = await FirebaseFirestore.instance
.collection("meinprofilsettings")
.doc(myID)
.collection('followers')
.get();
var followingdocuments = await FirebaseFirestore.instance
.collection("meinprofilsettings")
.doc(myID)
.collection('following')
.get();
followers = followersdocuments.docs.length;
following = followingdocuments.docs.length;
setState(() {
dataisthere = true;
});
}
#override
Widget build(BuildContext context) {
return getBody(context);
}
Widget getBody(BuildContext context) {
return dataisthere == false
? Scaffold(body: Center(child: CircularProgressIndicator()))
: Stack(children: <Widget>[
Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () {
Navigator.of(context)
.pushNamed(Searchuserinmeinebeitraege.route);
},
),
],
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: RefreshIndicator(
onRefresh: _handleRefresh,
color: Colors.black,
strokeWidth: 4,
child: ListView(
children: [
Column(children: <Widget>[
SizedBox(
height: 5,
),
StreamBuilder(
stream: myVideos,
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (videos > 0) {
return StaggeredGridView.countBuilder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: ScrollPhysics(),
crossAxisCount: 3,
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot video =
snapshot.data.docs[index];
return InkWell(
onTap: () {
NavigationService.instance
.navigateToRoute(MaterialPageRoute(
builder: (context) {
return VideoPage(
video.data()['videourl'],
video.data()['uid'],
video.id,
);
}));
},
child: Card(
elevation: 0.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
clipBehavior:
Clip.antiAliasWithSaveLayer,
child: Image.network(
video.data()['previewimage'],
fit: BoxFit.cover,
),
),
//imageData: searchImages[index],
),
);
},
staggeredTileBuilder: (index) =>
StaggeredTile.count(
(index % 7 == 0) ? 2 : 1,
(index % 7 == 0) ? 2 : 1),
mainAxisSpacing: 8.0,
crossAxisSpacing: 4.0,
);
} else {
return Center(
child: Padding(
padding:
const EdgeInsets.fromLTRB(0, 100, 0, 0),
child: Container(
child: Text(
"No Videos Yet",
style: TextStyle(
fontSize: 18, color: Colors.black),
),
),
),
);
}
}),
]),
],
),
),
),
]);
}
Future _handleRefresh() async {
await Future.delayed(new Duration(seconds: 2));
setState(() {
getalldata();
});
return null;
}
}
I am a beginner with flutter, I know that I just can change FuturBuilder into Streambuilder and then future to stream but what about How I'm getting the data is there any difference
I Mean something like this line
video.data()['videourl'],
Is it equal or is there any difference and also how can I change it in getalldata method. If you need more information please leave a comment.
StreamBuilder is different from FutureBuilder in many ways one main difference being
The main job of the FutureBuilder is to complete the future and return the result once the result is returned it has no way to fetch the latest snapshot from the future unless its parent rebuilds. Once the future attached returns the result the builder method gets executed to refresh the Ui.
while incase of StreamBuilder it contiuously listens to your specified collection and gets you the latest snapshot in realtime. that means any document in your firestore collection changes you get the latest updated collection and builder method rebuilds to refresh the UI.
You could use StreamBuilder to fetch data from your firestore's collection like this
String myID = FirebaseAuth.instance.currentUser.uid;
final queryVideos = await FirebaseFirestore.instance
.collection('videos')
.where('uid', arrayContains: listOfIds)
StreamBuilder<DocumentSnapshot>(
stream: queryVideos.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator()); /// show a loader
} else if (snapshot.data.docs.isEmpty) {
return const SizedBox.shrink(); // show an empty widget no docs
} else
return StaggeredGridView.countBuilder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: ScrollPhysics(),
crossAxisCount: 3,
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
/// fetch a doc by Index
final doc = snapshot.data.docs[index];
return InkWell(
onTap: () {
NavigationService.instance
.navigateToRoute(MaterialPageRoute(
builder: (context)=>VideoPage(
doc['videourl'], // this is how you access each property in a document
doc['uid'],
doc['id']
));
},
child: YourWidget());
}));
});

How do i catch error of authentication while logging in and signup using firebase and flutter?

I am pretty new to flutter and this is my first project in which i am using backend like firebase.
So i pre build an ui and started to integrate firebase in it it was successfully done and it is working as accepted but when i am trying to print out the errors while logging in signup i am failing to do that, i am able to catch the errors in my console but i wait to update my users with that error text.
when ever i am trying to log in though i am providing a wrong password it is taking me to the home page which i dont want
This is my Log In page with a pre build ui and with working setup of log in
import 'package:flutter/material.dart';
import 'package:notepad/Authentigation%20Screens/signUp.dart';
import 'package:notepad/animation/bouncypagetrans.dart';
import 'package:notepad/animation/fadeanimation.dart';
import 'package:notepad/auth/authMethod.dart';
import 'package:notepad/screens/homepage.dart';
import 'package:notepad/widgets/VxTextsHeaders.dart';
import 'package:notepad/widgets/customRaisedButton.dart';
import 'package:notepad/widgets/loading.dart';
import 'package:notepad/widgets/textformField.dart';
import 'ForgotPassword.dart';
class LogIn extends StatefulWidget {
#override
_LogInState createState() => _LogInState();
}
class _LogInState extends State<LogIn> {
String error;
AuthMethods authMethods = new AuthMethods();
bool isLoading = false;
final formKey = GlobalKey<FormState>();
TextEditingController emailTextEditingController =
new TextEditingController();
TextEditingController passwordTextEditingController =
new TextEditingController();
logMein() {
if (formKey.currentState.validate()) {
try {
setState(() {
isLoading = true;
});
authMethods
.signInWithEmailAndPassword(emailTextEditingController.text,
passwordTextEditingController.text)
.then((val) {
// print("${val.uId}");
Navigator.pushReplacement(
context,
BouncyPageRout(
widget: HomePage(),
),
);
});
} catch (e) {
setState(() {
error = e.message;
});
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: true,
body: isLoading
? Loading()
: SafeArea(
child: Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(30.0, 100.0, 30.0, 20.0),
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FadeAnimation(
1.0,
headerTitle("Hello,"),
),
FadeAnimation(
2.0,
headerSubTitle("Log in to continue"),
),
],
),
SizedBox(height: 65),
Column(
children: [
Form(
key: formKey,
child: Column(children: [
SizedBox(height: 20),
FadeAnimation(
3.0,
buildTextField(
validator: (val) {
return val.isEmpty ||
RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(val)
? null
: "Please provide a valid Email";
},
labelText: "Email",
controller: emailTextEditingController),
),
SizedBox(height: 20),
FadeAnimation(
3.5,
buildTextField(
validator: (val) {
return val.isEmpty || val.length < 6
? "Please Provide a Strong Password,/n Provide somthing greater than 6 "
: null;
},
labelText: "Password",
obscureText: true,
controller:
passwordTextEditingController),
),
])),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerRight,
child: FadeAnimation(
4.0,
InkWell(
onTap: () {
Navigator.push(
context,
BouncyPageRout(
widget: ForgotPassword(),
),
);
},
child: Text(
'Forgot Password?',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.deepOrange,
fontSize: 14),
),
),
),
),
SizedBox(height: 40),
FadeAnimation(
4.5,
raisedButton(
context: context,
onPressed: () {
logMein();
},
color: Colors.deepOrange,
title: "Log In",
textColor: Colors.white,
),
),
SizedBox(
height: 20.0,
),
FadeAnimation(
5.0,
raisedButton(
context: context,
onPressed: () {
Navigator.push(
context,
BouncyPageRout(
widget: SignUp(),
),
);
},
color: Colors.white,
title: "SignUp"),
),
],
)
],
),
),
),
),
);
}
}
AuthMethods page with contains all the codes of firebase
import 'package:notepad/auth/user.dart';
class AuthMethods {
String error;
final FirebaseAuth _auth = FirebaseAuth.instance;
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(userId: user.uid) : null;
}
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser firebaseUser = result.user;
return _userFromFirebaseUser(firebaseUser);
} catch (e) {
print(e.toString());
}
}
Future signUpwithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser firebaseUser = result.user;
return _userFromFirebaseUser(firebaseUser);
} catch (e) {
print(e.toString());
}
}
Future resetPass(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
}
}
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
}
}
}
so basically i want to notify my users a valid error message and untill they solve that they should not navigate to a perticular screen
You can use a snackbar widget and call them in your throw function! Follow this link to learn more about snackbars
https://flutter.dev/docs/cookbook/design/snackbars

Deleting document from cloud_firestore in flutter

I am returning a streamBuilder and inside the streamBuider, it returns a widget.
Now I have wrap a widget with dismissible so that I can delete the document from the collection from the cloud_firestore.
showingTheSelectedDateEvents() {
List<Widget> listViewContainer = [];
return StreamBuilder<QuerySnapshot>(
stream: firestoreInstance.collection('eventDetails').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
String theDatabaseDate;
final allDocuments = snapshot.data.docs;
//here we get all the documents from the snapshot.
for (var i in allDocuments) {
theDatabaseDate = i.data()['dateTime'];
if (theDatabaseDate == theDataProvider.databaseSelectedDate) {
print(theDatabaseDate +
" is same as " +
theDataProvider.databaseSelectedDate);
listViewContainer.add(Dismissible(
key: ObjectKey(snapshot.data.docs.elementAt(0)),
onDismissed: (direction) {
firestoreInstance
.collection("eventDetails")
.doc()
.delete()
.then((_) {
print("success!");
});
},
child://here
));
print(listViewContainer.length);
} else {
print("no any events for today");
}
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: listViewContainer,
),
);
},
);
}
I tried this for deleting the data from the cloud_firestore
key: ObjectKey(snapshot.data.docs.elementAt(0)),
onDismissed: (direction) {
firestoreInstance
.collection("eventDetails")
.doc()
.delete()
.then((_) {
print("success!");
});
},
I want to delete the specific document from the collection
I cannot figure out how to do that.
here is the database model
I am trying to delete the document of eventDetails collection.
doc() will generate a new random id, therefore if you don't have access to the id, then you need to do the following:
FirebaseFirestore.instance
.collection("eventDetails")
.where("chapterNumber", isEqualTo : "121 ")
.get().then((value){
value.docs.forEach((element) {
FirebaseFirestore.instance.collection("eventDetails").doc(element.id).delete().then((value){
print("Success!");
});
});
});
Use a where() condition to get the required document and delete it.
Since in your code you are using:
return StreamBuilder<QuerySnapshot>(
stream: firestoreInstance.collection('eventDetails').snapshots(),
Here you are fetching all the documents under eventDetails, therefore you can add a unique field to the document and then inside the for loop you can get the id:
for (var i in allDocuments) {
if(i.data()["subject"] == "Mathemtics")
docId = i.id;
And then you can delete it:
onDismissed: (direction) {
FirebaseFirestore.instance
.collection("eventDetails")
.doc(docId)
.delete()
.then((_) {
print("success!");
});
},
This way you dont need to fetch the documents twice.
You can always query the document to get the document ID and perform the deletion.
var collection = FirebaseFirestore.instance.collection('users');
var snapshot = await collection.where('age', isGreaterThan: 20).get();
for (var doc in snapshot.docs) {
await doc.reference.delete();
}
To delete all the documents, iterate through the QueryDocumentSnapshot.
var collection = FirebaseFirestore.instance.collection('collection');
var querySnapshots = await collection.get();
for (var doc in querySnapshots.docs) {
await doc.reference.delete();
}
I just had to use,
i.id
to get the document id. And I could delete the document from the firestore by swipping.
Here is the complete code,
showingTheSelectedDateEvents() {
List<Widget> listViewContainer = [];
return StreamBuilder<QuerySnapshot>(
stream: firestoreInstance.collection('eventDetails').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
String theDatabaseDate;
final allDocuments = snapshot.data.docs;
//here we get all the documents from the snapshot.
for (var i in allDocuments) {
// if(i.data()["subject"] == "Mathemtics")
theDatabaseDate = i.data()['dateTime'];
if (theDatabaseDate == theDataProvider.databaseSelectedDate) {
print(theDatabaseDate +
" is same as " +
theDataProvider.databaseSelectedDate);
listViewContainer.add(Dismissible(
key: ObjectKey(snapshot.data.docs.elementAt(0)),
onDismissed: (direction) async {
firestoreInstance.collection("eventDetails").doc(i.id).delete();
// allDocuments.removeAt(0);
},
background: Container(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 20, 0),
child: Text(
"Slide To Remove",
style: TextStyle(
fontSize: 15,
fontFamily: "Poppins",
color: Colors.black),
),
),
decoration: BoxDecoration(color: Color(0xFFF4F5F6)),
),
child: Widgets(
containerHeight: 170,
thePaddingValue:
EdgeInsets.only(left: 90, right: 10, top: 20, bottom: 20),
iconSize: 60,
chapterName: i.data()['chapterName'],
chapterNumber: i.data()['chapterNumber'],
meetType: i.data()['meetType'],
meetIcon: Icons.video_call,
subject: i.data()['subject'],
lectureTime: "09:30",
teacherImage:
AssetImage("assets/images/IMG-20200817-WA0000.jpg"),
teacherName: "Alex Jesus",
),
));
print(listViewContainer.length);
} else {
print("no any events for today");
}
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: listViewContainer,
),
);
},
);
}

how to display an error message if email and password is not valid in firebase flutter?

i have developed an login page,if the email and password matches from the database it successfully login's and moves to the new page,but if its wrong i want to display an error message email or password doesn't match.
Here's my code:
class _AdminLoginState extends State<AdminLogin> {
String _username, _password;
TextEditingController _email = TextEditingController();
final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('LOGIN'),
backgroundColor: Colors.indigo[900],
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(top: 50),
child: SizedBox(
height: 150.0,
width: 300,
child: Image.asset("assets/admin.png",
fit: BoxFit.contain,),
),
),
Container(
child: Text("ADMIN",style: TextStyle(fontSize: 15,fontWeight: FontWeight.bold,color: Colors.indigo),),
),
Container(
padding: const EdgeInsets.only(bottom: 50),
child: Column(
children: <Widget>[
SingleChildScrollView(
child: Form(
key: _formkey,
child: Column(
children: <Widget>[
SizedBox(
height: 60,
),
SizedBox(
width: 380,
height: 70,
child: Container(
padding: EdgeInsets.all(4),
width: 500,
height: 60,
child: TextFormField(
autofocus: false,
obscureText: false,
keyboardType: TextInputType.emailAddress,
validator:(input){
if(input.isEmpty){
return 'please type username';
}
return null;
},
onSaved: (input) => _username =input ,
decoration: InputDecoration(
labelText: 'Email',
hintText: "Email",
labelStyle: TextStyle(
color: Colors.black,
fontSize: 16,
),
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(20.0),
),
),
),
),
),
),
SizedBox(
width: 380,
height: 70,
child: Container(
padding: EdgeInsets.all(4),
width: 400,
height: 60,
child: TextFormField(
autofocus: false,
obscureText: true,
validator:(input){
if(input.isEmpty){
return 'please type Password';
}
return null;
},
onSaved: (input) => _password =input ,
decoration: InputDecoration(
labelText: 'Password',
hintText: "Password",
labelStyle: TextStyle(
color: Colors.black,
fontSize: 16,
),
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(20.0),
),
),
),
),
),
),
Container(
padding: EdgeInsets.all(4),
width: 500,
height: 60,
child: RaisedButton(
onPressed: login,
textColor: Colors.white,
color: Colors.indigo[900],
child: Text('Login'),
),
)
],
),
),
),
],
),
),
],
),
),
);
}
Future<void> login() async{
final formState = _formkey.currentState;
if(formState.validate()){
formState.save();
try{
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
Navigator.push(context, MaterialPageRoute(builder: (context) => Admin()));
}catch(e){
print(e.message);
}
}
}
}
it will be really helpful if someone also helps me in validating the right email format and give give the proper validation for password
signInWithEmailAndPassword() returns an exception with a special code if the attempt is unsuccessful.
In order to print a message you need to add a catch block to your signInWithEmailAndPassword() method. Then you can use the error message.
Example:
firebase.auth().signInWithEmailAndPassword(email, password)
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
console.log(error);
});
For security purposes I would suggest combining some of the messages together instead of giving a possible attacker a hint about if the email is already in the system or not.
I do not know how to use flutter so I can only give an idea;
In here you are directly trying to get the user from the method.
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
Instead I would suggest using something like this (this is angular but I think you can easily apply to flutter with some modification)
final FirebaseUser user;
await firebase.auth().signInWithEmailAndPassword(email, password)
.then((data) => {
this.user = data.user;
})
.catch((error) => {
switch (error.code) {
case "auth/invalid-email":
case "auth/wrong-password":
case "auth/user-not-found":
{
this.accountErrorMessage = "Wrong email address or password.";
break;
}
case "auth/user-disabled":
case "user-disabled":
{
this.accountErrorMessage = "This account is disabled";
break;
}
}
You can find which kind of errors it may return from here:
https://firebase.google.com/docs/reference/js/firebase.auth.Auth.html#signinwithemailandpassword
Use errortext in InputDecoration
here is demo
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: _text,
decoration: InputDecoration(
labelText: 'email',
errorText: loginfail ? 'email not match' : null,
),
),
TextField(
controller: _text,
decoration: InputDecoration(
labelText: 'password',
errorText: loginfail ? 'password not match' : null,
),
),
RaisedButton(
onPressed: () {
login();
},
child: Text('Submit'),
textColor: Colors.white,
color: Colors.blueAccent,
)
],
),
),
);
}
Future<void> login() async{
final formState = _formkey.currentState;
if(formState.validate()){
formState.save();
try{
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
if(!user.uid.isEmpty()){
Navigator.push(context, MaterialPageRoute(builder: (context) => Admin()));
}else{
setState((){
loginfail = true; //loginfail is bool
});
}
}catch(e){
print(e.message);
}
}
hope it helps..
Following #Jaydeepchatrola answer's
I used a try catch block and checked if password was invalid or email, for better results!
try {
setState(() {
wrongEmail = false;
wrongPassword = false;
});
final newUser = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (newUser != null) {
Navigator.pushNamed(context, Done.id);
}
} catch (e) {
print(e.code);
if (e.code == 'ERROR_WRONG_PASSWORD') {
setState(() {
wrongPassword = true;
});
} else {
setState(() {
emailText = 'User doesn\'t exist';
passwordText = 'Please check your email';
wrongPassword = true;
wrongEmail = true;
});
}
}
You need to catch the specific error. I had the problem by myself, with this code I solved the problem.
try {
final user = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (user != null) {
Navigator.pushNamed(context, HomeScreen.id);
}
} on auth.FirebaseAuthException catch (e) {
//Here you catch the specific error
if (e.code == 'wrong-password') {
//The thing that should happen if the password is incorrect
//In my case it will the change the hinttext
setState(() {
hintTextPassword = 'Password incorrect. Please try again';
passwordHintColor = Colors.red;
});
} else if (e.code == 'user-not-found') {
setState(() {
hintTextEmail = 'No user found for that email.';
emailHintColor = Colors.red;
});
}
} catch (e) {
print(e);
}
add rflutter_alert: ^2.0.4 in your project file pubspec.yaml under dependencies: and save it
add import 'package:rflutter_alert/rflutter_alert.dart'; in your file of your auth screen
add
Alert(
context: context,
title: "Failed Login",
desc: "Incorrect Email Or Password.")
.show();
in catch(e){}
like that:
Future<void> login() async{
final formState = _formkey.currentState;
if(formState.validate()){
formState.save();
try{
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
Navigator.push(context, MaterialPageRoute(builder: (context) => Admin()));
}catch(e){
Alert(
context: context,
title: "Failed Login",
desc: "Incorrect Email Or Password.")
.show();
}
}

Resources