Unity + Android: как запросить несколько разрешений?
Я работаю над проектом Unity (версия 2019.1.11) с целевой платформой Android, и мне нужно иметь следующие разрешения для работы моего приложения:
В документации Unity указан этот способ запрашивать разрешения Android. Моя цель — провести начальную проверку всех необходимых разрешений во время запуска приложения, например:
Однако это не работает: приложение показывает диалоговое окно только для первого разрешения, которое не авторизовано, а не для тех, кто не авторизован и которые проверяются впоследствии.
Как я могу гарантировать, чтобы всегда проверять все разрешения?
3 ответа
Кажется, что Permission.RequestUserPermission работает как-то асинхронно и не будет отображать диалоговое окно, когда оно уже открыто, и поэтому просто пропускает все остальные разрешения после нахождения первого не авторизованного.
Я мог бы обойти проблему следующим образом:
Я столкнулся с той же проблемой с проектом, над которым я работаю. Легкое решение — использовать сопрограмму для запроса разрешений и возврата в течение нескольких секунд между каждым разрешением. Или просто попросите разрешения в разных местах приложения. Например, запрашивайте только разрешение камеры, когда пользователь собирается ее использовать, или запись на внешнее хранилище, когда он собирается получить доступ. Поскольку это конфиденциальные разрешения, пользователю лучше заранее знать причину, по которой его просят предоставить эти разрешения.
Код выше работает. Вы можете настроить значение времени ожидания в секундах и добавить необходимые разрешения. Обратите внимание, что я спрашиваю разрешения, только если они еще не были предоставлены.
Разрешения среды выполнения Android, как известно, являются проблемными, в вашем случае проблема заключается в том, что панель пользовательского интерфейса запроса разрешений Android захватывает передний план на первом Permission.RequestUserPermission, приостанавливая работу вашего приложения и предотвращая выполнение следующего кода.
Самое чистое решение, которое я до сих пор предлагал для обработки прав доступа, состоит в том, чтобы запустить бесконечный цикл в сопрограмму, которая жадно проверяет необходимые вам разрешения и предлагает пользователю предоставить каждое из них, если это не так.
На первый взгляд это может показаться уродливым, но учтите, что когда запрашивается разрешение, цикл прерывается по той же причине, по которой ваш код не работает: потому что панель интерфейса запроса запроса захватывает передний план, и ваше приложение приостанавливается, когда фокус возвращается, ваш цикл запускается снова, проверяя наличие пропущенных разрешений, плюс вы можете замедлить ваш цикл с возвращением доходности new WaitForSeconds (0.2f)
Это код с некоторым оформлением, чтобы уведомить пользователя, что он не может продолжить работу, не предоставив все необходимые разрешения:
Это работает даже в сценариях, когда, например, пользователь отказывает в одном разрешении, а затем принудительно убивает ваше приложение, или какое-то другое приложение неожиданно захватывает передний план и различные другие рискованные случаи, с которыми я сталкивался до сих пор
Источник
Android permissions
Операционная система Android устроена таким образом, что для выполнения некоторых операций или доступа к определенным ресурсам, приложение должно иметь разрешение на это.
Разрешения могут быть двух типов: normal и dangerous. Отличие между ними в том, что dangerous разрешения опасны, т.к. могут быть использованы для получения ваших личных данных или информации о вас, или еще каким-то способом могут навредить вам. Примеры dangerous разрешений — это доступ к контактам или смс.
Полный список существующих разрешений можно посмотреть здесь. Характеристика Protection level подскажет насколько опасно это разрешение. А здесь можно сразу просмотреть весь список normal разрешений.
Если приложению необходимо получить какое-либо разрешение, то оно должно быть указано в AndroidManifest.xml, в корневом теге . Тег разрешения — .
Вот пример манифеста с разрешениями:
Здесь мы указываем, что приложению понадобятся разрешения на работу с интернет, контактами, bluetooth, локацией, камерой и смс. Пользователю необходимо будет подтвердить, что он предоставляет приложению эти разрешения.
В этом материале мы подробно рассмотрим, как происходит это подтверждение.
До Android 6
До выхода Android 6 все было просто и легко. Когда пользователь устанавливал приложение с манифестом, который мы рассмотрели чуть выше, то он видел такой экран:
Система показывает разрешения, которые были прописаны в манифесте. Сначала те, которые могут быть опасными с точки зрения приватности (отправка смс, доступ к камере/местоположению/контактам), а затем — обычные (интернет, bluetooth).
Таким образом пользователь видит, на что претендует приложение, и может примерно понять все ли в порядке. Если, например, приложение калькулятор при установке просит у вас доступ к контактам и смс, то скорее всего, что-то не так с этим приложением и оно может быть опасным для ваших данных.
Нажав кнопку Install, пользователь автоматически подтверждает свое согласие, что приложению будут предоставлены эти запрашиваемые разрешения. И далее, когда приложение, например, пытается в коде получить список контактов, то оно без проблем их получает.
Если же в манифесте не указать разрешение READ_CONTACTS, то его не будет и в списке тех разрешений, которые подтверждает пользователь. Соответственно, система не предоставит этому приложению доступ к контактам. И при попытке получить список контактов, будет ошибка:
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2
Android 6
С выходом Android 6 механизм подтверждения поменялся. Теперь при установке приложения пользователь больше не видит списка запрашиваемых разрешений. Приложение автоматически получает все требуемые normal разрешения, а dangerous разрешения необходимо будет программно запрашивать в процессе работы приложения.
Т.е. теперь недостаточно просто указать в манифесте, что вам нужен, например, доступ к контактам. Когда вы в коде попытаетесь запросить список контактов, то получите ошибку SecurityException: Permission Denial. Потому что вы явно не запрашивали это разрешение, и пользователь его не подтверждал.
Перед выполнением операции, требующей разрешения, необходимо спросить у системы, есть ли у приложения разрешение на это. Т.е. подтверждал ли пользователь, что он дает приложению это разрешение. Если разрешение уже есть, то выполняем операцию. Если нет, то запрашиваем это разрешение у пользователя.
Давайте посмотрим, как это выглядит на практике.
Проверка текущего статуса разрешения выполняется методом checkSelfPermission
На вход метод требует Context и название разрешения. Он вернет константу PackageManager.PERMISSION_GRANTED (если разрешение есть) или PackageManager.PERMISSION_DENIED (если разрешения нет).
Если разрешение есть, значит мы ранее его уже запрашивали, и пользователь подтвердил его. Можем получать список контактов, система даст нам доступ.
Если разрешения нет, то нам надо его запросить. Это выполняется методом requestPermissions. Схема его работы похожа на метод startActivityForResult. Мы вызываем метод, передаем ему данные и request code, а ответ потом получаем в определенном onResult методе.
Добавим запрос разрешения к уже имеющейся проверке.
Проверяем разрешение READ_CONTACTS. Если оно есть, то читаем контакты. Иначе запрашиваем разрешение READ_CONTACTS методом requestPermissions. На вход метод требует Activity, список требуемых разрешений, и request code. Обратите внимание, что для разрешений используется массив. Т.е. вы можете запросить сразу несколько разрешений.
После вызова метода requestPermissions система покажет следующий диалог
Здесь будет отображено разрешение, которое мы запросили методом requestPermissions. Пользователь может либо подтвердить его (ALLOW), либо отказать (DENY). Если будет запрошено сразу несколько разрешений, то на каждое из них будет показан отдельный диалог. И пользователь может какие-то разрешения подтвердить, а какие-то нет.
Решение пользователя мы получим в методе onRequestPermissionsResult
Проверяем, что requestСode тот же, что мы указывали в requestPermissions. В массиве permissions придут название разрешений, которые мы запрашивали. В массиве grantResults придут ответы пользователя на запросы разрешений.
Мы проверяем, что массив ответов не пустой и берем первый результат из него (т.к. мы запрашивали всего одно разрешение). Если пользователь подтвердил разрешение, то выполняем операцию. Если же пользователь отказал, то дальнейшие действия зависят от логики вашего приложения.
В итоге схема получения разрешения состоит из трех действий:
— проверка текущего состояния разрешения
— запрос на получение разрешения, если оно еще не было получено
— обработка ответа на запрос
Далее поговорим про некоторые дополнительные возможности, нюансы и прочие мелочи.
Манифест
При использовании новой схемы разрешений вам все равно необходимо указывать разрешение в манифесте. Если его там не указать и сделать запрос на это разрешение, то вам просто сразу придет отказ без всякого диалога.
Всегда проверяйте разрешение
Каждый раз (а не только первый) перед выполнением операции, требующей определенного разрешения, необходимо проверять, что это разрешение есть. Потому что, даже если пользователь уже давал это разрешение, он всегда может зайти в настройки приложения и отменить его. И если вы после этого не выполните проверку, то получите ошибку при выполнении операции.
Don’t ask again
Когда вы первый раз делаете запрос на какое-либо разрешение, пользователь может отказать. При последующих запросах этого же разрешения, в диалоге появится чекбокс Don’t ask again
Если пользователь включит этот чекбокс, то при последующих ваших запросах диалог не будет отображаться, а в onRequestPermissionsResult сразу будет приходить отказ.
Объяснение для пользователя
Когда вы запрашиваете разрешение, пользователю должно быть очевидно, зачем приложению понадобилось это разрешение, и у него не должно возникать вопросов. Но случаи бывают разные, и вы можете решить, что вам надо явно объяснить пользователю, почему приложению понадобилось это разрешение.
Диалог, который показывается при запросе разрешения, — системный, вы не можете менять его содержимое и добавлять туда свой текст. Но вы можете сделать свой диалог или что-то подобное и показать его перед тем, как будете делать запрос разрешения.
Есть метод shouldShowRequestPermissionRationale, который может быть полезен в данной ситуации. Передаете ему название разрешения, а он вам в виде boolean ответит, надо ли показывать объяснение для пользователя.
Т.е. вы сначала проверяете наличие разрешения. Если его нет, то вызываете shouldShowRequestPermissionRationale, чтобы решить, надо ли показывать объяснение пользователю. Если не надо, то делаете запрос разрешения. А если надо, то показываете ваш диалог с объяснением, а после этого диалога делаете запрос разрешения.
Алгоритм работы метода shouldShowRequestPermissionRationale прост.
Если вы еще ни разу не запрашивали это разрешение, то он вернет false. Т.е. перед первым запросом разрешения ничего объяснять не надо.
Если вы ранее уже запрашивали это разрешение и пользователь отказал, то метод вернет true. Т.е. пользователь не понимает, почему он должен давать это разрешение, и надо ему это объяснить.
Если пользователь ставил галку Don’t ask again, то метод вернет false. Запрос полномочий все равно не будет выполнен. Объяснять что-то не имеет смысла.
Разумеется, вы можете показывать дополнительную информацию согласно вашим правилам и не использовать метод shouldShowRequestPermissionRationale.
Группы
Dangerous разрешения собраны в группы. Список групп можно посмотреть здесь. Если вы запросили одно разрешение из группы и пользователь предоставил вам его, то вы автоматически получаете все разрешения этой группы.
Например, разрешения READ_CONTACTS и WRITE_CONTACTS принадлежат группе CONTACTS. И если пользователь уже подтверждал разрешение на READ_CONTACTS, то при проверке WRITE_CONTACTS вы получите PERMISSION_GRANTED.
Android 6 и targetSdkVersion 23
Схема работы разрешений зависит от версии Android, на которой запущено приложение и от параметра targetSdkVersion приложения.
Новая схема будет работать, если версия Android >= 6 И targetSdkVersion >= 23.
В остальных случаях, т.е. когда targetSdkVersion
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Русские Блоги
Обнаружение и запрос нескольких разрешений Android 6.0
1. Базовые знания
Начиная с Android 6.0 (API 23), пользователь предоставляет разрешения приложению во время его работы, а при установке приложения разрешения больше не предоставляются. До Android 6.0 все необходимые разрешения предоставлялись системой при установке приложения. При использовании приложения нет необходимости разбираться с разрешениями. Поскольку пользователи обычно подробно рассматривают, где эти разрешения используются во время установки, эти разрешения часто предоставляются по умолчанию, что приводит к множеству рисков для безопасности. Хотя динамические разрешения после Android 6.0 приносят в жертву часть удобства, они обеспечивают более высокий уровень безопасности системы.
При разработке приложений он в основном включает динамическую обработку опасных разрешений системы. Эти опасные разрешения можно разделить на 9 категорий, как показано на рисунке ниже:
В Интернете есть много сообщений в блогах, которые объясняют динамические разрешения Android 6.0, но многие сообщения в блогах реализуют только определение разрешений, а некоторые сообщения в блогах также реализуют запросы разрешений, но не адаптируются к нескольким разрешениям. Эта статья посвящена одновременному обнаружению нескольких разрешений Он более совместим с вопросами запроса и для некоторых практических сценариев запроса разрешений.
2. Идеи реализации
1. Реализуйте API под названием PermissionsUtils, который отвечает за обнаружение и запрос разрешений. Он в основном адаптирован для одновременного обнаружения нескольких разрешений.Если определенные разрешения запрещены, но разрешено запрашивать статус, для этих разрешений будет выполняться единая обработка запросов. Обратите внимание, что необходимые разрешения должны быть зарегистрированы в AndroidManifest.xml.
2. Реализуйте событие щелчка двух кнопок в MainActivity, активируйте операции мониторинга и запроса с одним и несколькими разрешениями соответственно и отобразите результаты.
3. PermisionsConst — это постоянный класс, который определяет массивы с одним и несколькими разрешениями, которые необходимо обнаруживать и запрашивать.
4. PermisionsBean — это класс Bean, определенный для удобства передачи параметров.Нетрудно понять код соответствующего метода PermissionsUtils.
Источник