here's a screenshot of the code
the code was running well before my current position was printing on the console then I terminated the program and ran it again then it just stopped working
Firstly, you need to decare your position variable outside the function block to be able to access it within your build Widgets.
class _LoadingScreenState extends State<LoadingScreen> {
late Position position;
// ...
Next, you need to update the position state using setState;
// ...
setState(() {
position = await Geolocator.getCurrentPosition( /* complete the call here*/;
});
print(position);
// ...
For any more help or explanation feel free to comment below. Bye!
The official documentation is cleared and detailed. You can consult this link geolocator, It's shows the steps to be followed during the implementation of get the current location.
Firstly, checking is location service enabled in the device,
Secondly, checking and requesting permission to access the position of the device.
Finally, get location service when service is enabled and
permissions are granted .
The following code, it's copied from official documentation:
import 'package:geolocator/geolocator.dart';
/// Determine the current position of the device.
///
/// When the location services are not enabled or permissions
/// are denied the `Future` will return an error.
Future<Position> _determinePosition() async {
bool serviceEnabled;
LocationPermission permission;
// Test if location services are enabled.
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// Location services are not enabled don't continue
// accessing the position and request users of the
// App to enable the location services.
return Future.error('Location services are disabled.');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
// Permissions are denied, next time you could try
// requesting permissions again (this is also where
// Android's shouldShowRequestPermissionRationale
// returned true. According to Android guidelines
// your App should show an explanatory UI now.
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
// When we reach here, permissions are granted and we can
// continue accessing the position of the device.
return await Geolocator.getCurrentPosition();
}
Related
I want to ask user to enable permission only if he denied the permission or the permission is not allowed
This function is working very well on android
Future _getLocationPermission() async {
if (await Permission.location.request().isGranted) {
permissionGranted = true;
} else if (await Permission.location.request().isPermanentlyDenied) {
throw('location.request().isPermanentlyDenied');
} else if (await Permission.location.request().isDenied) {
throw('location.request().isDenied');
permissionGranted = false;
}
}
but on iOS it throw exception permission isPermanentlyDenied
Unhandled Exception: location.request().isPermanentlyDenied
even if the user allowed location permission while using app
I'm using permission_handler package
iOS is stricter, it does not allow you to request for permission if the user has already permanently denied it. In this case your only option is to inform the user about this, and offer the possibility to open application settings and grant permission there. This will likely restart your application if the user grants.
So check the status without requesting:
final status = await Permission.location.status;
If status is permanently denied, display a Flutter dialog (you can't use the system permission grant dialog in this case):
if (status == PermissionStatus.permanentlyDenied) {
// display a dialog, explain the user that he/she can grant
// permission only in the phone's application settings
}
If the user want's to do it, you can route to the application settings:
openAppSettings(); // this is a method of the permission handler package
This method is a future, but in my experience you don't need to await it.
This is just a function that returns bool if the user enables location
or not simple
Future<bool> canGetLocation(Location location) async {
if (!await location.requestService()) return false;
final status = await location.requestPermission();
final granted = PermissionStatus.granted;
final grantedLimited = PermissionStatus.grantedLimited;
bool result = status == granted || status == granted;
return result;
}
if (await canGetLocation(location)) {
// Do something
} else {
final status = await handler.Permission.location.status;
if (status.isPermanentlyDenied || status.isDenied) {
// ask the user to open the app setting
// from permission handler package you have
openAppSettings();
} else {
// show info dialog or something that the user need to enable location services
}
}
Please check this link. You must have to mention permission in POD file also.
I'm using the permission_handler package to request permissions on Android. A user is able to download a file to the downloads folder when he clicks on "Allow" in the Permission.storage popup. (We are calling it Permission.storage when the user installs the app.)
The issue is that if a user clicks on "Don't allow" the first time and "Allow" the second time in other flows in the app, we are still getting a permission denied error and the user is not able to download files like above flow. I've logged and checked the value of the status; it is coming as PermissionStatus.granted only which is expected. Any ideas on how to fix this?
Below is the error log
I/flutter ( 8170): could not download file FileSystemException: Cannot open file, path = '/storage/emulated/0/Download/codes.txt' (OS Error: Permission denied, errno = 13)
/// Permission snippet of first time
final permission =
GetPlatform.isAndroid ? Permission.storage : Permission.photos;
final status = await permission.status;
if (status != PermissionStatus.granted) {
await permission.request().isGranted;
}
/// Snippet when user clicks on download second time
final permission = Permission.storage;
final status = await permission.status;
debugPrint('>>>Status $status'); /// here it is coming as PermissionStatus.granted
if (status != PermissionStatus.granted) {
await permission.request().isGranted;
debugPrint('>>> ${await permission.status}');
}
directory = Directory('/storage/emulated/0/Download');
///perform other stuff to download file
when permission_handler package send request to user with request() function, we made in await so after close dialog you check second time if permission granted or not and if permission granted then perform other stuff to download file else you can again send request for the permission.
/// Snippet when user clicks on download second time
final permission = Permission.storage;
final status = await permission.status;
debugPrint('>>>Status $status'); /// here it is coming as PermissionStatus.granted
if (status != PermissionStatus.granted) {
await permission.request();
if(await permission.status.isGranted){
directory = Directory('/storage/emulated/0/Download');
///perform other stuff to download file
} else {
await permission.request();
}
debugPrint('>>> ${await permission.status}');
}
directory = Directory('/storage/emulated/0/Download');
///perform other stuff to download file
I'm using the geolocator package to get the current location of a device. I recently installed a location Spoofer app to test some features .
However, upon using the spoofer, geolocator seems to break? It never returns a location whenever I try to get a location.
How do I resolve this issue? Thank you for your help!
(the problem is that the location no longer returns even after I uninstall the location spoofer. The GPS functions for my app no longer work on the device)
Heres the function I call whenever I try to get a location
Future<Position> getCurrentLocation() async {
bool serviceEnabled;
LocationPermission permission;
Position position;
// ignore: await_only_futures
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// ignore: await_only_futures
await requestLocation();
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
callSnackbar('Error', 'Location services are disabled');
return Future.error('Location services are disabled.');
}
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.deniedForever) {
callSnackbar('Error',
'Location permissions are permantly denied, we cannot request permissions');
return Future.error(
'Location permissions are permantly denied, we cannot request permissions.');
}
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission != LocationPermission.whileInUse &&
permission != LocationPermission.always) {
callSnackbar('Error',
'Location permissions are denied (actual value: $permission)');
return Future.error(
'Location permissions are denied (actual value: $permission).');
}
}
print('LOGIC');
position = await Geolocator.getCurrentPosition();
if (position == null) {
print('null');
} else {
print('LOCATION');
print(position);
}
return position;
}
and heres an example of me calling the function:
getCurrentLocation().then((contents) {
print('getting location');
print(contents.latitude);
);
}, onError: (e) {}).timeout(const Duration(seconds: 5),
onTimeout: () {
callSnackbar('Error', 'Couldn\'t get location');
});
the above code works fine until I install and use a location spoofer app. So even after the uninstall, the app no longer works and just timeouts because the future does not return.
Using a spoofer app on a real device could be difficult as many devices implement protections that block it from working.
While you are developing, instead of using a Spoofer app from a real device, I would use a Virtual emulator from Android Studio (AVD).
By doing soo you can use the Location tool directly provided with the emulator.
As you can see from the images, that tool enable you to use GPX or KML file to provide a location to your device.
I found this article which describe how you can build your own route: Here
Another way of providing location to a virtual device could be using a the command line tool Telnet.
I was able in the past to write a python script which uses Telnet to provide gps location to my AVD.
In that way you can have more control over the location, in my opinion.
I'm sure this is a silly error on my behalf.
Using Permission_handler to request camera permissions on iOS.
On first attempt the dialog shows requesting permission and successfully approves or denies. However, if I deny the request first and try launching the camera again there is no dialog requesting permissions.
static Future<bool> checkCameraPermissions() async {
PermissionStatus status = await Permission.camera.status;
if (status.isUndetermined || status.isDenied) {
print('cam is denied or undetermined'); //Prints
PermissionStatus newStatus = await Permission.camera.request();
print(await Permission.camera.isDenied); //Prints 'true' immediately
if (newStatus.isDenied)
return false;
print('cam is approved!'); //Nope QQ
}
return true;
}
How do I force Permission_handler to request the user again?
According to Apple, the user response is stored and the dialog doesn't open again. You can read more about it over here
What you can do is show a dialog with steps to enable required permissions and open settings page.
I have problem when user entered google map page without location enabled the map wont updated so i want to check if the user have location enabled beforehand so i need function that return true if location enabled and false if not.
use permission handler plugin
ServiceStatus serviceStatus = await PermissionHandler().checkServiceStatus(PermissionGroup.location);
bool enabled = (serviceStatus == ServiceStatus.enabled);
you can also show a rationale for requesting permission (Android only)
bool isShown = await PermissionHandler().shouldShowRequestPermissionRationale(PermissionGroup.location);
or Location Plugin
var location = Location();
bool enabled = await location.serviceEnabled();
and request to enable it by
bool gotEnabled = await location.requestService();
for those who came to this stackoverflow question like myself, there have been changes and updates on PermissionHandler package and the older solutions are now invalid.
you can check if the location service is enabled:
if (await Permission.locationWhenInUse.serviceStatus.isEnabled) {
// Use location.
}
You can install the permission handler plugin and then use it:
final PermissionStatus permission = await PermissionHandler()
.checkPermissionStatus(PermissionGroup.location);