Одна из самых важных функций Android – возможность перенаправлять пользователя из одного приложения в другое в зависимости от действия, которое он хочет выполнить. Например, если в вашем приложении есть адрес компании, который вы хотите показать на карте, вам не нужно создавать для этого отдельное действие. Вместо этого вы можете создать запрос на просмотр адреса с помощью Intent. Система Android запустит приложение, которое может показать адрес на карте.
Как объяснялось в первом уроке Создание первого приложения, для навигации между операциями в собственном приложении необходимо использовать объекты Intent. Как правило, это делается с помощью явного объекта Intent, который определяет точное имя класса компонента, который необходимо запустить. Однако если вы хотите, чтобы действие выполнялось в отдельном приложении, например "посмотреть карту", необходимо использовать неявное намерение.
В этом уроке рассказывается, как создать неявное намерение для определенного действия и как использовать его для запуска операции, которая выполняет это действие в другом приложении. Также посмотрите видео, чтобы понять, почему важно включать динамические проверки для неявных намерений.
Как создать неявный интент
Неявные намерения не объявляют имя класса компонента для запуска, а вместо этого объявляют действие, которое необходимо выполнить. Действие указывает на то, что вы хотите сделать, например посмотреть, изменить, отправить или получить что-то.
Как связать действия intent с данными
Намерения часто также включают данные, связанные с действием, например адрес, который вы хотите просмотреть, или сообщение электронной почты, которое вы хотите отправить.
В зависимости от того, какое намерение вы хотите создать, данные могут быть представлены в виде Uri или в одном из нескольких других типов данных. Также намерение может не требовать данных вообще.
Если ваши данные – это Uri, вы можете использовать простой конструктор Intent(), чтобы определить действие и данные.
Например, вот как создать намерение, чтобы инициировать телефонный звонок, используя данные Uri для указания номера телефона:
Kotlin
val callIntent: Intent = Uri.parse("tel:5551234").let { number -> Intent(Intent.ACTION_DIAL, number) }
Java
Uri number = Uri.parse("tel:5551234"); Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
Когда ваше приложение вызывает это намерение с помощью startActivity(), приложение "Телефон" инициирует звонок на указанный номер.
Вот ещё несколько примеров намерений и соответствующих им пар "действие – данные Uri":
Как посмотреть карту
Kotlin
// Map point based on address val mapIntent: Intent = Uri.parse( "geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California" ).let { location -> // Or map point based on latitude/longitude // val location: Uri = Uri.parse("geo:37.422219,-122.08364?z=14") // z param is zoom level Intent(Intent.ACTION_VIEW, location) }
Java
// Map point based on address Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"); // Or map point based on latitude/longitude // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
Как посмотреть веб-страницу
Kotlin
val webIntent: Intent = Uri.parse("https://www.android.com").let { webpage -> Intent(Intent.ACTION_VIEW, webpage) }
Java
Uri webpage = Uri.parse("https://www.android.com"); Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
Как добавить дополнительные данные в намерение
Другие виды неявных намерений требуют дополнительных данных, которые предоставляют разные типы данных, например строку. Вы можете добавить один или несколько фрагментов дополнительных данных, используя различные методы putExtra().
По умолчанию система определяет MIME-тип, необходимый для намерения, на основе включенных данных Uri. Если вы не включили в намерение Uri, то обычно нужно использовать setType(), чтобы указать тип данных, связанных с намерением. Указание MIME-типа позволяет точнее определить, какие действия должны получать намерение.
Вот ещё несколько примеров интентов, которые добавляют дополнительные данные для указания желаемого действия:
Как отправить письмо с прикрепленным файлом
Kotlin
Intent(Intent.ACTION_SEND).apply { // The intent does not have a URI, so declare the "text/plain" MIME type type = "text/plain" putExtra(Intent.EXTRA_EMAIL, arrayOf("jan@example.com")) // recipients putExtra(Intent.EXTRA_SUBJECT, "Email subject") putExtra(Intent.EXTRA_TEXT, "Email message text") putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment")) // You can also attach multiple items by passing an ArrayList of Uris }
Java
Intent emailIntent = new Intent(Intent.ACTION_SEND); // The intent does not have a URI, so declare the "text/plain" MIME type emailIntent.setType(HTTP.PLAIN_TEXT_TYPE); emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jan@example.com"}); // recipients emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject"); emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text"); emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment")); // You can also attach multiple items by passing an ArrayList of Uris
Как создать мероприятие в календаре
Примечание. Это намерение для мероприятия в календаре поддерживается только на уровне API 14 и выше.
Kotlin
// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM. Intent(Intent.ACTION_INSERT, Events.CONTENT_URI).apply { val beginTime: Calendar = Calendar.getInstance().apply { set(2021, 0, 23, 7, 30) } val endTime = Calendar.getInstance().apply { set(2021, 0, 23, 10, 30) } putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.timeInMillis) putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.timeInMillis) putExtra(Events.TITLE, "Ninja class") putExtra(Events.EVENT_LOCATION, "Secret dojo") }
Java
// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM. Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI); Calendar beginTime = Calendar.getInstance(); beginTime.set(2021, 0, 23, 7, 30); Calendar endTime = Calendar.getInstance(); endTime.set(2021, 0, 23, 10, 30); calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis()); calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis()); calendarIntent.putExtra(Events.TITLE, "Ninja class"); calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
Примечание. Важно, чтобы значение Intent было как можно более точным. Например, если вы хотите показать изображение с помощью намерения ACTION_VIEW, укажите MIME-тип image/*. Это предотвратит запуск приложений, которые могут "просматривать" другие типы данных (например, карты).
Запуск действия с намерением
После создания объекта Intent и настройки дополнительной информации вызовите метод startActivity(), чтобы отправить ее в систему:
Kotlin
startActivity(intent)
Java
startActivity(intent);
Как обрабатывать ситуации, когда ни одно приложение не может получить намерение
Хотя многие намерения успешно обрабатываются другими приложениями, установленными на устройстве (например, телефоном, электронной почтой или календарем), ваше приложение должно быть готово к ситуации, когда ни одно действие не может обработать его намерение. При вызове намерения будьте готовы перехватить исключение ActivityNotFoundException, которое возникает, если нет другого действия, способного обработать намерение вашего приложения.
Kotlin
try { startActivity(intent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
try { startActivity(intent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
После перехвата исключения определите, что приложение должно делать дальше. Дальнейшие действия зависят от характеристик интента, который вы пытались вызвать. Например, если вы знаете, что определенное приложение может обработать намерение, предоставьте пользователю ссылку на скачивание этого приложения. Подробнее о том, как создать ссылку на свой продукт в Google Play…
Диалоговое окно устранения неоднозначности
Если система обнаружит несколько действий, которые могут обработать намерение, она покажет диалоговое окно (иногда его называют окном устранения неоднозначности), в котором пользователь сможет выбрать приложение (см. рисунок 1). Если есть только одно действие, которое обрабатывает намерение, система немедленно запускает его.
Рисунок 1. Пример диалогового окна, которое появляется, когда намерение может быть обработано несколькими приложениями.
Полный пример
Ниже приведен полный пример, в котором показано, как создать намерение для просмотра карты, проверить, существует ли приложение для обработки намерения, а затем запустить его.
Kotlin
// Build the intent. val location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California") val mapIntent = Intent(Intent.ACTION_VIEW, location) // Try to invoke the intent. try { startActivity(mapIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
// Build the intent. Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"); Intent mapIntent = new Intent(Intent.ACTION_VIEW, location); // Try to invoke the intent. try { startActivity(mapIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
Показать окно выбора приложения
Рисунок 2. Диалоговое окно выбора.
Обратите внимание, что если вы запускаете действие, передавая Intent в startActivity(), и на намерение отвечает несколько приложений, пользователь может выбрать, какое из них использовать по умолчанию (установив флажок в нижней части диалогового окна, как показано на рисунке 1). Это удобно, когда пользователь обычно выполняет действие в одном и том же приложении, например открывает веб-страницу (скорее всего, в одном браузере) или делает снимок (скорее всего, одной камерой).
Однако если действие может быть выполнено несколькими приложениями и пользователь может каждый раз предпочитать разные приложения (например, действие "Поделиться", для которого у пользователей может быть несколько приложений, через которые они могут поделиться элементом), вы должны явно показать диалоговое окно выбора, как показано на рисунке 2. Диалоговое окно выбора заставляет пользователя каждый раз выбирать, какое приложение использовать для действия (пользователь не может выбрать приложение по умолчанию для действия).
Чтобы показать окно выбора, создайте Intent с помощью createChooser() и передайте его в startActivity(). Пример:
Kotlin
val intent = Intent(Intent.ACTION_SEND) // Create intent to show chooser val chooser = Intent.createChooser(intent, /* title */ null) // Try to invoke the intent. try { startActivity(chooser) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
Intent intent = new Intent(Intent.ACTION_SEND); // Create intent to show chooser Intent chooser = Intent.createChooser(intent, /* title */ null); // Try to invoke the intent. try { startActivity(chooser); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
Появится диалоговое окно со списком приложений, которые реагируют на намерение, переданное методу
createChooser(). Параметр title можно указать, если действие не равно
ACTION_SEND или
ACTION_SEND_MULTIPLE.