com*_*guy 3 c# permissions maui
我正在寻找一种简单的方法来查询和请求 .Net Maui 中的多个权限。我还需要请求蓝牙权限,但据我所知,毛伊岛没有内置的蓝牙权限。我在 2022 年最后一次听到的消息是,毛伊岛路线图中没有蓝牙,我觉得这是相当短视的。
我读了很多文章、问答、文档、观看了视频,并做了很多其他研究来解决这个问题。
到目前为止,我可以检查并请求个人权限,但我正在寻找比重复更干燥的东西:
PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.XXX>();
if (status != PermissionStatus.Granted){
status = await Permissions.RequestAsync<Permissions.XXX>();
}
Run Code Online (Sandbox Code Playgroud)
对于每一个许可。我需要多个权限,因此我的检查很快就会失控。
顺便说一句,根据 Google Play 的要求,我的目标是 Android 13.0。
我知道这要求很高,但我迷失在所有建议中,其中许多建议不起作用,所以帮助解决所有这些问题就太好了!
我使用了许多不同的来源来将其组合在一起,但这些是最有用的。
可用的 Maui 权限:https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/appmodel/permissions
主线程权限:/sf/answers/5290219931/
蓝牙和自定义权限:https://www.youtube.com/watch?
v=9GljgwfpiiE 位置服务检查:/sf/answers/4841110221/
为了使这更容易理解,我将把所有代码留到最后。
另外,我的项目面向 .Net 7.0、Android 13.0 (API 33)、iOS 11.0 和 Windows 10.0.19041.0 当前的 Google Play 要求。我还没有检查这是否适用于 iOS 或 Windows,但这至少让你/我在运行这些其他操作系统方面迈出了几步。更改 JIT 编译器的目标操作系统时,VS 2022 不会引发任何错误,因此它应该可以工作。如果没有,那么与 1-5 年前的建议或专为 Android 编写的 Java 建议相比,需要做的调整应该更少。
您需要设置 Manifest 和 .plist 文件以获得满足您需求的正确权限。我不打算在这里详细介绍这一点,因为它在我上面链接的第一个参考文献中已经很好地介绍了。
我建议将权限检查代码放入辅助方法中。由于这将是一个async方法,因此您需要从“OnAppearing”方法中调用它,您必须重写该方法并 make async。
我让我的辅助方法返回 a bool,这样我就可以检查是否所有权限都被接受,因为我的应用程序需要我请求的所有权限。没有他们,它根本就不会做任何事。为了轻松检查权限是否被授予/限制,我为此添加了另一种方法,因为我要检查太多权限。
您可以将个体CheckStatusAsync和移至RequestAsync通用方法并简单地调用它以帮助防止重复。
由于您/我需要蓝牙访问,因此您必须编写自定义权限检查器,但仅适用于 Android,不适用于 iOS 或 Windows。这并不难,但是没有太多资源可以向您展示如何操作,而且也不容易找到。
显然,如果手机上的定位服务未启用,则这些对于蓝牙权限都无关紧要。如果您的应用程序可以扫描蓝牙设备,但没有找到任何设备,则很有可能手机的定位服务未启用。我必须添加一个 Toast,以便在扫描返回零结果时让用户知道这是必要的。
或者您可以使用操作系统特定的方法直接检查位置服务状态。
MainPage.xaml.cs:
using CommunityToolkit.Maui.Alerts; // For the Toast
#if ANDROID
using Android.Content;
using Android.Locations;
#elif IOS || MACCATALYST
using CoreLocation;
#elif WINDOWS
using Windows.Devices.Geolocation;
#endif
protected override async void OnAppearing()
{
base.OnAppearing();
if (!await CheckPermissions())
{
await Toast.Make("Not all permissions were accepted. Application will close.").Show();
Application.Current.Quit();
}
}
private async Task<bool> CheckPermissions()
{
PermissionStatus bluetoothStatus = await CheckBluetoothPermissions();
PermissionStatus cameraStatus = await CheckPermissions<Permissions.Camera>();
PermissionStatus mediaStatus = await CheckPermissions<Permissions.Media>();
PermissionStatus storageWriteStatus = await CheckPermissions<Permissions.StorageWrite>();
//PermissionStatus photosStatus = await CheckPermissions<Permissions.Photos>();
...
bool locationServices = IsLocationServiceEnabled();
return IsGranted(cameraStatus) && IsGranted(mediaStatus) && IsGranted(storageWriteStatus) && IsGranted(bluetoothStatus);
}
private async Task<PermissionStatus> CheckBluetoothPermissions()
{
PermissionStatus bluetoothStatus = PermissionStatus.Granted;
if (DeviceInfo.Platform == DevicePlatform.Android)
{
if (DeviceInfo.Version.Major >= 12)
{
bluetoothStatus = await CheckPermissions<BluetoothPermissions>();
}
else
{
bluetoothStatus = await CheckPermissions<Permissions.LocationWhenInUse>();
}
}
return bluetoothStatus;
}
private async Task<PermissionStatus> CheckPermissions<TPermission>() where TPermission : Permissions.BasePermission, new()
{
PermissionStatus status = await Permissions.CheckStatusAsync<TPermission>();
if (status != PermissionStatus.Granted){
status = await Permissions.RequestAsync<TPermission>();
}
return status;
}
private static bool IsGranted(PermissionStatus status)
{
return status == PermissionStatus.Granted || status == PermissionStatus.Limited;
}
#if ANDROID
private bool IsLocationServiceEnabled()
{
LocationManager locationManager = (LocationManager)Android.App.Application.Context.GetSystemService(Context.LocationService);
return locationManager.IsProviderEnabled(LocationManager.GpsProvider);
}
#elif IOS || MACCATALYST
public bool IsLocationServiceEnabled()
{
return CLLocationManager.Status == CLAuthorizationStatus.Denied;
}
#elif WINDOWS
private bool IsLocationServiceEnabled()
{
Geolocator locationservice = new Geolocator();
return locationservice.LocationStatus == PositionStatus.Disabled;
}
#endif
Run Code Online (Sandbox Code Playgroud)
在您的项目中创建一个名为“BluetoothPermissions.cs”的新文件:
using static Microsoft.Maui.ApplicationModel.Permissions;
namespace YourNamespace;
internal class BluetoothPermissions : BasePlatformPermission
{
#if ANDROID
public override (string androidPermission, bool isRuntime)[] RequiredPermissions =>
new List<(string permission, bool isRuntime)>
{
("android.permission.BLUETOOTH", true),
("android.permission.BLUETOOTH_ADMIN", true),
("android.permission.BLUETOOTH_SCAN", true),
("android.permission.BLUETOOTH_CONNECT", true),
("android.permission.ACCESS_COARSE_LOCATION", true),
("android.permission.ACCESS_FINE_LOCATION", true)
}.ToArray();
// This list includes Bluetooth LE permissions.
// You will need to include these permissions in your Android Manifest, too.
#endif
}
Run Code Online (Sandbox Code Playgroud)
注意:当我继续开发此应用程序时,我正在寻找无需所有权限即可使用功能的方法,例如蓝牙。当我使这些功能能够打开和关闭时,我发现我越来越有可能必须在“主页”以外的设置页面上检查这些权限。我可能最终会将大多数(如果不是全部)这些权限转换为它自己的类,这样我就可以从我将打开和关闭功能的各个位置访问它。如果我这样做,我将保留这个答案,并做出一个新答案(如果它与这个答案有显着不同)。