Intent
— это объект сообщения, который можно использовать для запроса действия у другого компонента приложения . Хотя намерения облегчают взаимодействие между компонентами несколькими способами, существует три основных варианта их использования:
- Начало деятельности
Activity
представляет собой отдельный экран в приложении. Вы можете запустить новый экземплярActivity
, передавIntent
вstartActivity()
.Intent
описывает запускаемую активность и содержит все необходимые данные.Если вы хотите получить результат от активности после её завершения, вызовите
startActivityForResult()
. Ваша активность получает результат в виде отдельного объектаIntent
в обратном вызовеonActivityResult()
. Подробнее см. в руководстве по активности . - Запуск службы
Service
— это компонент, выполняющий операции в фоновом режиме без пользовательского интерфейса. В Android 5.0 (API уровня 21) и более поздних версиях можно запустить службу с помощьюJobScheduler
. Подробнее оJobScheduler
см.API-reference documentation
.В версиях до Android 5.0 (уровень API 21) запустить службу можно с помощью методов класса
Service
. Вы можете запустить службу для выполнения однократной операции (например, загрузки файла), передавIntent
вstartService()
.Intent
описывает запускаемую службу и содержит все необходимые данные.Если служба разработана с клиент-серверным интерфейсом, вы можете подключиться к службе из другого компонента, передав
Intent
вbindService()
. Подробнее см. в руководстве по службам . - Проведение трансляции
A broadcast is a message that any app can receive. The system delivers various broadcasts for system events, such as when the system boots up or the device starts charging. You can deliver a broadcast to other apps by passing an
Intent
tosendBroadcast()
orsendOrderedBroadcast()
.
Далее на этой странице объясняется, как работают намерения и как их использовать. Подробнее см. в разделах «Взаимодействие с другими приложениями» и «Обмен контентом» .
Типы намерений
Существует два типа намерений:
- Явные намерения определяют, какой компонент какого приложения будет соответствовать намерению, указывая полное
ComponentName
. Обычно вы используете явное намерение для запуска компонента в своём приложении, поскольку знаете имя класса активности или службы, которую хотите запустить. Например, вы можете запустить новую активность в своём приложении в ответ на действие пользователя или запустить службу для загрузки файла в фоновом режиме. - Неявные намерения не называют конкретный компонент, а вместо этого объявляют общее действие, которое необходимо выполнить, что позволяет компоненту из другого приложения выполнить его. Например, если вы хотите показать пользователю местоположение на карте, вы можете использовать неявное намерение, чтобы запросить у другого совместимого приложения отображение указанного местоположения на карте.
На рисунке 1 показано, как используется намерение при запуске действия. Когда объект Intent
явно указывает конкретный компонент действия, система немедленно запускает этот компонент.

Рисунок 1. Как неявное намерение передаётся через систему для запуска другого действия: [1] Действие A создаёт Intent
с описанием действия и передаёт его методу startActivity()
. [2] Система Android ищет во всех приложениях фильтр намерений, соответствующий этому намерению. При обнаружении совпадения [3] система запускает соответствующее действие ( действие B ), вызывая его метод onCreate()
и передавая ему Intent
.
При использовании неявного намерения система Android находит подходящий компонент для запуска, сравнивая его содержимое с фильтрами намерений, объявленными в файле манифеста других приложений на устройстве. Если намерение соответствует фильтру намерений, система запускает этот компонент и передает ему объект Intent
. Если несколько фильтров намерений совместимы, система отображает диалоговое окно, позволяющее пользователю выбрать приложение для использования.
Фильтр намерений — это выражение в файле манифеста приложения, которое определяет тип намерений, которые компонент хотел бы получать. Например, объявляя фильтр намерений для активности, вы позволяете другим приложениям напрямую запускать вашу активность с определённым типом намерения. Аналогично, если вы не объявляете фильтры намерений для активности, её можно запустить только с явным намерением.
Внимание: Чтобы обеспечить безопасность вашего приложения, всегда используйте явное намерение при запуске Service
и не объявляйте фильтры намерений для своих служб. Использование неявного намерения для запуска службы представляет угрозу безопасности, поскольку невозможно точно знать, какая служба отреагирует на намерение, и пользователь не видит, какая служба запустится. Начиная с Android 5.0 (уровень API 21), система выдаёт исключение при вызове bindService()
с неявным намерением.
Формирование намерения
Объект Intent
несет информацию, которую система Android использует для определения того, какой компонент запустить (например, точное имя компонента или категория компонента, который должен получить намерение), а также информацию, которую компонент-получатель использует для правильного выполнения действия (например, действие, которое нужно выполнить, и данные, с которыми нужно выполнить действие).
Основная информация, содержащаяся в Intent
, следующая:
- Имя компонента
- Имя компонента, который необходимо запустить.
Это необязательный, но критически важный элемент информации, который делает намерение явным , то есть оно должно быть передано только компоненту приложения, указанному в его имени. Без имени компонента намерение неявное , и система решает, какой компонент должен получить намерение, основываясь на другой информации о намерении (например, о действии, данных и категории, описанной ниже). Если вам нужно запустить определенный компонент в приложении, необходимо указать его имя.
Примечание: При запуске
Service
всегда указывайте имя компонента . В противном случае вы не сможете точно знать, какая служба отреагирует на намерение, и пользователь не сможет увидеть, какая служба запустится.Это поле объекта
Intent
представляет собой объектComponentName
, который можно указать, используя полное имя класса целевого компонента, включая имя пакета приложения, например,com.example.ExampleActivity
. Имя компонента можно задать с помощьюsetComponent()
,setClass()
,setClassName()
или конструктораIntent
. - Действие
- Строка, которая определяет общее действие, которое необходимо выполнить (например, просмотр или выбор ).
В случае трансляции намерения это действие, которое произошло и о котором сообщается. Действие во многом определяет структуру остальной части намерения, в частности, информацию, содержащуюся в данных и дополнительных материалах.
You can specify your own actions for use by intents within your app (or for use by other apps to invoke components in your app), but you usually specify action constants defined by the
Intent
class or other framework classes. Here are some common actions for starting an activity:-
ACTION_VIEW
- Используйте это действие в намерении с
startActivity()
, когда у вас есть некоторая информация, которую действие может показать пользователю, например фотография для просмотра в приложении галереи или адрес для просмотра в приложении карты. -
ACTION_SEND
- Также известное как намерение поделиться , его следует использовать в намерении с
startActivity()
когда у вас есть данные, которыми пользователь может поделиться через другое приложение, например, приложение электронной почты или приложение для обмена сообщениями в социальных сетях.
Дополнительные константы, определяющие общие действия, см. в справочнике по классу
Intent
Другие действия определены в других разделах фреймворка Android, например, вSettings
для действий, открывающих определённые экраны в системном приложении «Настройки».Вы можете указать действие для намерения с помощью
setAction()
или с помощью конструктораIntent
.Если вы определяете собственные действия, обязательно укажите имя пакета вашего приложения в качестве префикса, как показано в следующем примере:
Котлин
const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"
Ява
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
-
- Данные
- URI (объект
Uri
), ссылающийся на данные, над которыми необходимо выполнить действие, и/или тип MIME этих данных. Тип предоставляемых данных обычно определяется действием намерения. Например, если действие —ACTION_EDIT
, данные должны содержать URI документа, который нужно изменить.При создании намерения часто важно указать тип данных (MIME-тип) в дополнение к URI. Например, активность, способная отображать изображения, вероятно, не сможет воспроизвести аудиофайл, даже если форматы URI будут схожими. Указание MIME-типа данных помогает системе Android найти оптимальный компонент для обработки вашего намерения. Однако иногда MIME-тип можно определить по URI, особенно если данные представляют собой URI
content:
URIcontent:
указывает, что данные расположены на устройстве и контролируютсяContentProvider
, что делает тип MIME данных видимым для системы.Чтобы задать только URI данных, вызовите
setData()
. Чтобы задать только тип MIME, вызовитеsetType()
. При необходимости можно явно задать оба типа с помощьюsetDataAndType()
.Внимание: Если вы хотите задать и URI, и MIME-тип, не вызывайте
setData()
иsetType()
поскольку они обнуляют значение друг друга. Всегда используйтеsetDataAndType()
для задания и URI, и MIME-типа. - Категория
- Строка, содержащая дополнительную информацию о типе компонента, который должен обрабатывать намерение. В намерение можно добавить любое количество описаний категорий, но для большинства намерений категория не требуется. Вот некоторые распространённые категории:
-
CATEGORY_BROWSABLE
- Целевая активность позволяет веб-браузеру запускать ее для отображения данных, на которые ссылается ссылка, например изображения или сообщения электронной почты.
-
CATEGORY_LAUNCHER
- Действие является начальным действием задачи и отображается в панели запуска приложений системы.
Полный список категорий см. в описании класса
Intent
.Вы можете указать категорию с помощью
addCategory()
. -
Перечисленные выше свойства (имя компонента, действие, данные и категория) представляют собой определяющие характеристики намерения. Считывая эти свойства, система Android может определить, какой компонент приложения следует запустить. Однако намерение может содержать дополнительную информацию, которая не влияет на то, как оно преобразуется в компонент приложения. Намерение также может предоставлять следующую информацию:
- Дополнительно
- Пары «ключ-значение», содержащие дополнительную информацию, необходимую для выполнения запрошенного действия. Подобно тому, как некоторые действия используют определённые типы URI данных, некоторые действия также используют определённые дополнительные данные.
Вы можете добавлять дополнительные данные с помощью различных методов
putExtra()
, каждый из которых принимает два параметра: имя ключа и значение. Вы также можете создать объектBundle
со всеми дополнительными данными, а затем вставить этотBundle
вIntent
с помощьюputExtras()
.Например, при создании намерения отправить электронное письмо с помощью
ACTION_SEND
вы можете указать получателя с помощью ключаEXTRA_EMAIL
и указать тему с помощью ключаEXTRA_SUBJECT
.Класс
Intent
определяет множество константEXTRA_*
для стандартизированных типов данных. Если вам нужно объявить собственные дополнительные ключи (для намерений, которые получает ваше приложение), обязательно укажите имя пакета вашего приложения в качестве префикса, как показано в следующем примере:Котлин
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
Ява
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Внимание : не используйте данные
Parcelable
илиSerializable
при отправке намерения, которое, как вы ожидаете, получит другое приложение. Если приложение пытается получить доступ к данным в объектеBundle
, но не имеет доступа к классу Parceled или serializable, система вызывает исключениеRuntimeException
. - Флаги
- Флаги определяются в классе
Intent
и служат метаданными для намерения. Флаги могут указывать системе Android, как запускать активность (например, к какой задаче она должна относиться) и как с ней обращаться после запуска (например, находится ли она в списке недавних активностей).Для получения дополнительной информации см. метод
setFlags()
.
Пример явного намерения
Явное намерение — это намерение, которое вы используете для запуска определённого компонента приложения, например, определённой активности или службы. Чтобы создать явное намерение, определите имя компонента для объекта Intent
; все остальные свойства намерения необязательны.
Например, если вы создали в своем приложении службу под названием DownloadService
, предназначенную для загрузки файла из Интернета, вы можете запустить ее с помощью следующего кода:
Котлин
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" val downloadIntent = Intent(this, DownloadService::class.java).apply { data =Uri.parse
(fileUrl) } startService(downloadIntent)
Ява
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" Intent downloadIntent = new Intent(this, DownloadService.class); downloadIntent.setData(Uri.parse
(fileUrl)); startService(downloadIntent);
Конструктор Intent(Context, Class)
предоставляет приложению Context
и компоненту объект Class
. Таким образом, это намерение явно запускает класс DownloadService
в приложении.
Дополнительную информацию о создании и запуске службы см. в руководстве « Службы» .
Пример неявного намерения
Неявное намерение определяет действие, которое может вызвать любое приложение на устройстве, способное выполнить это действие. Использование неявного намерения полезно, когда ваше приложение не может выполнить действие, но другие приложения, вероятно, могут, и вы хотите, чтобы пользователь мог выбрать, какое приложение использовать.
Например, если у вас есть контент, которым пользователь хочет поделиться с другими людьми, создайте намерение с действием ACTION_SEND
и добавьте дополнительные элементы, указывающие, каким контентом нужно поделиться. При вызове startActivity()
с этим намерением пользователь может выбрать приложение, через которое он хочет поделиться контентом.
Котлин
// Create the text message with a string. val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra(Intent.EXTRA_TEXT, textMessage) type = "text/plain" } // Try to invoke the intent. try { startActivity(sendIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Ява
// Create the text message with a string. Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage); sendIntent.setType("text/plain"); // Try to invoke the intent. try { startActivity(sendIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
When startActivity()
is called, the system examines all of the installed apps to determine which ones can handle this kind of intent (an intent with the ACTION_SEND
action and that carries "text/plain" data). If there's only one app that can handle it, that app opens immediately and is given the intent. If no other apps can handle it, your app can catch the ActivityNotFoundException
that occurs. If multiple activities accept the intent, the system displays a dialog such as the one shown in Figure 2, so the user can pick which app to use.
Более подробная информация о запуске других приложений также приведена в руководстве по переключению пользователя в другое приложение .

Рисунок 2. Диалоговое окно выбора.
Принудительный выбор приложения
Если на ваше неявное намерение реагирует несколько приложений, пользователь может выбрать, какое из них использовать, и сделать его приложением по умолчанию для выполнения действия. Возможность выбора приложения по умолчанию полезна при выполнении действия, для которого пользователь, вероятно, захочет каждый раз использовать одно и то же приложение, например, при открытии веб-страницы (пользователи часто предпочитают использовать только один веб-браузер).
Однако, если на намерение могут реагировать несколько приложений, и пользователь может каждый раз использовать другое приложение, следует явно отображать диалоговое окно выбора. В этом диалоговом окне пользователю предлагается выбрать приложение для выполнения действия (пользователь не может выбрать приложение по умолчанию). Например, когда ваше приложение выполняет команду «Поделиться» с помощью действия ACTION_SEND
, пользователи могут захотеть поделиться информацией через другое приложение в зависимости от текущей ситуации, поэтому всегда следует использовать диалоговое окно выбора, как показано на рисунке 2.
Чтобы отобразить окно выбора, создайте Intent
с помощью метода createChooser()
и передайте его методу startActivity()
, как показано в следующем примере. В этом примере отображается диалоговое окно со списком приложений, которые отвечают на намерение, переданное методу createChooser()
, и используется предоставленный текст в качестве заголовка диалогового окна.
Котлин
val sendIntent = Intent(Intent.ACTION_SEND) ... // Always use string resources for UI text. // This says something like "Share this photo with" val title: String = resources.getString(R.string.chooser_title) // Create intent to show the chooser dialog val chooser: Intent = Intent.createChooser(sendIntent, title) // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(packageManager) != null) { startActivity(chooser) }
Ява
Intent sendIntent = new Intent(Intent.ACTION_SEND); ... // Always use string resources for UI text. // This says something like "Share this photo with" String title = getResources().getString(R.string.chooser_title); // Create intent to show the chooser dialog Intent chooser = Intent.createChooser(sendIntent, title); // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); }
Обнаружение небезопасных намеренных запусков
Ваше приложение может запускать намерения для навигации между компонентами внутри приложения или для выполнения действия от имени другого приложения. Для повышения безопасности платформы в Android 12 (уровень API 31) и более поздних версиях реализована функция отладки, которая предупреждает вас, если приложение выполняет небезопасный запуск намерения. Например, ваше приложение может выполнить небезопасный запуск вложенного намерения , которое передаётся как дополнительное в другое намерение.
If your app performs both of the following actions, the system detects an unsafe intent launch, and a StrictMode violation occurs:
- Ваше приложение извлекает вложенное намерение из дополнений доставленного намерения.
- Ваше приложение немедленно запускает компонент приложения , используя это вложенное намерение, например, передавая намерение в
startActivity()
,startService()
илиbindService()
.
Более подробную информацию о том, как определить эту ситуацию и внести изменения в свое приложение, можно найти в публикации блога об Android Nesting Intents на Medium.
Проверка на наличие небезопасных намеренных запусков
Чтобы проверить наличие небезопасных запусков намерений в вашем приложении, вызовите метод detectUnsafeIntentLaunch()
при настройке VmPolicy
, как показано в следующем фрагменте кода. Если ваше приложение обнаруживает нарушение StrictMode, вы можете остановить его выполнение, чтобы защитить потенциально конфиденциальную информацию.
Котлин
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
Ява
protected void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()); }
Используйте намерения более ответственно
Чтобы свести к минимуму вероятность небезопасного запуска намерения и нарушения StrictMode, следуйте этим рекомендациям.
Копируйте только необходимые дополнения из намерений и выполняйте необходимую очистку и валидацию. Ваше приложение может копировать дополнения из одного намерения в другое, используемое для запуска нового компонента. Это происходит, когда ваше приложение вызывает putExtras(Intent)
или putExtras(Bundle)
. Если ваше приложение выполняет одну из этих операций, копируйте только те дополнения, которые ожидает принимающий компонент. Если другое намерение (получающее копию) запускает компонент, который не экспортируется , очистьте и проверьте дополнения перед их копированием в намерение, запускающее этот компонент.
Не экспортируйте компоненты приложения без необходимости. Например, если вы планируете запустить компонент приложения с помощью внутреннего вложенного намерения, установите для атрибута android:exported
этого компонента значение false
.
Используйте PendingIntent
вместо вложенного Intent. Таким образом, когда другое приложение распаковывает PendingIntent
содержащего его Intent
, оно может запустить PendingIntent
, используя идентификатор вашего приложения. Такая конфигурация позволяет другому приложению безопасно запускать любой компонент вашего приложения, включая неэкспортированные.
Диаграмма на рисунке 2 показывает, как система передает управление от вашего (клиентского) приложения другому (сервисному) приложению и обратно вашему приложению:
- Ваше приложение создаёт намерение, которое вызывает действие в другом приложении. В это намерение вы добавляете объект
PendingIntent
в качестве дополнения. Это отложенное намерение вызывает компонент в вашем приложении; этот компонент не экспортируется. - Получив намерение вашего приложения, другое приложение извлекает вложенный объект
PendingIntent
. - Другое приложение вызывает метод
send()
для объектаPendingIntent
. - После передачи управления обратно вашему приложению система вызывает ожидающее намерение, используя контекст вашего приложения.
Рисунок 2. Схема взаимодействия приложений при использовании вложенного ожидающего намерения.
Получение неявного намерения
Чтобы указать, какие неявные намерения может получать ваше приложение, объявите один или несколько фильтров намерений для каждого компонента приложения с помощью элемента <intent-filter>
в файле манифеста . Каждый фильтр намерений определяет тип принимаемых намерений на основе действия, данных и категории намерения. Система передаёт неявное намерение компоненту приложения только в том случае, если оно может пройти через один из фильтров намерений.
Примечание: Явное намерение всегда доставляется своей цели, независимо от любых фильтров намерений, объявленных компонентом.
Компонент приложения должен объявлять отдельные фильтры для каждой уникальной задачи, которую он может выполнять. Например, одна активность в приложении галереи изображений может иметь два фильтра: один для просмотра изображения, а другой — для редактирования. При запуске активность проверяет Intent
и решает, как себя вести на основе информации в Intent
(например, отображать элементы управления редактором или нет).
Каждый фильтр намерений определяется элементом <intent-filter>
в файле манифеста приложения, вложенным в соответствующий компонент приложения (например, элемент <activity>
).
В каждом компоненте приложения, включающем элемент <intent-filter>
, явно задайте значение атрибута android:exported
. Этот атрибут указывает, доступен ли компонент приложения другим приложениям. В некоторых ситуациях, например, для действий, фильтры намерений которых включают категорию LAUNCHER
, полезно установить этот атрибут в true
. В противном случае безопаснее установить этот атрибут в false
.
Предупреждение: если действие, служба или приемник вещания в вашем приложении используют фильтры намерений и явно не задают значение android:exported
, ваше приложение не может быть установлено на устройстве под управлением Android 12 или выше.
Внутри <intent-filter>
вы можете указать тип принимаемых намерений, используя один или несколько из этих трех элементов:
-
<action>
- Объявляет действие намерения принятым в атрибуте
name
. Значение должно быть строковым значением действия, а не константой класса. -
<data>
- Объявляет тип принимаемых данных, используя один или несколько атрибутов, которые указывают различные аспекты URI данных (
scheme
,host
,port
,path
) и тип MIME. -
<category>
- Объявляет принятую категорию намерения в атрибуте
name
. Значение должно быть строковым значением действия, а не константой класса.Примечание: Для получения неявных намерений необходимо включить категорию
CATEGORY_DEFAULT
в фильтр намерений. МетодыstartActivity()
иstartActivityForResult()
обрабатывают все намерения так, как будто они объявляют категориюCATEGORY_DEFAULT
. Если эта категория не объявлена в фильтре намерений, никакие неявные намерения не будут преобразованы в вашу активность.
Например, вот объявление действия с фильтром намерений для получения намерения ACTION_SEND
, когда тип данных — текст:
<activity android:name="ShareActivity" android:exported="false"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>
Вы можете создать фильтр, включающий более одного экземпляра <action>
, <data>
или <category>
. В этом случае необходимо убедиться, что компонент может обрабатывать любые комбинации этих элементов фильтра.
Если вы хотите обрабатывать несколько видов намерений, но только в определенных сочетаниях действий, данных и типов категорий, вам необходимо создать несколько фильтров намерений.
Неявное намерение проверяется на соответствие фильтру путём сравнения намерения с каждым из трёх элементов. Для передачи компоненту намерение должно пройти все три проверки. Если оно не соответствует хотя бы одной из них, система Android не доставит его компоненту. Однако, поскольку компонент может иметь несколько фильтров намерений, намерение, не прошедшее через один из фильтров компонента, может пройти через другой фильтр. Подробнее о том, как система разрешает намерения, см. в разделе ниже, посвящённом разрешению намерений .
Внимание: использование фильтра намерений не является безопасным способом предотвращения запуска ваших компонентов другими приложениями. Хотя фильтры намерений ограничивают компонент реагированием только на определённые виды неявных намерений, другое приложение потенциально может запустить ваш компонент, используя явное намерение, если разработчик определил имена компонентов. Если важно, чтобы только ваше приложение могло запускать один из ваших компонентов, не объявляйте фильтры намерений в манифесте. Вместо этого установите для exported
компонента значение "false"
.
Аналогично, чтобы избежать непреднамеренного запуска Service
другого приложения, всегда используйте явное намерение для запуска собственной службы.
Примечание: Для всех действий необходимо объявить фильтры намерений в файле манифеста. Однако фильтры для приёмников широковещательных сообщений можно регистрировать динамически, вызвав метод registerReceiver()
. Затем можно отменить регистрацию приёмника с помощью unregisterReceiver()
. Это позволит вашему приложению прослушивать определённые широковещательные сообщения только в течение определённого периода времени, пока приложение работает.
Примеры фильтров
Чтобы продемонстрировать некоторые особенности поведения фильтра намерений, приведем пример из файла манифеста приложения для обмена сообщениями в социальных сетях:
<activity android:name="MainActivity" android:exported="true"> <!-- This activity is the main entry, should appear in app launcher --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="ShareActivity" android:exported="false"> <!-- This activity handles "SEND" actions with text data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data --> <intent-filter> <action android:name="android.intent.action.SEND"/> <action android:name="android.intent.action.SEND_MULTIPLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/vnd.google.panorama360+jpg"/> <data android:mimeType="image/*"/> <data android:mimeType="video/*"/> </intent-filter> </activity>
Первая активность, MainActivity
, является основной точкой входа приложения — активностью, которая открывается, когда пользователь первоначально запускает приложение с помощью значка запуска:
- Действие
ACTION_MAIN
указывает, что это основная точка входа, и не ожидает никаких данных о намерениях. - Категория
CATEGORY_LAUNCHER
указывает, что значок этого действия должен быть помещен в системную панель запуска приложений. Если элемент<activity>
не указывает значок с помощьюicon
, система использует значок из элемента<application>
.
Эти два действия должны быть объединены вместе, чтобы действие появилось в панели запуска приложений.
Второе действие, ShareActivity
, предназначено для упрощения обмена текстовым и медиаконтентом. Хотя пользователи могут перейти к этому действию, перейдя к нему из MainActivity
, они также могут перейти к ShareActivity
непосредственно из другого приложения, которое выдаёт неявное намерение, соответствующее одному из двух фильтров намерений.
Примечание: тип MIME application/vnd.google.panorama360+jpg
— это специальный тип данных, который определяет панорамные фотографии, с которыми можно работать с помощью API панорам Google .
Сопоставьте намерения с фильтрами намерений других приложений
Если другое приложение предназначено для Android 13 (уровень API 33) или выше, оно сможет обработать намерение вашего приложения только в том случае, если оно соответствует действиям и категориям элемента <intent-filter>
в этом другом приложении. Если система не находит совпадений, она генерирует исключение ActivityNotFoundException
. Отправляющее приложение должно обработать это исключение.
Аналогично, если вы обновляете приложение для Android 13 или более поздней версии, все намерения, исходящие от внешних приложений, доставляются экспортированному компоненту вашего приложения только в том случае, если это намерение соответствует действиям и категориям элемента <intent-filter>
, объявленного вашим приложением. Это происходит независимо от целевой версии SDK отправляющего приложения.
В следующих случаях сопоставление намерений не применяется:
- Намерения, отправляемые компонентам, которые не объявляют никаких фильтров намерений.
- Намерения, возникающие в одном и том же приложении.
- Намерения, исходящие из системы, то есть намерения, отправляемые с «системного UID» (uid=1000). Системные приложения включают
system_server
и приложения, которые устанавливаютandroid:sharedUserId
в значениеandroid.uid.system
. - Намерения, исходящие из корня.
Узнайте больше о сопоставлении намерений .
Использование ожидающего намерения
Объект PendingIntent
— это обёртка вокруг объекта Intent
. Основное назначение PendingIntent
— предоставить стороннему приложению разрешение использовать содержащийся в нём Intent
, как если бы он выполнялся из собственного процесса вашего приложения.
Основные варианты использования отложенного намерения включают следующее:
- Declaring an intent to be executed when the user performs an action with your Notification (the Android system's
NotificationManager
executes theIntent
). - Объявление намерения, которое будет выполнено, когда пользователь выполняет действие с вашим виджетом приложения (приложение на главном экране выполняет
Intent
). - Объявление намерения, которое будет выполнено в указанное время в будущем (
AlarmManager
системы Android выполняетIntent
).
Just as each Intent
object is designed to be handled by a specific type of app component (either an Activity
, a Service
, or a BroadcastReceiver
), so too must a PendingIntent
be created with the same consideration. When using a pending intent, your app doesn't execute the intent with a call such as startActivity()
. Instead, you must declare the intended component type when you create the PendingIntent
by calling the respective creator method:
-
PendingIntent.getActivity()
дляIntent
, который запускаетActivity
. -
PendingIntent.getService()
дляIntent
, который запускаетService
. -
PendingIntent.getBroadcast()
дляIntent
, который запускаетBroadcastReceiver
.
Если ваше приложение не получает ожидающие намерения от других приложений, то приведенные выше методы создания PendingIntent
, вероятно, единственные методы PendingIntent
, которые вам когда-либо понадобятся.
Каждый метод принимает текущий Context
приложения, Intent
вы хотите обернуть, и один или несколько флагов, которые указывают, как должно использоваться намерение (например, можно ли использовать намерение более одного раза).
Дополнительную информацию об использовании ожидающих намерений см. в документации по каждому из соответствующих вариантов использования, например, в руководствах по API уведомлений и виджетов приложений .
Укажите изменчивость
Если ваше приложение предназначено для Android 12 или более поздней версии, необходимо указать изменяемость каждого создаваемого вами объекта PendingIntent
. Чтобы объявить объект PendingIntent
изменяемым или неизменяемым, используйте флаг PendingIntent.FLAG_MUTABLE
или PendingIntent.FLAG_IMMUTABLE
соответственно.
Если ваше приложение попытается создать объект PendingIntent
, не установив ни одного флага изменяемости, система выдаст исключение IllegalArgumentException
, а в Logcat появится следующее сообщение:
PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
Создавайте неизменяемые отложенные намерения, когда это возможно
В большинстве случаев ваше приложение должно создавать неизменяемые объекты PendingIntent
, как показано в следующем фрагменте кода. Если объект PendingIntent
неизменяем, другие приложения не смогут изменять намерение, чтобы скорректировать результат его вызова.
Котлин
val pendingIntent = PendingIntent.getActivity(applicationContext, REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
Ява
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
Однако в некоторых случаях использования вместо этого требуются изменяемые объекты PendingIntent
:
- Поддержка действий прямого ответа в уведомлениях . Прямой ответ требует изменения данных клипа в объекте PendingIntent, связанном с ответом. Обычно это изменение запрашивается путем передачи
FILL_IN_CLIP_DATA
в качестве флага методуfillIn()
. - Связывание уведомлений с фреймворком Android Auto с использованием экземпляров
CarAppExtender
. - Размещение обсуждений в пузырьках с помощью экземпляров
PendingIntent
. Изменяемый объектPendingIntent
позволяет системе применять правильные флаги, такие какFLAG_ACTIVITY_MULTIPLE_TASK
иFLAG_ACTIVITY_NEW_DOCUMENT
. - Запрос информации о местоположении устройства с помощью вызова
requestLocationUpdates()
или аналогичных API. Изменяемый объектPendingIntent
позволяет системе добавлять дополнительные намерения, представляющие события жизненного цикла местоположения. К таким событиям относятся изменение местоположения и доступность поставщика. - Планирование будильников с помощью
AlarmManager
. Изменяемый объектPendingIntent
позволяет системе добавлять дополнительное значениеEXTRA_ALARM_COUNT
к интенту. Это дополнительное значение представляет количество срабатываний повторяющегося будильника. Благодаря этому дополнительному значению интент может точно уведомлять приложение о том, срабатывал ли повторяющийся будильник несколько раз, например, когда устройство находилось в спящем режиме.
Если ваше приложение создаёт изменяемый объект PendingIntent
, настоятельно рекомендуется использовать явное намерение и заполнить ComponentName
. Таким образом, всякий раз, когда другое приложение вызывает PendingIntent
и передаёт управление вашему приложению, в вашем приложении всегда запускается тот же компонент.
Используйте явные намерения в ожидаемых намерениях
Чтобы лучше определить, как другие приложения могут использовать ожидаемые намерения вашего приложения, всегда заключайте ожидаемое намерение в явное намерение . Чтобы следовать этой рекомендации, выполните следующие действия:
- Проверьте, что поля действия, пакета и компонента базового намерения установлены.
Use
FLAG_IMMUTABLE
, added in Android 6.0 (API level 23), to create pending intents. This flag prevents apps that receive aPendingIntent
from filling in unpopulated properties. If your app'sminSdkVersion
is22
or lower, you can provide safety and compatibility together using the following code:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
Разрешение намерений
Когда система получает неявное намерение начать действие, она ищет наилучшее действие для этого намерения, сравнивая его с фильтрами намерений на основе трех аспектов:
- Действие.
- Данные (как URI, так и тип данных).
- Категория.
В следующих разделах описывается, как намерения сопоставляются с соответствующими компонентами согласно объявлению фильтра намерений в файле манифеста приложения.
Тест действия
Чтобы указать принятые действия намерения, фильтр намерений может объявить ноль или более элементов <action>
, как показано в следующем примере:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
Чтобы пройти этот фильтр, действие, указанное в Intent
должно соответствовать одному из действий, перечисленных в фильтре.
Если фильтр не содержит никаких действий, намерению не с чем сопоставляться, поэтому все намерения не проходят проверку. Однако, если в Intent
не указано действие, оно проходит проверку, если фильтр содержит хотя бы одно действие.
Тест категории
Чтобы указать принятые категории намерений, фильтр намерений может объявить ноль или более элементов <category>
, как показано в следующем примере:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
Чтобы намерение прошло тест на категорию, каждая категория в Intent
должна соответствовать категории в фильтре. Обратное условие необязательно — фильтр намерения может объявить больше категорий, чем указано в Intent
, и Intent
всё равно будет успешно выполнено. Таким образом, намерение без категорий всегда проходит этот тест, независимо от того, какие категории объявлены в фильтре.
Примечание. Android автоматически применяет категорию CATEGORY_DEFAULT
ко всем неявным намерениям, передаваемым в startActivity()
и startActivityForResult()
. Если вы хотите, чтобы ваша деятельность получила неявные намерения, она должна включать категорию для "android.intent.category.DEFAULT"
в его намерениях, как показано в предыдущем примере <intent-filter>
.
Тест данных
Чтобы указать принятые данные о намерениях, фильтр намерения может объявить о нулевом или более элементах <data>
, как показано в следующем примере:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
Каждый элемент <data>
может указать структуру URI и тип данных (тип MIME Media). Каждая часть URI является отдельным атрибутом: scheme
, host
, port
и path
:
<scheme>://<host>:<port>/<path>
В следующем примере показаны возможные значения для этих атрибутов:
content://com.example.project:200/folder/subfolder/etc
В этом URI схема содержит content
, хост является com.example.project
, порт составляет 200
, а путь - folder/subfolder/etc
. Д.
Каждый из этих атрибутов является необязательным в элементе <data>
, но есть линейные зависимости:
- Если схема не указана, хост игнорируется.
- Если хост не указан, порт игнорируется.
- Если и схема, и хост не указаны, путь игнорируется.
Когда URI в намерении сравнивается со спецификацией URI в фильтре, он сравнивается только с частями URI, включенными в фильтр. Например:
- Если фильтр указывает только схему, все URI с этой схемой соответствуют фильтру.
- Если фильтр указывает схему и авторитет, но нет пути, все URI с одной и той же схемой и авторитетом проходят фильтр, независимо от их пути.
- Если фильтр указывает схему, полномочия и путь, только URI с той же схемой, авторитетом и пути проходят фильтр.
ПРИМЕЧАНИЕ. Спецификация пути может содержать звездочку подстановочного знака (*), чтобы потребовать только частичное соответствие имени пути.
Тест данных сравнивает как URI, так и тип MIME в намерении с URI и типом MIME, указанным в фильтре. Правила следующие:
- Намерение, которое содержит ни URI, ни тип MIME, проходит тест только в том случае, если в фильтре не указывается какие -либо типы URI или MIME.
- Намерение, которое содержит URI, но ни один тип MIME (ни явный, ни вывод из URI) не проходит тест, только если его URI соответствует формату URI фильтра, а фильтр также не указывает тип MIME.
- Намерение, которое содержит тип MIME, но не URI, проходит тест, только если в фильтре перечислены один и тот же тип MIME и не указывает формат URI.
- An intent that contains both a URI and a MIME type (either explicit or inferable from the URI) passes the MIME type part of the test only if that type matches a type listed in the filter. It passes the URI part of the test either if its URI matches a URI in the filter or if it has a
content:
orfile:
URI and the filter does not specify a URI. In other words, a component is presumed to supportcontent:
andfile:
data if its filter lists only a MIME type.
ПРИМЕЧАНИЕ. Если намерение указывает URI или тип MIME, тест данных не удастся, если в <data>
элементах <intent-filter>
.
Это последнее правило, правило (d), отражает ожидание того, что компоненты могут получить локальные данные из файла или поставщика контента. Следовательно, их фильтры могут перечислять только тип данных и не нужно явно называть content:
и file:
схемы. В следующем примере показан типичный случай, в котором элемент <data>
сообщает Android, что компонент может получить данные изображения от поставщика контента и отобразить его:
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
Фильтры, которые указывают тип данных, но не URI, пожалуй, наиболее распространены, потому что большинство доступных данных отдаются поставщиками контента.
Другая общая конфигурация - это фильтр со схемой и тип данных. Например, элемент <data>
, подобный следующему, сообщает Android, что компонент может извлечь видеоданные из сети, чтобы выполнить действие:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
Сопоставление намерений
Намерения соответствуют фильтрам намерения не только для обнаружения целевого компонента для активации, но и для того, чтобы узнать что -то о наборе компонентов на устройстве. Например, приложение Home заполняет запуск приложения, обнаружив все действия с помощью фильтров намерения, в которых указывается категория ACTION_MAIN
Action и CATEGORY_LAUNCHER
. Матч является успешным только в том случае, если действия и категории в намерениях совпадают с фильтром, как описано в документации для класса IntentFilter
.
Ваше приложение может использовать сопоставление намерений таким же образом, как это делает домашнее приложение. У PackageManager
есть набор методов query...()
, которые возвращают все компоненты, которые могут принять конкретное намерение, и аналогичную серию resolve...()
, которые определяют лучший компонент для реагирования на намерение. Например, queryIntentActivities()
возвращает список всех действий, которые могут выполнить намерение, принятое в качестве аргумента, и queryIntentServices()
возвращает аналогичный список услуг. Ни один из методов не активирует компоненты; Они просто перечисляют те, которые могут ответить. Есть аналогичный метод, queryBroadcastReceivers()
для вещательных приемников.