Android cung cấp hai cách để người dùng chia sẻ dữ liệu giữa các ứng dụng:
- Trang chia sẻ nội dung trong Android chủ yếu được thiết kế để gửi nội dung ra bên ngoài ứng dụng hoặc gửi trực tiếp đến người dùng khác. Ví dụ: chia sẻ URL với bạn bè.
- Trình phân giải ý định của Android phù hợp nhất để truyền dữ liệu đến giai đoạn tiếp theo của một tác vụ được xác định rõ ràng. Ví dụ: mở tệp PDF từ ứng dụng của bạn và cho phép người dùng chọn trình xem mà họ muốn.
Lý do nên sử dụng Trang chia sẻ nội dung trong Android
Sử dụng Trang chia sẻ nội dung trong Android để tạo sự nhất quán cho người dùng trên các ứng dụng. Đừng hiển thị danh sách mục tiêu chia sẻ của riêng ứng dụng hoặc tạo các biến thể Trang chia sẻ nội dung của riêng bạn.
Trang chia sẻ nội dung trong Android cho phép người dùng chia sẻ thông tin với đúng người, kèm theo các đề xuất ứng dụng phù hợp, tất cả chỉ bằng một lần nhấn. Trang chia sẻ nội dung có thể đề xuất cả những mục tiêu không sẵn có cho các giải pháp tuỳ chỉnh và sử dụng thứ hạng nhất quán. Điều này là do Sharesheet có thể xem xét thông tin về hoạt động của ứng dụng và người dùng mà chỉ hệ thống mới có.
Trang chia sẻ nội dung trong Android cũng có nhiều tính năng hữu ích cho nhà phát triển. Ví dụ: bạn có thể làm như sau:
- Tìm hiểu thời điểm người dùng hoàn tất việc chia sẻ và nơi họ chia sẻ
- Thêm mục tiêu tuỳ chỉnh và mục tiêu ứng dụng
- Cung cấp bản xem trước nội dung văn bản đa dạng thức, bắt đầu từ Android 10 (cấp độ API 29)
- Loại trừ các mục tiêu khớp với tên thành phần cụ thể
Sử dụng Trang chia sẻ nội dung trong Android
Đối với tất cả các loại chia sẻ, hãy tạo một ý định và đặt hành động của ý định đó thành Intent.ACTION_SEND.
Để hiển thị Trang chia sẻ nội dung trong Android, hãy gọi Intent.createChooser(), truyền đối tượng Intent vào đó.
Phương thức này trả về một phiên bản ý định luôn hiển thị Trang chia sẻ nội dung trong Android.
Gửi nội dung văn bản
Cách sử dụng Trang chia sẻ nội dung trong Android đơn giản và phổ biến nhất là gửi nội dung văn bản từ
hoạt động này sang hoạt động khác. Ví dụ: hầu hết các trình duyệt đều có thể chia sẻ URL của trang đang hiển thị dưới dạng văn bản với một ứng dụng khác. Điều này rất hữu ích khi chia sẻ bài viết hoặc trang web với bạn bè qua email hoặc mạng xã hội. Trong Jetpack Compose, hãy truy xuất bối cảnh hiện tại bằng cách sử dụng LocalContext.current và gọi context.startActivity().
Sau đây là ví dụ về cách thực hiện:
fun shareText(context: Context) { val sendIntent: Intent = Intent().apply { action = ACTION_SEND putExtra(Intent.EXTRA_TEXT, "This is my text to send.") type = "text/plain" } val shareIntent = Intent.createChooser(sendIntent, null) context.startActivity(shareIntent) }
Nếu muốn, bạn có thể thêm các thành phần bổ sung để cung cấp thêm thông tin, chẳng hạn như người nhận email
(EXTRA_EMAIL,
EXTRA_CC,
EXTRA_BCC),
hoặc tiêu đề email
(EXTRA_SUBJECT).
Lưu ý: Một số ứng dụng email, chẳng hạn như Gmail, yêu cầu String[] cho các thành phần bổ sung như EXTRA_EMAIL và EXTRA_CC. Sử dụng
putExtra(String, String[])
để thêm các giá trị này vào ý định của bạn.
Gửi nội dung nhị phân
Chia sẻ dữ liệu nhị phân bằng thao tác ACTION_SEND.
Đặt loại MIME thích hợp và đặt URI cho dữ liệu trong EXTRA_STREAM bổ sung, như trong ví dụ sau.
Ý định này thường được dùng để chia sẻ hình ảnh nhưng cũng có thể dùng để chia sẻ bất kỳ loại nội dung nhị phân nào.
fun shareBinaryContent(context: Context) { val shareIntent: Intent = Intent().apply { action = ACTION_SEND // Example: content://com.google.android.apps.photos.contentprovider/... val imageUri: Uri = Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1") putExtra(Intent.EXTRA_STREAM, imageUri) type = "image/jpeg" } context.startActivity(Intent.createChooser(shareIntent, null)) }
Ứng dụng nhận cần có quyền truy cập vào dữ liệu mà Uri trỏ đến. Có hai cách nên dùng để thực hiện việc này:
- Lưu trữ dữ liệu trong
ContentProvidercủa riêng bạn, đảm bảo rằng các ứng dụng khác có quyền truy cập chính xác vào nhà cung cấp của bạn. Cơ chế ưu tiên để cấp quyền truy cập là sử dụng quyền theo từng URI. Các quyền này là tạm thời và chỉ cấp quyền truy cập cho ứng dụng nhận. Để tạo mộtContentProvidernhư thế này, hãy sử dụng lớp trợ giúpFileProvider. - Sử dụng
MediaStorehệ thống.MediaStorechủ yếu dành cho các loại MIME video, âm thanh và hình ảnh. Tuy nhiên, kể từ Android 3.0 (API cấp 11), thư mục này cũng có thể lưu trữ các loại không phải nội dung nghe nhìn. Để biết thêm thông tin, hãy xemMediaStore.Files. Bạn có thể chèn tệp vàoMediaStorebằng cách sử dụngscanFile(), sau đó,Urikiểucontent://phù hợp để chia sẻ sẽ được chuyển đến lệnh gọi lạionScanCompleted()được cung cấp. Lưu ý rằng sau khi được thêm vào hệ thốngMediaStore, nội dung này sẽ có thể truy cập được đối với mọi ứng dụng trên thiết bị.
Sử dụng đúng loại MIME
Cung cấp loại MIME cụ thể nhất có thể cho dữ liệu bạn đang gửi. Ví dụ: sử dụng text/plain khi chia sẻ văn bản thuần tuý. Dưới đây là một số loại MIME phổ biến khi gửi dữ liệu trong Android:
| Bộ nhận đăng ký | Người gửi gửi |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| Đuôi tệp được hỗ trợ | application/pdf |
Để xác định loại MIME một cách linh động trong thời gian chạy thay vì cố định giá trị trong mã, hãy sử dụng các phương thức sau:
- Đối với URI
content://(chẳng hạn như các URI doFileProviderhoặcMediaStorecung cấp), hãy gọiContentResolver.getType(). - Đối với đuôi tệp, hãy gọi
MimeTypeMap.getSingleton().getMimeTypeFromExtension(). - Nếu sử dụng Khung truy cập bộ nhớ, bạn cũng có thể truy vấn
DocumentFile.getType().
Nếu bạn không thể xác định một loại MIME cụ thể, hãy sử dụng application/octet-stream cho dữ liệu nhị phân chung hoặc */* làm phương án cuối cùng.
Để biết thêm thông tin về loại MIME, hãy xem sổ đăng ký chính thức của IANA về loại nội dung nghe nhìn MIME.
Trang chia sẻ nội dung trong Android có thể hiển thị bản xem trước nội dung, tuỳ thuộc vào loại MIME được cung cấp. Một số tính năng đang ở giai đoạn xem trước chỉ có sẵn cho một số loại cụ thể.
Chia sẻ nhiều nội dung
Để chia sẻ nhiều nội dung, hãy sử dụng thao tác ACTION_SEND_MULTIPLE cùng với danh sách URI trỏ đến nội dung. Loại MIME sẽ thay đổi tuỳ theo
nội dung bạn đang chia sẻ. Ví dụ: nếu chia sẻ 3 hình ảnh JPEG, bạn sẽ sử dụng loại "image/jpg". Đối với nhiều loại hình ảnh, hãy sử dụng "image/*" để so khớp một hoạt động xử lý bất kỳ loại hình ảnh nào. Mặc dù bạn có thể chia sẻ nhiều loại dữ liệu, nhưng hãy tránh làm việc này vì người nhận sẽ không biết rõ bạn định gửi nội dung gì. Nếu cần gửi nhiều loại, hãy sử dụng "*/*". Ứng dụng nhận sẽ phân tích cú pháp và xử lý dữ liệu của bạn. Ví dụ:
fun shareMultiple(context: Context) { val imageUris: ArrayList<Uri> = arrayListOf( Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1"), Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/2") ) val shareIntent = Intent().apply { action = Intent.ACTION_SEND_MULTIPLE putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris) type = "image/*" } context.startActivity(Intent.createChooser(shareIntent, null)) }
Hãy đảm bảo các đối tượng Uri được cung cấp trỏ đến dữ liệu mà ứng dụng nhận có thể truy cập.
Thêm nội dung đa dạng thức vào bản xem trước văn bản
Kể từ Android 10 (cấp độ API 29), Trang chia sẻ nội dung trong Android sẽ hiển thị bản xem trước của văn bản đang được chia sẻ. Trong một số trường hợp, văn bản được chia sẻ có thể khó hiểu. Hãy cân nhắc việc chia sẻ một URL phức tạp như https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4. Bản xem trước chi tiết hơn có thể giúp người dùng yên tâm về nội dung đang được chia sẻ.
Nếu đang xem trước văn bản, bạn có thể đặt tiêu đề, hình thu nhỏ hoặc cả hai. Thêm nội dung mô tả vào Intent.EXTRA_TITLE trước khi gọi Intent.createChooser() và thêm hình thu nhỏ có liên quan bằng ClipData.
Lưu ý: URI nội dung hình ảnh được cung cấp từ một FileProvider, thường là từ một <cache-path> đã định cấu hình.
Để biết thêm thông tin, hãy xem bài viết Chia sẻ tệp. Hãy nhớ cấp cho Sharesheet các quyền phù hợp để đọc mọi hình ảnh mà bạn muốn dùng làm hình thu nhỏ. Để biết thêm thông tin,
hãy xem Intent.FLAG_GRANT_READ_URI_PERMISSION.
Ví dụ:
fun richContentToTextPreviewShares(context: Context) { val share = Intent.createChooser( Intent().apply { action = 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 = Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/A123456789") flags = Intent.FLAG_GRANT_READ_URI_PERMISSION }, null ) context.startActivity(share) }
Bản xem trước có dạng như sau:
Thêm thao tác tuỳ chỉnh vào trang chia sẻ nội dung
Trên Android 14 (cấp độ API 34) trở lên, ứng dụng có thể thêm thao tác tuỳ chỉnh vào Trang chia sẻ nội dung trong Android.
Các thao tác tuỳ chỉnh được hiển thị dưới dạng biểu tượng thao tác nhỏ ở đầu Trang chia sẻ nội dung trong Android và ứng dụng có thể chỉ định bất kỳ Intent nào làm thao tác được gọi khi người dùng nhấp vào biểu tượng.
Để thêm thao tác tuỳ chỉnh trên Trang chia sẻ nội dung trong Android, trước tiên, hãy tạo một ChooserAction bằng ChooserAction.Builder.
Bạn có thể chỉ định một PendingIntent làm hành động được gọi khi người dùng nhấp vào biểu tượng. Tạo một mảng chứa tất cả các thao tác tuỳ chỉnh và chỉ định mảng đó là EXTRA_CHOOSER_CUSTOM_ACTIONS của Intent chia sẻ.
fun sharesheetCustomActions(context: Context, previewText: String) { val sendIntent = Intent(ACTION_SEND) .setType("text/plain") .putExtra(Intent.EXTRA_TEXT, previewText) val shareIntent = Intent.createChooser(sendIntent, null) val customActions = arrayOf( ChooserAction.Builder( Icon.createWithResource(context, R.drawable.ic_logo), "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) }
Thêm mục tiêu tuỳ chỉnh
Trang chia sẻ nội dung trong Android cho phép bạn chỉ định tối đa hai ý định hoạt động tuỳ chỉnh được liệt kê trước các đề xuất ứng dụng bằng Intent.EXTRA_INITIAL_INTENTS.
Đối với các mục tiêu Chia sẻ trực tiếp (chẳng hạn như cuộc trò chuyện hoặc người liên hệ), hãy xuất bản lối tắt động bằng cách sử dụng
ShortcutManagerCompat
(xem phần Cung cấp mục tiêu Chia sẻ trực tiếp):
Thêm Intent.EXTRA_INITIAL_INTENTS vào
Ý định chia sẻ của bạn sau khi gọi
Intent.createChooser():
val sendIntent = Intent(ACTION_SEND).apply { type = "text/plain" putExtra(Intent.EXTRA_TEXT, previewText) } val customIntent = Intent().apply { component = ComponentName(context.packageName, "${context.packageName}.CustomActivity") } val shareIntent = Intent.createChooser(sendIntent, null).apply { putExtra( Intent.EXTRA_INITIAL_INTENTS, arrayOf(customIntent) ) } context.startActivity(shareIntent)
Hãy thận trọng khi sử dụng tính năng này. Mỗi Intent tuỳ chỉnh mà bạn thêm sẽ làm giảm số lượng đề xuất của hệ thống. Nói chung, hãy tránh
thêm mục tiêu tuỳ chỉnh. Một ví dụ phù hợp thường thấy về việc thêm Intent.EXTRA_INITIAL_INTENTS là cung cấp thêm các thao tác mà người dùng có thể thực hiện đối với nội dung được chia sẻ. Ví dụ: người dùng chia sẻ hình ảnh và Intent.EXTRA_INITIAL_INTENTS được dùng để cho phép họ gửi đường liên kết.
Loại trừ các mục tiêu cụ thể theo thành phần
Bạn có thể loại trừ các mục tiêu cụ thể bằng cách cung cấp Intent.EXTRA_EXCLUDE_COMPONENTS.
Chỉ làm việc này để xoá những mục tiêu mà bạn có quyền kiểm soát. Một trường hợp sử dụng phổ biến là ẩn các mục tiêu chia sẻ của ứng dụng khi người dùng chia sẻ từ trong ứng dụng của bạn, vì ý định của họ có thể là chia sẻ ra bên ngoài ứng dụng.
Thêm Intent.EXTRA_EXCLUDE_COMPONENTS vào ý định sau khi gọi Intent.createChooser():
fun excludeSpecificTargets(context: Context) { val share = Intent.createChooser(Intent(ACTION_SEND), null).apply { // Only use for components you have control over val excludedComponentNames = arrayOf(ComponentName("com.example.android", "ExampleClass")) putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames) } context.startActivity(share) }
Nhận thông tin về việc chia sẻ
Bạn nên biết thời điểm người dùng chia sẻ và mục tiêu họ chọn. Trang chia sẻ nội dung trong Android cho phép bạn lấy thông tin này bằng cách cung cấp ComponentName của các mục tiêu mà người dùng chọn bằng IntentSender.
Trước tiên, hãy tạo một PendingIntent cho BroadcastReceiver và cung cấp IntentSender của nó trong Intent.createChooser():
fun infoAboutSharing(context: Context, requestCode: Int) { var share = Intent(ACTION_SEND) // ... val pi = PendingIntent.getBroadcast( context, requestCode, Intent(context, ShareBroadcastReceiver::class.java), PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) share = Intent.createChooser(share, null, pi.intentSender) context.startActivity(share) }
Nhận lệnh gọi lại trong MyBroadcastReceiver và xem trong Intent.EXTRA_CHOOSER_RESULT:
override fun onReceive(context: Context?, intent: Intent) { val TAG = ShareBroadcastReceiver::class.simpleName val chooserResult: ChooserResult? = IntentCompat.getParcelableExtra( intent, Intent.EXTRA_CHOOSER_RESULT, ChooserResult::class.java, ) chooserResult?.let { Log.i(TAG, "Share callback: isShortcut: ${it.isShortcut}, type: ${typeToString(it.type)}, componentName: ${it.selectedComponent}", ) } ?: Log.i(TAG, "chooserResult is null") }
Để biết thêm thông tin, hãy xem mẫu chia sẻ nền tảng.
Sử dụng trình phân giải ý định của Android
ACTION_SEND trình phân giải ý định.Trình phân giải ý định của Android được dùng hiệu quả nhất khi gửi dữ liệu đến một ứng dụng khác trong một luồng tác vụ được xác định rõ ràng.
Để sử dụng trình phân giải ý định của Android, hãy tạo một ý định và thêm các thành phần bổ sung như khi bạn gọi Trang chia sẻ nội dung trong Android. Tuy nhiên, đừng gọi Intent.createChooser().
Nếu có nhiều ứng dụng đã cài đặt có bộ lọc khớp với ACTION_SEND và loại MIME, thì hệ thống sẽ hiển thị một hộp thoại phân định có tên là trình phân giải ý định cho phép người dùng chọn một mục tiêu để chia sẻ. Nếu một ứng dụng duy nhất khớp, ứng dụng đó sẽ chạy.
Dưới đây là ví dụ về cách sử dụng trình phân giải ý định của Android để gửi văn bản:
fun intentResolver(context: Context) { val sendIntent: Intent = Intent().apply { action = ACTION_SEND putExtra(Intent.EXTRA_TEXT, "This is my text to send.") type = "text/plain" } context.startActivity(sendIntent) }
Tìm hiểu thêm
Để biết thêm thông tin về cách gửi dữ liệu, hãy xem bài viết Ý định và bộ lọc ý định.