问题描述
当用户单击“不允许”时,我正在使用各种插件来获取用户数据,联系人,照片和相机,该应用程序将保持静音。 我想在用户选中``不再询问并且不允许''并再次进入应用程序时向用户显示``询问权限''对话框。
当前,当用户选中“不允许”时,应用程序再也不会询问
我知道用户必须授予应用访问权限才能访问个人信息,包括当前位置,相机,日历,联系人, mediaLibrary ,麦克风,传感器,语音和照片。尽管人们喜欢使用可以访问此信息的应用程序所带来的便利,但他们也希望能够控制自己的私人数据。例如,人们喜欢能够自动标记其实际位置的照片或找到附近的朋友,但他们也希望选择禁用这些功能。
如何再次扑通用户权限?
解决方法
我对此问题感到非常烦恼。应用了几种解决方案后,我发现了该解决方案。所以我想与所有人分享,这就是为什么我问这个问题并回答了
在大多数操作系统上,安装时不仅仅向应用授予权限。相反,开发人员必须在应用程序运行时向用户询问权限。
处理权限的最佳方法是使用permission_handler 插入。该插件提供了跨平台(iOS,Android)API来请求权限并检查其状态。
我们还可以打开设备的应用程序设置,以便用户可以授予权限。 在Android上,我们可以显示请求权限的原理。
-
将此添加到软件包的
pubspec.yaml
文件中:dependencies: permission_handler: ^5.0.1+1
-
现在在Dart代码中,您可以使用:
import 'package:permission_handler/permission_handler.dart';
-
在运行时请求权限的同时,您仍然需要告诉OS您的应用程序可能使用哪些权限。这就需要向Android和iOS专用文件添加权限配置。
iOS
- 向您的Info.plist文件添加权限。 Here是一个示例Info.plist,其中包含所有可能的权限的完整列表。
Android
-
将以下内容添加到“
gradle.properties
”文件中:android.useAndroidX=true android.enableJetifier=true
-
确保将“
compileSdkVersion
”文件中的android/app/build.gradle
设置为28:android { compileSdkVersion 28 ... }
-
确保您替换了所有的android系统。依赖于其AndroidX对应版本(可在此处找到完整列表:https://developer.android.com/jetpack/androidx/migrate)
为您的
AndroidManifest.xml
文件添加权限。有debug
,main
和profile
版,具体取决于您启动应用程序的方式。通常,仅向版本main
添加权限就足够了。这是一个示例AndroidManifest.xml
,其中包含所有可能的权限的完整列表。 -
有许多权限。您可以获得
Permission
的{{1}},可以是status
,undetermined
,granted
,denied
或restricted
。permanentlyDenied
在
var status = await Permission.camera.status; if (status.isUndetermined) { // We didn't ask for permission yet. } // You can can also directly ask the permission about its status. if (await Permission.location.isRestricted) { // The OS restricts access,for example because of parental controls. }
上致电request()
进行请求。如果以前已授予它,则什么也不会发生。Permission
返回request()
的新状态。Permission
在Android上,您可以显示使用权限的原理:
if (await Permission.contacts.request().isGranted) { // Either the permission was already granted before or the user just granted it. } // You can request multiple permissions at once. Map<Permission,PermissionStatus> statuses = await [ Permission.location,Permission.storage,].request(); print(statuses[Permission.location]);
完整示例
bool isShown = await Permission.contacts.shouldShowRequestRationale;
,
为简单起见,我使用了位置权限。要请求其他权限,只需将位置替换为该权限即可。这是list of all permissions。
1.安卓设置:
-
将这些添加到
android/grade.properties
文件:android.useAndroidX=true android.enableJetifier=true
-
在
android/app/build.gradle
文件中:android { compileSdkVersion 30 // Set this to at least 30 ... }
-
为
android/app/src/main/AndroidManifest.xml
文件添加权限<manifest xmlns:android="http://schemas.android.com/apk/res/android" <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> ... </manifest>
2. iOS 设置:
-
将此添加到
info.plist
文件:<key>NSLocationWhenInUseUsageDescription</key> <string>App needs location permission to work</string>
-
将
PERMISSION_LOCATION=1
添加到Podfile
:post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)',## Add the following line. 'PERMISSION_LOCATION=1' ] end end end
3.颤振设置:
将此添加到 pubspec.yaml
文件:
permission_handler: ^8.0.0+2
主要工作:
-
检查权限:
检查位置(即 GPS)是否开启。
final serviceStatus = await Permission.locationWhenInUse.serviceStatus; bool isGpsOn = serviceStatus == ServiceStatus.enabled;
-
请求许可:
final status = await Permission.locationWhenInUse.request(); if (status == PermissionStatus.granted) { print('Permission granted'); } else if (status == PermissionStatus.denied) { print('Denied. Show a dialog with a reason and again ask for the permission.'); } else if (status == PermissionStatus.permanentlyDenied) { print('Take the user to the settings page.'); }
完整代码:
class HomePage extends StatelessWidget {
Future<void> _checkPermission() async {
final serviceStatus = await Permission.locationWhenInUse.serviceStatus;
final isGpsOn = serviceStatus == ServiceStatus.enabled;
if (!isGpsOn) {
print('Turn on location services before requesting permission.');
return;
}
final status = await Permission.locationWhenInUse.request();
if (status == PermissionStatus.granted) {
print('Permission granted');
} else if (status == PermissionStatus.denied) {
print('Permission denied. Show a dialog and again ask for the permission');
} else if (status == PermissionStatus.permanentlyDenied) {
print('Take the user to the settings page.');
await openAppSettings();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: _checkPermission,child: Text('Check Permission'),),);
}
}
,
我建议使用 permission_handler
库并编写抽象代码(策略模式)以相同的方式处理所有权限。通常,文档是模糊的,并且没有显示如何处理不可恢复/禁用情况。
代码:
/// handles .isLimited for iOS 14+ where we can restrict access.
abstract class GrantPermissionStrategy {
final Permission permission;
GrantPermissionStrategy(this.permission);
Future<void> request({
required final OnPermatentlyDenied onPermatentlyDenied,required final OnGranted onGranted,}) async {
PermissionStatus status = await permission.status;
print("GrantPermissionStrategy status: $status");
if (status.isPermanentlyDenied) {
onPermatentlyDenied.call();
return;
}
if (!status.isLimited && !status.isGranted) {
final PermissionStatus result = await permission.request();
if (!result.isGranted) {
return;
}
}
onGranted.call();
}
}
typedef OnPermatentlyDenied = void Function();
typedef OnGranted = void Function();
而且,你可以做出具体的实现,比如:
class GrantPermissionCameraStrategy extends GrantPermissionStrategy {
GrantPermissionCameraStrategy() : super(Permission.camera);
}
class GrantPermissionPhotosStrategy extends GrantPermissionStrategy {
GrantPermissionPhotosStrategy() : super(Platform.isAndroid ? Permission.storage : Permission.photos);
}
最后,调用它!:
await GrantPermissionPhotosStrategy().request(onPermatentlyDenied: () {
// launch dialog,make user go to app settings
},onGranted: () async {
// we have passed! Launch the feature.
});
}