權限

Browse sample. 流覽範例

本文說明如何使用 .NET 多平臺應用程式 UI (.NET MAUI) Permissions 類別。 這個類別可讓您在執行時間檢查和要求許可權。 此 Permissions 類型可在命名空間中使用 Microsoft.Maui.ApplicationModel

可用的許可權

.NET MAUI 會嘗試盡可能擷取盡可能多的許可權。 不過,每個操作系統都有一組不同的許可權。 雖然 API 允許存取通用許可權,但與該許可權相關的作業系統之間可能會有差異。 下表描述可用的權限:

下表使用 ✔️ 來表示支持許可權,以及 ❌ 指出不支援或不需要許可權:

權限 Android iOS Windows tvOS
電池 ✔️
CalendarRead ✔️ ✔️
CalendarWrite ✔️ ✔️
相機 ✔️ ✔️
ContactsRead ✔️ ✔️
ContactsWrite ✔️ ✔️
手電筒 ✔️
LocationWhenInUse ✔️ ✔️ ✔️
LocationAlways ✔️ ✔️
媒體 ✔️
麥克風 ✔️ ✔️
NetworkState ✔️
手機 ✔️ ✔️
照片 ✔️ ✔️
PhotosAddOnly ✔️ ✔️
提醒 ✔️
感應器 ✔️ ✔️
短信 ✔️ ✔️
語音 ✔️ ✔️
儲存體 Read ✔️
儲存體 Write ✔️
震動 ✔️
權限 Android iOS Windows tvOS
電池 ✔️
Bluetooth ✔️
CalendarRead ✔️ ✔️
CalendarWrite ✔️ ✔️
相機 ✔️ ✔️
ContactsRead ✔️ ✔️
ContactsWrite ✔️ ✔️
手電筒 ✔️
LocationWhenInUse ✔️ ✔️ ✔️
LocationAlways ✔️ ✔️
媒體 ✔️
麥克風 ✔️ ✔️
NearbyWifiDevices ✔️
NetworkState ✔️
手機 ✔️ ✔️
照片 ✔️ ✔️
PhotosAddOnly ✔️ ✔️
提醒 ✔️
感應器 ✔️ ✔️
短信 ✔️ ✔️
語音 ✔️ ✔️
儲存體 Read ✔️
儲存體 Write ✔️
震動 ✔️

如果許可權標示為 ❌,則一律會在核取或要求時傳回 Granted

檢查權限

若要檢查某個權限的目前狀態,請搭配特定的權限使用 Permissions.CheckStatusAsync 方法來取得其狀態。 下列範例會檢查權限的狀態 LocationWhenInUse

PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();

PermissionException如果未宣告必要的權限,則會擲回 。

最好先檢查許可權的狀態,再要求許可權。 如果用戶從未收到提示,則每個操作系統都會傳回不同的默認狀態。 iOS 會傳 Unknown回 ,而其他則傳回 Denied。 如果狀態為 Granted ,則不需要進行其他呼叫。 在 iOS 上,如果狀態為 Denied ,您應該提示使用者變更設定中的許可權。 在 Android 上,您可以呼叫 ShouldShowRationale 來偵測使用者是否已經拒絕過去的許可權。

許可權狀態

使用 CheckStatusAsyncRequestAsync時, PermissionStatus 會傳回 ,可用來判斷後續步驟:

  • Unknown
    許可權處於未知狀態,或在iOS上,用戶從未收到提示。

  • Denied
    使用者拒絕許可權要求。

  • Disabled
    裝置上已停用此功能。

  • Granted
    使用者已授與許可權或自動授與。

  • Restricted
    處於限制狀態。

  • Limited
    處於有限狀態。 只有 iOS 會傳回此狀態。

要求許可權

若要從使用者要求權限,請搭配特定的權限使用 RequestAsync 方法來要求。 如果使用者先前已授與許可權,且尚未撤銷許可權,則此方法會傳回 Granted ,而不會向使用者顯示對話方塊。 許可權不應該從您的 MauiProgramApp 類別要求,而且只有在應用程式第一頁出現之後才要求。

下列範例會要求 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