Intent
— это объект обмена сообщениями, который можно использовать для запроса действия из другого компонента приложения . Хотя 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()
. Для получения дополнительной информации см. руководство по службам . - Проведение трансляции
Трансляция — это сообщение, которое может получить любое приложение. Система отправляет различные трансляции для системных событий, например, когда система загружается или устройство начинает заряжаться. Вы можете отправить трансляцию другим приложениям, передав
Intent
вsendBroadcast()
илиsendOrderedBroadcast()
.
Остальная часть этой страницы объясняет, как работают намерения и как их использовать. Для получения связанной информации см. Взаимодействие с другими приложениями и Обмен контентом .
Типы намерений
Существует два типа намерений:
- Явные намерения указывают, какой компонент какого приложения будет удовлетворять намерению, указывая полное
ComponentName
. Обычно вы будете использовать явное намерение для запуска компонента в своем собственном приложении, поскольку вы знаете имя класса действия или службы, которую хотите запустить. Например, вы можете запустить новое действие в своем приложении в ответ на действие пользователя или запустить службу для загрузки файла в фоновом режиме. - Неявные намерения не называют конкретный компонент, а вместо этого объявляют общее действие для выполнения, что позволяет компоненту из другого приложения обрабатывать его. Например, если вы хотите показать пользователю местоположение на карте, вы можете использовать неявное намерение, чтобы запросить, чтобы другое способное приложение показало указанное местоположение на карте.
Рисунок 1 показывает, как намерение используется при запуске действия. Когда объект Intent
явно называет конкретный компонент действия, система немедленно запускает этот компонент.

Рисунок 1. Как неявное намерение доставляется через систему для запуска другого действия: [1] Действие A создает Intent
с описанием действия и передает его startActivity()
. [2] Система Android ищет во всех приложениях фильтр намерений, который соответствует намерению. Когда совпадение найдено, [3] система запускает соответствующее действие ( Activity 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
. - Действие
- Строка, которая определяет общее действие, которое необходимо выполнить (например, просмотр или выбор ).
В случае трансляции намерения это действие, которое имело место и о котором сообщается. Действие во многом определяет, как структурирована остальная часть намерения, в частности, информация, содержащаяся в данных и дополнительных материалах.
Вы можете указать собственные действия для использования намерениями в вашем приложении (или для использования другими приложениями для вызова компонентов в вашем приложении), но обычно вы указываете константы действий, определенные классом
Intent
или другими классами фреймворка. Вот некоторые общие действия для запуска активности:-
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
, но не имеет доступа к пакетированному или сериализованному классу, система вызывает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. }
При вызове startActivity()
система проверяет все установленные приложения, чтобы определить, какие из них могут обрабатывать этот тип намерения (намерение с действием ACTION_SEND
, которое несет данные "text/plain"). Если есть только одно приложение, которое может его обработать, оно немедленно открывается и получает намерение. Если ни одно другое приложение не может его обработать, ваше приложение может перехватить ActivityNotFoundException
, которое возникает. Если несколько действий принимают намерение, система отображает диалоговое окно, подобное показанному на рисунке 2, чтобы пользователь мог выбрать, какое приложение использовать.
Более подробная информация о запуске других приложений также приведена в руководстве по отправке пользователя в другое приложение .

Рисунок 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) и выше предоставляют функцию отладки, которая предупреждает вас, если ваше приложение выполняет небезопасный запуск намерения. Например, ваше приложение может выполнять небезопасный запуск вложенного намерения , которое является намерением, переданным как дополнительное в другом намерении.
Если ваше приложение выполняет оба следующих действия, система обнаруживает небезопасный запуск намерения и происходит нарушение StrictMode :
- Ваше приложение извлекает вложенное намерение из дополнений доставленного намерения.
- Ваше приложение немедленно запускает компонент приложения , используя это вложенное намерение, например, передавая намерение в
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
вместо вложенного намерения. Таким образом, когда другое приложение распаковывает 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
, как если бы он был выполнен из собственного процесса вашего приложения.
Основные варианты использования ожидающего намерения включают следующее:
- Объявление намерения, которое будет выполнено, когда пользователь выполнит действие с вашим уведомлением (
NotificationManager
системы Android выполняетIntent
). - Объявление намерения, которое будет выполнено, когда пользователь выполняет действие с вашим виджетом приложения (приложение на главном экране выполняет
Intent
). - Объявление намерения, которое будет выполнено в указанное время в будущем (
AlarmManager
системы Android выполняетIntent
).
Так же, как каждый объект Intent
предназначен для обработки определенным типом компонента приложения ( Activity
, Service
или BroadcastReceiver
), так и PendingIntent
должен быть создан с тем же учетом. При использовании ожидаемого намерения ваше приложение не выполняет намерение с помощью вызова, такого как startActivity()
. Вместо этого вы должны объявить предполагаемый тип компонента при создании PendingIntent
, вызвав соответствующий метод-создателя:
-
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
и передает управление обратно вашему приложению, в вашем приложении всегда запускается тот же компонент.
Использовать явные намерения в ожидающих намерениях
Чтобы лучше определить, как другие приложения могут использовать ожидаемые намерения вашего приложения, всегда оборачивайте ожидаемое намерение вокруг явного намерения . Чтобы следовать этой передовой практике, выполните следующие действия:
- Проверьте, что поля действия, пакета и компонента базового намерения установлены.
Используйте
FLAG_IMMUTABLE
, добавленный в Android 6.0 (уровень API 23), для создания ожидающих намерений. Этот флаг не позволяет приложениям, получающимPendingIntent
, заполнять незаполненные свойства. ЕслиminSdkVersion
вашего приложения равен22
или ниже, вы можете обеспечить безопасность и совместимость вместе с помощью следующего кода: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.
- Намерение, которое содержит как URI, так и тип MIME (явное или предполагаемое из URI), проходит часть типа MIME в тесте, только если этот тип соответствует типу, указанному в фильтре. Он проходит часть URI часть теста, если его URI соответствует URI в фильтре, либо если он имеет
content:
илиfile:
URI, а фильтр не указывает URI. Другими словами, предполагается, что компонент поддерживаетcontent:
иfile:
данные, если его фильтр перечисляет только тип MIME.
ПРИМЕЧАНИЕ. Если намерение указывает 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()
для вещательных приемников.
Intent
- это объект обмена сообщениями, который вы можете использовать для запроса действия из другого компонента приложения . Хотя намерения облегчают связь между компонентами несколькими способами, существует три валяния фундаментальных использования:
- Запуск деятельности
Activity
представляет собой один экран в приложении. Вы можете начать новый экземплярActivity
, передавIntent
startActivity()
.Intent
описывает деятельность для начала и несет любые необходимые данные.Если вы хотите получить результат от деятельности, когда оно закончит, вызовите
startActivityForResult()
. Ваша деятельность получает результат в качестве отдельного объектаIntent
вonActivityResult()
вызове вашей деятельности. Для получения дополнительной информации см. Руководство по деятельности . - Запуск услуги
Service
- это компонент, который выполняет операции в фоновом режиме без пользовательского интерфейса. С Android 5.0 (API -уровень 21), а затем вы можете начать услугу сJobScheduler
. Для получения дополнительной информации оJobScheduler
см. В ееAPI-reference documentation
.Для версий раньше, чем Android 5.0 (уровень 21 API), вы можете запустить службу, используя методы
Service
класса. Вы можете запустить службу для выполнения единовременной операции (например, загрузки файла), передавIntent
startService()
.Intent
описывает службу для запуска и несет любые необходимые данные.Если сервис разработан с помощью интерфейса клиентского сервера, вы можете привязаться к службе из другого компонента, передавая
Intent
bindService()
. Для получения дополнительной информации см. Руководство по обслуживанию . - Доставка трансляции
Трансляция - это сообщение, которое может получить любое приложение. Система обеспечивает различные трансляции для системных событий, например, когда система загружается или устройство начинает заряжаться. Вы можете доставить трансляцию другим приложениям, передав
Intent
sendBroadcast()
илиsendOrderedBroadcast()
.
Остальная часть этой страницы объясняет, как намерения работать и как их использовать. Связанную информацию см. В взаимодействии с другими приложениями и обмена контентом .
Типы намерений
Есть два типа намерений:
- Явные намерения указывают, какой компонент, из какого приложения будет удовлетворять намерение, указав полное
ComponentName
. Вы обычно используете явное намерение запустить компонент в своем собственном приложении, потому что вы знаете название класса деятельности или услуги, которые вы хотите начать. Например, вы можете запустить новое действие в вашем приложении в ответ на действие пользователя или запустить службу для загрузки файла в фоновом режиме. - Неявные намерения не называют конкретный компонент, а вместо этого объявляют общее действие для выполнения, которое позволяет компоненту из другого приложения обрабатывать его. Например, если вы хотите показать пользователю местоположение на карте, вы можете использовать неявное намерение запросить, чтобы другое способное приложение показало указанное местоположение на карте.
На рисунке 1 показано, как используется намерение при запуске деятельности. Когда объект Intent
явно называет конкретный компонент активности, система немедленно запускает этот компонент.

Рисунок 1. Как проходит неявное намерение через систему, чтобы начать другое действие: [1] Заявление А создает 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
. - Действие
- Строка, которая указывает общее действие для выполнения (например, представление или выбор ).
В случае намерения вещания это произошло действие, которое произошло и сообщается. Действие в значительной степени определяет, как структурировано остальная часть намерения, особенно информация, которая содержится в данных и дополнениях.
Вы можете указать свои собственные действия для использования по намерениям в вашем приложении (или для использования другими приложениями для вызова компонентов в вашем приложении), но вы обычно указываете константы действий, определяемые классом
Intent
или другими классами Framework. Вот некоторые общие действия для начала деятельности:-
ACTION_VIEW
- Используйте это действие в намерении с
startActivity()
, когда у вас есть некоторая информация, которую деятельность может показать пользователю, такую как фотография для просмотра в приложении галереи, или адрес для просмотра в приложении карты. -
ACTION_SEND
- Также известный как намерение Share , вы должны использовать это в намерении с
startActivity()
когда у вас есть некоторые данные, которыми пользователь может поделиться через другое приложение, например, приложение по электронной почте или приложение для обмена социальным счетом.
См. Справочник по классу
Intent
для большего количества постоянных, которые определяют общие действия. Другие действия определены в другом месте в рамках Android, например, вSettings
для действий, которые открывают определенные экраны в приложении System's 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 документа для редактирования.При создании намерения часто важно указать тип данных (тип его падения) в дополнение к его URI. Например, действие, которое может отображать изображения, вероятно, не сможет воспроизводить аудиофайл, даже если форматы URI могут быть похожими. Указание типа MIME ваших данных помогает системе Android найти лучший компонент для получения ваших намерений. Тем не менее, тип MIME иногда может быть выведен из URI, особенно когда данные являются
content:
URI.content:
URI указывает, что данные расположены на устройстве и управляетсяContentProvider
, что делает тип данных MIME видимым для системы.Чтобы установить только URI DATA, вызовите
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
, но не имеет доступа к распределению или сериализованному классу, система повышает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. }
Когда называется startActivity()
, система проверяет все установленные приложения, чтобы определить, какие из них могут обрабатывать этот вид намерения (намерение с действием ACTION_SEND
и которые несут «текст/обычные» данные). Если есть только одно приложение, которое может справиться с ним, это приложение открывается немедленно и дается намерение. Если никакие другие приложения не могут справиться с этим, ваше приложение может поймать ActivityNotFoundException
, которое происходит. Если несколько действий принимают намерение, система отображает диалог, такой как показанный на рисунке 2, поэтому пользователь может выбрать, какое приложение использовать.
Более подробная информация о запуске других приложений также предоставляется в руководстве по отправке пользователя в другое приложение .

Рисунок 2. Диалог выбора.
Принуждение выбора приложения
Когда существует более одного приложения, которое отвечает на ваше неявное намерение, пользователь может выбрать, какое приложение использовать, и сделать это приложение выбором по умолчанию для действия. Возможность выбора по умолчанию полезна при выполнении действия, для которого пользователь, вероятно, хочет использовать одно и то же приложение каждый раз, например, при открытии веб -страницы (пользователи часто предпочитают только один веб -браузер).
Однако, если несколько приложений могут реагировать на намерение, и пользователь может захотеть использовать другое приложение каждый раз, вам следует явно показывать диалог выбора. Диалог выборочных выборов просит пользователя выбрать, какое приложение использовать для действия (пользователь не может выбрать приложение по умолчанию для действия). Например, когда ваше приложение выполняет «поделиться» с действием ACTION_SEND
, пользователи могут поделиться, используя другое приложение в зависимости от их текущей ситуации, поэтому вы всегда должны использовать диалог Chooser, как показано на рисунке 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) и более высокий уровень предоставляют функцию отладки, которая предупреждает вас, если ваше приложение выполняет небезопасную запуск намерения. Например, ваше приложение может выполнить небезопасную запуск вложенного намерения , который является намерением, которое передается как дополнительное в другом намерении.
Если ваше приложение выполняет оба следующих действиях, система обнаруживает небезопасную намерение, и происходит нарушение строгого моды :
- Ваше приложение не сочетает в себе вложенное намерение от дополнительных поставленных намерений.
- Ваше приложение немедленно запускает компонент приложения , используя это вложенное намерение, такое как передача намерения в
startActivity()
,startService()
илиbindService()
.
Для получения более подробной информации о том, как определить эту ситуацию и внести изменения в ваше приложение, прочитайте сообщение в блоге о гнездовании Android на среде.
Проверьте, что на предмет небезопасных намерений запускает
Чтобы проверить, что на создание небезопасного намерения в вашем приложении вызовите detectUnsafeIntentLaunch()
при настройке вашего VmPolicy
, как показано в следующем фрагменте кода. Если ваше приложение обнаруживает нарушение строгих мод, вы можете остановить выполнение приложения для защиты потенциально конфиденциальной информации.
Котлин
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()); }
Использовать намерения более ответственно
Чтобы свести к минимуму вероятность запуска небезопасного намерения и нарушение строгих мод, следуйте этим лучшим практикам.
Скопируйте только основные дополнения в пределах намерения и выполните любые необходимые санитарии и валидацию. Ваше приложение может скопировать дополнения с одного намерения в другое намерение, которое используется для запуска нового компонента. Это происходит, когда ваше приложение вызывает putExtras(Intent)
или putExtras(Bundle)
. Если ваше приложение выполняет одну из этих операций, скопируйте только те дополнения, которые ожидает приемный компонент. Если другое намерение (которое получает копию) запускает компонент, который не экспортируется , дезинфицирует и проверяет дополнения, прежде чем копировать их в намерение, которое запускает компонент.
Не экспортируйте компоненты вашего приложения без необходимости. Например, если вы намереваетесь запустить компонент приложения, используя внутреннее вложенное намерение, установите android:exported
атрибут этого компонента в false
.
Используйте PendingIntent
, а не вложенное намерение. Таким образом, когда другое приложение не сочетается 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 DATA (
scheme
,host
,port
,path
) и типа MIME. -
<category>
- Объявляет категорию намерений, принятую в атрибуте
name
. Значение должно быть буквальным строковым значением действия, а не константой класса.ПРИМЕЧАНИЕ. Методы
startActivity()
иstartActivityForResult()
рассматривают все намерения, как если бы они объявили категориюCATEGORY_DEFAULT
. Если вы не объявите эту категорию в своем фильтре намерения, никакие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 Panorama .
Совместите намерения с фильтрами намерений других приложений
Если другое приложение предназначено для 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
, как если бы оно было выполнено из собственного процесса вашего приложения.
Основные варианты использования для ожидаемого намерения включают следующее:
- Объявление намерения выполнять, когда пользователь выполняет действие с вашим уведомлением (
NotificationManager
системы Android, Manager выполняетIntent
). - Объявив намерение выполнять, когда пользователь выполняет действие с вашим виджетом приложения (приложение Home -экрана выполняет
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()
for anIntent
that starts anActivity
. -
PendingIntent.getService()
for anIntent
that starts aService
. -
PendingIntent.getBroadcast()
for anIntent
that starts aBroadcastReceiver
.
Unless your app is receiving pending intents from other apps, the above methods to create a PendingIntent
are probably the only PendingIntent
methods you'll ever need.
Each method takes the current app Context
, the Intent
you want to wrap, and one or more flags that specify how the intent should be used (such as whether the intent can be used more than once).
For more information about using pending intents, see the documentation for each of the respective use cases, such as in the Notifications and App Widgets API guides.
Specify mutability
If your app targets Android 12 or higher, you must specify the mutability of each PendingIntent
object that your app creates. To declare that a given PendingIntent
object is mutable or immutable, use the PendingIntent.FLAG_MUTABLE
or PendingIntent.FLAG_IMMUTABLE
flag, respectively.
If your app attempts to create a PendingIntent
object without setting either mutability flag, the system throws an IllegalArgumentException
, and the following message appears in 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.
Create immutable pending intents whenever possible
In most cases, your app should create immutable PendingIntent
objects, as shown in the following code snippet. If a PendingIntent
object is immutable, then other apps cannot modify the intent to adjust the result of invoking the intent.
Котлин
val pendingIntent = PendingIntent.getActivity(applicationContext, REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
Ява
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
However, certain use cases require mutable PendingIntent
objects instead:
- Supporting direct reply actions in notifications . The direct reply requires a change to the clip data in the PendingIntent object that's associated with the reply. Usually, you request this change by passing
FILL_IN_CLIP_DATA
as a flag to thefillIn()
method. - Associating notifications with the Android Auto framework, using instances of
CarAppExtender
. - Placing conversations in bubbles using instances of
PendingIntent
. A mutablePendingIntent
object allows the system to apply the correct flags, such asFLAG_ACTIVITY_MULTIPLE_TASK
andFLAG_ACTIVITY_NEW_DOCUMENT
. - Requesting device location information by calling
requestLocationUpdates()
or similar APIs. The mutablePendingIntent
object allows the system to add intent extras that represent location lifecycle events. These events include a change in location and a provider becoming available. - Scheduling alarms using
AlarmManager
. The mutablePendingIntent
object allows the system to add theEXTRA_ALARM_COUNT
intent extra. This extra represents the number of times that a repeating alarm has been triggered. By containing this extra, the intent can accurately notify an app as to whether a repeating alarm was triggered multiple times, such as when the device was asleep.
If your app creates a mutable PendingIntent
object, it's strongly recommended that you use an explicit intent and fill in the ComponentName
. That way, whenever another app invokes the PendingIntent
and passes control back to your app, the same component in your app always starts.
Use explicit intents within pending intents
To better define how other apps can use your app's pending intents, always wrap a pending intent around an explicit intent . To help follow this best practice, do the following:
- Check that the action, package, and component fields of the base intent are set.
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. }
Intent resolution
When the system receives an implicit intent to start an activity, it searches for the best activity for the intent by comparing it to intent filters based on three aspects:
- Действие.
- Data (both URI and data type).
- Category.
The following sections describe how intents are matched to the appropriate components according to the intent filter declaration in an app's manifest file.
Action test
To specify accepted intent actions, an intent filter can declare zero or more <action>
elements, as shown in the following example:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
To pass this filter, the action specified in the Intent
must match one of the actions listed in the filter.
If the filter does not list any actions, there is nothing for an intent to match, so all intents fail the test. However, if an Intent
does not specify an action, it passes the test as long as the filter contains at least one action.
Category test
To specify accepted intent categories, an intent filter can declare zero or more <category>
elements, as shown in the following example:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
For an intent to pass the category test, every category in the Intent
must match a category in the filter. The reverse is not necessary—the intent filter may declare more categories than are specified in the Intent
and the Intent
still passes. Therefore, an intent with no categories always passes this test, regardless of what categories are declared in the filter.
Note: Android automatically applies the CATEGORY_DEFAULT
category to all implicit intents passed to startActivity()
and startActivityForResult()
. If you want your activity to receive implicit intents, it must include a category for "android.intent.category.DEFAULT"
in its intent filters, as shown in the previous <intent-filter>
example.
Data test
To specify accepted intent data, an intent filter can declare zero or more <data>
elements, as shown in the following example:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
Each <data>
element can specify a URI structure and a data type (MIME media type). Each part of the URI is a separate attribute: scheme
, host
, port
, and path
:
<scheme>://<host>:<port>/<path>
The following example shows possible values for these attributes:
content://com.example.project:200/folder/subfolder/etc
In this URI, the scheme is content
, the host is com.example.project
, the port is 200
, and the path is folder/subfolder/etc
.
Each of these attributes is optional in a <data>
element, but there are linear dependencies:
- If a scheme is not specified, the host is ignored.
- If a host is not specified, the port is ignored.
- If both the scheme and host are not specified, the path is ignored.
When the URI in an intent is compared to a URI specification in a filter, it's compared only to the parts of the URI included in the filter. For example:
- If a filter specifies only a scheme, all URIs with that scheme match the filter.
- If a filter specifies a scheme and an authority but no path, all URIs with the same scheme and authority pass the filter, regardless of their paths.
- If a filter specifies a scheme, an authority, and a path, only URIs with the same scheme, authority, and path pass the filter.
Note: A path specification can contain a wildcard asterisk (*) to require only a partial match of the path name.
The data test compares both the URI and the MIME type in the intent to a URI and MIME type specified in the filter. The rules are as follows:
- An intent that contains neither a URI nor a MIME type passes the test only if the filter does not specify any URIs or MIME types.
- An intent that contains a URI but no MIME type (neither explicit nor inferable from the URI) passes the test only if its URI matches the filter's URI format and the filter likewise does not specify a MIME type.
- An intent that contains a MIME type but not a URI passes the test only if the filter lists the same MIME type and does not specify a URI format.
- 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.
Note: If an intent specifies a URI or MIME type, the data test will fail if there are no <data>
elements in the <intent-filter>
.
This last rule, rule (d), reflects the expectation that components are able to get local data from a file or content provider. Therefore, their filters can list just a data type and don't need to explicitly name the content:
and file:
schemes. The following example shows a typical case in which a <data>
element tells Android that the component can get image data from a content provider and display it:
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
Filters that specify a data type but not a URI are perhaps the most common because most available data is dispensed by content providers.
Another common configuration is a filter with a scheme and a data type. For example, a <data>
element like the following tells Android that the component can retrieve video data from the network in order to perform the action:
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
Intent matching
Intents are matched against intent filters not only to discover a target component to activate, but also to discover something about the set of components on the device. For example, the Home app populates the app launcher by finding all the activities with intent filters that specify the ACTION_MAIN
action and CATEGORY_LAUNCHER
category. A match is only successful if the actions and categories in the Intent match against the filter, as described in the documentation for the IntentFilter
class.
Your application can use intent matching in a manner similar to what the Home app does. The PackageManager
has a set of query...()
methods that return all components that can accept a particular intent and a similar series of resolve...()
methods that determine the best component to respond to an intent. For example, queryIntentActivities()
returns a list of all activities that can perform the intent passed as an argument, and queryIntentServices()
returns a similar list of services. Neither method activates the components; they just list the ones that can respond. There's a similar method, queryBroadcastReceivers()
, for broadcast receivers.