How to get Current User address every time in init State? - firebase

I am using GeoLocation and GeoCoding in my app but the address was always return null
Position? _currentPosition; >>>> always return null
String? _currentAddress;
String key = "location_cache";
_getCurrentLocation() {
Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
forceAndroidLocationManager: true)
.then((Position position) {
setState(() {
_currentPosition = position;
});
_getAddressFromLatLng();
}).catchError((e) {
print(e);
});
}
_getAddressFromLatLng() async {
try {
List<Placemark> p = await placemarkFromCoordinates(
_currentPosition!.latitude, _currentPosition!.longitude);
Placemark place = p[0];
setState(() {
_currentAddress = "${place.locality}";
});
} catch (e) {
print(e);
}
}
#override
void initState() {
_getCurrentLocation();
super.initState();
print(_currentAddress);
}
I WANT TO GET THE USER location every time he go to this screen ??
then I use it in my function to get data from firebase :
StreamBuilder<QuerySnapshot>(
stream: _productServices.getAnnouncesNearUser(
_currentAddress == null ? '' : _currentAddress.toString()),

please try using LocationAccuracy.medium,

Related

Why is it the passed data returns null in Flutter? I use Cloud Firestore as my data storage

I have a file named todo_repository.dart and has readTodo() function. Whenever I print the data variable here, there are returned contents/values but after I passed the data to another file named todo_list_cubit.dart, the data returns null value.
Here is the readTodo() of todo_repository.dart
Future<dynamic> readTodo() async {
try {
final User user = auth.currentUser!;
final uid = user.uid;
await usersTodo.doc(uid).get().then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
var data = documentSnapshot.data() as Map;
//The data here is not empty
print(data);
return data;
}
});
} on FirebaseException catch (e) {
throw CustomError(
code: e.code,
message: e.message!,
plugin: e.plugin,
);
} catch (e) {
throw CustomError(
code: 'Exception',
message: e.toString(),
plugin: 'flutter_error/server_error',
);
}
}
Here is the readTodo() of todo_list_cubit.dart
Future<void> readTodo() async {
try {
emit(state.copyWith(
todoListStatus: TodoListStatus.loading,
));
//Start - Part of code where I have issue
Map todoRepoRead = await todoRepository.readTodo();
**after I passed the data from todoRepository.readTodo(), the value returns null**
print(todoRepoRead);
//End - Part of code where I have issue
final rTodos = state.todos.map((Todo todo) {
return Todo(
id: todoRepoRead['id'],
description: todoRepoRead['description'],
completed: todoRepoRead['completed'],
);
}).toList();
emit(state.copyWith(
todoListStatus: TodoListStatus.loaded,
todos: rTodos,
));
} on CustomError catch (e) {
emit(state.copyWith(
todoListStatus: TodoListStatus.error,
error: e,
));
}
}
You should either use async/await or then, but not both.
Using just await, your code becomes:
Future<dynamic> readTodo() async {
try {
final User user = auth.currentUser!;
final uid = user.uid;
DocumentSnapshot documentSnapshot = await usersTodo.doc(uid).get();
if (documentSnapshot.exists) {
var data = documentSnapshot.data() as Map;
//The data here is not empty
print(data);
return data;
};
// TODO: you still need to return something here
} on FirebaseException catch (e) {
throw CustomError(
code: e.code,
message: e.message!,
plugin: e.plugin,
);
} catch (e) {
throw CustomError(
code: 'Exception',
message: e.toString(),
plugin: 'flutter_error/server_error',
);
}
}

How to save state with Firebase

I have switcher function which I created in order to change state of my icon according to information taken from firebase. So, when
"isFavSalon" in switcher is true the icon should be filled else it should be not filled. isFavSalon must be getting from firebase.
The switcher:
initState() {
isFavSalonBlock = widget.isFavSalon;
print(isFavSalonBlock);
super.initState();
}
#override
Widget build(BuildContext context) {
void switcherIsFavSalon() async {
var firebaseUser = FirebaseAuth.instance.currentUser;
var docRef = FirebaseFirestore.instance
.collection('customers')
.doc(firebaseUser.uid)
.collection('favSalons');
if (isFavSalonBlock == false) {
setState(() {
favIconBlock = 'assets/icons/heart_filled.png';
isFavSalonBlock = true;
docRef.add({
"salonName": widget.salonName,
"workTime": widget.workTime,
"location": widget.location,
"rating": widget.rating,
"isFavSalon": isFavSalonBlock,
});
});
} else {
setState(() {
favIconBlock = 'assets/icons/heart_border.png';
isFavSalonBlock = false;
docRef.get().then((value) {
value.docs.forEach((element) async {
if (element.data()['salonName'] == widget.salonName)
await docRef.doc(element.id).delete();
});
});
});
}
}
favIcon in this switcher pass to the icon's image path.
Also, I have function which gets information from firebase and stores it in my Block.
The function:
getFavSalons(AsyncSnapshot<QuerySnapshot> snapshot) {
return snapshot.data.docs
.map((doc) => SalonBlock(
salonName: doc.data()["salonName"],
location: doc.data()["location"],
workTime: doc.data()["workTime"],
rating: doc.data()["rating"],
))
.toList();
}
But when I restart my app and switch between pages state of icons doesn't change according to information stored in firebase.
However when I press on the icon information is sending to firebase.
So how can I save the state in my app?

I made database structure in Firestore like this: I have two collections: 1)students 2)schools. I can not get array from my database

I have two collections in my Firestore database.
From first collection('schools'), I need to get current user school. I did it and it is Ok. But I also need to use this school and get array of his school's available courses.
This array is situated in collection('students'). And as document I use schoolNameString which I took in previous collection. So in document(schoolNameString).data['available'], available is array of swings and I need
setState(){
myarrayvar = document(schoolNameString).data['available']
}
I can not do that and always see
error /flutter (25070): Tried calling: []("available")
This is my code:
class _Coirses_PageState extends State<Coirses_Page> with TickerProviderStateMixin
{
final _firesore = Firestore.instance;
String appBarName;
String studentSchoolString = 'mal';
String aseetRoadforCorcs;
List availableCorsces = [];
#override
void initState() {
FirebaseUser user;
super.initState();
getCurrentUser();
getCouses();
try {
var studentSchool = _firesore.collection('schools');
var docSchool = studentSchool.document(loggedInUser.uid);
docSchool.get().then((documents) {
setState(() {
studentSchoolString = documents.data['schoolName'];
print(studentSchoolString);
});
print(studentSchoolString);
});
} catch (e) {
print(e);
}
tabs = [
Tab(text: 'Barlyǵy',),
Tab(text: 'Oqyp jatyrmyn',),
Tab(text: 'Aıaqtadym',)
];
pages = [Progress_Bar()];
_controller = TabController(length: tabs.length, vsync: this);
}
Future<List<dynamic>> getCouses() async {
var document = Firestore.instance.collection("students").document(studentSchoolString). get();
return await document.then((doc) {
setState(() {
availableCorsces = doc.data['available'];
});
print('dsasdasdjnasndklasndasdkasld' + doc.data['available']);
return availableCorsces;
});
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser();
if (user != null) {
loggedInUser = user;
print(loggedInUser.email);
}
} catch (e) {
print(e);
}
}
}
I expected that I can use it in my UI like Text: ('available[0]' ......)
But I can't.

How to get user id from firebase auth as string?

I'm trying to insert data to firestore with the authenticated user id as the document id but i got null from the parameter.
Please take a look at my script.
void didChangeDependencies() {
uid = '';
super.didChangeDependencies();
}
Future _fetchUID() async {
var auth = AuthProvider.of(context).auth;
return await auth.getCurrentUser().then((user) => _uid = user.uid);
}
_validateAndSubmit() async {
setState(() {
_errorMessage = '';
_isLoading = true;
});
if (_validateAndSave()) {
try {
_fetchUID();
await Report.create(_uid, _suspectName, _plateNumber, _civilizationId,
_drivingLicenseId, _clause, _description);
return Navigator.of(context).pop();
} catch (e) {
setState(() {
_isLoading = false;
_errorMessage = e.message;
});
print(_errorMessage);
throw Exception(e);
}
}
}
In this method below you can see that I have already tried to set the _uid, but I still cannot get the _uid value.
Future _fetchUID() async {
var auth = AuthProvider.of(context).auth;
return await auth.getCurrentUser().then((user) => _uid = user.uid);
}
This is how the getCurrentUser() method looks like.
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
Am I doing it wrong?
First of all, you mixed the Future.then syntax and the async await syntax.
You should probably write your method this way:
void _fetchUID() async {
var auth = AuthProvider.of(context).auth;
_uid = (await auth.getCurrentUser()).uid;
}
If _uid is still null for you after calling _fetchUID this way, then you are simply not signed in, meaning that there is no FirebaseUser as you first need to sign in.
In your _validateAndSubmit method, you also first need to await your _fetchUID call, otherwise it will pass _uid before it has been assigned a value.
...
try {
await _fetchUID();
await Report.create(_uid, ..);
...

Flutter/Firebase : How can i access the current user without using '.then(...)' function

I'm trying to avoid using the .then((u) { return u.uid }) function in all my code where I need to access the current user's UID, instead just by calling getCurrentUser().uid for a much faster access. However, it gives me an error The getter 'uid' was called on null. but it's not null because it does print in the console but only after showing that it's null and the error at the end for some reason. I'm not well knowledge in the Future/Async/Await logic so any help would be greatly appreciated!
class UsersAPI {
final DatabaseReference usersRef = FirebaseDatabase.instance.reference().child(Config.users);
Future<FirebaseUser> currentUser() async {
return await FirebaseAuth.instance.currentUser();
}
FirebaseUser getCurrentUser() {
FirebaseUser user;
this.currentUser().then((u) {
user = u;
print('USER 1 $user'); // Prints after 'USER 2'
});
print('USER 2 $user'); // Prints first
if (user != null) {
return user;
} else {
return null;
}
}
DatabaseReference getCurrentUserRef() {
return this.usersRef.child(this.getCurrentUser().uid); // GIVES THE 'uid' WAS CALLED ON NULL ERROR
}
observeCurrentUser(Function onSuccess(User u)) {
this.usersRef.child(this.getCurrentUser().uid).onValue.listen( (event) { // GIVES THE 'uid' WAS CALLED ON NULL ERROR
DataSnapshot snapshot = event.snapshot;
if (snapshot.value != null) {
User user = User().transform(snapshot.key, snapshot.value);
onSuccess(user);
}
});
}
observeUser(String userID, Function onSuccess(User u), Function onFailure(String e)) {
this.usersRef.child(userID).onValue.listen( (e) {
DataSnapshot snapshot = e.snapshot;
if (snapshot.value != null) {
User user = User().transform(snapshot.key, snapshot.value);
onSuccess(user);
} else {
onFailure("User Not Found...");
}
});
}
}
Example Usage - WORKS:
APIs().usersAPI.currentUser().then((u) {
APIs().usersAPI.observeUser(u.uid, (u) {
onSuccess(u);
}, (e) {
print(e);
});
});
DOESN'T WORK:
APIs().usersAPI.observeCurrentUser((u) {
onSuccess(u);
});
DatabaseReference getCurrentUserRef() async {
return this.usersRef.child((await this.getCurrentUser()).uid); =
}
than call
var ref = await getCurrentUserRef()
Little bit more pretty
DatabaseReference getCurrentUserRef() async {
var firebaseUser = await this.getCurrentUser();
return this.usersRef.child(firebaseUser.uid);
}
EDIT: to clarify some question on asynchronicity
How would you call now this function to get the reference?
Lets say you want to update the data on the user, you can do
Firestore.instance.runTransaction((transaction) async {
var reference = await getCurrentUserRef();
await transaction.set(reference, someData);
});
Or you would like to read the data from that reference
readAndProcessData() async {
var reference = await getCurrentUserRef();
DocumentSnapshot user = await reference.get();
print(user.data.toString);
}

Resources