แอปสามารถส่งข้อมูลไปยังแอปอื่นๆ ได้ เช่นเดียวกับที่แอปสามารถรับข้อมูลจากแอปอื่นๆ ได้ ลองนึกถึงวิธีที่ผู้ใช้โต้ตอบกับแอปพลิเคชันของคุณและประเภทข้อมูลที่คุณต้องการรับจากแอปพลิเคชันอื่นๆ ตัวอย่างเช่น แอปพลิเคชันเครือข่ายสังคมอาจสนใจรับเนื้อหาข้อความ เช่น URL ของเว็บที่น่าสนใจ จากแอปอื่น
ในแอปที่ใช้ Compose Navigation การรับข้อมูลที่แอปอื่นส่งมาเป็นกระบวนการ 3 ขั้นตอน ดังนี้
ประกาศ
<intent-filter>ในไฟล์ Manifest: คุณยังคงต้องเพิ่มตัวกรอง Intent ลงในกิจกรรมในไฟล์AndroidManifest.xmlซึ่งจะบอกระบบปฏิบัติการ Android ว่าแอปพลิเคชันของคุณสามารถรับการดำเนินการที่เฉพาะเจาะจง (เช่นACTION_SEND) และประเภท MIME (เช่นtext/plain) ได้กำหนด
navDeepLinkในกราฟ Compose Navigation: แนบnavDeepLinkที่ตรงกับการดำเนินการและประเภท MIME กับปลายทางที่สร้างได้ (Composable Destination) ซึ่งควรแสดงเนื้อหาโดยตรงNavControllerจะสกัดกั้น Intent ขาเข้าและนำทางผู้ใช้ไปยังหน้าจอนั้นโดยอัตโนมัติแยกเพย์โหลดข้อมูลขาเข้า: ในหน้าจอปลายทาง ให้เข้าถึงส่วนเพิ่มเติมของ Intent (เช่น
EXTRA_TEXTหรือEXTRA_STREAM) เพื่อดึงเนื้อหาที่แชร์และอัปเดตสถานะ UI
เป้าหมายการแชร์โดยตรงคือ Deep Link ไปยังกิจกรรมที่เฉพาะเจาะจงภายในแอป โดยมักจะแสดงถึงบุคคลหรือกลุ่ม และ Android Sharesheet จะแสดงเป้าหมายเหล่านี้ ตัวอย่างเช่น แอปรับส่งข้อความสามารถระบุเป้าหมายการแชร์โดยตรงสำหรับบุคคลหนึ่งๆ ซึ่งเป็น Deep Link ที่นำไปยังการสนทนากับบุคคลนั้นโดยตรง ดูวิธีการโดยละเอียดได้ที่ระบุเป้าหมายการแชร์โดยตรง
ประเภท MIME ที่รองรับ
แอปควรรับประเภท MIME ได้หลากหลายที่สุดเท่าที่จะเป็นไปได้
ตัวอย่างเช่น แอปรับส่งข้อความที่ออกแบบมาเพื่อส่งข้อความ รูปภาพ และวิดีโอควรจะรองรับการรับ text/*, image/* และ video/* ต่อไปนี้คือประเภท MIME ทั่วไปบางประเภทสำหรับการส่งและรับข้อมูลใน Android
| ผู้รับลงทะเบียนเพื่อรับ | ผู้ส่งส่ง |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| นามสกุลไฟล์ที่รองรับ | application/pdf |
ดูรีจิสทรีอย่างเป็นทางการของประเภทสื่อ MIME ของ IANA
สร้างเป้าหมายการแชร์ที่ยอดเยี่ยม
เมื่อผู้ใช้แตะเป้าหมายการแชร์ที่เชื่อมโยงกับกิจกรรมที่เฉพาะเจาะจง ให้ผู้ใช้ยืนยันและแก้ไขเนื้อหาที่แชร์ได้ก่อนที่แอปของคุณจะใช้เนื้อหานั้น ซึ่งมีความสำคัญอย่างยิ่งสำหรับข้อมูลข้อความ
รับข้อมูลในแอป
การรับข้อมูลที่แชร์ในแอปที่ใช้ Compose เกี่ยวข้องกับการประกาศตัวกรอง Intent ในไฟล์ Manifest, การกำหนดเส้นทาง Intent ขาเข้าไปยังหน้าจอที่เหมาะสมด้วย Deep Link และการแยกเพย์โหลดออกจาก Intent เพื่ออัปเดต UI
อัปเดตไฟล์ Manifest
ตัวกรอง Intent จะแจ้งให้ระบบทราบว่าคอมโพเนนต์ของแอปยอมรับ Intent ใดบ้าง คุณสร้างตัวกรอง Intent เพื่อรับ
Intent ที่มีการดำเนินการนี้ในลักษณะเดียวกับวิธีที่คุณสร้าง Intent ด้วยการดำเนินการ ACTION_SEND ในบทเรียนSending
data to other apps คุณกำหนดตัวกรอง Intent ในไฟล์ Manifest โดยใช้
<intent-filter> องค์ประกอบ ตัวอย่างเช่น หากแอปของคุณจัดการการรับเนื้อหาข้อความ ไฟล์ Manifest ที่มีรูปภาพอย่างน้อย 1 รูปภาพทุกประเภทจะมีลักษณะคล้ายกับข้อมูลโค้ดต่อไปนี้
<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>
เมื่อแอปอื่นพยายามแชร์สิ่งเหล่านี้โดยการสร้าง Intent และส่งไปยัง startActivity() แอปพลิเคชันของคุณจะแสดงเป็นตัวเลือกใน Android Sharesheet หรือตัวแก้ปัญหา Intent หากผู้ใช้เลือกแอปของคุณ ระบบจะเริ่มกิจกรรมที่เกี่ยวข้อง (.ui.MyActivity ในตัวอย่างก่อนหน้า) จากนั้นคุณต้องจัดการเนื้อหาอย่างเหมาะสมภายในโค้ดและ UI
กำหนด Deep Link ในกราฟการนำทาง
ใน Compose Navigation ให้แนบ navDeepLink กับปลายทางที่สร้างได้ (Composable Destination) ซึ่งควรแสดงเนื้อหาโดยตรง เมื่อแอปอื่นแชร์ข้อมูลที่ตรงกับตัวกรอง Intent ของคุณ Compose Navigation จะนำทางผู้ใช้ไปยังปลายทางนี้โดยตรง
composable( route = "incoming_share", deepLinks = listOf( navDeepLink { action = Intent.ACTION_SEND mimeType = "text/plain" }, navDeepLink { action = Intent.ACTION_SEND mimeType = "image/*" }, navDeepLink { action = Intent.ACTION_SEND_MULTIPLE mimeType = "image/*" } ) ) { SharesheetHandler() }
navDeepLink จะจับคู่การดำเนินการและประเภท MIME ของ Intent ขาเข้าเพื่อไปยังหน้าจอปลายทางที่ถูกต้อง เมื่ออยู่ในปลายทางนั้น ตัวจัดการจะตรวจสอบ Intent เพื่อกำหนดว่าได้รับเพย์โหลดใด (เช่น รูปภาพเดียวเทียบกับรูปภาพหลายรูป) และแยกส่วนเพิ่มเติมที่เกี่ยวข้อง
จัดการเนื้อหาขาเข้า
หากต้องการดึงเนื้อหาที่ส่งโดย Intent ให้อ่านกิจกรรมปัจจุบันจาก LocalActivity.current ภายในส่วนที่สร้างได้ (Composable) จากนั้นตรวจสอบ Intent เพื่อกำหนดสิ่งที่ต้องทำต่อไป หากกิจกรรมนี้สามารถเริ่มต้นจากส่วนอื่นๆ ของระบบ (เช่น Launcher) ให้พิจารณาเรื่องนี้เมื่อตรวจสอบ Intent
ตรวจสอบข้อมูลขาเข้าอย่างละเอียดเป็นพิเศษ เนื่องจากอาจมีการตั้งค่าประเภท MIME ที่ไม่ถูกต้อง หรือรูปภาพที่ส่งอาจมีขนาดใหญ่มาก ประมวลผลข้อมูลไบนารีหรือการดำเนินการ I/O ที่ซับซ้อน (เช่น การถอดรหัสรูปภาพขนาดใหญ่หรือการเขียนไฟล์) แบบไม่พร้อมกันโดยใช้ Coroutine (เช่น Dispatchers.IO) แทนที่จะใช้ในเธรด 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 } }
เมื่อแยกข้อมูลไบนารีหรือ URI ออกจากส่วนเพิ่มเติมของ Intent (เช่น EXTRA_STREAM) ให้ใช้ IntentCompat.getParcelableExtra() หรือ IntentCompat.getParcelableArrayListExtra() จากไลบรารี AndroidX Core ดังที่แสดงในฟังก์ชัน handleSendImage และ handleSendMultipleImages ก่อนหน้า Android 13 (ระดับ API 33) เลิกใช้งานเมธอด Intent.getParcelableExtra(String) ที่ไม่มีพารามิเตอร์เพื่อสนับสนุนเมธอดที่ปลอดภัยตามประเภทซึ่งใช้ประเภทคลาสที่คาดไว้
การอัปเดต UI หลังจากได้รับข้อมูลอาจทำได้ง่ายๆ เพียงแค่อัปเดต
สถานะเพื่อป้อนข้อมูลใน TextField หรือซับซ้อนถึงขั้นใช้ตัวกรอง
กับรูปภาพ แอปของคุณจะเป็นผู้กำหนดสิ่งที่เกิดขึ้นต่อไป
การแชร์ URL ของภาพหน้าจอ
เมื่อถ่ายภาพหน้าจอ คุณสามารถแชร์ภาพหน้าจอและ URL ที่เชื่อมโยงได้
ซึ่งจะมอบประสบการณ์การใช้งานที่ดียิ่งขึ้น เมื่อได้รับ URL ให้ตรวจสอบว่าได้รับฟิลด์ EXTRA_TEXT จาก Intent ดังที่แสดงในตัวอย่างต่อไปนี้
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 และตัวแก้ปัญหา Intent ซึ่งทั้ง 2 อย่างนี้กำหนดไว้ในไฟล์ Manifest คุณสามารถตั้งค่าป้ายกำกับกิจกรรมหรือตัวกรอง Intent เพื่อให้บริบทเพิ่มเติมได้
ตั้งแต่ Android 10 (ระดับ API 29) เป็นต้นไป Android Sharesheet จะใช้เฉพาะไอคอนที่ตั้งค่าไว้ในไฟล์ Manifest ในแท็ก application Android จะไม่สนใจไอคอนที่ตั้งค่าไว้ในแท็ก intent-filter และ activity
รับข้อมูลอย่างละเอียด
แม้ว่า Intent ACTION_SEND จะช่วยให้รับข้อมูลจากแผ่นแชร์ของ Android และตัวแก้ปัญหา Intent ได้ในระดับกิจกรรมหรือการนำทาง แต่แอปยังรับเนื้อหาอย่างละเอียด (เช่น รูปภาพ วิดีโอ ไฟล์เสียง และข้อความที่มีสไตล์) ผ่านการโต้ตอบ UI โดยตรงได้ด้วย กลไกเหล่านี้ประกอบด้วย
- การวางจากคลิปบอร์ด (เมนูแตะค้างไว้)
- การแทรกสื่อจากแป้นพิมพ์เสมือน (IME) โดยตรง เช่น สติกเกอร์หรือ GIF
- การลากและวางเนื้อหาจากแอปอื่นในโหมดหลายหน้าต่างหรือโหมดแยกหน้าจอ
ใน UI ที่อิงตาม View, Android 12 (ระดับ API 31) และ AndroidX Core 1.7 ได้เปิดตัว OnReceiveContentListener API แบบรวม Listener นี้จะรวมการจัดการเนื้อหาจากคลิปบอร์ด แป้นพิมพ์ และการลากและวางไว้ในการเรียกกลับเดียว ดูวิธีการโดยละเอียดเกี่ยวกับการใช้
Listener นี้ใน View ได้ที่ รับข้อมูลอย่างละเอียด
ใน Jetpack Compose คุณสามารถจัดการการรับเนื้อหาอย่างละเอียดที่แทรกลงในคอมโพเนนต์ UI (เช่น ช่องข้อความ) ได้โดยใช้ตัวปรับแต่ง
Modifier.contentReceiver หรือ
ตัวปรับแต่งการลากและวาง