我已经使用
Location
实现了一个渐进式 Geolocator
权限请求,因为我需要我的应用程序的后台位置,并且 Android
和 iOS
平台都要求它只有在被授予 while in use
权限后才被询问。问题是,虽然在 Android
上它一切都按预期工作,但我第二次使用 Prominent Disclosure
请求许可它打开 Location Permission
屏幕,在 iOS
上没有显示第二个弹出窗口要求更改always allow
的权限,只返回 LocationPermission.whileInUse
状态。
在运行 iOS
12.5 的 iPhone6 和运行 iOS 16
的模拟器上都尝试过,但没有出现第二个系统弹出窗口。
第二次请求权限时,我期望看到第二个系统弹出窗口,我错了吗?
这里是控制台的打印:
// at start
flutter: LocationBloc.getLocationPermission value is denied
// at first request system popup appears
flutter: LocationBloc._requestLocationPermission value is whileInUse
// at second request system popup doesn't appear
flutter: TrackingRepository.getLocationPermission() LocationPermission is: LocationPermission.whileInUse
flutter: TrackingBloc._getBackgroundLocationPermission value is whileInUse
flutter: TrackingRepository.requestLocationPermission() LocationPermission is: LocationPermission.whileInUse
flutter: TrackingBloc._requestLocationPermission value is whileInUse
这是请求权限的方法:
Future<String> requestLocationPermission() async {
return await locationManager.checkPermission().then((value) async {
late String permission;
if (value != LocationPermission.always) {
permission =
await locationManager.requestPermission().then((value) async {
print(
'TrackingRepository.requestLocationPermission() LocationPermission is: $value');
switch (value) {
case LocationPermission.denied:
return 'denied';
case LocationPermission.deniedForever:
return 'deniedForever';
case LocationPermission.whileInUse:
return 'whileInUse';
case LocationPermission.always:
return 'always';
case LocationPermission.unableToDetermine:
return 'unableToDetermine';
}
}).catchError((e) {
print('TrackingRepository.requestLocationPermission() error: $e');
});
}
return permission;
});
}
我已经设置了
Deployment target: 12.4
,在info.plist
中添加了两个条目
<key>NSLocationWhenInUseUsageDescription</key>
<string>fixit needs you position to enable its functionalities</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>fixit needs your position to enable you to track your routes even when is in background</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>fixit needs your position to enable you to track your routes even when is in background</string>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>location</string>
<string>processing</string>
<string>remote-notification</string>
</array>
我还在
Location updates
中添加了Signing & Capabilities/Background Modes
。
这是位置流方法,区分
Android
和iOS
设置:
Stream<Position> startTracking() {
_positionStreamController = new StreamController<Position>.broadcast();
locationManager.checkPermission().then((value) async {
if (value == LocationPermission.denied ||
value == LocationPermission.deniedForever ||
value == LocationPermission.whileInUse) {
await locationManager.requestPermission().then((value) {
print(
'TrackingRepository.startTracking() requestPermission is: $value');
}).catchError((e) {
print(
'TrackingRepository.startTracking() requestPermission error: $e');
});
}
}).catchError((e) {
print('TrackingRepository.startTracking() error: $e');
});
late var locationSettings = Platform.isIOS
? AppleSettings(
accuracy: LocationAccuracy.bestForNavigation,
allowBackgroundLocationUpdates: true,
showBackgroundLocationIndicator: true,
activityType: ActivityType.otherNavigation)
: LocationSettings(accuracy: LocationAccuracy.best, distanceFilter: 0);
_positionSubscription = locationManager
.getPositionStream(locationSettings: locationSettings)
.listen((event) {
_positionStreamController.sink.add(event);
});
return _positionStreamController.stream;
}
现在,当我在装有 iOS 12.5 的 iPhone 6 上试用它时,我在系统弹出窗口中只看到
Accept
和Deny
选项,但我还期望有一个Always allow
选项,所以我必须手动选择它否则未收到背景位置更新。
不应该出现第二个系统弹出窗口以允许更改权限吗?
我错过了一些设置吗? 非常感谢。
在多次尝试(全部失败)以打开第二个系统弹出窗口以请求
always
权限后,我开始认为正如 Paulw11
所评论的那样,问题可能出在 Geolocator
所做的通用位置权限请求,所以我决定尝试 permission_handler
插件(只是为了 iOS
开始)它允许检查状态并请求特定的位置权限类型。它确实有效..它现在终于打开了第二个系统弹出窗口,因此用户可以在 iOS(在模拟器和我即将退休的 iPhone6 上)以及 Android 平台上将权限更改为始终。一般位置许可实际上可能是 iOS
没有显示第二个系统弹出窗口的真正原因,即使我使用 permission_handler
也没有显示第二个系统弹出窗口,而 Permission.location.request()
显示。
这是工作代码:地点
Permission.locationWhenInUse.request()
Bg位置
/// Using permission_handler for both platforms
Future<String> getLocationPermission() async {
print('\n\nLocationRepository.getLocationPermission() started\n\n');
late String permission;
permission = await Permission.locationWhenInUse.status.then((value) {
print(
'\n\n LocationRepository.getLocationPermission Permission.locationWhenInUse.status is ${value.name}');
// permission = await Permission.location.status.then((value) {
// print(
// '\n\n LocationRepository.getLocationPermission Permission.location.status is ${value.name}');
switch (value) {
case PermissionStatus.denied:
return 'denied';
case PermissionStatus.permanentlyDenied:
return 'deniedForever';
case PermissionStatus.limited:
return 'limited';
case PermissionStatus.granted:
return 'granted';
case PermissionStatus.restricted:
return 'restricted';
}
});
return permission;
}
Future<String> requestLocationPermission() async {
print('LocationRepository.requestLocationPermission started');
late String permission;
// general location doesn't open the popup
// var status = await Permission.location.status;
// print('Permission.location.status is $status');
var status = await Permission.locationWhenInUse.status;
print('Permission.locationWhenInUse.status is $status');
/// NOT Granted
if (!status.isGranted) {
// var status = await Permission.location.request();
// print('Permission.location.request() status is $status');
var status = await Permission.locationWhenInUse.request();
print('Permission.locationWhenInUse.request() status is $status');
if (status.isGranted) {
permission = 'granted';
} else {
permission = 'denied';
}
}
/// Granted
else {
permission = 'granted';
}
return permission;
}