How to retrieve current user data from firebase? - flutter

I tried this way, but i'm getting an error.
The error:
The method 'data' isn't defined for the type 'CollectionReference'. (undefined_method at [myapp] android\app\lib\useracc.dart:32)
void getData() async{
User? user = await FirebaseAuth.instance.currentUser;
var vari =FirebaseFirestore.instance.collection("users");
setState (() {
name = vari.data()['firstname'];
}
);
}
Signup/Register Page
Future<User?> _register(String fname,String lname ,String email, String password) async{
FirebaseAuth _auth = FirebaseAuth.instance;
FirebaseFirestore _firestore = FirebaseFirestore.instance;
try {
UserCredential userCrendetial = await _auth.createUserWithEmailAndPassword(email: emailController.text, password: passwordController.text);
print("Account created Succesfull");
userCrendetial.user!.updateDisplayName(fname);
userCrendetial.user!.updateDisplayName(lname);
await _firestore.collection('users').doc(_auth.currentUser!.uid).set({
"firstname": fname,
"lastname" : lname,
"email": email,
"uid": _auth.currentUser!.uid,
});
return userCrendetial.user;
} catch (e) {
print(e);
return null;
}
}
This is the user account from where i want to fetch info:
Please help. I'm struck here a long time.

You should retrieve the currentUser document then access its data:
void getData() async{
var vari = await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser.uid)
.get();
setState (() {
name = vari.data()['firstname'];
});
}

if you've saved your user's details in firestore and its document id is the same as that of user ID (which is preferred for ease of access and control), then:
var vari =FirebaseFirestore.instance.collection("users").doc(user!.uid).get();
This gets the document of the user, and the type is DocumentSnapshot.
Map<String,dynamic> userData = vari as Map<String,dynamic>;
now userData is stored in form of Map. suppose you want to access their 'name', so the syntax now goes like userData['name'].
Similarly other fields can be accessed from variable. It's preferred to store userData in a Provider to access it's contents anywhere in your app.
Full code snippet
void getData() async{
User? user = await FirebaseAuth.instance.currentUser;
var vari =FirebaseFirestore.instance.collection("users").doc(user!.uid).get();
Map<String,dynamic> userData = vari as Map<String,dynamic>;
setState (() {
name = userData['firstname']; //or name = userData['name']
}
);
}

Related

Instance of 'Future<String?>' flutter

Why is returning Instance of 'Future<String?>' instead String value?
Future<String?> getUser() async {
User user = await FirebaseAuth.instance.currentUser!;
FirebaseFirestore firestore = await FirebaseFirestore.instance;
String uid = user.uid;
String? userName;
// to get username from firebase
return firestore
.collection("users")
.doc(uid)
.get()
.then((value) {
if (value.exists) {
var data = value.data();
userName = data?["name"];
print("There is data :$userName");
} else {
print("There no Data!");
}
return Future.value(userName);
});
}
I am trying to get String value?
The place you like to get data from this method use await & the method is needed to be async. like
_myFunction() async{
final value = await getUser();
Also I will suggest to not mixing await and .then.
Future<String?> getUser() async {
User user = FirebaseAuth.instance.currentUser!;
FirebaseFirestore firestore = FirebaseFirestore.instance;
String uid = user.uid;
String? userName;
// to get username from firebase
final value = await firestore.collection("users").doc(uid).get();
if (value.exists) {
var data = value.data();
userName = data?["name"];
print("There is data :$userName");
} else {
print("There no Data!");
}
return userName;
}

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.

FireStore when adding FCM token to User doc, deletes and doesn't store UserId

It's my first time using Firestore Cloud Messaging and I want to get the FCM token for each specific device. For quick development, I added the firebase_auth_ui package, which basically outsources the firebase auth login and registration flow. To capture the user's id and store in their doc, I use a simple function that works fine: and gets the job done:
Future<void> addUserDataToFireStore() async {
CollectionReference users = FirebaseFirestore.instance.collection('users');
String uid = FirebaseAuth.instance.currentUser!.uid;
users.doc(uid).set({
'userId': uid,
// 'displayName': currentUser!.displayName!,
});
}
Now, for some reason when I try to access the registration token, my userId gets deleted. When I try to add the token to the same user doc, the userId gets deleted and the fcm token stays. I generate the token as follows:
generateDeviceToken() async {
String? fcmToken = await FirebaseMessaging.instance.getToken();
final userId = FirebaseAuth.instance.currentUser!.uid;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.set({'fcmToken': fcmToken});
}
The issue is when I try to call them both. I can't get the two. The doc will fill with either UserId or FCM, but now both. This is what happens when I try to call both,
Perhaps I should make a method that updates fcm token and not set it everytimg?
When you use "set", the entire document is saved with only that one value. Use "update" to update the document and add your token without removing other content.
generateDeviceToken() async {
String? fcmToken = await FirebaseMessaging.instance.getToken();
final userId = FirebaseAuth.instance.currentUser!.uid;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.update({'fcmToken': fcmToken});
}
Future<void> addUserDataToFireStore() async {
CollectionReference users = FirebaseFirestore.instance.collection('users');
String uid = FirebaseAuth.instance.currentUser!.uid;
users.doc(uid).update({
'userId': uid,
// 'displayName': currentUser!.displayName!,
});
}
I ended up changing my logic a little bit. Thanks to #Maniak pointing me in the rigth direction. Solution that worked out was the following:
Future<void> addUserDataToFireStore() async {
final userId = FirebaseAuth.instance.currentUser!.uid;
final userDocRef = FirebaseFirestore.instance.collection('users').doc(userId);
final doc = await userDocRef.get();
if (doc.exists) {
return;
} else {
userDocRef.set({
'userId': userId,
});
}
}
Future<void> generateDeviceToken() async {
String? fcmToken = await FirebaseMessaging.instance.getToken();
final userId = FirebaseAuth.instance.currentUser!.uid;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.update({'fcmToken': fcmToken});
}

await Function does not return a value

I have created function get user and set it's data from firestore, this is the code of function getUser.
Future<User> getUser(String uid) async{
User user;
_firestore
.collection(USERS_COLLECTION)
.where("uid", isEqualTo: uid.toString())
.getDocuments()
.then((doc) {
_firestore
.document('/$USERS_COLLECTION/${doc.documents[0].documentID}')
.get()
.then((userData) {
user = User(
name: userData.data["name"],
username: userData.data["username"],
profilePhoto: userData.data["profilePic"],
);
}).catchError((e) {
print(e);
});
});
return user;
}
Then I have my profile page I have created function to set user from getUser() to current user like this:
User me;
String myUID = "t4skPFRXcLPxAWvhHpaiPOfsrPI3";
#override
void initState() {
super.initState();
setUser();
}
......
Future<void> setUser() async{
me = await userManagment.getUser(myUID);
}
But when I try to use print for example print(me.name) does not anything happen, when I try to set url of networkImage to me.profilePhoto there is an error showing tell me the url it's null.
Don't mix async-await and .then syntax. It's something that can be done, but it will more likely confuse than help. Adding the async modifier to your function is doing nothing since your function does not use await.
Consider the following options:
With .then
Future<User> getUser(String uid) {
return _firestore
.collection(USERS_COLLECTION)
.where("uid", isEqualTo: uid.toString())
.getDocuments()
.then((doc) {
return _firestore
.document('/$USERS_COLLECTION/${doc.documents[0].documentID}')
.get()
.then((userData) {
return User(
name: userData.data["name"],
username: userData.data["username"],
profilePhoto: userData.data["profilePic"],
);
}).catchError((e) {
print(e);
});
});
}
With async-await
Future<User> getUser(String uid) async{
User user;
try{
var doc = await _firestore
.collection(USERS_COLLECTION)
.where("uid", isEqualTo: uid.toString())
.getDocuments();
var userData = await _firestore
.document('/$USERS_COLLECTION/${doc.documents[0].documentID}')
.get();
user = User(
name: userData.data["name"],
username: userData.data["username"],
profilePhoto: userData.data["profilePic"],
);
}
catch(e) {
print(e);
}
return user;
}

How convert FirebaseUser to string in flutter?

Here is my code of a stateful class:
String id = FirebaseAuth.instance.currentUser().toString();
my function :
readLocal() async {
prefs = await SharedPreferences.getInstance();
id = prefs.getString('id') ?? '';
if (id.hashCode <= peerId.hashCode) {
groupChatId = '$id-$peerId';
} else {
groupChatId = '$peerId-$id';
}
setState(() {});
}
It works fine in String id.
I want the ID to be the same as the current user UID.
Calling FirebaseAuth.instance.currentUser() return a FirebaseUser, which is an object with all user data. If you only want the UID of the user:
FirebaseUser user = await FirebaseAuth.instance.currentUser();
String uid = user.uid;
Update: I just ran this and it prints the UID for me:
void _getUser() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
print(user.uid);
}
Which printed:
flutter: P07IXLCrwEahYlDhzO1Iv0SKDat2
Things to notice:
In order to be able to use await in the code, the method must be marked as async.