他のアプリからシンプルなデータを受信する

1 つのアプリから別のアプリへデータを送信できるのと同様に、他のアプリからデータを受信することもできます。ユーザーがアプリをどのように操作するのか、他のアプリからどのデータタイプを受け取るのかを検討する必要があります。たとえば、ソーシャル ネットワーキング アプリの場合、興味深いウェブ URL など、テキスト コンテンツを他のアプリから受信できると便利です。

他のアプリのユーザーが Android Sharesheet やインテント リゾルバを通じてアプリにデータを送信することがよくあります。アプリにデータを送信するアプリは、そのデータの MIME タイプを設定する必要があります。アプリは、他のアプリから送信されたデータを次の方法で受信できます。

  • マニフェスト内の intent-filter タグに合致する Activity
  • アプリが公開している共有ショートカット。

ダイレクト シェア ターゲットは、アプリ内の特定の Activity へのディープリンクです。多くの場合、このようなディープリンクはユーザーまたはグループを指し示し、Android Sharesheet に表示されます。 たとえば、メッセージ アプリの場合、各ユーザーを対象とするダイレクト シェア ターゲットを提供すると便利です。ダイレクト シェア ターゲットをタップすると、ディープリンクの機能により、直接そのユーザーとのスレッドを開始できます。詳細な手順については、 ダイレクト シェア ターゲットを提供するをご覧ください。

MIME タイプをサポートする

アプリは、可能な限り幅広い MIME タイプを受信できる必要があります。 たとえば、テキスト、画像、動画の送信に使用するメッセージ アプリの場合、text/*image/*video/* の受信をサポートする必要があります。Android でシンプルなデータを送受信する際の一般的な MIME タイプを以下に示します。

受信者が登録する 送信者が送信する
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
`image/*`
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
サポートされているファイル拡張子 application/pdf

MIME メディアタイプの IANA 公式レジストリをご覧ください。

*/*

適切な共有ターゲットを作成する

特定のアクティビティに関連付けられた共有ターゲットをユーザーがタップしたときは、共有コンテンツの使用を開始する前に、その確認や編集が可能になっている必要があります。この機能は、特にテキストデータの場合に重要になります。

アクティビティを使用してデータを受信する

アクティビティを使用してデータを受信するには、マニフェストを更新し、受信コンテンツを処理して、アプリがユーザーに認識されるようにする必要があります。

マニフェストを更新する

インテント フィルタは、アプリ コンポーネントが受け入れるインテントをシステムに通知します。 レッスン「 他のアプリにシンプルなデータを送信する 」で ACTION_SEND アクションを使用してインテントを作成した方法と同じように、このアクションを使用してインテントを受信できるようにインテント フィルタを作成します。マニフェスト内でインテント フィルタを定義するには、<intent-filter> 要素を使用します。たとえば、アプリがテキスト コンテンツの受信を処理する場合、任意のタイプの 1 つ以上の画像を含むマニフェストは次のスニペットのようになります。

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

別のアプリがインテントを作成して startActivity() に渡すことで、上記のデータタイプのいずれかを共有しようとすると、受信側アプリのリストが Android Sharesheet またはインテント リゾルバ内に表示されます。その中からユーザーが 1 つの受信側アプリを選択すると、対応するアクティビティ(上記の例の場合は .ui.MyActivity)が起動します。その後、受信側アプリが、コードや UI 内でコンテンツを適切に処理します。

受信コンテンツを処理する

Intent によって配信されたコンテンツを処理するには、 getIntent() を呼び出して Intent オブジェクトを取得します。オブジェクトを取得したら、その内容を調べて、次の処理を決定できます。システム内の別の場所(ランチャーなど)からこのアクティビティを起動できる場合は、インテントを調査する際にこの点を考慮する必要があります。

受信データをチェックする場合は特に注意してください。他のアプリから何が送信されたのかを事前に知ることは決してできません。たとえば、MIME タイプが誤って設定されている場合や、送信された画像が極端に大きい場合などがあります。必ず、メイン(「UI」)スレッドではなく、別個のスレッドでバイナリデータを処理するようにしてください。

@Composable
fun SharesheetHandler() {
    val context = LocalContext.current
    val intent = (context as? Activity)?.intent

    when (intent?.action) {
        ACTION_SEND -> {
            if ("text/plain" == intent.type) {
                handleSendText(intent) // Handle text being sent.
            } else if (intent.type?.startsWith("image/") == true) {
                handleSendImage(intent) // Handle single image being sent
            }
        }

        Intent.ACTION_SEND_MULTIPLE -> {
            if (intent.type?.startsWith("image/") == true) {
                handleSendMultipleImages(intent) // Handle multiple images being sent
            }
        }

        else -> {
            // Handle other intents, such as being started from the home screen
        }
    }
}

fun handleSendText(intent: Intent) {
    intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
        // Update ViewModel state to change state of text being shared
    }
}

fun handleSendImage(intent: Intent) {
    IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
        // Update ViewModel state to change state of image being shared
    }
}

fun handleSendMultipleImages(intent: Intent) {
    IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
        // Update ViewModel state to change state of image(s) being shared
    }
}

データを受信した後の UI の更新としては、 EditTextにデータを入力するだけのシンプルなケースもあれば、 魅力的な写真フィルタを画像に適用するような高度なケースもあります。その後の処理方法は、アプリによって異なります。

スクリーンショットの URL の共有

スクリーンショットを撮影する際に、スクリーンショットと関連する URL を共有できます。 これにより、ユーザー エクスペリエンスが向上します。URL を受信する場合は、次の例に示すように、インテントから EXTRA_TEXT フィールドを取得してください。

IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
    // Handle the EXTRA_TEXT as well
    val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
    // Update ViewModel state to change state image being shared and the EXTRA_TEXT
    // if available
}

アプリがユーザーに認識されるようにする

アプリは、Android Sharesheet やインテント リゾルバ内で アイコンラベルで示されます。これらはいずれもマニフェスト内で定義します。アクティビティ ラベルやインテント フィルタ ラベルを設定すると、詳細なコンテキストを指定できます。

Android 10(API レベル 29)以降、Android Sharesheet が使用するアイコンは、マニフェスト内で application タグに対して設定されたアイコンに限られるようになりました。intent-filter タグと activity タグに設定されたアイコンは無視されます。