- Подменяем Runtime permissions в Android
- Runtime permission
- Это невозможно
- Что под капотом
- Разрешение GET_ACCOUNTS при использовании GCM – зачем это нужно?
- Подробнее о реализации поддержки GCM на Android-клиенте
- Тут уже писали об GCM. Для чего эта статья?
- Необходимые разрешения
- Изменяется ли код регистрации (registationId)?
- AccountManager
- Requesting Runtime Permissions in Android M and N
- Declaring Permissions
- Asking for Permission
- Handling the Results
- Location Request
- Conclusion
Подменяем 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 необходимо запрашивать у пользователя как только они понадобятся приложению.
Источник
Разрешение GET_ACCOUNTS при использовании GCM – зачем это нужно?
У меня есть приложение с включенными Push-уведомлениями.
Я хочу понять причину, по которой нам нужно «GET_ACCOUNTS» (android.permission.GET_ACCOUNTS) при реализации GCM? Некоторые пользователи вызывают озабоченность этим разрешением. Я использовал это разрешение в манифесте, так как он был указан на официальном сайте здесь .
Насколько безопасно это разрешение? И если я удалю это, из моего манифеста, будут ли push-уведомления работать?
Он использует существующее соединение для служб Google. Для устройств с предустановкой 3.0 это требует, чтобы пользователи настраивали свою учетную запись Google на своих мобильных устройствах. Учетная запись Google не является обязательным требованием для устройств под управлением Android 4.0.4 или выше.
Итак, это причина требования разрешения
Для чтения учетной записи Google.
Подробнее об этом обзоре GCM
Вход в учетную запись Google больше не требуется для работы GCM. Поэтому вам не нужно разрешение android.permission.GET_ACCOUNTS .
Если вы используете GCM API с GoogleCloudMessaging.register ), вам больше не нужно настраивать учетную запись Google на любой версии Android. Но если вы используете устаревшую библиотеку ( GCMRegistrar.register ), вам все равно нужна учетная запись Google в старых версиях (до ICS).
Подробнее см. На странице https://groups.google.com/forum/#!topic/android-gcm/ecG-RfH-Aso . Другой поток симуляторов: почему для входа в систему GCM для устройств ниже 4.0.4 ОС требуется учетная запись Google?
Для работы GCM больше не требуется разрешение GET_ACCOUNTS. Раньше это требовалось для регистрации в GCM, но недавнее обновление Play Services прекратило использование учетной записи Google даже на Froyo и Gingerbread. Если вы регистрируетесь в GCM с Play Services (т. Е. С помощью GoogleCloudMessaging.register), вам больше не нужно это разрешение на любую версию Android. Если вы используете устаревшую библиотеку (GCMRegistrar.register), вам все равно нужна учетная запись Google для версии 4.0.4, для которой требуется это разрешение.
Источник (размещен на android-gcm Google Group разработчиком Google):
Регистрация Froyo и Gingerbread осуществляется в GoogleServicesFramework, используя учетную запись Google для регистрации. Это привело к множеству ошибок auth для людей, где учетная запись не была в хорошем состоянии.
Начиная с ICS, GCM не зависит или использует учетную запись Google – вы можете использовать ее, прежде чем добавлять учетную запись или без каких-либо учетных записей.
Обновление «Службы обслуживания» реализует новую схему на всех устройствах, но, похоже, у небольшого числа устройств есть проблемы с этим, мы расследуем, но цифры намного ниже, чем у старой схемы.
Как говорили все остальные, GET_ACCOUNT необходим для устройств Android ниже 4.0.4.
Если вы похожи на меня и установили библиотеку, которая автоматически добавляет это разрешение, но вам это не нужно, вы можете сказать AndroidManifest удалить это разрешение, добавив разрешение с помощью tools:node=»remove» :
В вашем файле AndroidManifest.xml убедитесь, что атрибут xmlns:tools он определен в вашем теге manifest а затем добавьте его с remove набором:
Слово или предупреждение, что это никогда не работает для меня, но я знаю, что он работал на других. Если вы видите, что я могу делать неправильно, или у вас есть больше информации об этом, прокомментируйте!
* Редактировать: есть отчет об ошибке, открывающий эту функцию: https://bugzilla.xamarin.com/show_bug.cgi?id=48153
Когда вы используете
Compile ‘com.google.android.gms: play-services: 7.5.0’ Добавить файл build.gradle означает, что автоматически добавлено разрешение GET_ACCOUNT.
- Например, если разработчику нужно использовать только admob в проекте, укажите только это разрешение в файле build.gradle compile ‘com.google.android.gms: play-services-ads: 7.5.0’, если есть какие-либо другие разъяснения, см. Ссылку https: //developers.google.com/android/guides/setup
Я не думаю, что это на самом деле. Я протестировал его на новом устройстве Gingerbread с заводской перезагрузкой с новой учетной записью Gmail, и я мог получать сообщения GCM просто отлично без этого разрешения. Таким образом, документация НЕПРАВИЛЬНАЯ.
GET_ACCOUNT – проверить, синхронизирует ли пользователь аккаунт Google на мобильном устройстве и генерирует значение ключа для каждого пользователя (каждый аккаунт Google). Это необходимо, если на устройстве установлена версия ниже Android 4.0.4.
Источник
Подробнее о реализации поддержки GCM на Android-клиенте
Тут уже писали об GCM. Для чего эта статья?
Верно, писали. Буквально на этой неделе на Хабре была опубликована статья GCM – новый сервис Push-уведомлений от Google (если вы еще не знакомы с Google Cloud Messaging for Android, то советую прочитать её перед прочтением этой статьи, тем более в моей статье не описываются процесс создания проекта с GCM). Не знаю использовал её автор GCM в реальном приложении или нет, а вот мне пришлось. Поэтому-то я и хочу описать кое-что, чему не нашлось места в предыдущей статье, или что не было объяснено. Добавить это все комментарием в предыдущую статью, боюсь, невыполнимая задача.
Необходимые разрешения
- Тут всё ясно, без доступа к интернету GCM нам и не нужен
- GCM требует доступ к Google-аккаунту
По этому поводу в прошлой теме даже был спор, но никто из участников не решил посмотреть в исходных код. Документация этот момент умалчивает, и лишь говорит, что возможно вы захотите захватить PowerManager.WakeLock . Так вот, если вы пользуетесь стандартной библиотекой GCM, то вам придется добавлять такое разрешение.
Вкратце механизм работы такой: наше приложение подписывается на получение широковещательных запросов. При получении запроса мы устанавливаем полученному Intent’у имя класса ( setClassName() ) в имя нашего сервиса расширяющего GCMBaseIntentService , затем захватываем WakeLock с флагом PowerManager.PARTIAL_WAKE_LOCK (не даем уснуть только CPU, экран и прочее спит спокойно), запускаем Intent как сервис, по выходу из onHandleIntent сервиса освобождаем WakeLock .
Не поверили и не стали добавлять это разрешение, и в итоге получаем вот такое исключение:
Создаем свое собственное разрешение и сами его запрашиваем. Это мы делаем для того, чтобы никто кроме нас не смог получать наши сообщения.
Примечание: если вы выставили minSdkVersion в 16 или выше (Jelly Bean и последующие версии), то это разрешение вам не нужно (года через 2, надеюсь, можно будет опускать).
Изменяется ли код регистрации (registationId)?
Рассмотрим код из приложения-примера:
Вроде бы других условий нет. Так что, не изменяется? Если перейти по этой ссылке: http://developer.android.com/intl/ru/guide/google/gcm/adv.html#reg-state, можно узнать что все-таки может измениться. Таких случая два:
- Обновление программы
- Создание резервной копии и восстановление из неё
Для проверки на обновление программы я написал небольшой класс-помощник. Может быть кому-нибудь пригодится:
Источник
AccountManager
Иногда разработчик хочет отслеживать пользователя. Первый вариант, который приходит в голову — попросить его ввести какие-то данные о себе и сохранить их где-нибудь. Но просить пользователя повторять эту процедуру при покупке нового устройства не самая лучшая идея. Кроме того, вы не можете гарантировать уникальность данных. Второй вариант — запомнить идентификатор телефона. Но пользователи иногда пользуются двумя телефонами, планшетами и т.д. и тут одним идентификатором не обойдёшься. Опять проблема.
Третий вариант – использовать класс AccountManager. С разрешения пользователя, вы можете использовать AccountManager для извлечения имён учетных записей, которые пользователь хранит на устройстве. Имея полученную информацию, вы можете, например, автоматически заполнить форму с адресом электронной почты.
Само устройство может хранить несколько аккаунтов от разных сервисов. Вы можете отфильтровать результат по типам аккаунтов. Например, у Гугла аккаунт имеет тип «com.google», Twitter использует тип «com.twitter.android.auth.login».
Для извлечения информации требуется разрешение:
В приложении вы сначала получаете экземпляр AccountManager через метод get(), а затем можете вызвать список аккаунтов определённого типа через getAccountsByType().
Метод getAccountsByType() возвращает массив учётных записей. Если в массиве более одной учётной записи, то покажите пользователю диалоговое окно с запросом для выбора одного аккаунта.
Объект Account содержит имя учетной записи, для учетных записей Google – это адрес электронной почты, который вы можете использовать для автоматического заполнения полей или в качестве ключа в базе данных и т.д.
В других учётных записях в имени не обязательно может содержаться электронный адрес. Например, это может быть часть электронного адреса или просто имя пользователя.
На эмуляторе скорее всего нет никаких аккаунтов, поэтому лучше проверять на устройстве. В большинстве случаев на телефоне есть аккаунт для Гугла. В логах я проверил количество аккаунтов, а в текстовом поле вывел имя аккаунта, который оказался моим электронным адресом.
Метод getAccounts() выводит все учётные записи, которые есть на устройстве.
На моём устройстве оказалось три учётные записи. Чтобы понять, кому они принадлежат, я заменил account.name на account.toString() и получил следующий результат.
Теперь стало понятно.
Мы рассмотрели только базовый пример работы с AccountManager. На самом деле, у класса много других возможностей. Например, вы можете добавить новую учётную запись и управлять ею.
Источник
Requesting Runtime Permissions in Android M and N
Starting from Android Marshmallow (API 23), users will be asked for permissions while the app is running. This way, a user is able to choose which permissions they should grant without affecting the application flow. In this tutorial I will cover requesting runtime permissions in Android M and N, how to perform a request, get its result and then handle it.
There are many user-permissions in Android but I am only going to focus on some of the most used.
You can find the code for this project in github.
To begin, create a new project in Android Studio, choosing a minimum API level of 23 and adding an Empty Activity. This will be the only activity in the project.
Declaring Permissions
Open AndroidManifest.xml and add the following permissions:
The permissions above are some of the most used in android apps, but all of them work in a similar way.
Asking for Permission
Each of this permissions will be asked for by using a button. Update the code inside activity_main.xml to:
This is the layout you just created:
At this stage, if a user installed the application, it would require the following permissions:
Inside MainActivity.java, after onCreate add this method:
This method asks a user for permissions. Firstly it checks whether the permission you are asking for is granted or not. If it is, then the app shows a Toast saying that the permission was already granted. If the permission is not granted, it checks if the user has denied this permission before. If the permission is important for the app, it should be requested again. If the permission was not denied before, perform a request by calling ActivityCompat.requestPermissions(MainActivity.this, new String[]
Each permission request needs three parameters. The first is context , the second a String array of permission(s), and the third the requestCode of type Integer . The last parameter is a random code attached to the request, and can be any number that suits your use case. When a result returns in the activity, it contains this code and uses it to differentiate multiple results from each other.
The method is ready to perform requests, and now it should be linked with the corresponding buttons. Each of the buttons created has an android:onClick=»ask» property.
You need to create a public method called ask that will be called on each click of the buttons. It’s code is:
The second parameter of the askForPermission method are some random integers. Add their declarations before the onCreate() method:
Now the application can perform requests. The next step is handling the request results.
Handling the Results
To handle the results of a permission request, the onRequestPermissionsResult method is called. It’s code is below:
When a result is returned, it checks whether the permission was granted or not. If it is, the requestCode is passed to a switch statement to differentiate the results. I added extra lines inside each case to show further steps, but they are just examples.
Location Request
At case 1: there is a function called askForGPS() . This function prompts the user to enable GPS if it’s not enabled. If the device is not connected to GPS after the user has granted the location permission, the dialog below is shown:
To show this dialog, you need a GoogleApiClient . First, declare some variables by adding these lines before onCreate :
And build the client inside the onCreate method:
Now the client is built, it needs to connected when the app starts and disconnect when it stops. Add these two overriden methods to MainActivity :
Finally, add the function that shows the GPS dialog:
Conclusion
In this tutorial, I showed how to ask for permissions, and handle the results with Android’s new permission model. The aim of this new model is to put users in control of what our apps need to do. I’d love to hear your comments and opinions on this change and how to handle it below.
Источник