應用程式可以傳送資料給其他應用程式,也可以接收其他應用程式的資料。請思考使用者與應用程式的互動方式,以及您想從其他應用程式接收哪些資料類型。舉例來說,社群網路應用程式可能會想接收來自其他應用程式的文字內容,例如有趣的網頁網址。
在使用 Compose Navigation 的應用程式中,接收其他應用程式傳送的資料需要三個步驟:
在資訊清單中宣告
<intent-filter>:您仍須在AndroidManifest.xml檔案中,為活動新增意圖篩選器。這會告知 Android 作業系統,您的應用程式能夠接收特定動作 (例如ACTION_SEND) 和 MIME 類型 (例如text/plain)。在 Compose Navigation 圖表中定義
navDeepLink:將符合動作和 MIME 類型的navDeepLink直接附加至應顯示內容的可組合目的地。NavController會自動攔截傳入的意圖,並將使用者直接導向該畫面。擷取傳入的資料酬載:在目的地畫面中,存取意圖額外資訊 (例如
EXTRA_TEXT或EXTRA_STREAM),以擷取共用內容並更新 UI 狀態。
直接分享目標是應用程式中特定 Activity 的深層連結。這些目標通常代表個人或群組,並會顯示在 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。這個事件監聽器會將剪貼簿、鍵盤和拖放操作的內容處理作業整合至單一回呼。如需在 Views 中導入這項功能的詳細操作說明,請參閱「接收多媒體內容」。
在 Jetpack Compose 中,您可以使用 Modifier.contentReceiver 修飾符或拖曳修飾符,處理插入 UI 元件 (例如文字欄位) 的多媒體內容。