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

アプリが別のアプリにとって役立つアクションを行う可能性がある場合は、アクティビティで適切なインテント フィルタを指定して、アクション リクエストに応答する準備をします。

たとえば、メッセージや写真を友だちと共有できるソーシャル アプリを作成する場合、ACTION_SEND インテントをサポートします。ユーザーが別のアプリで「共有」アクションを開始したときに、図 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> 要素を使用して指定します。

アクティビティが受け入れる条件をインテント フィルタ内で宣言するには、各条件に対応する 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>

ヒント: 選択ツール ダイアログのアイコンをアクティビティのデフォルト アイコンと区別するには、<intent-filter> 要素に android:icon を追加します。

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

アクションとデータのペアが 2 つあり、それぞれの動作において相互に排他的である場合は、それぞれ別のインテント フィルタを作成して、どのデータ型と組み合わせたときにどのアクションが受け入れ可能になるのかを指定します。

たとえば、ACTION_SENDACTION_SENDTO の両方のインテントに対し、アクティビティでテキストと画像の両方を処理することにします。この場合、ACTION_SENDTO インテントの方は、データ Uri を使用し、send または sendto の URI スキームを使用して受信者アドレスを指定する必要があるため、2 つのアクション用に別々の 2 つのインテント フィルタを定義する必要があります。これを次の例に示します。

<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_OKRESULT_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() に提供する結果が自動的に配信されます。そうでない場合、結果は無視されます。