接收其他應用程式的資料

應用程式可以傳送資料給其他應用程式,也可以接收其他應用程式的資料。請思考使用者與應用程式的互動方式,以及您想從其他應用程式接收哪些資料類型。舉例來說,社群網路應用程式可能會想接收來自其他應用程式的文字內容,例如有趣的網頁網址。

在使用 Compose Navigation 的應用程式中,接收其他應用程式傳送的資料需要三個步驟:

  1. 在資訊清單中宣告 <intent-filter>:您仍須在 AndroidManifest.xml 檔案中,為活動新增意圖篩選器。這會告知 Android 作業系統,您的應用程式能夠接收特定動作 (例如 ACTION_SEND) 和 MIME 類型 (例如 text/plain)。

  2. 在 Compose Navigation 圖表中定義 navDeepLink:將符合動作和 MIME 類型的 navDeepLink 直接附加至應顯示內容的可組合目的地。NavController 會自動攔截傳入的意圖,並將使用者直接導向該畫面。

  3. 擷取傳入的資料酬載:在目的地畫面中,存取意圖額外資訊 (例如 EXTRA_TEXT 或 EXTRA_STREAM),以擷取共用內容並更新 UI 狀態。

直接分享目標是應用程式中特定 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

請參閱 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 會直接將使用者導向這個目的地:

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 元件 (例如文字欄位) 的多媒體內容。