Разрешение другим приложениям запускать вашу деятельность

Предыдущие два урока сосредоточены на одной стороне истории: запуске деятельности другого приложения из вашего приложения. Но если ваше приложение может выполнять действия, которые могут быть полезны для других приложений, то ваше приложение должно быть готово ответить на запросы действий других приложений. Например, если вы построили социальное приложение, которое может поделиться сообщениями или фотографиями с друзьями пользователя, то в ваших интересах поддержать ACTION_SEND намерение, так что пользователи смогут инициировать действие "поделиться" из другого приложения, и запустить ваше приложение для выполнения действия.

Чтобы разрешить другим приложениям запускать вашу деятельность, вам нужно добавить <intent-filter> элемент в вашем файле манифеста для соответствующего <activity> элемента.

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

Добавить фильтр намерения

Чтобы правильно определить, какие намерения ваша деятельность может обрабатывать, каждый фильтр намерения, который вы добавляете должен быть как можно более конкретным с точки зрения типа действия и данных, поддерживаемых деятельностью.

Система может посылать данный Intent в деятельность, если эта деятельность имеет фильтр намерения удовлетворяющий следующим критериям Intent объекта:

action (действие)
Строка с название выполняемого действия. Обычно одно из значений определенных платформой, такое как ACTION_SEND или ACTION_VIEW.

Укажите его в своем фильтре намерений с помощью <action> элемента. Указанное значение в этом элементе должна быть строка с полным именем действия, а не константы API (см. примеры ниже).

data (данные)
Описание данных, связанных с намерением.

Укажите его в своем фильтре намерений с помощью <data> элемента. Используя один или несколько атрибутов в этом элементе, вы можете указать только MIME тип, только префикс URI, только схему URI, или сочетание этих и других элементов, которые описывают тип принимаемых данных.

Примечание: Если вам не нужно объявлять специфику данных Uri (например, когда ваша деятельность обрабатывает другие «дополнительные» данные, вместо URI), вы должны указать только android:mimeType атрибут, объявить тип данных, который ваша деятельность обрабатывает, например, такой как text/plain или image/jpeg.

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

Укажите его в своем фильтре намерений с помощью <category> элемента.

В своих фильтрах намерений, можно объявить, какие критерии ваша деятельность поддерживает, объявив каждый из них с соответствующем XML элементе, вложенном в <intent-filter> элемент.

Например, вот деятельность с фильтром намерений, который обрабатывает ACTION_SEND намерение, когда тип данных либо текст либо изображение:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
</activity>

Каждое входящее намерение определяет только одно действие и один тип данных, но это нормально объявить несколько экземпляров <action>, <category>, и <data> элементов в каждом <intent-filter>.

Если какие-либо две пары действий и данных являются взаимоисключающими в их поведении, вы должны создать отдельные фильтры намерений, чтобы указать, какие действия являются приемлемыми и с какими типами данных в паре.

Например, предположим, ваша деятельность обрабатывает текст и изображения для двух ACTION_SEND и ACTION_SENDTO намерений. В этом случае, необходимо определить два отдельных фильтра намерений для двух действий, потому что ACTION_SENDTO намерение должно использовать данные Uri для указания адреса получателя с помощью send или sendto схемы URI. Например:

<activity android:name="ShareActivity">
    <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    </intent-filter>
    <!-- filter for sending text or images; accepts SEND action and text or image data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

Примечание: Чтобы получать неявные намерения, необходимо использовать CATEGORY_DEFAULT категорию в намерениях фильтра. Методы startActivity() и startActivityForResult() рассматривают все намерения, как если бы они объявили категорию CATEGORY_DEFAULT . Если вы не объявите её в фильтре намерения, неявные намерения не попадут в вашу деятельность.

Дополнительные сведения об отправке и получении ACTION_SEND намерения, которое выполняет обмен данными в социальных сетях, см. урок Получение простых данных из других приложений.

Обработать намерение в вашей деятельности

Чтобы решить, какие действия следует выполнять в вашей деятельности, вы можете прочитать Intent , который был использован для запуска.

Когда ваша деятельность запустилась, вызовите getIntent() для получения Intent , который запустил деятельность. Вы можете сделать это в любое время в течение всего жизненного цикла деятельности, но как правило, это следует сделать это во время вызова ранних методов обратного вызова, таких как onCreate() или onStart().

Например:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // Get the intent that started this activity
    Intent intent = getIntent();
    Uri data = intent.getData();

    // Figure out what to do based on the intent type
    if (intent.getType().indexOf("image/") != -1) {
        // Handle intents with image data ...
    } else if (intent.getType().equals("text/plain")) {
        // Handle intents with text ...
    }
}

Вернуть результат

Если вы хотите вернуть результат в деятельность, которая вызвала вашу, просто вызовите setResult() для указания кода результата и результирующего Intent. Когда ваша операция завершилась, и пользователь должен вернуться в исходную деятельность, вызовите finish() для закрытия (и уничтожения) ваша деятельности. Например:

// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri");
setResult(Activity.RESULT_OK, result);
finish();

Вы всегда должны указать код результата вместе с результатом. Как правило, это или RESULT_OK или RESULT_CANCELED. Затем вы можете предоставить дополнительные данные с Intent, по мере необходимости.

Примечание: Результат установлен в RESULT_CANCELED по умолчанию. Так что, если пользователь нажимает кнопку Назад до завершения действия, и, прежде чем вы установили результат, то вызывающая деятельность получает результат "отменен".

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

setResult(RESULT_COLOR_RED);
finish();

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

Примечание: Нет необходимости проверять, была ли ваша деятельность запущена с помощью startActivity() или startActivityForResult(). Просто вызовите setResult() если намерение, которое запустило вашу деятельность может ожидать результат. Если исходная деятельность вызывала startActivityForResult(), то система доставит ей результат, который вы передали в setResult(); в противном случае, результат игнорируется.