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

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

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

Этот урок покажет вам, как создать неявное намерение для того или иного действия, и как его использовать для запуска деятельности, которая выполняет действие в другом приложении.

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

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

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

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

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

Когда ваше приложение вызывает это намерение с помощью startActivity(), приложение Телефон инициирует вызов по данному номеру телефона.

Вот несколько других намерений и их действий и Uri пар данных:

  • Открыть карту:
    // 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);
    
  • Открыть веб-страницу:
    Uri webpage = Uri.parse("http://www.android.com");
    Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
    

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

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

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

  • Отправить письмо с вложением:
    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[] {"jon@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
    
  • Создание события календаря:
    Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
    Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
    Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 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");
    

    Примечание: Это намерение для напоминания о событии поддерживается только начиная с уровня API 14.

Примечание: Важно, чтобы вы определяли Intent как можно более точно. Например, если вы хотите отобразить изображение с помощью ACTION_VIEW намерения, вы должны указать MIME тип один из image/*. Это предотвращает приложения, которые могут «просматривать» другие типы данных (такие как приложения карт) от запуска из-за этого намерения.

Убедитесь, что существует приложение способное обработать намерение

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

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

Для проверки есть ли доступная деятельность, которая может ответить на намерение, вызовите queryIntentActivities() для получения перечня деятельностей, способных обработать ваше Intent. Если возвращенный List не пустой, вы можете спокойно использовать намерение. Например:

PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
boolean isIntentSafe = activities.size() > 0;

Если isIntentSafe является true, то по крайней мере одно приложение будет отвечать на намерения. Если значение равно false, то нет приложений для обработки намерения.

Примечание: Вы должны выполнять эту проверку, когда ваша деятельность запускается, т.к. в этом случае вам нужно отключить функцию, которая использует намерение, прежде чем пользователь попытается использовать эту функцию. Если вы знаете о конкретной программе, которая может обрабатывать намерение, вы также можете предоставить ссылку для пользователя, чтобы он смог загрузить приложение (смотрите как сослаться на ваш продукт на Google Play).

Запуск деятельности при помощи намерения

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

После того как вы создали Intent и установили дополнительную информацию, вызовите startActivity() для отправки его в систему. Если система определяет, что более одной деятельности может обрабатывать намерение, она отображает диалоговое окно пользователю, чтобы он выбрал, какое приложение использовать, как показано на рисунке 1. Если есть только одна деятельность, которая обрабатывает намерение, система немедленно её запускает.

startActivity(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);

// Verify it resolves
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;

// Start an activity if it's safe
if (isIntentSafe) {
    startActivity(mapIntent);
}

Показать диалог выбора приложения

Рисунок 2. Диалог выбора.

Обратите внимание, что когда вы начинаете деятельность, передавая свой Intent в startActivity() и есть более чем одно приложение, которое отвечает на намерения, пользователь может выбрать, какое приложение использовать по умолчанию (по отметив флажок в нижней части диалогового окна; см. рисунок 1). Это хорошо, когда выполнение действия, для которых пользователь обычно хочет использовать одно и того же приложения каждый раз, например, при открытии веб-страницы (пользователи, вероятно, предпочитают использовать только один веб-браузер) или принимать фотографии (пользователи, вероятно, предпочитают одну и ту же камеру).

Однако, если выполняемое действие может обрабатываться несколькими приложениями, и пользователь может предпочитать каждый раз другое приложение — такое как действия "поделиться", для которых пользователи могли бы иметь несколько приложений, через которые они могли бы поделиться — вы должны явно показывать диалог выбора, как показано на рисунке 2. Диалог выбора заставляет пользователя каждый раз выбирать, какое приложения использовать для действия (пользователь не может выбрать приложение по умолчанию для действия).

Чтобы показать диалог выбора, создайте Intent используя createChooser() и передайте его в startActivity(). Например:

Intent intent = 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 chooser
Intent chooser = Intent.createChooser(intent, title);

// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

Это код отображает диалог со списком приложений, которые отвечают на намерение переданного в createChooser() метод и используют предоставленный текст в качестве заголовка диалога.