Android 會利用意圖和相關聯的額外功能,讓使用者透過自己喜愛的應用程式快速輕鬆地分享資訊。
Android 提供兩種讓使用者在應用程式之間共用資料的方式:
- Android Sharesheet 主要用於將內容傳送至應用程式外部,和/或直接傳送給其他使用者。例如與好友分享網址。
- Android 意圖解析器最適合用來將資料傳遞至定義明確工作的下一個階段。例如,從應用程式開啟 PDF,讓使用者選擇偏好的檢視器。
建構意圖時,請指定您希望意圖執行的動作。Android 會使用 ACTION_SEND
動作在活動之間傳送資料,甚至是跨程序邊界。您必須指定資料和資料類型。系統會自動識別可接收資料的相容活動,並向使用者顯示。對意圖解析器而言,如果只有一個活動可以處理意圖,則該活動會立即啟動。
使用 Android Sharesheet 的好處
強烈建議您使用 Android Sharesheet,讓各應用程式的使用者能保持一致。請勿顯示應用程式本身的共用目標清單,或自行建立 Sharesheet 變化版本。
Android Sharesheet 可讓使用者與適當對象分享資訊,並提供相關的應用程式建議,而且只要輕觸一下。Sharesheet 可提供自訂解決方案無法使用的目標建議,且採用一致的排名。 這是因為 Sharesheet 可將僅適用於系統的應用程式和使用者活動相關資訊納入考量。
Android Sharesheet 也提供許多開發人員實用的功能。舉例來說,您可以執行下列操作:
- 瞭解使用者何時完成共用動作以及前往何處
- 新增自訂
ChooserTarget
和應用程式目標 - 從 Android 10 (API 級別 29) 開始,提供 RTF 格式內容預覽
- 排除與特定元件名稱相符的目標
使用 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_EMAIL
、EXTRA_CC
、EXTRA_BCC
)、電子郵件主旨 (EXTRA_SUBJECT
) 等。
注意:部分電子郵件應用程式 (例如 Gmail) 會預期 EXTRA_EMAIL
和 EXTRA_CC
等額外項目的 String[]
。請使用 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
輔助類別。 - 使用系統
MediaStore
。MediaStore
主要適用於影片、音訊和圖片 MIME 類型。不過,從 Android 3.0 (API 級別 11) 開始,也可以儲存非媒體類型。詳情請參閱MediaStore.Files
。您可以使用scanFile()
將檔案插入MediaStore
,之後,適合共用的content://
樣式Uri
會傳遞至提供的onScanCompleted()
回呼。請注意,將內容新增至系統MediaStore
後,裝置上的任何應用程式皆可存取內容。
使用正確的 MIME 類型
針對要傳送的資料提供最明確的 MIME 類型。舉例來說,在分享純文字時使用 text/plain
。以下是在 Android 中傳送簡單資料時常見的 MIME 類型:
接收器註冊 | 寄件者傳送 |
---|---|
text/* |
|
`image/*` |
|
video/* |
|
支援的副檔名 | application/pdf |
如要進一步瞭解 MIME 類型,請參閱 IANA 官方的 MIME 媒體類型註冊資料庫。
視提供的 MIME 類型而定,Android Sharesheet 可能會顯示內容預覽。部分預先發布版功能僅適用於特定類型。
分享多個內容
如要共用多段內容,請使用 ACTION_SEND_MULTIPLE
動作以及指向該項內容的 URI 清單。MIME 類型會因共用的內容組合而異。舉例來說,如果您分享三張 JPEG 圖片,請使用 "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.EXTRA_TITLE
加入說明,然後再呼叫 Intent.createChooser()
,並使用 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));
預覽畫面看起來會像這樣:
在 Sharesheet 中新增自訂動作
在 Android 14 (API 級別 34) 以上版本中,應用程式可以在 Android Sharesheet 中新增自訂動作。自訂動作會以小型動作圖示顯示在 Android Sharesheet 頂端,應用程式可以指定任何 Intent
做為點選圖示時叫用的動作。
如要在 Android Sharesheet 上新增自訂動作,請先使用 ChooserAction.Builder
建立 ChooserAction
。您可以指定 PendingIntent
做為點選圖示時叫用的動作。建立包含所有自訂動作的陣列,並將其指定為共用 Intent
的 EXTRA_CHOOSER_CUSTOM_ACTIONS
。
Kotlin
val sendIntent = Intent(Intent.ACTION_SEND) .setType("text/plain") .putExtra(Intent.EXTRA_TEXT, text) val shareIntent = Intent.createChooser(sendIntent, null) val customActions = arrayOf( ChooserAction.Builder( Icon.createWithResource(context, R.drawable.ic_custom_action), "Custom", PendingIntent.getBroadcast( context, 1, Intent(Intent.ACTION_VIEW), PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT ) ).build() ) shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions) context.startActivity(shareIntent)
Java
Intent sendIntent = new Intent(Intent.ACTION_SEND) .setType("text.plain") .putExtra(Intent.EXTRA_TEXT, text); Intent shareIntent = Intent.createChooser(sendIntent, null); ChooserAction[] actions = new ChooserAction[]{ new ChooserAction.Builder( Icon.createWithResource(context, R.drawable.ic_custom_action), "Custom", PendingIntent.getBroadcast( context, 1, new Intent(Intent.ACTION_VIEW), PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT ) ).build() }; shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, actions); context.startActivity(shareIntent);
新增自訂目標
Android Sharesheet 可讓您指定最多兩個 ChooserTarget
物件,這些物件會顯示在共用捷徑和從 ChooserTargetServices
載入的選擇工具目標之前。您也可以指定最多兩個意圖指向應用程式建議之前列出的活動:
呼叫 Intent.createChooser()
之後,將 Intent.EXTRA_CHOOSER_TARGETS
和 Intent.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);
使用此功能時請務必謹慎。您新增的每個自訂 Intent
和 ChooserTarget
都會減少系統建議的數量。我們通常不建議新增自訂目標。新增 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); }
在 Sharesheet 中新增自訂動作
在 Android 14 (API 級別 34) 以上版本中,應用程式可以在 Android Sharesheet 中新增自訂動作。使用 ChooserAction.Builder
建立 ChooserAction
。您可以指定 PendingIntent
做為點選圖示時叫用的動作。建立包含所有自訂動作的陣列,並將其指定為共用 Intent
的 EXTRA_CHOOSER_CUSTOM_ACTIONS
。
Kotlin
val sendIntent = Intent(Intent.ACTION_SEND) .setType("text/plain") .putExtra(Intent.EXTRA_TEXT, text) val shareIntent = Intent.createChooser(sendIntent, null) val customActions = arrayOf( ChooserAction.Builder( Icon.createWithResource(context, R.drawable.ic_custom_action), "Custom", PendingIntent.getBroadcast( context, 1, Intent(Intent.ACTION_VIEW), PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT ) ).build() ) shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions) context.startActivity(shareIntent)
Java
Intent sendIntent = new Intent(Intent.ACTION_SEND) .setType("text.plain") .putExtra(Intent.EXTRA_TEXT, text); Intent shareIntent = Intent.createChooser(sendIntent, null); ChooserAction[] actions = new ChooserAction[]{ new ChooserAction.Builder( Icon.createWithResource(context, R.drawable.ic_custom_action), "Custom", PendingIntent.getBroadcast( context, 1, new Intent(Intent.ACTION_VIEW), PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT ) ).build() }; shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, actions); context.startActivity(shareIntent);
使用 Android 意圖解析器
在明確定義的工作流程中,將資料傳送至其他應用程式時,最適合使用 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);
瞭解詳情
如要進一步瞭解如何傳送資料,請參閱意圖和意圖篩選器。