應用程式可以將資料傳送至其他應用程式,也可以接收其他應用程式傳送的資料。請思考使用者與應用程式互動的方式,以及您想從其他應用程式接收哪些資料類型。舉例來說,社群網路應用程式可能會想從其他應用程式接收文字內容,例如有趣的網址。
在採用 Compose Navigation 的應用程式中,接收其他應用程式傳送的資料需要三個步驟:
在資訊清單中宣告
<intent-filter>:您仍須在AndroidManifest.xml檔案中,為活動新增意圖篩選器。這會告知 Android 作業系統,您的應用程式能夠接收特定動作 (例如ACTION_SEND) 和 MIME 類型 (例如text/plain)。在 Compose Navigation 圖中定義
navDeepLink:將與動作和 MIME 類型相符的navDeepLink直接附加至應顯示內容的可組合目的地。NavController會自動攔截傳入的意圖,並將使用者直接導向該畫面。擷取傳入的資料酬載:在目的地畫面中,存取意圖額外項目 (例如
EXTRA_TEXT或EXTRA_STREAM),擷取共用內容並更新 UI 狀態。
「直接分享」目標是應用程式中特定活動的深層連結。這些目標通常代表使用者或群組,並會顯示在 Android Sharesheet 中。舉例來說,訊息應用程式可以為使用者提供直接分享目標,直接深層連結至與該使用者的對話。如需詳細操作說明,請參閱「提供直接分享目標」。
支援 MIME 類型
理想情況下,應用程式必須能接收盡可能廣泛的 MIME 類型。舉例來說,如果訊息應用程式設計用於傳送文字、圖片和影片,則最好支援接收 text/*、image/* 和 video/*。以下列出在 Android 中傳送及接收資料時,常用的幾種 MIME 類型。
| 接收器會註冊 | 傳送者傳送 |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| 支援的副檔名 | application/pdf |
請參閱 IANA 的 MIME 媒體類型官方註冊資料。
建立優質的分享目標
當使用者輕觸與特定活動相關聯的分享目標時,請讓他們先確認及編輯分享內容,再由應用程式使用。這點對文字資料尤為重要。
在應用程式中接收資料
如要在使用 Compose 的應用程式中接收共用資料,您必須在資訊清單中宣告意圖篩選器、使用深層連結將傳入的意圖轉送至適當畫面,並從意圖中擷取酬載,以便更新 UI。
更新資訊清單
意圖篩選器會告知系統,應用程式元件接受哪些意圖。與您在「將資料傳送至其他應用程式」課程中,使用 ACTION_SEND 動作建構意圖的方式類似,您需要建立意圖篩選器,才能接收具有此動作的意圖。您可以使用 <intent-filter> 元素在資訊清單中定義意圖篩選器。舉例來說,如果應用程式會處理接收的文字內容,則包含一或多張任何類型圖片的資訊清單會類似下列程式碼片段:
<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 類型,或傳送的圖片可能過大。使用協同程式 (例如 Dispatchers.IO) 非同步處理二進位資料或繁重的 I/O 作業 (例如解碼大型圖片或寫入檔案),而非在主 UI 執行緒上處理。
@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 時,請使用 AndroidX Core 程式庫中的 IntentCompat.getParcelableExtra() 或 IntentCompat.getParcelableArrayListExtra(),如上述 handleSendImage 和 handleSendMultipleImages 函式所示。Android 13 (API 級別 33) 淘汰了無參數的 Intent.getParcelableExtra(String) 方法,改用採用預期類別類型的類型安全方法。
收到資料後,更新 UI 的方式可能很簡單,例如更新狀態以填入 TextField,也可能很複雜,例如對圖片套用濾鏡。後續動作由應用程式決定。
分享螢幕截圖網址
擷取螢幕截圖時,你可以分享螢幕截圖和任何相關網址。
提供更豐富的使用者體驗。接收網址時,請務必從意圖中取得 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
- 在多視窗模式或分割畫面模式下,從其他應用程式拖放內容
在以 View 為基礎的 UI 中,Android 12 (API 級別 31) 和 AndroidX Core 1.7 導入了統一的 OnReceiveContentListener API。這個事件監聽器會將剪貼簿、鍵盤和拖放操作的內容處理作業整合至單一回呼。如需在檢視畫面中實作這項功能的詳細操作說明,請參閱「接收多媒體內容」。
在 Jetpack Compose 中,您可以使用 Modifier.contentReceiver 修飾符或拖曳修飾符,處理插入 UI 元件 (例如文字欄位) 的多媒體內容。