アクセス許可
この記事では、.NET マルチプラットフォーム アプリ UI (.NET MAUI) の Permissions クラスを使用する方法について説明します。 このクラスを使用すると、実行時にアクセス許可を確認したり要求したりできます。 Permissions
型は Microsoft.Maui.ApplicationModel
名前空間で使用できます。
使用可能なアクセス許可
.NET MAUI では、できるだけ多くのアクセス許可を抽象化しようとします。 しかし、各オペレーティング システムでは、アクセス許可がそれぞれ異なります。 API を通じて共通のアクセス許可を利用できる場合でも、オペレーティング システム間に、そのアクセス許可に関連する違いがある可能性があります。 使用可能なアクセス許可を次の表に示します。
次の表では、そのアクセス許可がサポートされていることを ✔️ で示し、そのアクセス許可がサポートされていないか必要ないことを ❌ で示しています。
アクセス許可 | Android | iOS | Windows | tvOS |
---|---|---|---|---|
バッテリー | ✔️ | ❌ | ❌ | ❌ |
Bluetooth | ✔️ | ❌ | ❌ | ❌ |
CalendarRead | ✔️ | ✔️ | ❌ | ❌ |
CalendarWrite | ✔️ | ✔️ | ❌ | ❌ |
カメラ | ✔️ | ✔️ | ❌ | ❌ |
ContactsRead | ✔️ | ✔️ | ❌ | ❌ |
ContactsWrite | ✔️ | ✔️ | ❌ | ❌ |
懐中電灯 | ✔️ | ❌ | ❌ | ❌ |
LocationWhenInUse | ✔️ | ✔️ | ❌ | ✔️ |
LocationAlways | ✔️ | ✔️ | ❌ | ❌ |
Media | ❌ | ✔️ | ❌ | ❌ |
マイク | ✔️ | ✔️ | ❌ | ❌ |
NearbyWifiDevices | ✔️ | ❌ | ❌ | ❌ |
NetworkState | ✔️ | ❌ | ❌ | ❌ |
電話 | ✔️ | ✔️ | ❌ | ❌ |
Photos | ❌ | ✔️ | ❌ | ✔️ |
PhotosAddOnly | ❌ | ✔️ | ❌ | ✔️ |
PostNotifications | ✔️ | ❌ | ❌ | ❌ |
アラーム | ❌ | ✔️ | ❌ | ❌ |
センサー | ✔️ | ✔️ | ❌ | ❌ |
SMS | ✔️ | ✔️ | ❌ | ❌ |
Speech | ✔️ | ✔️ | ❌ | ❌ |
StorageRead | ✔️ | ❌ | ❌ | ❌ |
StorageWrite | ✔️ | ❌ | ❌ | ❌ |
バイブレーション | ✔️ | ❌ | ❌ | ❌ |
重要
StorageRead と StorageWrite のアクセス許可は、常に Android API 33 以降で返Grantedされます。 これは、基になる Android READ_EXTERNAL_STORAGE
と WRITE_EXTERNAL_STORAGE
アクセス許可が API 33 から使用できなくなったためです。
アクセス許可に ❌ マークが付いている場合は、確認または要求されたときに常に 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 がスローされます。
重要
一部のプラットフォームでは、アクセス許可の要求をアクティブにできるのは 1 回だけです。 開発者がさらにプロンプトを処理して、アクセス許可が 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>();
その後、カスタム アクセス許可の実装を解決し、ビューモデルなど、自分の型の 1 つから呼び出すことができます。
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 です。
.NET MAUI