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

Одной из наиболее важных функций Android является возможность приложения перенаправлять пользователя в другое приложение на основе «действия», которое оно хочет выполнить. Например, если в вашем приложении есть адрес компании, который вы хотели бы отобразить на карте, вам не нужно создавать в приложении действие, отображающее карту. Вместо этого вы можете создать запрос на просмотр адреса, используя Intent . Затем система Android запускает приложение, которое может отображать адрес на карте.

Как объяснялось в первом занятии « Создание первого приложения» , вы должны использовать намерения для навигации между действиями в вашем собственном приложении. Обычно вы делаете это с явным намерением , которое определяет точное имя класса компонента, который вы хотите запустить. Однако если вы хотите, чтобы отдельное приложение выполняло действие, например «просмотр карты», вы должны использовать неявное намерение .

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

Создайте неявное намерение

Неявные намерения не объявляют имя класса запускаемого компонента, а вместо этого объявляют действие, которое необходимо выполнить. Действие определяет, что вы хотите сделать, например просмотреть , отредактировать , отправить или получить что-либо.

Связывание действий намерения с данными

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

Если ваши данные представляют собой Uri , существует простой конструктор Intent() который вы можете использовать для определения действия и данных.

Например, вот как создать намерение инициировать телефонный звонок, используя данные Uri для указания номера телефона:

Котлин

val callIntent: Intent = Uri.parse("tel:5551234").let { number ->
    Intent(Intent.ACTION_DIAL, number)
}

Ява

Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

Когда ваше приложение вызывает это намерение, вызывая startActivity() , приложение «Телефон» инициирует вызов на заданный номер телефона.

Вот еще пара намерений и их пары данных действия и Uri :

Посмотреть карту

Котлин

// 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)
}

Ява

// 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);

Просмотр веб-страницы

Котлин

val webIntent: Intent = Uri.parse("https://www.android.com").let { webpage ->
    Intent(Intent.ACTION_VIEW, webpage)
}

Ява

Uri webpage = Uri.parse("https://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

Добавьте дополнения к намерению

Другие виды неявных намерений требуют «дополнительных» данных, предоставляющих разные типы данных, например строку. Вы можете добавить один или несколько фрагментов дополнительных данных, используя различные методы putExtra() .

По умолчанию система определяет соответствующий тип MIME, необходимый для намерения, на основе включенных данных Uri . Если вы не включаете Uri в намерение, вам обычно следует использовать setType() чтобы указать тип данных, связанных с намерением. Установка типа MIME дополнительно определяет, какие виды действий должны получать намерение.

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

Отправить электронное письмо с вложением

Котлин

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
}

Ява

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 и выше.

Котлин

// 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")
}

Ява

// 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() , чтобы отправить ее в систему:

Котлин

startActivity(intent)

Ява

startActivity(intent);

Обработайте ситуацию, когда ни одно приложение не может получить намерение.

Хотя многие намерения успешно обрабатываются другим приложением, установленным на устройстве, например приложением телефона, электронной почты или календаря, ваше приложение должно быть подготовлено к ситуации, когда никакое действие не может обработать намерение вашего приложения. Всякий раз, когда вы вызываете намерение, будьте готовы перехватить ActivityNotFoundException , которое возникает, если нет другой активности, которая могла бы обработать намерение вашего приложения:

Котлин

try {
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Ява

try {
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

После того как вы поймаете это исключение, решите, что вашему приложению следует делать дальше. Следующий шаг зависит от конкретных характеристик намерения, которое вы пытались вызвать. Например, если вам известно конкретное приложение, которое может обработать это намерение, предоставьте пользователю ссылку для загрузки приложения. Узнайте больше о том, как разместить ссылку на свой продукт в Google Play .

Диалоговое окно устранения неоднозначности

Если система определяет более одного действия, которое может обработать намерение, она отображает диалоговое окно (иногда называемое «диалогом устранения неоднозначности»), в котором пользователь может выбрать, какое приложение использовать, как показано на рисунке 1. Если есть только одно активность, которая обрабатывает намерение, система немедленно запускает ее.

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

Рисунок 1. Пример диалогового окна выбора, которое появляется, когда несколько приложений могут обрабатывать намерение.

Полный пример

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

Котлин

// 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.
}

Ява

// 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() . Например:

Котлин

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.
}

Ява

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