傳送簡單資料給其他應用程式

Android 使用意圖及相關額外項目,讓使用者透過喜愛的應用程式輕鬆快速地分享資訊。

Android 提供兩種方式讓使用者在不同應用程式之間共用資料:

  • Android Sharesheet 主要用於將內容傳送到應用程式外,和/或直接傳送給其他使用者。舉例來說,您可以將網址分享給好友。
  • Android 意圖解析器最適合用來將資料傳送至定義明確工作的下一個階段。舉例來說,您可以從應用程式開啟 PDF 檔案,並讓使用者挑選偏好的檢視器。

建構意圖時,您必須指定意圖執行的動作。Android 會使用 ACTION_SEND 動作,將資料從一個活動傳送至另一個活動,甚至是跨越程序邊界。您必須指定資料及其類型。系統會自動識別可接收資料的相容活動,並向使用者顯示這些活動。如果是意圖解析器,如果只有一個活動能夠處理意圖,該活動會立即啟動。

使用 Android Sharesheet 的好處

強烈建議您使用 Android Sharesheet,為使用者提供跨應用程式的一致性。請勿顯示應用程式專屬的共用目標清單,或建立自己的 Sharesheet 變化版本。

Android Sharesheet 可讓使用者只要輕觸一下,就能向合適的對象分享資訊,以及相關的應用程式建議。Sharesheet 可以建議自訂解決方案無法使用的目標,並採用一致的排名。這是因為 Sharesheet 可能會將僅適用於系統的應用程式與使用者活動相關資訊納入考量。

Android Sharesheet 也為開發人員提供許多實用功能。舉例來說,您可以執行以下操作:

使用 Android Sharesheet

針對所有類型的共用,建立意圖並將動作設為 Intent.ACTION_SEND。如要顯示 Android Sharesheet,請呼叫 Intent.createChooser(),並向其 Intent 物件傳遞。此方法會傳回會一律顯示 Android Sharesheet 的意圖版本。

傳送文字內容

Android Sharesheet 最簡單且最常見的用法,是將文字內容從一個活動傳送至另一個活動。舉例來說,大部分瀏覽器都可以將目前顯示的網頁網址以文字與其他應用程式分享。這對於透過電子郵件或社群網路與好友分享文章或網站非常有用。操作方法範例如下:

Kotlin

val sendIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
    type = "text/plain"
}

val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)

Java

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");

Intent shareIntent = Intent.createChooser(sendIntent, null);
startActivity(shareIntent);

您也可以選擇新增其他項目以提供更多資訊,例如電子郵件收件者 (EXTRA_EMAILEXTRA_CCEXTRA_BCC)、電子郵件主旨 (EXTRA_SUBJECT) 等。

注意:部分電子郵件應用程式 (例如 Gmail) 的 String[] 額外提供 EXTRA_EMAILEXTRA_CC 等額外功能。請使用 putExtra(String, String[]) 將這些內容新增至意圖。

傳送二進位內容

使用 ACTION_SEND 動作共用二進位資料。設定適當的 MIME 類型,並將資料的 URI 放入額外的 EXTRA_STREAM 中,如以下範例所示。這通常用於分享圖片,但可用來分享任何類型的二進位內容。

Kotlin

val shareIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    // Example: content://com.google.android.apps.photos.contentprovider/...
    putExtra(Intent.EXTRA_STREAM, uriToImage)
    type = "image/jpeg"
}
startActivity(Intent.createChooser(shareIntent, null))

Java

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
// Example: content://com.google.android.apps.photos.contentprovider/...
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, null));

接收應用程式需要權限,才能存取 Uri 指向的資料。建議採取以下兩種做法:

  • 將資料儲存在您自己的 ContentProvider 中,確認其他應用程式有存取供應器的正確權限。我們建議您使用個別 URI 權限提供存取權,這是暫時性的,並且僅將存取權授予接收的應用程式。如要建立這類 ContentProvider,最簡單的方法就是使用 FileProvider 輔助類別。
  • 請使用系統 MediaStoreMediaStore 主要用於影片、音訊和圖片的 MIME 類型。不過,從 Android 3.0 (API 級別 11) 開始,也可以儲存非媒體類型。詳情請參閱 MediaStore.Files。您可以使用 scanFile() 插入檔案至 MediaStore,之後,適合共用的 content:// 樣式 Uri 就會傳遞至提供的 onScanCompleted() 回呼。請注意,新增到系統 MediaStore 後,裝置上的任何應用程式皆可存取該內容。

使用正確的 MIME 類型

針對您要傳送的資料提供最明確可用的 MIME 類型。舉例來說,分享純文字時請使用 text/plain。在 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

如要進一步瞭解 MIME 類型,請參閱 IANA 官方登錄的 MIME 媒體類型。

視提供的 MIME 類型而定,Android Sharesheet 可能會顯示內容預覽畫面。部分預覽功能僅適用於特定類型。

分享多個內容

如要分享多個內容片段,請將 ACTION_SEND_MULTIPLE 動作與指向內容的 URI 清單搭配使用。MIME 類型則視您分享的內容組合而定。舉例來說,如要分享三張圖片,請使用 "image/jpg" 類型。如要混合圖片類型,請使用 "image/*" 來比對處理任何類型圖片的活動。雖然可以共用多種類型,但強烈建議您不要這麼做,因為接收方並不清楚即將傳送的內容。如果您需要傳送多種類型,請使用 "*/*"。視接收應用程式而定,可剖析及處理您的資料。範例如下:

Kotlin

val imageUris: ArrayList<Uri> = arrayListOf(
        // Add your image URIs here
        imageUri1,
        imageUri2
)

val shareIntent = Intent().apply {
    action = Intent.ACTION_SEND_MULTIPLE
    putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
    type = "image/*"
}
startActivity(Intent.createChooser(shareIntent, null))

Java

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, null));

請確認提供的 Uri 物件指向接收應用程式可存取的資料。

在文字預覽中加入多媒體內容

從 Android 10 (API 級別 29) 開始,Android Sharesheet 會顯示分享文字的預覽畫面。在某些情況下,分享的文字可能難以理解。考慮共用複雜的網址,例如 https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4。更豐富的預覽內容可以讓使用者安心。

預覽文字時,您可以設定標題和/或縮圖。請在呼叫 Intent.createChooser() 之前,為 Intent.EXTRA_TITLE 加入說明,並使用 ClipData 新增相關縮圖。

注意:圖片內容 URI 是由 FileProvider 提供,通常來自設定的 <cache-path>。詳情請參閱共用檔案。請務必授予 Sharesheet 適當的權限,讓其能夠讀取任何您要做為縮圖的圖片。詳情請參閱 Intent.FLAG_GRANT_READ_URI_PERMISSION

範例如下:

Kotlin

 val share = Intent.createChooser(Intent().apply {
      action = Intent.ACTION_SEND
      putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")

      // (Optional) Here you're setting the title of the content
      putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

      // (Optional) Here you're passing a content URI to an image to be displayed
      data = contentUri
      flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
  }, null)
  startActivity(share)

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/");

// (Optional) Here you're setting the title of the content
sendIntent.putExtra(Intent.EXTRA_TITLE, "Introducing content previews");

// (Optional) Here you're passing a content URI to an image to be displayed
sendIntent.setData(contentUri);
sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Show the Sharesheet
startActivity(Intent.createChooser(sendIntent, null));

預覽看起來會像這樣:

新增自訂目標

Android Sharesheet 可讓您指定最多兩個 ChooserTarget 物件,這些物件會在共用捷徑和從 ChooserTargetServices 載入的選擇器目標之前顯示。您也可以指定最多兩個意圖,指向應用程式建議之前列出的活動:

呼叫 Intent.createChooser() 之後,將 Intent.EXTRA_CHOOSER_TARGETSIntent.EXTRA_INITIAL_INTENTS 新增至共用意圖:

Kotlin

val share = Intent.createChooser(myShareIntent, null).apply {
    putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray)
    putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray)
}

Java

Intent shareIntent = Intent.createChooser(sendIntent, null);
share.putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray);
share.putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray);

請謹慎使用此功能。您新增的每個自訂 IntentChooserTarget 都會減少系統建議的數量。我們通常不建議您新增自訂目標。新增 Intent.EXTRA_INITIAL_INTENTS 的常見範例是提供使用者可以對共用內容採取的其他動作。舉例來說,使用者共用圖片時,系統會使用 Intent.EXTRA_INITIAL_INTENTS 讓他們改為傳送連結。新增 Intent.EXTRA_CHOOSER_TARGETS 的常見例子是顯示應用程式提供的相關使用者或裝置。

依元件排除特定目標

您可以提供 Intent.EXTRA_EXCLUDE_COMPONENTS 來排除特定目標。只這麼做即可移除您可以控管的指定目標。常見的情況是,當使用者在應用程式中分享內容時,隱藏應用程式的共用目標,因為他們的意圖很可能會在應用程式外共用。

呼叫 Intent.createChooser() 後,將 Intent.EXTRA_EXCLUDE_COMPONENTS 新增至意圖:

Kotlin

  val share = Intent.createChooser(Intent(), null).apply {
    // Only use for components you have control over
    val excludedComponentNames = arrayOf(ComponentName("com.example.android", "ExampleClass"))
    putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames)
  }

Java

  Intent shareIntent = Intent.createChooser(new Intent(), null);
  // Only use for components you have control over
  ComponentName[] excludedComponentNames = {
          new ComponentName("com.example.android", "ExampleClass")
  };
  shareIntent.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames);

取得共用相關資訊

瞭解使用者何時與他人共用,以及他們選取的目標為何,是非常實用的做法。Android Sharesheet 可透過 IntentSender 為使用者提供所選目標的 ComponentName,方便您取得這項資訊。

首先,為 BroadcastReceiver 建立 PendingIntent,並在 Intent.createChooser() 中提供其 IntentSender

Kotlin

var share = Intent(Intent.ACTION_SEND)
// ...
val pi = PendingIntent.getBroadcast(
    myContext, requestCode,
    Intent(myContext, MyBroadcastReceiver::class.java),
    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
share = Intent.createChooser(share, null, pi.intentSender)

Java

Intent share = new Intent(ACTION_SEND);
...
PendingIntent pi = PendingIntent.getBroadcast(myContext, requestCode,
        new Intent(myContext, MyBroadcastReceiver.class),
        PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
share = Intent.createChooser(share, null, pi.getIntentSender());

接收 MyBroadcastReceiver 中的回呼並查看 Intent.EXTRA_CHOSEN_COMPONENT

Kotlin

override fun onReceive(context: Context, intent: Intent) {
  ...
  val clickedComponent : ComponentName = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
}

Java

@Override public void onReceive(Context context, Intent intent) {
  ...
  ComponentName clickedComponent = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
}

使用 Android 意圖解析器

ACTION_SEND 意圖解析器的螢幕截圖。

如要在定義明確的工作流程中將資料傳送至其他應用程式,建議您使用 Android 意圖解析器。

如要使用 Android 意圖解析器,請建立意圖並新增額外項目,方法與呼叫 Android Sharesheet 相同。不過,請「不要」呼叫 Intent.createChooser()

如果已安裝多個已安裝應用程式且篩選器符合 ACTION_SEND 和 MIME 類型,則系統會顯示稱為「意圖解析器」的消歧對話方塊,讓使用者選擇要分享的目標。如果單一應用程式相符,應用程式就會執行。

以下範例說明如何使用 Android 意圖解析器傳送簡訊:

Kotlin

val sendIntent: Intent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
    type = "text/plain"
}
startActivity(sendIntent)

Java

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);

瞭解詳情

如要進一步瞭解如何傳送資料,請參閱「意圖和意圖篩選器」。