Разработка под Android в .NET MAUI. Получение разрешений

Получение разрешений приложениями в Android — это одна из необходимых процедур, призванная информировать пользователя о том, какие операции планирует выполнять приложение с данными устройства, в том числе и с конфиденциальными. Например, если ваше приложение должно работать с камерой устройства, то вы должны запросить необходимое разрешение у пользователя. Для разных типов операций требуется получение различных разрешений.

Получение разрешений приложения Android в .NET MAUI

Доступ к некоторым возможностям Android может быть получен только после того как приложение запросит и получит необходимые разрешения. Например, мы не сможем воспользоваться геолокацией или фонариком на устройстве пока не получим необходимые разрешения. При этом, не стоит увлекаться и запрашивать сразу все возможные разрешения для вашего приложения. Будет очень странно выглядеть, если приложение-фонарик при запуске запросит у пользователя разрешение на просмотр контактов.

В .NET MAUI константы различных разрешений Android расположены в классе Android.Manifest.Permission. Приложения .NET MAUI может получать разрешения различными способами:

  1. Используя атрибуты сборки
  2. Используя манифест приложения
  3. Используя явный запрос разрешения при выполнении приложения.

Рассмотрим процесс получения разрешений на примере приложения, которое выводит информацию о заряде батареи устройства.

Пример приложения

Создадим новое приложение .NET MAUI и изменим класс MainPage следующим образом:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void Button_Clicked(object sender, EventArgs e)
    {
        ChargeLevelLabel.Text = $"Заряд батареи {Battery.Default.ChargeLevel * 100}%";


        var accState = Battery.Default.State switch
        {
            BatteryState.Unknown => "Unknown",
            BatteryState.Charging => "Заряжается",
            BatteryState.Discharging => "Разряжается",
            BatteryState.Full => "Полный заряд",
            BatteryState.NotCharging => "Не заряжается",
            BatteryState.NotPresent => "Аккумулятор отсутствует"
        };
        AccumulatorStateLabel.Text = $"Состояние аккумулятора {accState}";


        var accSource = Battery.Default.PowerSource switch
        {
            BatteryPowerSource.Unknown => "Unknown",
            BatteryPowerSource.Battery => "Аккумулятор",
            BatteryPowerSource.AC => "Зарядное устройство",
            BatteryPowerSource.Usb => "USB-порт",
            BatteryPowerSource.Wireless => "Беспроводная зарядка"

        };
        AccumulatorSourceLabel.Text = $"Источник питания {accSource}";


        var energySaver = Battery.Default.EnergySaverStatus switch
        {
            EnergySaverStatus.Unknown => "Unknown",
            EnergySaverStatus.On => "Включено",
            EnergySaverStatus.Off => "Выключено"
        };
        EnergySaverLabel.Text = $"Экономия заряда: {energySaver}";
    }
}

XAML-код страницы MainPage изменим так:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiAndroidPermissions.MainPage">

    <ScrollView>
        <VerticalStackLayout
            Padding="30,0"
            Spacing="25">

            <Button Text="Проверить" Clicked="Button_Clicked"/>

            <Label x:Name="ChargeLevelLabel"/>
            <Label x:Name="AccumulatorStateLabel"/>
            <Label x:Name="AccumulatorSourceLabel"/>
            <Label x:Name ="EnergySaverLabel"/>
        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

В нашем приложении клик по кнопке приводит к выполнению обработчика Button_Clicked() в котором мы получаем доступ к реализации по умолчанию интерфейса IBattery. Интерфейс IBattery предоставляет нам свойства для отслеживания состояния аккумулятора устройства:

Свойство Тип Описание
ChargeLevel double Возвращает текущий уровень заряда устройства от 0,0 до 1,0.
EnergySaverStatus EnergySaverStatus Возвращает текущее состояние экономии энергии устройства. Может принимать следующие значения:

  • Unknown — состояние экономии энергии неизвестно.
  • On — экономия энергии включена.
  • Off — экономия энергии отключена
PowerSource BatteryPowerSource Возвращает текущий источник питания для устройства. Может принимать следующие значение:

  • Unknown — невозможно определить источник питания.
  • Battery — источник питания — батарея и в настоящее время она не заряжается.
  • AC — источник питания — зарядное устройство AC.
  • Usb — источник питания — USB-порт.
  • Wireless— беспроводной источник питания
State BatteryState Возвращает состояние зарядки устройства. Может принимать следующие значения:

  • Unknown — не удалось определить состояние батареи.
  • Charging — аккумулятор заряжается.
  • Discharging — аккумулятор разряжается.
  • Full — аккумулятор полностью заряжен.
  • NotCharging — аккумулятор не заряжается.
  • NotPresent — аккумулятор отсутствует на устройстве.

Также нам доступны для события:

Событие Описание
event EventHandler<BatteryInfoChangedEventArgs> BatteryInfoChanged;
Событие, которое генерируется каждый раз, когда изменяются свойства ChargeLevel, PowerSource или State
event EventHandler<EnergySaverStatusChangedEventArgs> EnergySaverStatusChanged;
Событие, которое генерируется при изменении свойства EnergySaverStatus

Получив необходимые сведения о состоянии аккумулятора мы выводим их в метки Label. Теперь, если запустить приложение и попытаться нажать на кнопку, то мы гарантированно получим ошибку следующего создержания:

Microsoft.Maui.ApplicationModel.PermissionException: ‘You need to declare using the permission: android.permission.BATTERY_STATS in your AndroidManifest.xml’

Так как для доступа к состоянию батареи требуется получить разрешение, то попытка получения такого доступа без предварительной настройки манифеста приложения приводит к ошибке. На примере этого приложения мы и рассмотрим различные варианты получения разрешений Android.

Получение разрешений с использованием манифеста

Самый простой вариант определить разрешения для своего приложения — это добавить их в манифест приложения. Кликните дважды по файлу Platforms/Android/AndroidMainfest.xml. По умолчанию в Visual Studio откроется редактор манифеста:

В списке «Required permissions» перечислены все доступные разрешения, которые мы можем декларировать для нашего приложения. Здесь нам необходимо выбрать разрешение BATTERY_STATS:

Получение разрешенийСохраним файл и снова запустим приложение. Теперь клик по кнопке не приведет к появлению ошибки:

Получение разрешений с использованием атрибутов сборки

Второй вариант объявления необходимых для приложения Android разрешений в .NET MAUI — это использование атрибутов сборки. Атрибуты UsesPermission объявляются только в файле Platform/Android/MainApplication.cs. Применительно к нашему приложению, файл MainApplication.cs должен выглядеть следующим образом:

using Android.App;
using Android.Runtime;

[assembly: UsesPermission(Android.Manifest.Permission.BatteryStats)]

namespace MauiAndroidPermissions;
[Application]
public class MainApplication : MauiApplication
{
    public MainApplication(IntPtr handle, JniHandleOwnership ownership)
        : base(handle, ownership)
    {
    }

    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

Как можно видеть по представленному выше коду, атрибут сборки объявляется перед сразу после using и перед всеми остальными частями файла. При сборке приложения .NET MAUI проанализирует все атрибуты сборки и внесет информацию о разрешениях в манифест приложения.

Использование класса Permissions

В Android все разрешения делятся на обычные и опасные (dangerous ). Обычные разрешения, например, для доступа к заряду батареи, получаются непосредственно при установке приложения.

Опасные разрешения Android — это такие разрешения, благодаря получению которых, приложение получает доступ к конфиденциальной информации и к информации, использование которой может повлиять на безопасность устройства. Опасные разрешения необходимо запрашивать у пользователя непосредственно при работе приложения. Это помогает снизить риск утечки конфиденциальной информации или взлома устройства. Например, разрешение на использование геолокации относится к опасным.

Чтобы узнать к какой группе разрешение относится разрешение, необходимое вашему приложению, можно обратиться к документации по API Android и посмотреть на Protection level конкретного разрешения.

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

Пользователь может запретить использовать данные о своем местоположении, поэтому при следующей попытке получить доступ к конфиденциальным данным нам необходимо проверить наличие необходимых разрешений.

Класс Permissions используется для проверки и, при необходимости, запроса разрешений у пользователя на выполнение каких-либо операций. Например, если нам необходимо проверить и запросить разрешение на получение доступа к местоположению устройства, то можно написать вот такой метод проверки необходимого разрешения:

public async Task<PermissionStatus> CheckPermissionStatus()
{
    var currentStatus =  await Permissions.CheckStatusAsync<Permissions.LocationAlways>();
    if (currentStatus != PermissionStatus.Granted)
    {
        currentStatus = await Permissions.RequestAsync<Permissions.LocationAlways>();
    }
    return currentStatus;
}

Метод CheckPermissionStatus() возвращает один из следующих статусов разрешения:

  • Unknown — разрешение находится в неизвестном состоянии.
  • Denied — пользователь отказался от запроса на разрешение.
  • Disabled — эта функция отключена на устройстве.
  • Granted — пользователь предоставил разрешение или автоматически предоставляется.
  • Restricted — разрешено в ограниченном состоянии.

Вначале мы проверяем текущий статус разрешения:

var currentStatus = await Permissions.CheckStatusAsync<Permissions.LocationAlways>();

если разрешение ещё не получено от пользователя, то мы запрашиваем необходимое разрешение:

currentStatus = await Permissions.RequestAsync<Permissions.LocationAlways>();

и возвращаем результат. Воспользоваться этим методом можно, например, так:

private async void Button_Clicked(object sender, EventArgs e)
{
    PermissionStatus status = await CheckPermissionStatus(); 
    
    if (status != PermissionStatus.Granted)
    {
       await DisplayAlert("Разрешение не получено", "Доступ к информации о местоположении запрещен", "Понятно");
    }
    else
    {
         //выполняем операции, связанные с местоположением устройства
    }

        
}

Если пользователь отклонит разрешение, то увидит на экране сообщение о том, что доступ к местоположению был запрещен.

Итого

Для получения разрешений приложения Android в .NET MAUI мы можем воспользоваться атрибутами сборки, или объявить необходимые разрешения в манифесте приложения. При этом, для опасных разрешений необходимо явное разрешение пользователя на выполнение необходимых операций. Чтобы проверить статус того или иного разрешения, необходимо воспользоваться методами класса Permissions.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии