Xamarin.Essentials:許可權

Permissions 類別能提供檢查及要求執行階段權限的能力。

開始使用

若要開始使用此 API,請閱讀 入門指南Xamarin.Essentials,以確保連結庫已正確安裝並設定在您的專案中。

此 API 會在 Android 上使用執行時間許可權。 請確定 Xamarin.Essentials 已完全初始化,且已在您的應用程式中設定許可權處理。

在 Android 專案的 MainLauncher 或任何 Activity 啟動時 Xamarin.Essentials ,必須在 方法中 OnCreate 初始化:

protected override void OnCreate(Bundle savedInstanceState) 
{
    //...
    base.OnCreate(savedInstanceState);
    Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
    //...
}    

若要處理 Android 上的執行時間權限, Xamarin.Essentials 必須接收任何 OnRequestPermissionsResult。 將下列程式碼新增到所 Activity 類別:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
    Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

使用權限

在類別中新增 的 Xamarin.Essentials 參考:

using Xamarin.Essentials;

檢查權限

若要檢查某個權限的目前狀態,請搭配特定的權限使用 CheckStatusAsync 方法來取得其狀態。

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

如果所需的權限未宣告,便會擲回 PermissionException

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

要求權限

若要從使用者要求權限,請搭配特定的權限使用 RequestAsync 方法來要求。 如果使用者先前已授與許可權且尚未撤銷許可權,則此方法會立即傳回 Granted ,而不會顯示對話方塊。

var status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();

如果所需的權限未宣告,便會擲回 PermissionException

請注意,在某些平台上,權限要求只能單次啟動。 開發人員必須處理進一步的提示,以檢查許可權是否處於 Denied 狀態,並要求使用者手動開啟。

權限狀態

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

  • Unknown:權限處於未知的狀態
  • Denied:使用者已拒絕權限要求
  • Disabled:裝置上已停用該功能
  • Granted:使用者已授與權限,或是系統已自動授與權限
  • Restricted:處於受限制的狀態

說明需要許可權的原因

最佳做法是說明應用程式為何需要特定許可權。 在 iOS 上,您必須指定向使用者顯示的字串。 Android 沒有這項功能,也預設為 [已停用] 的許可權狀態。 這會限制使用者是否拒絕許可權或第一次提示使用者的能力。 ShouldShowRationale方法可用來判斷是否應該顯示教育UI。 如果方法傳 true 回,這是因為用戶過去已拒絕或停用許可權。 呼叫此方法時,其他平臺一律會傳回 false

可用的權限

Xamarin.Essentials 嘗試盡可能擷取盡可能多的許可權。 不過,每個作業系統都有一組不同的運行時間許可權。 此外,針對某些許可權提供單一 API 時也有差異。 以下是目前可用權限的指南:

圖示指南:

  • Full Support -支援
  • Not Supported - 不支援/必要
權限 Android iOS UWP watchOS tvOS Tizen
CalendarRead Android supported iOS supported UWP not supported watchOS supported tvOS not supported Tizen not supported
CalendarWrite Android supported iOS supported UWP not supported watchOS supported tvOS not supported Tizen not supported
相機 Android supported iOS supported UWP not supported watchOS not supported tvOS not supported Tizen supported
ContactsRead Android supported iOS supported UWP supported watchOS not supported tvOS not supported Tizen not supported
ContactsWrite Android supported iOS supported UWP supported watchOS not supported tvOS not supported Tizen not supported
Flashlight Android supported iOS not supported UWP not supported watchOS not supported tvOS not supported Tizen supported
LocationWhenInUse Android supported iOS supported UWP supported watchOS supported tvOS supported Tizen supported
LocationAlways Android supported iOS supported UWP supported watchOS supported tvOS not supported Tizen supported
媒體 Android not supported iOS supported UWP not supported watchOS not supported tvOS not supported Tizen not supported
麥克風 Android supported iOS supported UWP supported watchOS not supported tvOS not supported Tizen supported
手機 Android supported iOS supported UWP not supported watchOS not supported tvOS not supported Tizen not supported
相片 Android not supported iOS supported UWP not supported watchOS not supported tvOS supported Tizen not supported
提醒 Android not supported iOS supported UWP not supported watchOS supported tvOS not supported Tizen not supported
感應器 Android supported iOS supported UWP supported watchOS supported tvOS not supported Tizen not supported
Sms Android supported iOS supported UWP not supported watchOS not supported tvOS not supported Tizen not supported
Speech Android supported iOS supported UWP not supported watchOS not supported tvOS not supported Tizen not supported
StorageRead Android supported iOS not supported UWP not supported watchOS not supported tvOS not supported Tizen not supported
StorageWrite Android supported iOS not supported UWP not supported watchOS not supported tvOS not supported Tizen not supported

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

一般使用方式

下列程式代碼會呈現一般使用模式,以判斷是否已授與許可權,並在未授與許可權時要求許可權。 此程式代碼使用 1.6.0 版或更新版本可用的 Xamarin.Essentials 功能。

public async Task<PermissionStatus> CheckAndRequestLocationPermission()
{
    var 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;
}

每個權限類型都可以建立其自己的執行個體,以用來直接呼叫方法。

public async Task GetLocationAsync()
{
    var status = await CheckAndRequestPermissionAsync(new Permissions.LocationWhenInUse());
    if (status != PermissionStatus.Granted)
    {
        // Notify user permission was denied
        return;
    }

    var location = await Geolocation.GetLocationAsync();
}

public async Task<PermissionStatus> CheckAndRequestPermissionAsync<T>(T permission)
            where T : BasePermission
{
    var status = await permission.CheckStatusAsync();
    if (status != PermissionStatus.Granted)
    {
        status = await permission.RequestAsync();
    }

    return status;
}

延伸權限

許可權 API 已建立為彈性且可延伸的應用程式,這些應用程式需要其他驗證或未包含在 中 Xamarin.Essentials的許可權。 建立繼承自 BasePermission 的新類別,並實作必要的抽象方法。

public class MyPermission : 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();
    }
}

在特定的平台上實作權限時,便可以繼承自 BasePlatformPermission 類別。 這會提供額外的平臺協助程式方法來自動檢查宣告。 建立進行群組的自定義許可權時,這可有所説明。 例如,您可以使用下列自定義許可權,要求對 Android 上的記憶體進行讀取和寫入存取。

public class ReadWriteStoragePermission : Xamarin.Essentials.Permissions.BasePlatformPermission
{
    public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
    {
        (Android.Manifest.Permission.ReadExternalStorage, true),
        (Android.Manifest.Permission.WriteExternalStorage, true)
    }.ToArray();
}

然後,您可以從 Android 專案呼叫新的許可權。

await Permissions.RequestAsync<ReadWriteStoragePermission>();

如果您想要從共用程式代碼呼叫此 API,您可以建立介面並使用 相依性服務 來註冊並取得實作。

public interface IReadWritePermission
{        
    Task<PermissionStatus> CheckStatusAsync();
    Task<PermissionStatus> RequestAsync();
}

然後在您的平台項目中實作 介面:

public class ReadWriteStoragePermission : Xamarin.Essentials.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();
}

然後,您可以註冊特定的實作:

DependencyService.Register<IReadWritePermission, ReadWriteStoragePermission>();

然後,從您的共享專案,您可以解析並使用它:

var readWritePermission = DependencyService.Get<IReadWritePermission>();
var status = await readWritePermission.CheckStatusAsync();
if (status != PermissionStatus.Granted)
{
    status = await readWritePermission.RequestAsync();
}

平台實作特性

權限必須擁有在 Android 資訊清單檔中設定的相符屬性。 許可權狀態預設為 [拒絕]。

請在 Xamarin.Android 中的權限 \(英文\) 文件中深入閱讀。

API

Channel 9YouTube 上尋找更多 Xamarin 影片。