Flutter中的请求权限服务的实现
当你想在用户使用过程中获取很多很多权限的时候,请求权限通常会成为一个混乱的任务。
为了开始清理所有的权限代码,我们将把它包装在一个带有专门权限请求功能的服务中。
设置
在本教程中,我们将使用permissions_handler包来请求我们的权限,所以让我们把它添加到pubspec中。
# Permission checking
permission_handler: ^9.2.0
我们将创建函数来请求两种类型的权限:我们将获取位置以及联系人权限。
首先,我们需要告诉操作系统,我们的应用程序将使用这些权限。
安卓
在AndroidManifest中,为这两个功能添加uses-permission标签。
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
iOS
在info.plist文件中添加密钥和你的信息
<key>NSContactsUsageDescription</key>
<string>This app requires contacts access to function.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app requires access to your location when in use to show relevan information.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app requires always on access to to your location to notifiy you when are near a store.</string>
实施
PermissionsService上将有一个专门的函数来处理你所需要的权限。
这样,当用户想使用需要的功能时,就可以调用它。
通过提供回调,它也将很容易为每个函数(组)编写自定义逻辑。
创建一个名为permissions_service.dart的新文件,在其中,我们要做一个类,它有一个来自包的PermissionHandler的实例。
import 'package:permission_handler/permission_handler.dart';
class PermissionsService {
final PermissionHandler _permissionHandler = PermissionHandler();
}
然后我们可以添加一个通用函数,接收一个PermissionGroup来请求我们想要的权限。
...
Future<bool> _requestPermission(PermissionGroup permission) async {
var result = await _permissionHandler.requestPermissions([permission]);
if (result[permission] == PermissionStatus.granted) {
return true;
}
return false;
}
...
而使用这个函数,我们可以为每个权限创建特定的函数。
...
/// Requests the users permission to read their contacts.
Future<bool> requestContactsPermission() async {
return _requestPermission(PermissionGroup.contacts);
}
/// Requests the users permission to read their location when the app is in use
Future<bool> requestLocationPermission() async {
return _requestPermission(PermissionGroup.locationWhenInUse);
}
...
自定义许可逻辑
很多时候,当涉及到权限的时候,我们想做一些自定义的事情,或者想再次提示用户允许我们的权限。因为我们有专门的功能,我们现在可以用自定义的方式处理每个权限请求。
比方说,应用程序需要访问联系人才能工作,类似于WhatsApp。我们可以提供一个函数,当权限被拒绝时就会被调用,这样我们就可以在外面显示一个对话框。
我们将传入一个onPermissionDenied函数,当用户拒绝许可时,该函数将被调用。
/// Requests the users permission to read their contacts.
Future<bool> requestContactsPermission({Function onPermissionDenied}) async {
var granted = await _requestPermission(PermissionGroup.contacts);
if (!granted) {
onPermissionDenied();
}
return granted;
}
现在在外面,你可以传入你的函数,当它被拒绝时显示你的对话框,然后如果用户选择再次请求它 :)
拥有权限
另一件事是检查应用程序是否已经拥有权限。
我们将创建同样的设置,一个通用的函数接收一个PermissionGroup,然后为特定的权限使用专用函数。
你不必这样做,我只是觉得这样做更容易维护,而且它使外部代码对PermissionHandler包的依赖性降低。
...
Future<bool> hasContactsPermission() async {
return hasPermission(PermissionGroup.contacts);
}
Future<bool> hasPermission(PermissionGroup permission) async {
var permissionStatus =
await _permissionHandler.checkPermissionStatus(permission);
return permissionStatus == PermissionStatus.granted;
}
...
使用方法
在代码中,我们现在可以像这样使用服务来请求权限。
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Center(
child: MaterialButton(
color: Colors.yellow[300],
child: Text('Request contacts permission'),
onPressed: () {
PermissionsService().requestContactsPermission(
onPermissionDenied: () {
print('Permission has been denied');
});
},
),
),
));
}
}
服务应该被注入或定位,如图所示,只使用提供者或像这样的架构中的提供者和get_it。
将你的功能包装在一个服务中,可以消除你的代码和第三方实现细节之间的任何关系,所以对我来说,这一直是一个首选解决方案。