By using simple_permissions and location package of Dart, it is only asking for user permission to ALLOW or DENY the app to use device location to show the current location of user on Google Maps.
When i turn on the GPS manually on my device, I'm able to get the current location, but how can I ask the user to enable GPS from the app itself with a dialog to enable the GPS like Google Maps?
This Plugin shows the Turn on Gps Dialogue for flutter (as like the Native android)
If you already have geolocator or if you are using the two (geolocator and location packages), then first import one of them as an alias, for example for location, import it as:
import 'package:location/location.dart' as loc;
loc.Location location = loc.Location();//explicit reference to the Location class
Future _checkGps() async {
if (!await location.serviceEnabled()) {
location.requestService();
}
}
Notice that use of var location = Location() or var location = loc.Location() wont work, you have to reference the Location class exclusively with the alias loc for the example above.
Then call the method in the initState as below to be checked every once the app starts as below:
#Override
void initState()
{
super.initState();//comes first for initState();
_checkGPS();
}
you can user location library
var location = Location();
Future checkGps() async {
if (!await location.serviceEnabled()) {
location.requestService();
}
}
With the use of (android_intent: ^2.0.2), you can request GPS in android
if (Platform.isAndroid) {
Get.dialog(
AlertDialog(
title: Text("Can't get current location"),
content: const Text('Please make sure you enable GPS and try again'),
actions: <Widget>[
TextButton(
child: Text('Ok'),
onPressed: () {
GeneralController.to.isPermissionAsked.value = true;
final AndroidIntent intent = AndroidIntent(action: 'android.settings.LOCATION_SOURCE_SETTINGS');
intent.launch();
Get.back();
})
],
),
barrierDismissible: false,
);
}
and handle it in
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
print("app in resumed");
break;
case AppLifecycleState.inactive:
print("app in inactive");
break;
case AppLifecycleState.paused:
print("app in paused");
break;
case AppLifecycleState.detached:
print("app in detached");
break;
}
}
if you using the Geolocator package , just use this code below and Geolocator will open a location service for the user to turn it on then rebuild your widget
await Geolocator.openLocationSettings().then(value){
//call function of whatever you need to do
}
By using access_settings_menu, the location settings page can be opened for Android devices
Related
I am developing in Flutter and am trying to get GPS information using the geolocator package.
I was able to get GPS information on the emulator with no problem, but when I started the app on the actual device, I could not get GPS.
The app was working fine, so it was not an error, but there was a message.
"This method can cause UI unresponsiveness if invoked on the main thread. Instead, consider waiting for the -locationMana gerDidChangeAuthorization: callback and checking authorizationStatus first."
Code on Flutter side
Future<Position> getGps(BuildContext context) async {
return await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
timeLimit: Duration(seconds: 5),
);
}
(WARNING)Code on IOS side
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return [CLLocationManager locationServicesEnabled] ? ServiceSttus Enabled
: ServiceStatusDisabled;
}
2023/1/26 added
I had added it to info.plist. Still, I am not getting GPS information.
info.plist
<key>NSLocationAlwaysUsageDescription</key>
<string>Access location information to get a location</string>.
<key>NSLocationWhenInUseUsageDescription</key>
<string>Access location information to get location</string>
How do I get GPS information?
Permission to acquire location services is granted.
iOS:16.2
xcode: 14
geolocator: 7.7.1
2023/1/26 added
Current Status
Emulator(Android) ...〇(GPS information has been acquired.)
Emulator(iOS(iphone SE2)) ...〇(GPS information has been acquired.)
Actual Device(iOS(iphone SE2)) ...× (GPS cannot be acquired)
Try this
Add "location_permissions: 3.0.0+1" this dependencies in "pubspec.yaml". Please note that I did that for flutter 1.22.0 so for flutter 2.0 this might be an issue.
Import the package in the file
import 'package:location_permissions/location_permissions.dart';
Add the following code on the page where you want to ask for permission. (Better to add that on the very first page of your app.)
#override
void initState() {
....
if (Platform.isIOS) {
location_permission();
}
....
}
Add the following two methods in the same file
void location_permission() async {
final PermissionStatus permission = await _getLocationPermission();
if (permission == PermissionStatus.granted) {
final position = await geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best);
// Use the position to do whatever...
}
}
Future<PermissionStatus> _getLocationPermission() async {
final PermissionStatus permission = await LocationPermissions()
.checkPermissionStatus(level: LocationPermissionLevel.location);
if (permission != PermissionStatus.granted) {
final PermissionStatus permissionStatus = await LocationPermissions()
.requestPermissions(
permissionLevel: LocationPermissionLevel.location);
return permissionStatus;
} else {
return permission;
}
}
I was able to solve my problem.
I thought it was a permissions issue in my case, but it was just a location acquisition timeout. I modified the location acquisition timeout from 5 seconds to 20 seconds and was able to get the necessary information without any problems.
The warnings are still there, but we decided not to worry about them since we were able to solve the problem.
return await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
timeLimit: Duration(seconds: 20),
);
I am building an app using React Native and photo upload is one of its key functions. Here is what I am trying to do:
When the user clicks on the button to open the camera roll, tell whether the user allowed camera access or not.
If the user didn't allow, show an alert to ask the user to turn on the permission from settings to ensure proper experience on the app.
Where should I look at to start tackling this? I am new to programming in general and not familiar at all with native code. I know this is a high-level question so some high-level guidance will be appreciated. Thanks!
You can start at looking at react-native-permissions module. It allows you to ask for any kind of permissions that a mobile app can require, and also the dialogs are handled natively so you dont have to worry about building the alerts yourself.
https://github.com/zoontek/react-native-permissions
Here's an example on how to handle image selection with permissions
import ImagePicker, {
ImagePickerOptions,
ImagePickerResponse,
} from 'react-native-image-picker';
import { openSettings } from 'react-native-permissions';
import { alertWrapper } from './alert';
export const selectPicture = (options: ImagePickerOptions) => {
const pickerPromise = new Promise<ImagePickerResponse>((resolve) => {
try {
ImagePicker.showImagePicker(options, (response: ImagePickerResponse) => {
if (response.didCancel) {
return;
}
if (response.error) {
if (response.error.includes('permissions')) {
alertWrapper('Error', response.error, [
{ text: 'Open Settings', onPress: () => openSettings() },
]);
}
return;
}
resolve(response);
});
} catch (e) {
throw e;
}
});
return pickerPromise;
};
Whenever I am opening my app I need to check the GPS is on or off. If the GPS is off, I need to redirect the user to the location settings page. I have done the android part using the dependency service like below.
ILocSettings
public interface ILocSettings
{
void OpenSettings();
bool isGpsAvailable();
}
Android implementation
[assembly: Dependency(typeof(LocationShare))]
namespace Projectname.Droid.Services
{
public class LocationShare : ILocSettings
{
public bool isGpsAvailable()
{
bool value = false;
Android.Locations.LocationManager manager = (Android.Locations.LocationManager)Android.App.Application.Context.GetSystemService(Android.Content.Context.LocationService);
if (!manager.IsProviderEnabled(Android.Locations.LocationManager.GpsProvider))
{
//gps disable
value = false;
}
else
{
//Gps enable
value = true;
}
return value;
}
public void OpenSettings()
{
Intent intent = new Android.Content.Intent(Android.Provider.Settings.ActionLocationSourceSettings);
intent.AddFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
}
}
}
Finally from the shared project called like below:
//For checking the GPS Status
bool gpsStatus = DependencyService.Get<ILocSettings>().isGpsAvailable();
//For opening the location settings
DependencyService.Get<ILocSettings>().OpenSettings();
For ios how I can I do the same features? I tried like below:
[assembly: Dependency(typeof(LocationShare))]
namespace Projectname.iOS.Serivces
{
class LocationShare : ILocSettings
{
public bool isGpsAvailable()
{
//how to check the GPS is on or off here
}
public void OpenSettings()
{
UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));
}
}
}
Location settings page opening on ios simulators, but don't know how to check the GPS status.
Update1
I have tried the CLLocationManager code and it is not working as expected. It returns true always even if the location is off or on.
OpenSettings() function code (UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));) is also not working as expected, it is redirecting to some other page, I need to open the location settings page if the GPS is off.
Also, I am requesting location permission like below:
var status = await Permissions.RequestAsync<Permissions.LocationAlways>();
In android, location permission is asking, but in ios, no permissions are asking.
Update2
I have tried the new codes and getting false value always as GPS status. I have added all the location permission on the info.plist like below:
But location permission is not asking when running the app (not even a single time). I have tried Permissions.LocationWhenInUse instead of Permissions.LocationAlways, but no luck.
Update 3
Following is my complete flow for checking location permission, checking GPS status, and open settings. The permission status value is always Disabled.
//Requesting permission like below:
var status = await Permissions.RequestAsync<Permissions.LocationAlways>();
if (status == PermissionStatus.Granted)
{
//Then checking the GPS state like below
bool gpsStatus = DependencyService.Get<ILocSettings>().isGpsAvailable();
if (!gpsStatus)
{
//show a message to user here for sharing the GPS
//If user granted GPS Sharing, opening the location settings page like below:
DependencyService.Get<ILocSettings>().OpenSettings();
}
}
I have tried the below 2 codes for requesting or checking permission. In both cases, the status value is Disabled. If I uninstall the app and reinstall it again, getting the same status and not showing any permission pop-up window.
var status = await Permissions.RequestAsync<Permissions.LocationAlways>();
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
Unlike the Android system, iOS can set the GPS switch separately, and can only get the status of whether the location service is turned on. The rest of the specific positioning method will be left to the iOS system to choose.
At the beginning, we need to have a look at the status of location in iOS:
CLAuthorizationStatus Enum
UIApplicationOpenSettingsURLString: Used to create a URL that you can pass to the openURL: method. When you open the URL built from this string, the system launches the Settings app and displays the app’s custom settings, if it has any.
From now, iOS only support this way to displays the app’s custom settings. There are two helpful discussion, you could have a look. How to jump to system setting's location service on iOS10? and Open Location Settings Not working in ios 11 Objective c?.
If it is redirecting to some other page as follows:
That means your app not do any settings about the location service after installing the app . Therefore, you not need to open the setting page, because it will not show the location service bellow the setting page of your app. Now the CLAuthorizationStatus should be NotDetermined. You could use CLLocationManager.RequestWhenInUseAuthorization to request the permission, the
popup window of location service will show for customer to choose inside the app.
If customer select Don't Allow first time, that means next time opening the app to check the location service that will show Denied status. Now you will need to use UIApplicationOpenSettingsURLString to open the settings page and will see the location service inside the app’s custom settings list.
At last, the final code of LocationShare is as follows:
public class LocationShare : ILocSettings
{
public bool isGpsAvailable()
{
bool value = false;
if ( CLLocationManager.LocationServicesEnabled )
{
if(CLLocationManager.Status == CLAuthorizationStatus.Authorized || CLLocationManager.Status == CLAuthorizationStatus.AuthorizedAlways || CLLocationManager.Status == CLAuthorizationStatus.AuthorizedWhenInUse)
{//enable
value = true;
}
else if (CLLocationManager.Status == CLAuthorizationStatus.Denied)
{
value = false;
OpenSettings();
}
else{
value = false;
RequestRuntime();
}
}
else
{
//location service false
value = false;
//ask user to open system setting page to turn on it manually.
}
return value;
}
public void RequestRuntime()
{
CLLocationManager cLLocationManager = new CLLocationManager();
cLLocationManager.RequestWhenInUseAuthorization();
}
public void OpenSettings()
{
UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));
}
}
Similarly, if CLAuthorizationStatus is Denied (the same as status == PermissionStatus.Unknown in Forms), the following code will not work in Forms.
var status = await Permissions.RequestAsync<Permissions.LocationAlways>();
It only works when CLAuthorizationStatus is NotDetermined. And you'd better request Permissions.LocationWhenInUse instead of Permissions.LocationAlways, this should be the better recommanded option.
============================Update #2================================
I have modified the above code, and you will see that if CLLocationManager.LocationServicesEnabled is false, we only can ask user to redirect to the system setting page to turn on the service manually. Because from iOS 10, iOS not supports to navigate to system setting page from non-system app.
============================Update #3======================================
If location service is enabled, when using UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString)); method you will see the similar screenshot as follows:
The Loaction option will show in the list.
I'm using qr_code_scanner to scan barcodes in my Flutter app and it works fine for Android, but when I try to scan for iOS a pop-up appears and looks like:
I'm using the descriptions Flutter code that looks like the following:
QRView(
key: qrKey,
onQRViewCreated: (controller) => {
controller.scannedDataStream.listen((code) async {
...
})
})
And in my Info.plist file I have the following fields:
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera permission is required to scan QR codes.</string>
However even with these settings set, I can't seem to figure out how to have access to the camera. Thanks for any help.
Update
I followed #EvgeniyTrubilo suggestion and used permission_handler to request permission using the following code:
void getCameraPermission() async {
print(await Permission.camera.status); // prints PermissionStatus.granted
var status = await Permission.camera.status;
if (!status.isGranted) {
final result = await Permission.camera.request();
if (result.isGranted) {
setState(() {
canShowQRScanner = true;
});
} else {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Please enable camera to scan barcodes')));
Navigator.of(context).pop();
}
} else {
setState(() {
canShowQRScanner = true;
});
}
}
The first time this code was executed it successfully requested permission to access camera, and once permission was granted, the same error showed up. Sequential tries the print statement at the top of the above function said the Permission was granted??
Update 2x
Just realized you can mock the camera in an iOS simulator like you can on Android. I will try this on an actual device and update.
You can use permission_handler. With this, you could ask for camera permission before build QRView. Of course, you should build QRView after camera permission is enabled.
I'm not sure it would be right solution for your issue, but I think that would be an awesome improvement.
My application collects location data when the user presses on a certain button, but if the user turns gps option off then turns it back the location no more works even if the gps is enabled.How to handle such a thing in flutter??
As per example in this link https://pub.dartlang.org/packages/location you should put add below code in button's click event.
var location = new Location();
// Platform messages may fail, so we use a try/catch PlatformException.
try {
currentLocation = await location.getLocation;
} on PlatformException {
currentLocation = null;
}