Flutter, How to use multiple shared preferences - flutter

My goal was to avoid users getting logged out once they close and reopened the app. So, I used shared_preferences to store the user's email and password locally so, that whenever the user reopens the app I could use firebase's signInWithEmailAndPassword and provide locally stored email and password to it. I used setString() to store email password but I was able to store only email and not the password, I get the error "Password is null" How do I solve this. Did I do the code right?
Storing email and password when user registers in app
onPressed: () async {
try {
final user =
await _auth.createUserWithEmailAndPassword(
email: email, password: password);
if (user != null) {
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
sharedPreferences.setString(
'email',
email,
);
sharedPreferences.setString('password', password);
Get.to(() => const BorrowerList());
}
} catch (e) {
Get.snackbar('Error', e.toString(),
backgroundColor: (Colors.red));
}
},
fetching email password and login after reopening.
#override
void initState() {
super.initState();
validateUserAuth();
}
final _firestore = FirebaseFirestore.instance;
void validateUserAuth() async {
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
var obtainedEmail = sharedPreferences.getString('email');
var obtainedPassword = sharedPreferences.getString('password');
if (obtainedEmail != null || obtainedPassword != null) {
setState(() {
loggedinUserEmail = obtainedEmail!;
loggedinUserPassword = obtainedPassword!;
});
if (loggedinUserEmail != null || loggedinUserPassword != null) {
final loggedinuser = await auth.signInWithEmailAndPassword(
email: loggedinUserEmail, password: obtainedPassword!);
if (loggedinuser != null) {
Get.to(() => const BorrowerList());
}
}
} else {
Get.to(() => AuthScreen());
}
}

The error is apparent.
You can't save a null value in shared_preferences.
Your code is not complete. somehow your password variable is null.
You can paste complete code so we can help you better

Can you provide more information about the project? So far, it's obvious that you're trying to store a null value in shared_preferences. You can't do that. I'm pretty sure the problem is that when the user enters a password, it's not stored in the password variable here:
try {
final user =
await _auth.createUserWithEmailAndPassword(
email: email, password: password);
if (user != null) {
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
sharedPreferences.setString(
'email',
email,
);
// NULLABLE VARIABLE!
sharedPreferences.setString('password', password);
Get.to(() => const BorrowerList());
}
} catch (e) {
Get.snackbar('Error', e.toString(),
backgroundColor: (Colors.red));
}
},
Additionally, it is not recommended to use shared_preferences for storing sensitive data. Flutter Secure Storage is much better suited for this.

Related

Can we set user displayName in firebase using password authentication through flutter? [duplicate]

I can save the email and the password with Firebase Authentication. I also save this information with Cloud Firestore. But how can I add and save the displayName after registering?
my code:
Future registerWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
// create a new document for the user with the uid
await DatabaseService(uid: user.uid)
.updateUserData('User', user.email, 'test.de/test.png', user.uid);
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
the register form button:
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
dynamic result = await _auth
.registerWithEmailAndPassword(
email, password);
if (result == null) {
setState(() {
error = 'Valid email, please';
loading = false;
});
}
}
}
You can use updateProfile method given in the FirebaseUser class to update the name and photo url.
updateProfile({String displayName, String photoURL}).
For email you can use the different method
updateEmail(String newEmail) which is a async method.
Or to save the username directly into the firestore, after successful login you can use 'set' method of the FirebaseFirestore to save email, password and the username.
Here's the code if you want to save the Username together with the email and password
final FirebaseAuth _auth = FirebaseAuth.instance;
//register with email & password & save username instantly
Future registerWithEmailAndPassword(String name, String password, String email) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
User user = result.user;
user.updateProfile(displayName: name); //added this line
return _user(user);
} catch(e) {
print(e.toString());
return null;
}
}
late User userFirebase;
Future<UserCredential> userCredential =await //Your code signin or signup
await userCredential.then((UserCredential value) {
userFirebase = value.user!;
});
await userFirebase.updateDisplayName(event.name);
You can use updateDisplayName() and updatePhotoURL() methods on a User object to add the displayName/profile image to Firebase user.
final userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
//After creating a user in Firebase, we then are able to change name/pictue
await userCredential.user?.updateDisplayName(name);
await userCredential.user?.updatePhotoURL(imageUrl);
As of october 2021, updateProfile() is deprecated, and you should use updateDisplayName() and updatePhotoURL() instead.

Cloud Firestore Database is not displaying users after authentication?

I am trying to do authentication using createUserWithEmailAndPassword .The user iis getting created since I can signin using the email and password which created using createUserWithEmailAndPassword .But my firestore database is not showing the document which I have created using createUserWithEmailAndPassword().
This is my code:
onPressed: () async {
try {
final newuser = await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: email ?? 'error',
password: password ?? 'error',
);
if (newuser != null) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => home()),
);
}
} catch (e) {
print(e);
}
I have created 3 users with this method and I'm able to login with these credential but these users are not showing in my Firestore Database.
As #ashish already mentioned, you need to store all your extra parameters in the firestore as documents. A better way to implement this is to use different function to register user and create a user document related to that registered user.
Below is an example I created to help out!
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
void main() {
String email = "test#test.com";
String password = "123456";
String firstName = "test";
String lastName = "test";
String phoneNumber = "09876543456";
/// This is the function to create new user
Future<void> createUser(
email,
password,
firstName,
lastName,
phoneNumber,
/*... and any other params you wish to collect */
) async {
// firebase auth
final FirebaseAuth auth = FirebaseAuth.instance;
// firestore db
FirebaseFirestore db = FirebaseFirestore.instance;
// try-catch creation process to accurate exception
try {
final credential = await auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
// get user id
String userID = credential.user!.uid;
// creating user profile on db
await db.collection("users").doc(userID).set({
"id": userID,
"firstName": firstName,
"lastName": lastName,
"phoneNumber": phoneNumber,
// ... other params
});
print("Signed up successfully!");
} on FirebaseAuthException catch (error) {
print("Something is wrong: $error");
}
}
/// this is the create button
TextButton(
onPressed: () async {
await createUser(
email,
password,
firstName,
lastName,
phoneNumber,
/*... and any other params you wish to collect */
);
},
child: const Text("Create test user"),
);
}
Let me know if you need anything else :). BYE!!!
To store the data in the database you need to use a Firestore instance to store data in firebase Firestore.
onPressed: () async {
try {
final newuser = await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: email ?? 'error',
password: password ?? 'error',
);
await FirebaseFirestore.instance.collection('Users').doc(newuser!.uid).set({
email: newuser.email
});
if (newuser != null) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => home()),
);
}
} catch (e) {
print(e);
}
}
You need to put the data which you want to store in firestore in set() function.
Firebase Authentication data are show into the login into firebase then on tap of Authentication options menu -> user section , you can view store 3 users data in this section

How to pass uid and email to sharedpreference method When signUp in flutter?

I built the google signin and email password signup app using flutter,
I want when user log to application then user's "uid" and "email" save in shared preference.
In google login I built when login then pass the boolean value and pass uid and email to shared preference. Then when users close app and when reopen then login in home screen and can get uid and email.
But when user signup or login using email password then can not pass the boolean value and uid and email to google login shared preference. In below I'll mentioned google login method and email password method.
googlelogin method
// handling google sigin in
Future handleGoogleSignIn() async {
final sp = context.read<SignInProvider>();
final ip = context.read<InternetProvider>();
await ip.checkInternetConnection();
if (ip.hasInternet == false) {
openSnackbar(context, 'Check your Internet connection', Colors.red);
googleController.reset();
} else {
await sp.signInWithGoogle().then((value) {
if (sp.hasError == true) {
openSnackbar(context, sp.errorCode.toString(), Colors.white);
googleController.reset();
} else {
// checking whether user exists or not
sp.checkUserExists().then((value) async {
if (value == true) {
// user exists
await sp.getUserDataFromFirestore(sp.uid).then((value) => sp
.saveDataToSharedPreferences()
.then((value) => sp.setSignIn().then((value) {
googleController.success();
handleAfterSignIn();
})));
} else {
// user does not exist
sp.saveDataToFirestore().then((value) => sp
.saveDataToSharedPreferences()
.then((value) => sp.setSignIn().then((value) {
googleController.success();
handleAfterSignIn();
})));
}
});
}
});
}
//login function
}
saveDataToSharedPreferences method and setSignIn boolean value (it has in a siginprovider class in another file)
class SignInProvider extends ChangeNotifier {
//instantiate of firebaseAuth, facebook and google
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
bool _isSignedIn = false;
bool get isSignedIn => _isSignedIn;
//hasError, errorCode, provider,uid,email,name,imageUrl
bool _hasError = false;
bool get hasError => _hasError;
String? _errorCode;
String? get errorCode => _errorCode;
String? _uid;
String? get uid => _uid;
String? _email;
String? get email => _email;
SignInProvider() {
checkSignInUser();
}
Future checkSignInUser() async {
final SharedPreferences s = await SharedPreferences.getInstance();
_isSignedIn = s.getBool('signed_in') ?? false;
notifyListeners();
}
Future setSignIn() async {
final SharedPreferences s = await SharedPreferences.getInstance();
s.setBool('signed_in', true);
_isSignedIn = true;
notifyListeners();
}
Future saveDataToSharedPreferences() async {
final SharedPreferences s = await SharedPreferences.getInstance();
await s.setString('email', _email!);
await s.setString('uid', _uid!);
notifyListeners();
}
Future getDataFromSharedPreferences() async {
final SharedPreferences s = await SharedPreferences.getInstance();
_email = s.getString('email');
_uid = s.getString('uid');
notifyListeners();
}
}
**email password signup**
void signUp(String email, String password) async {
if (_formkey.currentState!.validate()) {
await _auth
.createUserWithEmailAndPassword(email: email, password: password)
.saveDataToSharedPreferences()
.sp.setSignIn()
.then((value) => {postDetailsToFirestore()})
.catchError((e) {
Fluttertoast.showToast(msg: e!.message);
});
}
}
in email password signup has postDetailsToFirestore method
postDetailsToFirestore() async {
// calling our fireStore
//calling our user model
// sending these values
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
User? user = _auth.currentUser;
UserModel userModel = UserModel();
if (user != null) {
//writing all the values
userModel.email = user?.email;
userModel.uid = user?.uid;
await firebaseFirestore
.collection("users")
.doc(user?.uid)
.set(userModel.toMap());
Fluttertoast.showToast(msg: "Account created successfully ");
Navigator.pushAndRemoveUntil(
(context),
MaterialPageRoute(builder: (context) => HomeScreen()),
(route) => false);
}
}
in email password signup I called
these 2 methods but show this error
when signup how to pass uid and emaill to saveDataToSharedPreferences method and pass sp.setSignIn() boolean like as in google signing?
You are trying to use method saveDataToSharedPreferences from Future class, not from auth. For fix this issue, call prefs from main object:
final result = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
result.saveDataToSharedPreferences()
.sp.setSignIn()
// etc.

Flutter firebase Reauthenticating a user not working

I am working on a project which is based on firebase authentication (Email/password).
I need to add change password Options. when try to change credential showing error.
Error "The password is invalid or the user does not have a password."
I have tried with this code.
FirebaseAuth auth = FirebaseAuth.instance;
checkUser() {
if (auth.currentUser != null) {
print(auth.currentUser.email);
changePass();
} else {
print("user not found");
}
}
void changePass() async {
print("clicked");
EmailAuthCredential credential =
EmailAuthProvider.credential(email: auth.currentUser.email, password: "Password#3221");
await auth.currentUser.reauthenticateWithCredential(credential);
}
use this one for reset password:
Future resetpassword (String email)
async
{
await _auth.sendPasswordResetEmail(email: email);
}

Flutter, firebase. I want to show my registration form data other than the email and password and connect to a unique uid

Register Screen On Pressed method given, I believe there is a problem with calling Firebase user = result.user
onPressed: () async {
if(_formKey.currentState.validate()){
setState(() => loading = true);
dynamic result = await _auth.registerWithEmailAndPassword(email, password);
FirebaseUser user = result.user;
await DatabaseService(uid: user.uid).newUserInfo(
_nameC.text,
_cityC.text,
_contactnoC.toString()
);
if(result == null) {
setState(() {
error = 'Please supply a valid email';
loading = false;
});
}}},
// Database backend
class DatabaseService {
final String uid;
DatabaseService ({this.uid});
final CollectionReference userdata2 = Firestore.instance.collection('UserData');
Future newUserInfo(String name, String city, String contactno) async {
return await userdata2.document(uid).setData({
'name' : name,
'city' : city,
'contactno' : contactno
});
}}
// authentication backend
// register with email and password
Future registerWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
DatabaseService(uid: user.uid);
return _userFromFirebaseUser(user);
} catch (error) {
print(error.toString());
return null;
} }
// user.dart
class User {
final String uid;
User({this.uid});
}