Requires android permission read contacts or android permission write contacts

Подменяем Runtime permissions в Android

Здравствуйте, меня зовут Виталий.

Мне 25 лет, закончил магистратуру СПБГЭТУ «ЛЭТИ» в своем родном городе. Уже 10 лет занимаюсь программированием, из которых 4 пишу под Android. Автор многих Homebrew программ, известный под ником VITTACH, для Sony PlayStation Portable (PSP).

Сегодня я бы хотел обсудить с вами проблему безопасности мобильных приложений. Разработчики из Google постоянно улучшают Android, находя и исправляя уязвимости не без помощи обширного сообщества, собранного благодаря программе Android Security Rewards, о которой мы поговорим позже. Тем не менее, проблемы все еще остаются, и наша общая задача как коммьюнити сообщать о них, чтобы их своевременно исправляли.

Уязвимость о которой я буду говорить, относится к классу с Priority:​ P2 и Severity:​ S2, что согласно таблице в широком смысле означает:

Проблему, которую необходимо решить в разумные сроки;

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

Runtime permission

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

Это невозможно

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

Что под капотом

Runtime Permission впервые появились в Android 6.0 в ответ на потребность повышенного внимания в области выдачи dangerous-разрешений. Фактически основная идея состоит в том, чтобы взаимодействовать с пользователем при запросе разрешений через всплывающее окно. Поэтому теперь разрешения из списка dangerous необходимо запрашивать у пользователя как только они понадобятся приложению.

Источник

Android permissions

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

Разрешения могут быть двух типов: normal и dangerous. Отличие между ними в том, что dangerous разрешения опасны, т.к. могут быть использованы для получения ваших личных данных или информации о вас, или еще каким-то способом могут навредить вам. Примеры dangerous разрешений — это доступ к контактам или смс.

Полный список существующих разрешений можно посмотреть здесь. Характеристика Protection level подскажет насколько опасно это разрешение. А здесь можно сразу просмотреть весь список normal разрешений.

Если приложению необходимо получить какое-либо разрешение, то оно должно быть указано в AndroidManifest.xml, в корневом теге . Тег разрешения — .

Вот пример манифеста с разрешениями:

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

В этом материале мы подробно рассмотрим, как происходит это подтверждение.

До Android 6

До выхода Android 6 все было просто и легко. Когда пользователь устанавливал приложение с манифестом, который мы рассмотрели чуть выше, то он видел такой экран:

Читайте также:  Прошивка андроид для нокия люмия 520

Система показывает разрешения, которые были прописаны в манифесте. Сначала те, которые могут быть опасными с точки зрения приватности (отправка смс, доступ к камере/местоположению/контактам), а затем — обычные (интернет, 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 button onclick example android onclick

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

PermissionsAndroid

Project with Native Code Required

The following section only applies to projects with native code exposed. If you are using the managed expo-cli workflow, see the guide on Permissions in the Expo documentation for the appropriate alternative.

PermissionsAndroid provides access to Android M’s new permissions model. The so-called «normal» permissions are granted by default when the application is installed as long as they appear in AndroidManifest.xml . However, «dangerous» permissions require a dialog prompt. You should use this module for those permissions.

On devices before SDK version 23, the permissions are automatically granted if they appear in the manifest, so check should always result to true and request should always resolve to PermissionsAndroid.RESULTS.GRANTED .

If a user has previously turned off a permission that you prompt for, the OS will advise your app to show a rationale for needing the permission. The optional rationale argument will show a dialog prompt only if necessary — otherwise the normal permission prompt will appear.

Example​

  • Function Component
  • Class Component

Permissions that require prompting the user​

Available as constants under PermissionsAndroid.PERMISSIONS :

  • READ_CALENDAR : ‘android.permission.READ_CALENDAR’
  • WRITE_CALENDAR : ‘android.permission.WRITE_CALENDAR’
  • CAMERA : ‘android.permission.CAMERA’
  • READ_CONTACTS : ‘android.permission.READ_CONTACTS’
  • WRITE_CONTACTS : ‘android.permission.WRITE_CONTACTS’
  • GET_ACCOUNTS : ‘android.permission.GET_ACCOUNTS’
  • ACCESS_FINE_LOCATION : ‘android.permission.ACCESS_FINE_LOCATION’
  • ACCESS_COARSE_LOCATION : ‘android.permission.ACCESS_COARSE_LOCATION’
  • ACCESS_BACKGROUND_LOCATION : ‘android.permission.ACCESS_BACKGROUND_LOCATION’
  • RECORD_AUDIO : ‘android.permission.RECORD_AUDIO’
  • READ_PHONE_STATE : ‘android.permission.READ_PHONE_STATE’
  • CALL_PHONE : ‘android.permission.CALL_PHONE’
  • READ_CALL_LOG : ‘android.permission.READ_CALL_LOG’
  • WRITE_CALL_LOG : ‘android.permission.WRITE_CALL_LOG’
  • ADD_VOICEMAIL : ‘com.android.voicemail.permission.ADD_VOICEMAIL’
  • USE_SIP : ‘android.permission.USE_SIP’
  • PROCESS_OUTGOING_CALLS : ‘android.permission.PROCESS_OUTGOING_CALLS’
  • BODY_SENSORS : ‘android.permission.BODY_SENSORS’
  • SEND_SMS : ‘android.permission.SEND_SMS’
  • RECEIVE_SMS : ‘android.permission.RECEIVE_SMS’
  • READ_SMS : ‘android.permission.READ_SMS’
  • RECEIVE_WAP_PUSH : ‘android.permission.RECEIVE_WAP_PUSH’
  • RECEIVE_MMS : ‘android.permission.RECEIVE_MMS’
  • READ_EXTERNAL_STORAGE : ‘android.permission.READ_EXTERNAL_STORAGE’
  • WRITE_EXTERNAL_STORAGE : ‘android.permission.WRITE_EXTERNAL_STORAGE’
  • BLUETOOTH_CONNECT : ‘android.permission.BLUETOOTH_CONNECT’
  • BLUETOOTH_SCAN : ‘android.permission.BLUETOOTH_SCAN’
  • BLUETOOTH_ADVERTISE : ‘android.permission.BLUETOOTH_ADVERTISE’

Result strings for requesting permissions​

Available as constants under PermissionsAndroid.RESULTS :

  • GRANTED : ‘granted’
  • DENIED : ‘denied’
  • NEVER_ASK_AGAIN : ‘never_ask_again’

Reference

Methods​

constructor() ​

check() ​

Returns a promise resolving to a boolean value as to whether the specified permissions has been granted.

Parameters:

Name Type Required Description
permission string Yes The permission to check for.

request() ​

Prompts the user to enable a permission and returns a promise resolving to a string value (see result strings above) indicating whether the user allowed or denied the request or does not want to be asked again.

If rationale is provided, this function checks with the OS whether it is necessary to show a dialog explaining why the permission is needed (https://developer.android.com/training/permissions/requesting.html#explain) and then shows the system permission dialog.

Parameters:

Name Type Required Description
permission string Yes The permission to request.
rationale object No See rationale below.

Rationale:

Name Type Required Description
title string Yes The title of the dialog.
message string Yes The message of the dialog.
buttonPositive string Yes The text of the positive button.
buttonNegative string No The text of the negative button.
buttonNeutral string No The text of the neutral button.

requestMultiple() ​

Prompts the user to enable multiple permissions in the same dialog and returns an object with the permissions as keys and strings as values (see result strings above) indicating whether the user allowed or denied the request or does not want to be asked again.

Источник

Оцените статью