Android ใช้ Intent และส่วนเสริมที่เกี่ยวข้องเพื่อให้ผู้ใช้แชร์ข้อมูลได้อย่างรวดเร็ว โดยใช้แอปโปรด
Android มี 2 วิธีให้ผู้ใช้แชร์ข้อมูลระหว่างแอป
- Android Sharesheet ออกแบบมาเพื่อส่งเนื้อหาภายนอกแอปและ/หรือส่งไปยังผู้ใช้รายอื่นโดยตรงเป็นหลัก เช่น การแชร์ URL กับเพื่อน
- ตัวแก้ไข Intent ของ Android เหมาะที่สุดสำหรับการส่งข้อมูลไปยัง ขั้นตอนถัดไปของงานที่กำหนดไว้อย่างดี เช่น การเปิด PDF จากแอปของคุณและอนุญาตให้ผู้ใช้ เลือกโปรแกรมอ่านที่ต้องการ
เมื่อสร้างความตั้งใจ คุณจะระบุการกระทำที่ต้องการให้ความตั้งใจนั้นทำ
Android ใช้การดำเนินการ ACTION_SEND
เพื่อส่งข้อมูลจากกิจกรรมหนึ่งไปยังอีกกิจกรรมหนึ่ง
แม้จะอยู่ข้ามขอบเขตของกระบวนการก็ตาม คุณต้องระบุ
ข้อมูลและประเภทของข้อมูล ระบบจะระบุกิจกรรมที่เข้ากันได้โดยอัตโนมัติ
ซึ่งรับข้อมูลได้ และแสดงต่อผู้ใช้ ในกรณีของตัวแก้ไข Intent
หากมีเพียงกิจกรรมเดียวที่จัดการ Intent ได้ กิจกรรมนั้นจะเริ่มทันที
เหตุผลที่ควรใช้ Android Sharesheet
เราขอแนะนำเป็นอย่างยิ่งให้ใช้ Android Sharesheet เพื่อสร้างความสอดคล้องให้แก่ผู้ใช้ในแอปต่างๆ อย่าแสดงรายการเป้าหมายการแชร์ของแอปเองหรือสร้าง รูปแบบชีตการแชร์ของคุณเอง
Android Sharesheet ช่วยให้ผู้ใช้แชร์ข้อมูลกับบุคคลที่เหมาะสม พร้อมคำแนะนำเกี่ยวกับแอปที่เกี่ยวข้องได้ด้วยการแตะเพียงครั้งเดียว ชีตการแชร์สามารถแนะนำเป้าหมายที่โซลูชันที่กำหนดเองใช้ไม่ได้ และใช้การจัดอันดับที่สอดคล้องกัน เนื่องจากชีตการแชร์สามารถพิจารณาข้อมูลเกี่ยวกับกิจกรรมในแอปและกิจกรรมของผู้ใช้ ซึ่งมีเฉพาะในระบบเท่านั้น
นอกจากนี้ Android Sharesheet ยังมีฟีเจอร์ที่มีประโยชน์มากมายสำหรับนักพัฒนาแอปด้วย ตัวอย่างเช่น คุณสามารถทำสิ่งต่อไปนี้ได้
- ดูว่าผู้ใช้แชร์เมื่อใดและแชร์ไปที่ใด
- เพิ่ม
ChooserTargetและเป้าหมายแอปที่กำหนดเอง - แสดงตัวอย่างเนื้อหา Rich Text ตั้งแต่ Android 10 (ระดับ API 29) เป็นต้นไป
- ยกเว้นเป้าหมายที่ตรงกับชื่อคอมโพเนนต์ที่เฉพาะเจาะจง
ใช้ชีตการแชร์ของ Android
สำหรับการแชร์ทุกประเภท ให้สร้าง Intent และตั้งค่าการดำเนินการเป็น
Intent.ACTION_SEND
หากต้องการแสดง Android Sharesheet ให้เรียกใช้
Intent.createChooser()
โดยส่งออบเจ็กต์ Intent ไปให้
โดยจะแสดงผล Intent เวอร์ชันที่แสดง Android Sharesheet เสมอ
ส่งเนื้อหาข้อความ
การใช้งาน Android Sharesheet ที่ตรงไปตรงมาและพบได้บ่อยที่สุดคือการส่งเนื้อหาข้อความจากกิจกรรมหนึ่งไปยังอีกกิจกรรมหนึ่ง ตัวอย่างเช่น เบราว์เซอร์ส่วนใหญ่สามารถแชร์ URL ของหน้าที่แสดงอยู่ในปัจจุบันเป็นข้อความกับแอปอื่นได้ ซึ่งมีประโยชน์ในการแชร์บทความหรือเว็บไซต์กับเพื่อนๆ ผ่านอีเมลหรือโซเชียลเน็ตเวิร์ก ตัวอย่างวิธีดำเนินการมีดังนี้
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) }
คุณเลือกเพิ่มข้อมูลเพิ่มเติมได้ เช่น ผู้รับอีเมล
(EXTRA_EMAIL,
EXTRA_CC,
EXTRA_BCC)
หัวเรื่องอีเมล
(EXTRA_SUBJECT) เป็นต้น
หมายเหตุ: แอปอีเมลบางแอป เช่น Gmail คาดหวังว่าจะมี
String[]สำหรับส่วนเสริมต่างๆ เช่น
EXTRA_EMAILและEXTRA_CC ใช้
putExtra(String, String[])
เพื่อเพิ่มสิ่งเหล่านี้ลงในเจตนา
ส่งเนื้อหาไบนารี
แชร์ข้อมูลไบนารีโดยใช้การดำเนินการ ACTION_SEND
ตั้งค่าประเภท MIME ที่เหมาะสมและวาง URI ไปยังข้อมูลในส่วน <extra>
EXTRA_STREAM ดังที่แสดงในตัวอย่างต่อไปนี้
โดยทั่วไปจะใช้เพื่อแชร์รูปภาพ แต่ก็ใช้เพื่อแชร์เนื้อหาไบนารีประเภทใดก็ได้
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)) }
แอปพลิเคชันที่รับต้องมีสิทธิ์เข้าถึงข้อมูลที่ Uri
ชี้ไป ซึ่งทำได้ 2 วิธีที่แนะนำดังนี้
- จัดเก็บข้อมูลใน
ContentProviderของคุณเอง และตรวจสอบว่าแอปอื่นๆ มีสิทธิ์ที่ถูกต้องในการเข้าถึงผู้ให้บริการ กลไกที่แนะนำสำหรับการให้สิทธิ์เข้าถึงคือการใช้สิทธิ์ต่อ URI ซึ่งเป็นสิทธิ์ชั่วคราวและให้สิทธิ์เข้าถึงแก่แอปพลิเคชันที่รับเท่านั้น หากต้องการสร้างContentProviderแบบนี้ ให้ใช้คลาสตัวช่วยFileProvider - ใช้ระบบ
MediaStoreMediaStoreมีไว้สำหรับประเภท MIME ของวิดีโอ เสียง และรูปภาพเป็นหลัก อย่างไรก็ตาม ตั้งแต่ Android 3.0 (API ระดับ 11) เป็นต้นไป ก็สามารถจัดเก็บประเภทที่ไม่ใช่สื่อได้ด้วย ดูข้อมูลเพิ่มเติมได้ที่MediaStore.Filesคุณสามารถแทรกไฟล์ลงในMediaStoreได้โดยใช้scanFile()หลังจากนั้นระบบจะส่งcontent://Uriรูปแบบที่เหมาะสำหรับการแชร์ไปยังonScanCompleted()การเรียกกลับที่ระบุ โปรดทราบว่าเมื่อเพิ่มลงในระบบMediaStoreแล้ว แอปใดก็ตามในอุปกรณ์จะเข้าถึงเนื้อหาได้
ใช้ประเภท MIME ที่ถูกต้อง
ระบุประเภท MIME ที่เฉพาะเจาะจงที่สุดสำหรับข้อมูลที่คุณ
ส่ง เช่น ใช้ text/plain เมื่อแชร์ข้อความธรรมดา ต่อไปนี้คือประเภท MIME ที่พบบ่อยเมื่อส่งข้อมูลใน Android
| ตัวรับสัญญาณลงทะเบียนสำหรับ | ผู้ส่งส่ง |
|---|---|
text/* |
|
`image/*` |
|
video/* |
|
| นามสกุลไฟล์ที่รองรับ | application/pdf |
ดูข้อมูลเพิ่มเติมเกี่ยวกับประเภท MIME ได้ที่รีจิสทรีอย่างเป็นทางการของประเภทสื่อ MIME ของ IANA
Android Sharesheet อาจแสดงตัวอย่างเนื้อหา ทั้งนี้ขึ้นอยู่กับประเภท MIME ที่ระบุ ฟีเจอร์เวอร์ชันตัวอย่างบางอย่างใช้ได้กับบางประเภทเท่านั้น
แชร์เนื้อหาหลายรายการ
หากต้องการแชร์เนื้อหาหลายรายการ ให้ใช้การดำเนินการ ACTION_SEND_MULTIPLE
ร่วมกับรายการ URI ที่ชี้ไปยังเนื้อหา ประเภท MIME จะแตกต่างกันไปตาม
ส่วนผสมของเนื้อหาที่คุณแชร์ เช่น หากแชร์รูปภาพ JPEG 3 รูป คุณจะใช้ประเภท
"image/jpg" หากใช้รูปภาพหลายประเภท ให้ใช้ "image/*" เพื่อจับคู่กิจกรรมที่จัดการรูปภาพทุกประเภท แม้ว่าคุณจะแชร์ไฟล์หลายประเภทพร้อมกันได้ แต่เราไม่ขอแนะนำให้ทำเช่นนี้ เนื่องจากผู้รับอาจไม่ทราบว่าคุณต้องการส่งไฟล์ใด
หากจำเป็นต้องส่งหลายประเภท ให้ใช้
"*/*" แอปพลิเคชันที่รับจะเป็นผู้แยกวิเคราะห์
และประมวลผลข้อมูล ตัวอย่าง
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)) }
ตรวจสอบว่าออบเจ็กต์ Uri ที่ระบุชี้
ไปยังข้อมูลที่แอปพลิเคชันที่รับเข้าถึงได้
เพิ่มข้อมูลอย่างละเอียดลงในตัวอย่างข้อความ
ตั้งแต่ Android 10 (ระดับ API 29) เป็นต้นไป Android Sharesheet จะแสดงตัวอย่างข้อความที่กำลังแชร์ ในบางกรณี ข้อความที่แชร์อาจเข้าใจยาก ลองแชร์ URL ที่ซับซ้อน เช่น https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4 ตัวอย่างที่สมบูรณ์ยิ่งขึ้น
จะช่วยให้ผู้ใช้มั่นใจได้ว่ากำลังแชร์อะไร
หากดูตัวอย่างข้อความ คุณสามารถตั้งชื่อ รูปภาพปก หรือทั้ง 2 อย่างได้ เพิ่มคำอธิบายใน
Intent.EXTRA_TITLE ก่อนเรียกใช้ Intent.createChooser() และเพิ่ม
ภาพปกที่เกี่ยวข้องโดยใช้ ClipData
หมายเหตุ: URI เนื้อหาของรูปภาพมาจาก
FileProvider ซึ่งมักมาจาก <cache-path> ที่กำหนดค่าไว้
ดูข้อมูลเพิ่มเติมได้ที่การแชร์ไฟล์ อย่าลืมให้สิทธิ์ที่เหมาะสมแก่
ชีตการแชร์เพื่ออ่านรูปภาพที่คุณต้องการใช้เป็นภาพปก ดูข้อมูลเพิ่มเติมได้ที่ Intent.FLAG_GRANT_READ_URI_PERMISSION
ตัวอย่าง
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) }
ตัวอย่างจะมีลักษณะดังนี้
เพิ่มการกระทำที่กำหนดเองลงในชีตการแชร์
ใน Android 14 (ระดับ API 34) ขึ้นไป แอปจะเพิ่มการดำเนินการที่กำหนดเองลงใน Android Sharesheet ได้
การดำเนินการที่กำหนดเองจะแสดงเป็นไอคอนการดำเนินการขนาดเล็กที่ด้านบนของชีตการแชร์ของ Android และแอป
สามารถระบุ Intent ใดก็ได้เป็นการดำเนินการที่เรียกใช้เมื่อคลิกไอคอน
หากต้องการเพิ่มการดำเนินการที่กำหนดเองใน Android Sharesheet ให้สร้าง
ChooserAction
ก่อนโดยใช้
ChooserAction.Builder
คุณระบุ PendingIntent เป็นการดำเนินการที่เรียกใช้เมื่อคลิกไอคอนได้ สร้าง
อาร์เรย์ที่มีการดำเนินการที่กำหนดเองทั้งหมด แล้วระบุเป็น
EXTRA_CHOOSER_CUSTOM_ACTIONS
ของการแชร์ Intent
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) }
เพิ่มเป้าหมายที่กำหนดเอง
ชีตการแชร์ของ Android ช่วยให้คุณระบุออบเจ็กต์ ChooserTarget ได้สูงสุด 2 รายการซึ่งจะแสดงก่อนทางลัดการแชร์และเป้าหมายตัวเลือกที่โหลดจาก ChooserTargetServices นอกจากนี้ คุณยังระบุ Intent ได้สูงสุด 2 รายการที่ชี้ไปยังกิจกรรมที่แสดงก่อนคำแนะนำเกี่ยวกับแอป
เพิ่ม Intent.EXTRA_CHOOSER_TARGETS และ Intent.EXTRA_INITIAL_INTENTS ไปยัง
Intent การแชร์หลังจากเรียกใช้
Intent.createChooser()
val share = Intent.createChooser(shareIntent, null).apply { putExtra( Intent.EXTRA_CHOOSER_TARGETS, arrayOf(chooserTargetJessica, chooserTargetSpyros) ) putExtra( Intent.EXTRA_INITIAL_INTENTS, arrayOf(intentTargetNearbyShare, intentTargetMaps) ) }
โปรดใช้ฟีเจอร์นี้ด้วยความระมัดระวัง Intent
และ ChooserTarget ที่กำหนดเองทุกรายการที่คุณเพิ่มจะลดจำนวนที่ระบบแนะนำ โดยทั่วไปเรา
ไม่แนะนำให้เพิ่มเป้าหมายที่กำหนดเอง ตัวอย่างที่เหมาะสมทั่วไปของการเพิ่ม
Intent.EXTRA_INITIAL_INTENTS คือการให้การดำเนินการเพิ่มเติมที่ผู้ใช้สามารถทำกับเนื้อหาที่แชร์
ได้ ตัวอย่างเช่น ผู้ใช้แชร์รูปภาพและใช้ Intent.EXTRA_INITIAL_INTENTS เพื่อ
อนุญาตให้ผู้ใช้ส่งลิงก์แทน ตัวอย่างที่เหมาะสมทั่วไปของการเพิ่ม Intent.EXTRA_CHOOSER_TARGETS
คือการเปิดเผยบุคคลหรืออุปกรณ์ที่เกี่ยวข้องซึ่งแอปของคุณมีให้
ยกเว้นเป้าหมายที่เฉพาะเจาะจงตามคอมโพเนนต์
คุณยกเว้นเป้าหมายที่เฉพาะเจาะจงได้โดยระบุ Intent.EXTRA_EXCLUDE_COMPONENTS
โปรดดำเนินการนี้เพื่อนำเป้าหมายที่คุณควบคุมได้ออกเท่านั้น กรณีการใช้งานทั่วไปคือการซ่อนเป้าหมายการแชร์ของแอปเมื่อผู้ใช้แชร์จากภายในแอป เนื่องจากมีแนวโน้มที่ผู้ใช้จะแชร์ภายนอกแอป
เพิ่ม Intent.EXTRA_EXCLUDE_COMPONENTS ในความตั้งใจของคุณหลังจากเรียกใช้ 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) }
ดูข้อมูลเกี่ยวกับการแชร์
การทราบว่าผู้ใช้แชร์เมื่อใดและเลือกเป้าหมายใดอาจมีประโยชน์
ชีตการแชร์ของ Android ช่วยให้คุณได้รับข้อมูลนี้โดยการระบุ ComponentName ของ
เป้าหมายที่ผู้ใช้เลือกโดยใช้ IntentSender
ก่อนอื่น ให้สร้าง PendingIntent สำหรับ BroadcastReceiver แล้วระบุ
IntentSender ใน 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) }
รับการติดต่อกลับในอีก MyBroadcastReceiver และดูใน
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") }
ดูข้อมูลเพิ่มเติมได้ที่ตัวอย่างส่วนแบ่งแพลตฟอร์ม
ใช้ตัวแก้ไข Intent ของ Android
ACTION_SENDตัวแก้ไขความตั้งใจตัวแก้ไข Intent ของ Android จะใช้ได้ดีที่สุดเมื่อส่งข้อมูลไปยังแอปอื่นเป็นส่วนหนึ่งของโฟลว์งานที่กำหนดไว้อย่างดี
หากต้องการใช้ตัวแก้ไข Intent ของ Android ให้สร้าง Intent และเพิ่มส่วนเสริมเหมือนกับที่คุณใช้เรียก
ชีตการแชร์ของ Android แต่อย่าโทรหา
Intent.createChooser()
หากมีแอปพลิเคชันที่ติดตั้งไว้หลายรายการซึ่งมีตัวกรองที่ตรงกับ
ACTION_SEND
และประเภท MIME ระบบจะแสดงกล่องโต้ตอบการแยกความกำกวมที่เรียกว่าตัวแก้ไข Intent
ซึ่งช่วยให้ผู้ใช้เลือกเป้าหมายที่จะแชร์ได้ หากมีแอปพลิเคชันเดียวที่ตรงกัน ระบบจะเรียกใช้แอปพลิเคชันนั้น
ตัวอย่างวิธีใช้ตัวแก้ไข Intent ของ Android เพื่อส่งข้อความมีดังนี้
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) }
ดูข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการส่งข้อมูลได้ที่Intent และ Intent Filter