Xamarin.Essentials:アクセス許可

Permissions クラスでは、実行時のアクセス許可を確認および要求する機能が提供されます。

作業開始

この API の使用を始めるには、Xamarin.Essentials の概要ガイドを読み、ライブラリが正しくインストールされてプロジェクトに設定されていることを確認してください。

この API では、Android の実行時のアクセス許可を使用します。 Xamarin.Essentials が完全に初期化されており、アクセス許可の処理がアプリで設定されていることを確認してください。

Android プロジェクトの MainLauncher、または起動されるすべての Activity では、OnCreate メソッド内で Xamarin.Essentials を初期化する必要があります。

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 上で実行時のアクセス許可を処理するには、OnRequestPermissionsResult で、すべての Xamarin.Essentials を受け取る必要があります。 すべての 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);
}

Permissions の使用

クラスの 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 がスローされます。

一部のプラットフォームでは、アクセス許可要求をアクティブにできるのは 1 回だけであることに注意してください。 アクセス許可が Denied 状態であるかどうかを確認し、手動で有効にするようにユーザーに依頼するには、開発者がさらにプロンプトを処理する必要があります。

アクセス許可の状態

CheckStatusAsync または RequestAsync を使用すると、PermissionStatus が返されます。これを使って次の手順を決定できます。

  • Unknown - アクセス許可は不明な状態です
  • Denied - ユーザーがアクセス許可要求を拒否しました
  • Disabled - この機能はデバイス上で無効になっています
  • Granted - ユーザーがアクセス許可を付与したか、自動的に付与されます
  • Restricted - 制限された状態です

アクセス許可が必要な理由を説明する

アプリケーションに特定のアクセス許可が必要な理由を説明することをお勧めします。 iOS では、ユーザーに表示される文字列を指定する必要があります。 Android にはこの機能がなく、アクセス許可の状態の既定値は "Disabled" です。 そのため、ユーザーがアクセス許可を拒否したかどうか、またはユーザーにプロンプトを表示するのが初めてかどうかはわかりません。 ShouldShowRationale メソッドを使用すると、教育用 UI を表示する必要があるかどうかを判断できます。 このメソッドが true を返す場合、ユーザーは、過去にアクセス許可を拒否または無効にしています。 このメソッドを呼び出すと、他のプラットフォームは常に false を返します。

利用可能なアクセス許可

Xamarin.Essentials では、可能な限り多くのアクセス許可を抽象化しようとします。 しかし、各オペレーティング システムには、それぞれ異なる実行時のアクセス許可セットが備わっています。 また、一部のアクセス許可に対して 1 つの 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
Camera 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
懐中電灯 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
Media Android not supported iOS supported UWP not supported watchOS not supported tvOS not supported Tizen not supported
Microphone 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
Photos 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 が返されます。

一般的な使用法

次のコードは、アクセス許可が付与されているかどうかを判断し、付与されていない場合は要求するための一般的な使用パターンを示しています。 このコードは、Xamarin.Essentials バージョン 1.6.0 以降で使用できる機能を使用しています。

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;
}

アクセス許可の拡張

Permissions 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 マニフェスト ファイルに一致する属性が設定されている必要があります。 アクセス許可の状態の既定値は "Denied" です。

詳細については、「Xamarin.Android のアクセス許可」のドキュメントをご覧ください。

API

他の Xamarin ビデオは、Channel 9 および YouTube でご覧いただけます。