Ограничить взаимодействие с другими приложениями

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

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

Как проверить разрешения другого приложения

Чтобы посмотреть набор разрешений, которые запрашивает другое приложение, выполните следующие действия на устройстве или в эмуляторе:

  1. Откройте экран О приложении.
  2. Выберите Разрешения. Откроется экран Разрешения для приложений.

    На этом экране показан набор групп разрешений. Система организует набор разрешений, объявленных приложением, в эти группы.

Есть и другие способы проверить разрешения:

  • Чтобы проверить разрешение во время вызова сервиса, передайте строку разрешения в Context.checkCallingPermission(). Этот метод возвращает целое число, указывающее, было ли это разрешение предоставлено текущему вызывающему процессу. Обратите внимание, что этот метод можно использовать только при выполнении вызова, поступающего из другого процесса, обычно через интерфейс IDL, опубликованный из сервиса или предоставленный другому процессу каким-либо другим способом.
  • Чтобы проверить, предоставлено ли определенное разрешение другому процессу, передайте идентификатор процесса (PID) в Context.checkPermission().
  • Чтобы проверить, предоставлено ли определенное разрешение другому пакету, передайте название пакета в PackageManager.checkPermission().

Ограничение взаимодействий с действиями в приложении

В манифесте используйте атрибут android:permission тега <activity>, чтобы ограничить список приложений, которые могут запускать этот Activity. Разрешение проверяется во время выполнения методов Context.startActivity() и Activity.startActivityForResult(). Если у вызывающего абонента нет необходимых разрешений, возникает ошибка SecurityException.

Как ограничить взаимодействие с сервисами приложения

В манифесте используйте атрибут android:permission тега <service>, чтобы ограничить список приложений, которые могут запускать связанный объект Service или привязываться к нему. Разрешение проверяется во время выполнения методов Context.startService(), Context.stopService() и Context.bindService(). Если у вызывающего абонента нет необходимого разрешения, возникает ошибка SecurityException.

Ограничьте взаимодействие с поставщиками контента в приложении

В манифесте используйте атрибут android:permission тега <provider>, чтобы ограничить доступ других приложений к данным в ContentProvider. Поставщики контента имеют важную дополнительную функцию безопасности, которая называется разрешениями URI и описана в следующем разделе. В отличие от других компонентов, для поставщиков контента можно задать два отдельных атрибута разрешений: android:readPermission ограничивает, какие приложения могут считывать данные из поставщика, а android:writePermission – какие приложения могут записывать данные в него. Обратите внимание, что если поставщик защищен разрешениями на чтение и запись, то наличие только разрешения на запись не позволяет приложению читать данные из поставщика.

Разрешения проверяются при первом получении поставщика и когда приложение выполняет операции с ним. Если у запрашивающего приложения нет ни одного из этих разрешений, возникает ошибка SecurityException. Для использования ContentResolver.query() требуется разрешение на чтение, а для использования ContentResolver.insert(), ContentResolver.update() или ContentResolver.delete() – разрешение на запись. Во всех этих случаях отсутствие необходимого разрешения приводит к ошибке SecurityException.

Предоставление доступа на уровне URI

Система предоставляет вам дополнительный детальный контроль над тем, как другие приложения могут получать доступ к поставщикам контента вашего приложения. В частности, поставщик контента может защитить себя с помощью разрешений на чтение и запись, позволяя при этом своим прямым клиентам делиться определенными URI с другими приложениями. Чтобы заявить о поддержке этой модели, используйте атрибут android:grantUriPermissions или элемент <grant-uri-permission>.

Вы также можете предоставлять разрешения для отдельных URI. При запуске действия или возврате результата в действие установите флаг намерения Intent.FLAG_GRANT_READ_URI_PERMISSION, флаг намерения Intent.FLAG_GRANT_WRITE_URI_PERMISSION или оба флага. Это дает другим приложениям разрешения на чтение, запись или чтение и запись соответственно для URI данных, включенного в намерение. Другие приложения получают эти разрешения для определенного URI независимо от того, есть ли у них разрешение на доступ к данным в поставщике контента в целом.

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

Ещё один важный аспект – видимость приложения. Если ваше приложение предназначено для Android 11 (уровень API 30) или более поздней версии, система автоматически делает некоторые приложения видимыми для него, а другие по умолчанию скрывает. Если в вашем приложении есть поставщик контента и вы предоставили другому приложению разрешения URI, ваше приложение автоматически становится видимым для другого приложения.

Дополнительную информацию вы найдете в справочных материалах по методам grantUriPermission(), revokeUriPermission() и checkUriPermission().

Ограничьте взаимодействие с широковещательными приемниками приложения

Используйте атрибут android:permission тега <receiver>, чтобы ограничить список приложений, которые могут отправлять широковещательные сообщения связанному объекту BroadcastReceiver. Система проверяет разрешение после возврата Context.sendBroadcast(), когда пытается доставить отправленную трансляцию указанному получателю. Это означает, что ошибка разрешения не приводит к возврату исключения вызывающему объекту – она просто не доставляет Intent.

Вы также можете настроить разрешения программно:

  • Чтобы указать, какие приложения могут отправлять широковещательные сообщения программно зарегистрированному приемнику, предоставьте разрешение Context.registerReceiver().
  • Чтобы ограничить список широковещательных приемников, которые могут получать трансляцию, укажите разрешение при вызове Context.sendBroadcast().

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