Разрешения

Browse sample. Обзор примера

В этой статье описывается, как использовать класс многоплатформенного пользовательского интерфейса приложений .NET (.NET MAUI). Permissions Этот класс позволяет проверка и запрашивать разрешения во время выполнения. Тип Permissions доступен в Microsoft.Maui.ApplicationModel пространстве имен.

Доступные разрешения

.NET MAUI пытается абстрагировать как можно больше разрешений. Однако у каждой операционной системы есть другой набор разрешений. Несмотря на то что API разрешает доступ к общему разрешению, могут быть различия между операционными системами, связанными с этим разрешением. В следующей таблице описаны доступные разрешения:

В следующей таблице показано ✔️, что разрешение поддерживается и ❌ указывает, что разрешение не поддерживается или не требуется:

Разрешение Android iOS Windows tvOS
Батарея ✔️
CalendarRead ✔️ ✔️
CalendarWrite ✔️ ✔️
Камера ✔️ ✔️
ContactsRead ✔️ ✔️
ContactsWrite ✔️ ✔️
Фонарик ✔️
LocationWhenInUse ✔️ ✔️ ✔️
LocationAlways ✔️ ✔️
Медиа ✔️
Микрофон ✔️ ✔️
NetworkState ✔️
Для телефонов ✔️ ✔️
Фотографии ✔️ ✔️
PhotoAddOnly ✔️ ✔️
Напоминания ✔️
Датчики ✔️ ✔️
Sms ✔️ ✔️
Голосовые функции ✔️ ✔️
StorageRead ✔️
StorageWrite ✔️
Вибрация ✔️
Разрешение Android iOS Windows tvOS
Батарея ✔️
Bluetooth ✔️
CalendarRead ✔️ ✔️
CalendarWrite ✔️ ✔️
Камера ✔️ ✔️
ContactsRead ✔️ ✔️
ContactsWrite ✔️ ✔️
Фонарик ✔️
LocationWhenInUse ✔️ ✔️ ✔️
LocationAlways ✔️ ✔️
Медиа ✔️
Микрофон ✔️ ✔️
БлизлежащиеWifiDevices ✔️
NetworkState ✔️
Для телефонов ✔️ ✔️
Фотографии ✔️ ✔️
PhotoAddOnly ✔️ ✔️
Напоминания ✔️
Датчики ✔️ ✔️
Sms ✔️ ✔️
Голосовые функции ✔️ ✔️
StorageRead ✔️
StorageWrite ✔️
Вибрация ✔️

Если разрешение помечается как❌, оно всегда возвращается 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 метод можно использовать для определения того, должен ли отображаться информативный пользовательский интерфейс. Если метод возвращается 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умолчанию.