Xamarin.Essentials:Разрешения
Класс Permissions позволяет проверять и запрашивать разрешения среды выполнения.
Начало работы
Чтобы начать использовать этот API, ознакомьтесь с руководством по началу работы с Xamarin.Essentials, чтобы правильно настроить и установить библиотеку в проектах.
Этот API использует разрешения среды выполнения для Android. Убедитесь, что набор Xamarin.Essentials полностью инициализирован и в вашем приложении настроена обработка разрешений.
В MainLauncher
проекта Android или в любом запущенном действии 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
, и просить пользователя активировать его вручную.
Состояние разрешения
При использовании CheckStatusAsync
или RequestAsync
будет возвращен объект PermissionStatus
, который можно использовать для определения следующих шагов:
- Unknown — состояние разрешения неизвестно.
- Denied — пользователь отклонил запрос на разрешение.
- Disabled — эта возможность отключена на устройстве.
- Granted — пользователь предоставил разрешение или оно предоставляется автоматически.
- Restricted — в ограниченном состоянии.
Пояснение причины, по которой требуется разрешение
Рекомендуется объяснять, почему приложению требуется определенное разрешение. В iOS необходимо указать строку, которая будет отображаться для пользователя. В Android нет такой возможности, и по умолчанию разрешение имеет состояние "Отключено". Из-за этого не так легко определить, отказался ли пользователь от предоставления разрешения или оно запрашивается впервые. Чтобы определить, следует ли отображать пользовательский интерфейс с пояснением, можно использовать метод ShouldShowRationale
. Если метод возвращает true
, значит пользователь отклонил или отключил разрешение в прошлом. На других платформах при вызове этого метода всегда возвращается false
.
Доступные разрешения
Xamarin.Essentials пытается абстрагировать максимально возможное число разрешений. Однако каждая операционная система имеет свой набор разрешений среды выполнения. Кроме того, есть различия при использовании одного API для некоторых разрешений. Ниже приведено руководство по доступным сейчас разрешениям:
Условные обозначения:
- -Поддержанный
- — не поддерживается или требуется
Разрешение | Android | iOS | UWP | watchOS | tvOS | Tizen |
---|---|---|---|---|---|---|
CalendarRead | ||||||
CalendarWrite | ||||||
Камера | ||||||
ContactsRead | ||||||
ContactsWrite | ||||||
Flashlight | ||||||
LocationWhenInUse | ||||||
LocationAlways | ||||||
Средства массовой информации | ||||||
Микрофон | ||||||
Номер телефона | ||||||
Photos | ||||||
Напоминания | ||||||
Датчики | ||||||
SMS | ||||||
Речь | ||||||
StorageRead | ||||||
StorageWrite |
Если разрешение помечается как оно всегда возвращается 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;
}
Расширение разрешений
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.