รับข้อมูลจากแอปอื่นๆ

แอปสามารถรับข้อมูลจากแอปอื่นๆ ได้เช่นเดียวกับที่ส่งข้อมูลไปยังแอปอื่นๆ ลองนึกถึงวิธีที่ผู้ใช้โต้ตอบกับแอปพลิเคชันของคุณและประเภทข้อมูลที่คุณต้องการรับจากแอปพลิเคชันอื่นๆ ตัวอย่างเช่น แอปพลิเคชันโซเชียลเน็ตเวิร์กอาจสนใจรับเนื้อหาข้อความ เช่น URL ของเว็บที่น่าสนใจจากแอปอื่น

ในแอปที่ใช้ Compose Navigation การรับข้อมูลที่แอปอื่นส่งมาจะมีกระบวนการ 3 ขั้นตอนดังนี้

  1. ประกาศ <intent-filter> ในไฟล์ Manifest: คุณยังคงต้องเพิ่มตัวกรอง Intent ลงในกิจกรรมในไฟล์ AndroidManifest.xml ซึ่งจะบอกระบบปฏิบัติการ Android ว่าแอปพลิเคชันของคุณสามารถรับการดำเนินการที่เฉพาะเจาะจง (เช่น ACTION_SEND) และประเภท MIME (เช่น text/plain) ได้

  2. กำหนด navDeepLink ในกราฟ Compose Navigation โดยแนบ navDeepLink ที่ตรงกับการดำเนินการและประเภท MIME โดยตรงกับปลายทาง Composable ที่ควรแสดงเนื้อหา NavController จะสกัดกั้น Intent ขาเข้าโดยอัตโนมัติและนำทางผู้ใช้ไปยังหน้าจอนั้นโดยตรง

  3. ดึงเพย์โหลดข้อมูลขาเข้า: ในหน้าจอปลายทาง ให้เข้าถึง Intent Extras (เช่น EXTRA_TEXT หรือ EXTRA_STREAM) เพื่อดึงเนื้อหาที่แชร์และอัปเดตสถานะ UI

เป้าหมายการแชร์โดยตรงคือ Deep Link ไปยังกิจกรรมที่เฉพาะเจาะจงภายในแอปของคุณ ซึ่งมักจะแสดงถึงบุคคลหรือกลุ่ม และ Android Sharesheet จะแสดงเป้าหมายดังกล่าว ตัวอย่างเช่น แอปรับส่งข้อความสามารถระบุเป้าหมายการแชร์โดยตรงสำหรับบุคคลที่ทำ Deep Link ไปยังการสนทนากับบุคคลนั้นโดยตรง ดูวิธีการโดยละเอียดได้ที่ระบุเป้าหมายการแชร์โดยตรง

รองรับประเภท MIME

ตามหลักการแล้ว แอปต้องรับประเภท MIME ได้หลากหลายที่สุดเท่าที่จะเป็นไปได้ ตัวอย่างเช่น แอปรับส่งข้อความที่ออกแบบมาเพื่อส่งข้อความ รูปภาพ และวิดีโอควรจะรองรับการรับ text/*, image/* และ video/* ต่อไปนี้คือประเภท MIME ที่พบบ่อยสำหรับการส่งและรับข้อมูลใน Android

ผู้รับลงทะเบียนเพื่อรับ ผู้ส่งส่ง
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

สร้างเป้าหมายการแชร์ที่ยอดเยี่ยม

เมื่อผู้ใช้แตะเป้าหมายการแชร์ที่เชื่อมโยงกับกิจกรรมหนึ่งๆ ให้ผู้ใช้ยืนยันและแก้ไขเนื้อหาที่แชร์ก่อนที่แอปจะใช้เนื้อหานั้น ซึ่งสำคัญอย่างยิ่งสำหรับข้อมูลข้อความ

รับข้อมูลในแอป

การรับข้อมูลที่แชร์ในแอปโดยใช้ Compose เกี่ยวข้องกับการประกาศตัวกรอง Intent ในไฟล์ Manifest, การกำหนดเส้นทาง Intent ขาเข้าไปยังหน้าจอที่เหมาะสมด้วย Deep Link และการดึงเพย์โหลดจาก Intent เพื่ออัปเดต UI

อัปเดตไฟล์ Manifest

ตัวกรอง Intent จะแจ้งให้ระบบทราบว่าคอมโพเนนต์ของแอปยอมรับ Intent ใดบ้าง คุณสร้างตัวกรอง Intent เพื่อรับ Intent ที่มีการดำเนินการนี้ได้ในลักษณะเดียวกับที่สร้าง Intent ด้วยการดำเนินการ ACTION_SEND ในบทเรียนการส่งข้อมูลไปยังแอปอื่นๆ คุณกำหนดตัวกรอง 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 Resolver หากผู้ใช้เลือกแอปของคุณ ระบบจะเริ่มกิจกรรมที่เกี่ยวข้อง (.ui.MyActivity ในตัวอย่างก่อนหน้า) จากนั้นคุณจะต้องจัดการเนื้อหาอย่างเหมาะสมภายในโค้ดและ UI ของคุณ

ใน Compose Navigation ให้แนบ navDeepLink โดยตรงกับปลายทาง Composable ที่ควรแสดงเนื้อหา เมื่อแอปอื่นแชร์ข้อมูลที่ตรงกับตัวกรอง Intent ของคุณ Compose Navigation จะกำหนดเส้นทางให้ผู้ใช้ไปยังปลายทางนี้โดยตรง

navDeepLink จะจับคู่กับการดำเนินการและประเภท MIME ของ Intent ขาเข้าเพื่อไปยังหน้าจอปลายทางที่ถูกต้อง เมื่ออยู่ที่ปลายทางนั้น ตัวแฮนเดิลจะตรวจสอบ Intent เพื่อระบุเพย์โหลดที่ได้รับ (เช่น รูปภาพเดียวเทียบกับหลายรูปภาพ) และดึงข้อมูลเพิ่มเติมที่เกี่ยวข้อง

จัดการเนื้อหาที่เข้ามา

หากต้องการดึงเนื้อหาที่ส่งโดย Intent ให้อ่านกิจกรรมปัจจุบันจาก LocalActivity.current ภายใน Composable จากนั้นตรวจสอบ Intent เพื่อพิจารณาสิ่งที่ต้องทำต่อไป หากกิจกรรมนี้สามารถเริ่มต้นจากส่วนอื่นๆ ของระบบได้ (เช่น Launcher) ให้พิจารณาเรื่องนี้เมื่อตรวจสอบ Intent

โปรดตรวจสอบข้อมูลขาเข้าอย่างละเอียด เนื่องจากอาจมีการตั้งค่าประเภท MIME ที่ไม่ถูกต้อง หรือรูปภาพที่ส่งอาจมีขนาดใหญ่เกินไป ประมวลผลข้อมูลไบนารีหรือการดำเนินการ I/O ที่หนักหน่วง (เช่น การถอดรหัสรูปภาพขนาดใหญ่หรือการเขียนไฟล์) แบบไม่พร้อมกันโดยใช้โครูทีน (เช่น 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 (เช่น 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 Resolver ซึ่งทั้ง 2 รายการนี้จะกำหนดไว้ในไฟล์ Manifest คุณสามารถตั้งค่าป้ายกำกับกิจกรรมหรือตัวกรอง Intent เพื่อให้บริบทเพิ่มเติมได้

ตั้งแต่ Android 10 (API ระดับ 29) เป็นต้นไป Android Sharesheet จะใช้เฉพาะไอคอนที่ตั้งค่าไว้ในไฟล์ Manifest บนแท็ก application Android จะไม่สนใจไอคอนที่ตั้งค่าในแท็ก intent-filter และ activity

รับข้อมูลอย่างละเอียด

แม้ว่า Intent ACTION_SEND จะช่วยให้รับข้อมูลจาก Android Sharesheet และ Intent Resolver ได้ในระดับกิจกรรมหรือการนําทาง แต่แอปก็สามารถรับข้อมูลอย่างละเอียด (เช่น รูปภาพ วิดีโอ ไฟล์เสียง และข้อความที่มีการจัดรูปแบบ) ผ่านการโต้ตอบกับ UI โดยตรงได้ด้วย กลไกเหล่านี้ ได้แก่

  • การวางจากคลิปบอร์ด (เมนูแตะค้างไว้)
  • การแทรกสื่อโดยตรงจากแป้นพิมพ์เสมือน (IME) เช่น สติกเกอร์หรือ GIF
  • การลากและวางเนื้อหาจากแอปอื่นในโหมดหลายหน้าต่างหรือโหมดแยกหน้าจอ

ใน UI แบบอิงตามมุมมอง Android 12 (ระดับ API 31) และ AndroidX Core 1.7 มี API OnReceiveContentListener แบบรวม Listener นี้จะรวมการจัดการเนื้อหาจากคลิปบอร์ด แป้นพิมพ์ และการลากและวางไว้ใน Callback เดียว ดูวิธีการโดยละเอียดเกี่ยวกับการใช้ฟีเจอร์นี้ใน Views ได้ที่รับข้อมูลอย่างละเอียด

ใน Jetpack Compose คุณสามารถจัดการการรับข้อมูลอย่างละเอียดที่แทรกลงในคอมโพเนนต์ UI (เช่น ช่องข้อความ) โดยใช้ตัวปรับแต่ง Modifier.contentReceiver หรือตัวปรับแต่งการลากและวาง