權限
本文說明如何使用 .NET 多平臺應用程式 UI (.NET MAUI) Permissions 類別。 這個類別可讓您在執行時間檢查和要求許可權。 此 Permissions
類型可在命名空間中使用 Microsoft.Maui.ApplicationModel
。
可用的許可權
.NET MAUI 會嘗試盡可能擷取盡可能多的許可權。 不過,每個操作系統都有一組不同的許可權。 雖然 API 允許存取通用許可權,但與該許可權相關的作業系統之間可能會有差異。 下表描述可用的權限:
下表使用 ✔️ 來表示支持許可權,以及 ❌ 指出不支援或不需要許可權:
權限 | Android | iOS | Windows | tvOS |
---|---|---|---|---|
電池 | ✔️ | ❌ | ❌ | ❌ |
Bluetooth | ✔️ | ❌ | ❌ | ❌ |
CalendarRead | ✔️ | ✔️ | ❌ | ❌ |
CalendarWrite | ✔️ | ✔️ | ❌ | ❌ |
相機 | ✔️ | ✔️ | ❌ | ❌ |
ContactsRead | ✔️ | ✔️ | ❌ | ❌ |
ContactsWrite | ✔️ | ✔️ | ❌ | ❌ |
手電筒 | ✔️ | ❌ | ❌ | ❌ |
LocationWhenInUse | ✔️ | ✔️ | ❌ | ✔️ |
LocationAlways | ✔️ | ✔️ | ❌ | ❌ |
媒體 | ❌ | ✔️ | ❌ | ❌ |
麥克風 | ✔️ | ✔️ | ❌ | ❌ |
NearbyWifiDevices | ✔️ | ❌ | ❌ | ❌ |
NetworkState | ✔️ | ❌ | ❌ | ❌ |
手機 | ✔️ | ✔️ | ❌ | ❌ |
照片 | ❌ | ✔️ | ❌ | ✔️ |
PhotosAddOnly | ❌ | ✔️ | ❌ | ✔️ |
PostNotifications | ✔️ | ❌ | ❌ | ❌ |
提醒 | ❌ | ✔️ | ❌ | ❌ |
感應器 | ✔️ | ✔️ | ❌ | ❌ |
短信 | ✔️ | ✔️ | ❌ | ❌ |
語音 | ✔️ | ✔️ | ❌ | ❌ |
StorageRead | ✔️ | ❌ | ❌ | ❌ |
StorageWrite | ✔️ | ❌ | ❌ | ❌ |
震動 | ✔️ | ❌ | ❌ | ❌ |
重要
StorageRead 和 StorageWrite 許可權一律會在 Android API 33+ 上傳回Granted。 這是因為 API 33 不再提供基礎 Android READ_EXTERNAL_STORAGE
和 WRITE_EXTERNAL_STORAGE
許可權。
如果許可權標示為 ❌,則一律會在核取或要求時傳回 Granted 。
檢查權限
若要檢查某個權限的目前狀態,請搭配特定的權限使用 Permissions.CheckStatusAsync 方法來取得其狀態。 下列範例會檢查權限的狀態 LocationWhenInUse
:
PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
PermissionException如果未宣告必要的權限,則會擲回 。
最好先檢查許可權的狀態,再要求許可權。 如果用戶從未收到提示,則每個操作系統都會傳回不同的默認狀態。 iOS 會傳 Unknown回 ,而其他則傳回 Denied。 如果狀態為 Granted ,則不需要進行其他呼叫。 在 iOS 上,如果狀態為 Denied ,您應該提示使用者變更設定中的許可權。 在 Android 上,您可以呼叫 ShouldShowRationale 來偵測使用者是否已經拒絕過去的許可權。
許可權狀態
使用 CheckStatusAsync 或 RequestAsync時, PermissionStatus 會傳回 ,可用來判斷後續步驟:
Unknown
許可權處於未知狀態,或在iOS上,用戶從未收到提示。Denied
使用者拒絕許可權要求。Disabled
裝置上已停用此功能。Granted
使用者已授與許可權或自動授與。Restricted
處於限制狀態。Limited
處於有限狀態。 只有 iOS 會傳回此狀態。
要求許可權
若要從使用者要求權限,請搭配特定的權限使用 RequestAsync 方法來要求。 如果使用者先前已授與許可權,且尚未撤銷許可權,則此方法會傳回 Granted ,而不會向使用者顯示對話方塊。 許可權不應該從您的 MauiProgram
或 App
類別要求,而且只有在應用程式第一頁出現之後才要求。
下列範例會要求 LocationWhenInUse
許可權:
PermissionStatus status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
PermissionException如果未宣告必要的權限,則會擲回 。
重要
在某些平臺上,只能啟用許可權要求一次。 開發人員必須處理進一步的提示,以檢查許可權是否處於 Denied 狀態,然後要求使用者手動開啟。
說明需要許可權的原因
最佳做法是向使用者說明您的應用程式為何需要特定許可權。 在 iOS 上,您必須指定向使用者顯示的字串。 Android 沒有這項功能,也會將權限狀態預設為 Disabled。 這會限制使用者是否拒絕許可權或第一次要求許可權的能力。 ShouldShowRationale方法可用來判斷是否應該顯示資訊性UI。 如果方法傳 true
回 ,這是因為用戶過去已拒絕或停用許可權。 呼叫此方法時,其他平臺一律會傳回 false
。
範例
下列程式代碼會呈現一般使用模式,以判斷是否已授與許可權,如果尚未授與許可權,則會要求它。
public async Task<PermissionStatus> CheckAndRequestLocationPermission()
{
PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (status == PermissionStatus.Granted)
return status;
if (status == PermissionStatus.Denied && DeviceInfo.Platform == DevicePlatform.iOS)
{
// Prompt the user to turn on in settings
// On iOS once a permission has been denied it may not be requested again from the application
return status;
}
if (Permissions.ShouldShowRationale<Permissions.LocationWhenInUse>())
{
// Prompt the user with additional information as to why the permission is needed
}
status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
return status;
}
擴充許可權
許可權 API 是針對需要 .NET MAUI 中未包含更多驗證或許可權的應用程式,建立為彈性且可擴充。 建立繼承自 Permissions.BasePermission的類別,並實作必要的抽象方法。 下列範例程式代碼示範基本抽象成員,但沒有實作:
public class MyPermission : Permissions.BasePermission
{
// This method checks if current status of the permission.
public override Task<PermissionStatus> CheckStatusAsync()
{
throw new System.NotImplementedException();
}
// This method is optional and a PermissionException is often thrown if a permission is not declared.
public override void EnsureDeclared()
{
throw new System.NotImplementedException();
}
// Requests the user to accept or deny a permission.
public override Task<PermissionStatus> RequestAsync()
{
throw new System.NotImplementedException();
}
// Indicates that the requestor should prompt the user as to why the app requires the permission, because the
// user has previously denied this permission.
public override bool ShouldShowRationale()
{
throw new NotImplementedException();
}
}
在特定的平台上實作權限時,便可以繼承自 Permissions.BasePlatformPermission 類別。 這個類別提供額外的平臺協助程式方法,以自動檢查許可權宣告。 這有助於建立進行群組的自定義許可權,例如要求 Android 上記憶體的讀取 和 寫入 存取權。 下列程式代碼範例示範要求 讀取 和 寫入 記憶體存取:
public class ReadWriteStoragePerms : Permissions.BasePlatformPermission
{
public override (string androidPermission, bool isRuntime)[] RequiredPermissions =>
new List<(string androidPermission, bool isRuntime)>
{
(global::Android.Manifest.Permission.ReadExternalStorage, true),
(global::Android.Manifest.Permission.WriteExternalStorage, true)
}.ToArray();
}
然後,您會以與 .NET MAUI 所提供的任何其他許可權類型相同的方式檢查許可權:
PermissionStatus status = await Permissions.RequestAsync<ReadWriteStoragePerms>();
如果您想要從跨平臺程式代碼呼叫此 API,您可以建立介面,並將自定義許可權註冊為應用程式服務容器中的相依性。 下列範例顯示 IReadWritePermission
介面:
public interface IReadWritePermission
{
Task<PermissionStatus> CheckStatusAsync();
Task<PermissionStatus> RequestAsync();
}
然後在您的自訂權限中實作 介面:
public class ReadWriteStoragePermission : Permissions.BasePlatformPermission, IReadWritePermission
{
public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
{
(Android.Manifest.Permission.ReadExternalStorage, true),
(Android.Manifest.Permission.WriteExternalStorage, true)
}.ToArray();
}
在類別中 MauiProgram
,您應該在應用程式的服務容器中註冊介面及其具體類型,以及將取用自定義許可權的類型:
builder.Services.AddTransient<MyViewModel>();
builder.Services.AddSingleton<IReadWritePermission, ReadWriteStoragePermission>();
然後,您可以從其中一個類型解析和叫用自定義許可權實作,例如 viewmodel:
public class MyViewModel
{
IReadWritePermission _readWritePermission;
public MyViewModel(IReadWritePermission readWritePermission)
{
_readWritePermission = readWritePermission;
}
public async Task CheckPermissionAsync()
{
var status = await _readWritePermission.CheckStatusAsync();
if (status != PermissionStatus.Granted)
{
status = await _readWritePermission.RequestAsync();
}
}
}
平台差異
本節說明許可權 API 的平臺特定差異。
權限必須擁有在 Android 資訊清單檔中設定的相符屬性。 權限狀態預設為 Denied。