他のアプリからのアクティビティの開始を許可する

自分のアプリで別のアプリにとって役に立つかもしれないアクションを実行できる場合、アクティビティの中で適切なインテント フィルタを指定することにより、自分のアプリがアクション リクエストに応答できるようにする必要があります。

たとえば、メッセージや写真をユーザーの友達と共有できるソーシャル アプリを作成する場合、ACTION_SEND インテントをサポートする必要があります。そのようにしておけば、ユーザーが別のアプリから「share」アクションを開始した時点で、図 1 に示されているように、選択ダイアログ(「曖昧解消ダイアログ」)の中で該当アプリがオプションの 1 つとして表示されるようになります。

図 1. 選択ダイアログ

このようにして他のアプリからアクティビティを開始できるようにするには、マニフェスト ファイルの対応する <activity> 要素に <intent-filter> 要素を追加する必要があります。

アプリが端末にインストールされると、インテント フィルタが特定され、インストールされている全アプリでサポートされているインテントの内部カタログに情報が追加されます。アプリが startActivity() または startActivityForResult() を暗黙のインテントで呼び出すと、そのインテントにどのアクティビティかが応答できるのかがシステムによって検出されます。

インテント フィルタを追加する

アクティビティがどのインテントを処理できるか適切に定義するためには、アクティビティが受け入れるアクションとデータのタイプについて、追加する各インテント フィルタをできるだけ具体的にする必要があります。

アクティビティが Intent オブジェクトに関する次の基準を満たしているインテント フィルタを持つ場合、システムは、アクティビティに対して所定の Intent を送信することができます。

アクション
実行するアクション名を表す文字列。通常、ACTION_SENDACTION_VIEW などのプラットフォームに定義された値のいずれか。

<action> 要素を使用して、インテント フィルタでこれを指定します。この要素で指定する値は、API 定数ではなく、アクションの完全な文字列名(下記の例を参照)である必要があります。

データ
インテントに関連するデータの詳細。

<data> 要素を使用して、インテント フィルタでこれを指定します。この要素で 1 つ以上の属性を使用して、MIME タイプのみ、URI 接頭辞のみ、URI スキームのみ、またはこれらと受け入れられるデータタイプを示すその他の項目の組み合わせを指定することができます。

注: Uri データに関する詳細を宣言する必要がない場合(アクティビティが URI ではなく他の種類の「特別」データを処理するときなど)は、アクティビティが処理する text/plainimage/jpeg のようなデータタイプを宣言する android:mimeType 属性のみを指定する必要があります。

カテゴリ
インテントを処理するアクティビティを特徴づけるための追加的な方法を提供し、通常はユーザーの操作や起動元の場所に関連付けられます。システムでサポートされているいくつかの異なるカテゴリがありますが、大抵のカテゴリはほとんど使用されません。しかし、すべての暗黙的インテントは、デフォルトではCATEGORY_DEFAULT を使用して定義されています。

<category> 要素を使用して、インテント フィルタでこれを指定します。

インテント フィルタでは、それぞれの基準を <intent-filter> 要素内でネストした対応する XML 要素を使用して宣言することによって、アクティビティが受け入れる基準を宣言することができます。

次に、データタイプがテキストまたは画像の場合に、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>

ヒント:選択ダイアログに表示されるアイコンをアクティビティのデフォルト アイコンとは異なるものにする場合は、android:icon<intent-filter> 要素の中に追加します。

受信するインテントはそれぞれ 1 つのアクションと 1 つのデータタイプのみを指定しますが、各 <intent-filter> 内で <action><category><data> 要素の複数のインスタンスを宣言することもできます。

アクションとデータのいずれか 2 つのペアが、各自の動作において相互に排他的である場合は、別のインテント フィルタを作成して、どのデータタイプと組み合わされたときにどのアクションが受け入れられるかを指定する必要があります。

たとえば、アクティビティが ACTION_SENDACTION_SENDTO の両方のインテントに関してテキストと画像の両方を処理するとします。この場合は、次の 2 つのアクションのための 2 つの別々のインテント フィルタを定義する必要があります。なぜなら 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() などの早い段階のコールバックの間に行う必要があります。

たとえば:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.main)

    val data: Uri? = intent?.data

    // Figure out what to do based on the intent type
    if (intent?.type?.startsWith("image/") == true) {
        // Handle intents with image data ...
    } else if (intent?.type == "text/plain") {
        // Handle intents with text ...
    }
}

Java

@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() を呼び出してアクティビティを閉じます(その後破棄します)。たとえば:

Kotlin

// Create intent to deliver some kind of result data
Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri")).also { result ->
    setResult(Activity.RESULT_OK, result)
}
finish()

Java

// 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 に設定されています。したがって、ユーザーがアクションを完了する前に戻るボタンを押して、結果がまだ設定されていない場合、元のアクティビティは「キャンセルされた」結果を受け取ります。

いくつかの結果オプションのいずれかを示す整数を返す必要がある場合は、0 よりも大きい任意の値に結果コードを設定することができます。結果コードを使用して整数を返す場合に Intent を含める必要がなければ、setResult() を呼び出して結果コードのみを渡すことができます。たとえば:

Kotlin

setResult(RESULT_COLOR_RED)
finish()

Java

setResult(RESULT_COLOR_RED);
finish();

この場合、可能性のある結果の数はわずかであるため、結果コードは、ローカルに定義されている整数(0 より大きい)になります。これは、自分が作成したアプリのアクティビティに結果を返す場合に役立ちます。結果を受け取るアクティビティがパブリック定数を参照でき、結果コードの値を判断できるためです。

注:自分のアクティビティが startActivity() または startActivityForResult() を使用して開始されたかどうかをチェックする必要はありません。アクティビティを開始したインテントが結果を待っている場合は、setResult() を呼び出します。元のアクティビティが startActivityForResult() を呼び出していた場合、setResult() に提供した結果がそこに送られます。それ以外の場合は、結果は無視されます。