เอกสารนี้นำเสนอกรณีการใช้งานทั่วไปหลายรายการที่แอปโต้ตอบกับ แอปอื่นๆ แต่ละส่วนจะมีคำแนะนำเกี่ยวกับวิธีทำให้แอป ที่มีระดับการเข้าถึงแพ็กเกจจำกัด ซึ่งคุณต้องดูว่า แอปกำหนดเป้าหมายเป็น Android 11 (API ระดับ 30) ขึ้นไป
เมื่อแอปที่กำหนดเป้าหมายเป็น Android 11 ขึ้นไปใช้ 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 มีแฟล็กนี้ การเรียกใช้ไปยัง 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 ด้วยตนเองแทน
คุณสามารถใช้ความตั้งใจที่จะกำหนด
FLAG_ACTIVITY_REQUIRE_DEFAULT
การแจ้งเกี่ยวกับ Intent
หาก Intent มีแฟล็กนี้ การเรียกใช้ไปยัง startActivity()
จะทำให้มีการตั้งค่า
ทิ้ง ActivityNotFoundException
เมื่อการโทรจะแสดง
กล่องโต้ตอบที่มีคำอธิบายให้ผู้ใช้ได้อย่างชัดเจน
หาก Intent มีทั้งแฟล็กนี้และ
FLAG_ACTIVITY_REQUIRE_NON_BROWSER
การแจ้ง Intent การเรียกไปยัง startActivity()
จะทำให้เกิดActivityNotFoundException
แสดงเมื่อเกิดเงื่อนไขข้อใดข้อหนึ่งต่อไปนี้
- เนื่องจากการโทรจะเป็นการเปิดแอปเบราว์เซอร์โดยตรง
- ซึ่งจะทำให้ผู้ใช้เห็นกล่องโต้ตอบที่มีคำอธิบายที่ชัดเจน
ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้ 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
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเพิ่มแฟล็ก 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>
ระบุฟังก์ชันที่กำหนดเอง
หากแอปจำเป็นต้องดำเนินการที่ปรับแต่งได้หรือแสดงการดำเนินการที่ปรับแต่งได้
ข้อมูลที่อิงตามการโต้ตอบของแอปกับแอปอื่นๆ คุณจะแสดงให้เห็นว่า
ลักษณะการทำงานที่กำหนดเองโดยใช้ตัวกรองความตั้งใจ
เป็นลายเซ็น
ของเอลิเมนต์ <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 ที่กำหนดเอง
หากเป็นไปได้ ให้ใช้ระบบที่จัดเตรียมไว้
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>