เอกสารนี้แสดงกรณีการใช้งานทั่วไปหลายรายการที่แอปโต้ตอบกับแอปอื่นๆ แต่ละส่วนมีคำแนะนำเกี่ยวกับวิธีทำให้แอปทำงานได้โดยมีระดับการเข้าถึงแพ็กเกจแบบจำกัด ซึ่งคุณควรพิจารณาหากแอปกำหนดเป้าหมายเป็น Android 11 (API ระดับ 30) ขึ้นไป
เมื่อแอปที่กำหนดเป้าหมายเป็น Android 11 ขึ้นไปใช้ Intent เพื่อเริ่มกิจกรรมในแอปอื่น วิธีที่ใช้ได้ผลที่สุดคือเรียกใช้ Intent และจัดการข้อยกเว้น ActivityNotFoundException
หากไม่มีแอปใดพร้อมใช้งาน
หากส่วนหนึ่งของแอปขึ้นอยู่กับว่ามีการเรียกไปยัง
startActivity()
เช่น การแสดง UI, เพิ่มองค์ประกอบลงใน
<queries>
องค์ประกอบของแอป
ไฟล์ Manifest โดยปกติแล้วจะเป็นองค์ประกอบ <intent>
URL แบบเปิด
ส่วนนี้อธิบายถึงวิธีต่างๆ ในการเปิด URL ในแอปที่กำหนดเป้าหมาย Android 11 ขึ้นไป
เปิด URL ในเบราว์เซอร์หรือแอปอื่น
หากต้องการเปิด URL ให้ใช้ Intent ที่มีการดำเนินการของ Intent ACTION_VIEW
ตามที่อธิบายไว้ในคู่มือการโหลด URL ของเว็บ หลังจากเรียก startActivity()
โดยใช้ Intent นี้ สิ่งใดสิ่งหนึ่งต่อไปนี้จะเกิดขึ้น
- URL จะเปิดในแอปเว็บเบราว์เซอร์
- URL จะเปิดขึ้นในแอปที่สนับสนุน URL นี้ในรูปแบบ Deep ลิงก์
- กล่องโต้ตอบที่มีคำอธิบายจะปรากฏขึ้น ซึ่งช่วยให้ผู้ใช้เลือกแอปได้ เปิด URL
ActivityNotFoundException
เกิดขึ้นเนื่องจากไม่มีแอปติดตั้งใน อุปกรณ์ที่สามารถเปิด URL ได้ (ซึ่งผิดปกติ)เราขอแนะนําให้แอปของคุณจับและจัดการ
ActivityNotFoundException
หากเกิดขึ้น
เนื่องจากเมธอด startActivity()
ไม่จำเป็นต้องใช้ระดับการเข้าถึงแพ็กเกจเพื่อเริ่มกิจกรรมของแอปพลิเคชันอื่น คุณจึงไม่ต้องเพิ่มองค์ประกอบ <queries>
ลงในไฟล์ Manifest ของแอปหรือทำการเปลี่ยนแปลงใดๆ กับองค์ประกอบ <queries>
ที่มีอยู่ กรณีนี้จะเกิดขึ้นกับ Intent ทั้งโดยนัยและโดยชัดแจ้งซึ่งเปิด URL ขึ้นมา
ตรวจสอบว่าเบราว์เซอร์พร้อมใช้งานหรือไม่
ในบางกรณี แอปอาจต้องตรวจสอบว่ามีเบราว์เซอร์อย่างน้อย 1 รายการที่พร้อมใช้งานในอุปกรณ์ หรือเบราว์เซอร์หนึ่งๆ เป็นเบราว์เซอร์เริ่มต้น ก่อนที่จะพยายามเปิด URL ในกรณีเหล่านั้น ให้ระบุข้อมูลต่อไปนี้
องค์ประกอบ <intent>
เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" /> </intent>
เมื่อคุณเรียกใช้ queryIntentActivities()
และส่ง Intent ของเว็บเป็นอาร์กิวเมนต์ รายการที่แสดงผลจะรวมแอปเบราว์เซอร์ที่พร้อมใช้งานในบางกรณี รายการนี้จะไม่รวมแอปเบราว์เซอร์หากผู้ใช้กำหนดค่า URL ให้เปิดในแอปที่ไม่ใช่เบราว์เซอร์โดยค่าเริ่มต้น
เปิด URL ในแท็บที่กำหนดเอง
แท็บที่กำหนดเองช่วยให้
จะปรับรูปลักษณ์ของเบราว์เซอร์เอง คุณสามารถเปิด URL ใน
แท็บที่กำหนดเอง
โดยไม่ต้องเพิ่มหรือเปลี่ยนองค์ประกอบ <queries>
ในไฟล์ Manifest ของแอป
แต่คุณอาจต้องตรวจสอบว่าอุปกรณ์มีเบราว์เซอร์ที่รองรับหรือไม่
แท็บที่กำหนดเอง
หรือเลือกเบราว์เซอร์เฉพาะที่จะเปิดด้วยแท็บที่กำหนดเองโดยใช้
CustomTabsClient.getPackageName()
ในกรณีดังกล่าว ให้ใส่องค์ประกอบ <intent>
ต่อไปนี้เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.support.customtabs.action.CustomTabsService" /> </intent>
อนุญาตให้แอปที่ไม่ใช่เบราว์เซอร์จัดการ URL
แม้ว่าแอปของคุณจะเปิด URL โดยใช้แท็บที่กำหนดเองได้ แต่เราขอแนะนำให้คุณ
ให้แอปที่ไม่ใช่เบราว์เซอร์เปิด URL หากเป็นไปได้ หากต้องการให้ข้อมูลนี้
ในแอปของคุณ ลองโทรหา startActivity()
โดยใช้ Intent
ซึ่งกำหนด
FLAG_ACTIVITY_REQUIRE_NON_BROWSER
การแจ้งเกี่ยวกับ Intent หากระบบแสดง ActivityNotFoundException
แอปจะเปิด URL ในแท็บที่กำหนดเองได้
หาก Intent มี Flag นี้ การเรียก startActivity()
จะทําให้ระบบแสดง ActivityNotFoundException
เมื่อเงื่อนไขข้อใดข้อหนึ่งต่อไปนี้เกิดขึ้น
- เนื่องจากการโทรจะเป็นการเปิดแอปเบราว์เซอร์โดยตรง
- การเรียกใช้นี้จะแสดงกล่องโต้ตอบการแยกแยะให้กับผู้ใช้ซึ่งมีตัวเลือกเดียวคือแอปเบราว์เซอร์
ข้อมูลโค้ดต่อไปนี้จะแสดงวิธีอัปเดตตรรกะของคุณเพื่อใช้
การแจ้งเกี่ยวกับ Intent FLAG_ACTIVITY_REQUIRE_NON_BROWSER
:
Kotlin
try { val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply { // The URL should either launch directly in a non-browser app (if it's // the default) or in the disambiguation dialog. addCategory(CATEGORY_BROWSABLE) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER } startActivity(intent) } catch (e: ActivityNotFoundException) { // Only browser apps are available, or a browser is the default. // So you can open the URL directly in your app, for example in a // Custom Tab. openInCustomTabs(url) }
Java
try { Intent intent = new Intent(ACTION_VIEW, Uri.parse(url)); // The URL should either launch directly in a non-browser app (if it's the // default) or in the disambiguation dialog. intent.addCategory(CATEGORY_BROWSABLE); intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER); startActivity(intent); } catch (ActivityNotFoundException e) { // Only browser apps are available, or a browser is the default. // So you can open the URL directly in your app, for example in a // Custom Tab. openInCustomTabs(url); }
หลีกเลี่ยงกล่องโต้ตอบการชี้แจง
หากต้องการหลีกเลี่ยงการแสดงกล่องโต้ตอบการแยกแยะความหมายที่ผู้ใช้อาจเห็นเมื่อเปิด URL และต้องการจัดการ URL ด้วยตนเองในสถานการณ์เหล่านี้แทน ให้ใช้ Intent ที่ตั้งค่า Flag ของ Intent FLAG_ACTIVITY_REQUIRE_DEFAULT
หาก Intent มีแฟล็กนี้ การเรียกใช้ไปยัง startActivity()
จะทำให้มีการตั้งค่า
ทิ้ง ActivityNotFoundException
เมื่อการโทรจะแสดง
กล่องโต้ตอบที่มีคำอธิบายให้ผู้ใช้ได้อย่างชัดเจน
หาก Intent มีทั้งแฟล็กนี้และ
FLAG_ACTIVITY_REQUIRE_NON_BROWSER
การแจ้ง Intent การเรียกไปยัง startActivity()
จะทำให้เกิดActivityNotFoundException
แสดงเมื่อเกิดเงื่อนไขข้อใดข้อหนึ่งต่อไปนี้
- เนื่องจากการโทรจะเป็นการเปิดแอปเบราว์เซอร์โดยตรง
- ซึ่งจะทำให้ผู้ใช้เห็นกล่องโต้ตอบที่มีคำอธิบายที่ชัดเจน
ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้ Flag FLAG_ACTIVITY_REQUIRE_NON_BROWSER
และ FLAG_ACTIVITY_REQUIRE_DEFAULT
ร่วมกัน
Kotlin
val url = URL_TO_LOAD try { // For this intent to be invoked, the system must directly launch a // non-browser app. val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply { addCategory(CATEGORY_BROWSABLE) flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER or FLAG_ACTIVITY_REQUIRE_DEFAULT } startActivity(intent) } catch (e: ActivityNotFoundException) { // This code executes in one of the following cases: // 1. Only browser apps can handle the intent. // 2. The user has set a browser app as the default app. // 3. The user hasn't set any app as the default for handling this URL. openInCustomTabs(url) }
Java
String url = URL_TO_LOAD; try { // For this intent to be invoked, the system must directly launch a // non-browser app. Intent intent = new Intent(ACTION_VIEW, Uri.parse(url)); intent.addCategory(CATEGORY_BROWSABLE); intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER | FLAG_ACTIVITY_REQUIRE_DEFAULT); startActivity(intent); } catch (ActivityNotFoundException e) { // This code executes in one of the following cases: // 1. Only browser apps can handle the intent. // 2. The user has set a browser app as the default app. // 3. The user hasn't set any app as the default for handling this URL. openInCustomTabs(url); }
เปิดไฟล์
หากแอปของคุณจัดการกับไฟล์หรือไฟล์แนบ เช่น ตรวจสอบว่าอุปกรณ์สามารถ
การเปิดไฟล์ที่ต้องการ วิธีที่ดีที่สุดคือการพยายามเริ่มกิจกรรมที่
จัดการไฟล์ ซึ่งทำได้โดยใช้ Intent ที่มี ACTION_VIEW
และ URI ที่แสดงถึงไฟล์นั้นๆ หากไม่มีแอปให้บริการใน
อุปกรณ์ แอปของคุณสามารถตรวจจับ ActivityNotFoundException
ในตรรกะการจัดการข้อยกเว้น คุณสามารถแสดงข้อผิดพลาดหรือพยายามจัดการไฟล์ด้วยตนเอง
หากแอปต้องทราบล่วงหน้าว่าแอปอื่นเปิดไฟล์หนึ่งๆ ได้หรือไม่ ให้ใส่องค์ประกอบ <intent>
ไว้ในข้อมูลโค้ดต่อไปนี้เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest ใส่ประเภทไฟล์หากคุณทราบอยู่แล้ว
เวลาคอมไพล์
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.VIEW" /> <!-- If you don't know the MIME type in advance, set "mimeType" to "*/*". --> <data android:mimeType="application/pdf" /> </intent>
จากนั้นคุณจะตรวจสอบว่าแอปพร้อมใช้งานหรือไม่ได้โดยโทรไปที่ resolveActivity()
ด้วยความตั้งใจของคุณ
ให้สิทธิ์เข้าถึง URI
หมายเหตุ: การประกาศสิทธิ์การเข้าถึง URI ตามที่อธิบายในส่วนนี้เป็นสิ่งจําเป็นสําหรับแอปที่กําหนดเป้าหมายเป็น Android 11 (API ระดับ 30) ขึ้นไป และแนะนําสําหรับแอปทั้งหมด ไม่ว่า SDK เป้าหมายจะเป็นเวอร์ชันใดและส่งออกผู้ให้บริการเนื้อหาหรือไม่ก็ตาม
สำหรับแอปที่กำหนดเป้าหมายเป็น Android 11 ขึ้นไป
เข้าถึง URI เนื้อหา Intent ของแอปต้องประกาศการเข้าถึง URI
สิทธิ์
โดยการตั้งค่า Intent Flag ข้อใดข้อหนึ่งหรือทั้ง 2 อย่างต่อไปนี้
FLAG_GRANT_READ_URI_PERMISSION
และ
FLAG_GRANT_WRITE_URI_PERMISSION
ใน Android 11 ขึ้นไป สิทธิ์การเข้าถึง URI จะให้สิทธิ์ ความสามารถต่อไปนี้ของแอปที่ได้รับ Intent
- อ่านจากหรือเขียนไปยังข้อมูลที่ URI เนื้อหาแสดง โดยขึ้นอยู่กับ สิทธิ์ URI ที่กำหนด
- รับสิทธิ์เข้าถึงแอปที่มีผู้ให้บริการเนื้อหาที่ตรงกับ สิทธิ์ URI แอปที่มีผู้ให้บริการเนื้อหาอาจแตกต่างจากแอปที่ส่ง Intent
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเพิ่ม Flag Intent สิทธิ์ URI เพื่อให้แอปอื่นที่กำหนดเป้าหมายเป็น Android 11 ขึ้นไปดูข้อมูลใน URI เนื้อหาได้
Kotlin
val shareIntent = Intent(Intent.ACTION_VIEW).apply { flags = Intent.FLAG_GRANT_READ_URI_PERMISSION data = CONTENT_URI_TO_SHARE_WITH_OTHER_APP }
Java
Intent shareIntent = new Intent(Intent.ACTION_VIEW); shareIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION); shareIntent.setData(CONTENT_URI_TO_SHARE_WITH_OTHER_APP);
เชื่อมต่อกับบริการ
หากแอปของคุณจำเป็นต้องโต้ตอบกับบริการที่ไม่แสดงตัว
โดยอัตโนมัติ คุณสามารถประกาศ
การดำเนินการผ่าน Intent ที่เหมาะสมภายในเอลิเมนต์ <queries>
ส่วนต่อไปนี้จะแสดงตัวอย่างการใช้บริการที่เข้าถึงได้ทั่วไป
เชื่อมต่อกับเครื่องมืออ่านออกเสียงข้อความ
หากแอปของคุณโต้ตอบกับเครื่องมืออ่านออกเสียงข้อความ (TTS) ให้ใส่องค์ประกอบ <intent>
ต่อไปนี้เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.TTS_SERVICE" /> </intent>
เชื่อมต่อกับบริการการรู้จำคำพูด
หากแอปของคุณโต้ตอบกับบริการการจดจำคำพูด ให้ใส่ข้อมูลต่อไปนี้
องค์ประกอบ <intent>
เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.speech.RecognitionService" /> </intent>
เชื่อมต่อกับบริการเบราว์เซอร์สื่อ
หากแอปของคุณเป็นแอปเบราว์เซอร์สื่อไคลเอ็นต์ ให้ใส่องค์ประกอบ <intent>
ต่อไปนี้เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.media.browse.MediaBrowserService" /> </intent>
ระบุฟังก์ชันที่กำหนดเอง
หากแอปต้องดำเนินการที่ปรับแต่งได้หรือแสดงข้อมูลที่ปรับแต่งได้โดยอิงตามการโต้ตอบกับแอปอื่นๆ คุณสามารถแสดงลักษณะการทำงานที่กำหนดเองได้โดยใช้ลายเซ็นตัวกรอง Intent เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest ส่วนต่อไปนี้ให้คำแนะนำโดยละเอียดสำหรับสถานการณ์ทั่วไปหลายประการ
การค้นหาแอป SMS
หากแอปต้องการข้อมูลเกี่ยวกับชุดแอป SMS ที่ติดตั้งใน
เช่น ตรวจสอบว่าแอปใดเป็นเครื่องจัดการ SMS เริ่มต้นของอุปกรณ์
รวมเอลิเมนต์ <intent>
ต่อไปนี้เป็นส่วนหนึ่งของเอลิเมนต์ <queries>
ใน
ไฟล์ Manifest ของคุณ:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.SENDTO"/> <data android:scheme="smsto" android:host="*" /> </intent>
สร้างชีตการแชร์ที่กำหนดเอง
หากเป็นไปได้ ให้ใช้ระบบที่จัดเตรียมไว้
Sharesheet หรือ
รวมเอลิเมนต์ <intent>
ต่อไปนี้เป็นส่วนหนึ่งของเอลิเมนต์ <queries>
ใน
ไฟล์ Manifest ของคุณ:
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.SEND" /> <!-- Replace with the MIME type that your app works with, if needed. --> <data android:mimeType="image/jpeg" /> </intent>
กระบวนการสร้าง Sharesheet ในตรรกะของแอป เช่น การเรียก
queryIntentActivities()
มิฉะนั้นจะไม่มีการเปลี่ยนแปลงเมื่อเทียบกับ
ของ Android เวอร์ชันเก่ากว่า Android 11
แสดงการดำเนินการการเลือกข้อความที่กำหนดเอง
เมื่อผู้ใช้เลือกข้อความในแอป การเลือกข้อความ
แถบเครื่องมือ
แสดงชุดของการดำเนินการที่เป็นไปได้ที่จะทำกับข้อความที่เลือก หากแถบเครื่องมือนี้แสดงการดำเนินการที่กำหนดเองจากแอปอื่นๆ ให้ใส่องค์ประกอบ <intent>
ต่อไปนี้เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest
<!-- Place inside the <queries> element. --> <intent> <action android:name="android.intent.action.PROCESS_TEXT" /> <data android:mimeType="text/plain" /> </intent>
แสดงแถวข้อมูลที่กำหนดเองสำหรับรายชื่อติดต่อ
แอปต่างๆ สามารถเพิ่มข้อมูลที่กำหนดเองได้ แถวไปยังรายชื่อติดต่อ ผู้ให้บริการ แอปรายชื่อติดต่อต้องทําสิ่งต่อไปนี้ได้จึงจะแสดงข้อมูลที่กําหนดเองนี้ได้
- อ่านไฟล์
contacts.xml
จากแอปอื่นๆ - โหลดไอคอนที่สอดคล้องกับประเภท MIME ที่กําหนดเอง
หากแอปเป็นแอปรายชื่อติดต่อ ให้ใส่องค์ประกอบ <intent>
ต่อไปนี้เป็นส่วนหนึ่งขององค์ประกอบ <queries>
ในไฟล์ Manifest
<!-- Place inside the <queries> element. --> <!-- Lets the app read the contacts.xml file from other apps. --> <intent> <action android:name="android.accounts.AccountAuthenticator" /> </intent> <!-- Lets the app load an icon corresponding to the custom MIME type. --> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="content" android:host="com.android.contacts" android:mimeType="vnd.android.cursor.item/*" /> </intent>