アプリは、他のアプリにデータを送信できるだけでなく、他のアプリからデータを受信することもできます。ユーザーがアプリケーションをどのように操作するか、他のアプリケーションからどのようなデータタイプを受け取るかを検討します。たとえば、ソーシャル ネットワーキング アプリは、別のアプリからテキスト コンテンツ(興味深いウェブ URL など)を受け取る場合があります。
Compose Navigation を使用するアプリで、別のアプリから送信されたデータを受信するプロセスは、次の 3 つのステップで構成されます。
マニフェストで
<intent-filter>を宣言する:AndroidManifest.xmlファイルでアクティビティにインテント フィルタを追加する必要があります。これにより、アプリが特定のアクション(ACTION_SENDなど)と MIME タイプ(text/plainなど)を受信できることを Android OS に通知します。Compose Navigation グラフで
navDeepLinkを定義します。アクションと MIME タイプに一致するnavDeepLinkを、コンテンツを表示するコンポーズ可能なデスティネーションに直接アタッチします。NavControllerは、受信したインテントを自動的にインターセプトし、ユーザーをその画面に直接ルーティングします。受信データ ペイロードを抽出する: リンク先の画面で、インテント エクストラ(
EXTRA_TEXTやEXTRA_STREAMなど)にアクセスして、共有コンテンツを取得し、UI の状態を更新します。
ダイレクト シェア ターゲットは、アプリ内の特定のアクティビティへのディープリンクです。多くの場合、個人またはグループを表し、Android Sharesheet に表示されます。たとえば、メッセージ アプリは、ユーザーとの会話に直接ディープリンクするユーザーの Direct Share ターゲットを提供できます。詳しい手順については、Direct Share ターゲットを提供するをご覧ください。
MIME タイプをサポートする
理想的には、アプリは可能な限り幅広い MIME タイプを受信できる必要があります。たとえば、テキスト、画像、動画を送信するように設計されたメッセージ アプリは、text/*、image/*、video/* の受信をサポートするのが理想的です。Android でデータを送受信するための一般的な MIME タイプをいくつか紹介します。
| 受信者が登録する | 送信者が送信する |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| サポートされているファイル拡張子 | application/pdf |
MIME メディアタイプの IANA 公式レジストリをご覧ください。
優れた共有ターゲットを作成する
特定のアクティビティに関連付けられた共有ターゲットをユーザーがタップした場合は、アプリが共有コンテンツを使用する前に、ユーザーが共有コンテンツを確認して編集できるようにします。これは、テキストデータの場合に特に重要です。
アプリでデータを受信する
Compose を使用するアプリで共有データを受信するには、マニフェストでインテント フィルタを宣言し、受信したインテントをディープリンクで適切な画面にルーティングして、インテントからペイロードを抽出して UI を更新します。
マニフェストを更新する
インテント フィルタは、アプリ コンポーネントが受け入れるインテントをシステムに通知します。他のアプリにデータを送信するレッスンで ACTION_SEND アクションを使用してインテントを作成したのと同様に、このアクションを使用してインテントを受信するインテント フィルタを作成します。インテント フィルタは、<intent-filter> 要素を使用してマニフェストで定義します。たとえば、アプリがテキスト コンテンツの受信を処理する場合、任意のタイプの 1 つ以上の画像を含むマニフェストは、次のスニペットのようになります。
<activity android:name=".ui.MyActivity" android:exported="true">
<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 またはインテント リゾルバにオプションとして表示されます。ユーザーがアプリを選択すると、対応するアクティビティ(上記の例では .ui.MyActivity)が開始されます。その後、コードと UI 内でコンテンツを適切に処理するのは、デベロッパーの責任です。
ナビゲーション グラフでディープリンクを定義する
Compose Navigation では、コンテンツを表示するコンポーザブル デスティネーションに navDeepLink を直接アタッチします。別のアプリがインテント フィルタに一致するデータを共有すると、Compose Navigation はユーザーをこのデスティネーションに直接ルーティングします。
composable( route = "incoming_share", deepLinks = listOf( navDeepLink { action = Intent.ACTION_SEND mimeType = "text/plain" }, navDeepLink { action = Intent.ACTION_SEND mimeType = "image/*" }, navDeepLink { action = Intent.ACTION_SEND_MULTIPLE mimeType = "image/*" } ) ) { SharesheetHandler() }
navDeepLink は、受信インテントのアクションと MIME タイプを照合して、正しいデスティネーション画面に移動します。その宛先に到達すると、ハンドラはインテントを検査して、受信したペイロード(単一の画像か複数の画像かなど)を特定し、対応するエクストラを抽出します。
受信コンテンツを処理する
Intent によって配信されたコンテンツを取得するには、コンポーザブル内の LocalActivity.current から現在のアクティビティを読み取り、インテントを調べて次に何を行うかを決定します。このアクティビティをシステムの他の部分(ランチャーなど)から開始できる場合は、インテントを調べる際にこの点を考慮してください。
受信データを確認する際は、特に注意してください。間違った MIME タイプが設定されている場合や、送信される画像が非常に大きい場合があります。バイナリデータや負荷の高い I/O オペレーション(大きな画像のデコードやファイルの書き込みなど)は、メイン UI スレッドではなく、コルーチン(Dispatchers.IO など)を使用して非同期で処理します。
@Composable fun SharesheetHandler() { val activity = LocalActivity.current val intent = activity?.intent when (intent?.action) { Intent.ACTION_SEND -> { if (intent.type == "text/plain") { 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 } } } private fun handleSendText(intent: Intent) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { // Update UI state with the shared text } } private fun handleSendImage(intent: Intent) { val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUri?.let { // Update UI state with the shared image } } private fun handleSendMultipleImages(intent: Intent) { val imageUris = IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUris?.let { // Update UI state with the shared images } }
インテント エクストラ(EXTRA_STREAM など)からバイナリデータまたは URI を抽出する場合は、前述の handleSendImage 関数と handleSendMultipleImages 関数に示すように、AndroidX Core ライブラリの IntentCompat.getParcelableExtra() または IntentCompat.getParcelableArrayListExtra() を使用します。Android 13(API レベル 33)では、パラメータ化されていない Intent.getParcelableExtra(String) メソッドが非推奨となり、想定されるクラスタイプを受け取るタイプセーフなメソッドが推奨されます。
データを受信した後に UI を更新する処理は、TextField にデータを入力するために状態を更新するような単純なものから、画像にフィルタを適用するような複雑なものまでさまざまです。次に何が起こるかはアプリ次第です。
スクリーンショットの 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 UI state with the shared image and the EXTRA_TEXT if available }
アプリがユーザーに認識されるようにする
アプリは、Android Sharesheet とインテント リゾルバでアイコンとラベルによって表されます。どちらもマニフェストで定義されています。アクティビティ ラベルまたはインテント フィルタ ラベルを設定して、より詳細なコンテキストを提供できます。
Android 10(API レベル 29)以降、Android Sharesheet は、マニフェストの application タグで設定されたアイコンのみを使用します。Android は、intent-filter タグと activity タグに設定されたアイコンを無視します。
リッチ コンテンツを受信する
ACTION_SEND インテントを使用すると、アクティビティ レベルまたはナビゲーション レベルで Android Sharesheet とインテント リゾルバからデータを受信できますが、アプリは直接的な UI 操作を通じてリッチ コンテンツ(画像、動画、音声ファイル、スタイル付きテキストなど)を受信することもできます。このようなメカニズムには、以下が含まれます。
- クリップボードから貼り付ける(長押しメニュー)
- ステッカーや GIF などのメディアをソフトウェア キーボード(IME)から直接挿入する
- マルチ ウィンドウ モードまたは分割画面モードで、別のアプリからコンテンツをドラッグ&ドロップする
ビューベースの UI では、Android 12(API レベル 31)と AndroidX Core 1.7 で、統合された OnReceiveContentListener API が導入されています。このリスナーは、クリップボード、キーボード、ドラッグ&ドロップからのコンテンツ処理を 1 つのコールバックに統合します。ビューにこれを実装する詳細な手順については、リッチ コンテンツを受信するをご覧ください。
Jetpack Compose では、Modifier.contentReceiver 修飾子またはドラッグ&ドロップ修飾子を使用して、UI コンポーネント(テキスト フィールドなど)に挿入されたリッチ コンテンツの受信を処理できます。