アプリは、他のアプリにデータを送信できるだけでなく、他のアプリからデータを受信することもできます。ユーザーがアプリケーションをどのように操作するか、他のアプリケーションからどのようなデータタイプを受け取るかを検討します。たとえば、ソーシャル ネットワーキング アプリケーションは、別のアプリから興味深いウェブ 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 操作を通じてリッチ コンテンツ(画像、動画、音声ファイル、スタイル付きテキストなど)を受け取ることもできます。このようなメカニズムには、以下が含まれます。
- クリップボードから貼り付ける(長押しメニュー)
- ソフトウェア キーボード(IME)からステッカーや GIF などのメディアを直接挿入する
- マルチ ウィンドウ モードまたは分割画面モードで別のアプリからコンテンツをドラッグ&ドロップする
ビューベースの UI では、Android 12(API レベル 31)と AndroidX Core 1.7 で、統合された OnReceiveContentListener API が導入されています。このリスナーは、クリップボード、キーボード、ドラッグ&ドロップからのコンテンツ処理を 1 つのコールバックに統合します。ビューにこれを実装する詳細な手順については、リッチ コンテンツを受信するをご覧ください。
Jetpack Compose では、Modifier.contentReceiver 修飾子またはドラッグ&ドロップ修飾子を使用して、UI コンポーネント(テキスト フィールドなど)に挿入されたリッチ コンテンツの受信を処理できます。