Android 11 เปิดตัวการเปลี่ยนแปลงเกี่ยวกับวิธีที่แอปโต้ตอบกับแอปอื่นๆ ที่ผู้ใช้ติดตั้งไว้ในอุปกรณ์ อ่านข้อมูลเพิ่มเติมเกี่ยวกับการเปลี่ยนแปลงดังกล่าวได้ในเอกสารประกอบของ Android
เมื่อแอป Android ที่ใช้ Custom Tabs กำหนดเป้าหมายเป็น SDK ระดับ 30 ขึ้นไป คุณอาจต้องทำการเปลี่ยนแปลงบางอย่าง บทความนี้จะกล่าวถึงการเปลี่ยนแปลงที่อาจจำเป็นสำหรับแอปเหล่านั้น
ในกรณีแบบง่ายที่สุด แท็บที่กำหนดเองจะเปิดได้ด้วยบรรทัดเดียว ดังนี้
new CustomTabsIntent.Builder().build()
.launchUrl(this, Uri.parse("https://www.example.com"));
แอปพลิเคชันที่เปิดแอปพลิเคชันโดยใช้แนวทางนี้ หรือแม้แต่การเพิ่มการปรับแต่ง UI เช่น การเปลี่ยนสีแถบเครื่องมือ การเพิ่มปุ่มดำเนินการ จะไม่ต้องทำการเปลี่ยนแปลงใดๆ ในแอปพลิเคชัน
การใช้แอปที่มาพร้อมเครื่อง
แต่หากคุณทำตามแนวทางปฏิบัติแนะนำ ก็อาจต้องเปลี่ยนแปลงบางอย่าง
แนวทางปฏิบัติแนะนำที่เกี่ยวข้องข้อแรกคือแอปพลิเคชันควรใช้แอปเนทีฟเพื่อจัดการ Intent แทนแท็บที่กำหนดเอง หากติดตั้งแอปที่จัดการ Intent ได้
ใน Android 11 ขึ้นไป
Android 11 เปิดตัว Flag Intent ใหม่ FLAG_ACTIVITY_REQUIRE_NON_BROWSER
ซึ่งเป็นวิธีที่แนะนําในการลองเปิดแอปเนทีฟ เนื่องจากแอปไม่จําเป็นต้องประกาศการค้นหา Package Manager
static boolean launchNativeApi30(Context context, Uri uri) {
Intent nativeAppIntent = new Intent(Intent.ACTION_VIEW, uri)
.addCategory(Intent.CATEGORY_BROWSABLE)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER);
try {
context.startActivity(nativeAppIntent);
return true;
} catch (ActivityNotFoundException ex) {
return false;
}
}
วิธีแก้ปัญหาคือลองเปิด Intent และใช้ FLAG_ACTIVITY_REQUIRE_NON_BROWSER
เพื่อขอให้ Android หลีกเลี่ยงเบราว์เซอร์เมื่อเปิด
หากไม่พบแอปเนทีฟที่สามารถจัดการ Intent นี้ ระบบจะแสดงActivityNotFoundException
ก่อน Android 11
แม้ว่าแอปพลิเคชันจะกำหนดเป้าหมายเป็น Android 11 หรือ API ระดับ 30 แต่ Android เวอร์ชันเก่าจะไม่เข้าใจ Flag FLAG_ACTIVITY_REQUIRE_NON_BROWSER
เราจึงต้องหันไปใช้การค้นหา Package Manager ในกรณีเหล่านี้
private static boolean launchNativeBeforeApi30(Context context, Uri uri) {
PackageManager pm = context.getPackageManager();
// Get all Apps that resolve a generic url
Intent browserActivityIntent = new Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.fromParts("http", "", null));
Set<String> genericResolvedList = extractPackageNames(
pm.queryIntentActivities(browserActivityIntent, 0));
// Get all apps that resolve the specific Url
Intent specializedActivityIntent = new Intent(Intent.ACTION_VIEW, uri)
.addCategory(Intent.CATEGORY_BROWSABLE);
Set<String> resolvedSpecializedList = extractPackageNames(
pm.queryIntentActivities(specializedActivityIntent, 0));
// Keep only the Urls that resolve the specific, but not the generic
// urls.
resolvedSpecializedList.removeAll(genericResolvedList);
// If the list is empty, no native app handlers were found.
if (resolvedSpecializedList.isEmpty()) {
return false;
}
// We found native handlers. Launch the Intent.
specializedActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(specializedActivityIntent);
return true;
}
แนวทางที่ใช้ในที่นี้คือค้นหา Package Manager สําหรับแอปพลิเคชันที่รองรับ Intent แบบทั่วไป http
แอปพลิเคชันเหล่านั้นอาจเป็นเบราว์เซอร์
จากนั้นค้นหาแอปพลิเคชันที่จัดการข้อมูลสำหรับ URL ที่เฉพาะเจาะจงซึ่งเราต้องการเปิดตัว ซึ่งจะแสดงทั้งเบราว์เซอร์และแอปพลิเคชันเนทีฟที่ตั้งค่าให้จัดการ URL นั้น
ตอนนี้ให้นําเบราว์เซอร์ทั้งหมดที่พบในรายการแรกออกจากรายการที่ 2 แล้วเราจะเหลือเพียงแอปเนทีฟเท่านั้น
หากรายการว่างเปล่า เราจะทราบว่าไม่มีตัวแฮนเดิลแบบเนทีฟและแสดงผลเป็นเท็จ มิเช่นนั้น เราจะเปิดใช้งาน Intent สําหรับตัวแฮนเดิลแบบเนทีฟ
สรุปข้อมูลทั้งหมด
เราต้องตรวจสอบว่าใช้วิธีการที่เหมาะสมกับแต่ละกรณี ดังนี้
static void launchUri(Context context, Uri uri) {
boolean launched = Build.VERSION.SDK_INT >= 30 ?
launchNativeApi30(context, uri) :
launchNativeBeforeApi30(context, uri);
if (!launched) {
new CustomTabsIntent.Builder()
.build()
.launchUrl(context, uri);
}
}
Build.VERSION.SDK_INT
ให้ข้อมูลที่เราต้องการ หากค่าเท่ากับหรือมากกว่า 30 แสดงว่า Android รู้จัก FLAG_ACTIVITY_REQUIRE_NON_BROWSER
และเราสามารถลองเปิดแอปเนทีฟด้วยแนวทางใหม่ มิเช่นนั้น เราจะลองเปิดตัวด้วยแนวทางเดิม
หากเปิดแอปเนทีฟไม่สำเร็จ เราจะเปิดแท็บที่กำหนดเอง
แนวทางปฏิบัติแนะนำนี้เกี่ยวข้องกับข้อความที่เขียนขึ้นไว้ล่วงหน้า เรากำลังดำเนินการทำให้การดำเนินการนี้ง่ายขึ้นด้วยการรวมความซับซ้อนไว้ในไลบรารี โปรดคอยติดตามการอัปเดตไลบรารีการสนับสนุน android-browser-helper
การตรวจหาเบราว์เซอร์ที่รองรับแท็บที่กำหนดเอง
รูปแบบที่พบบ่อยอีกอย่างหนึ่งคือการใช้ PackageManager เพื่อตรวจหาเบราว์เซอร์ที่รองรับแท็บที่กำหนดเองในอุปกรณ์ กรณีการใช้งานทั่วไปสำหรับกรณีนี้คือการตั้งค่าแพ็กเกจใน Intent เพื่อหลีกเลี่ยงกล่องโต้ตอบการแยกความแตกต่างของแอป หรือเลือกเบราว์เซอร์ที่จะเชื่อมต่อเมื่อเชื่อมต่อกับบริการแท็บที่กำหนดเอง
เมื่อกำหนดเป้าหมายเป็น API ระดับ 30 นักพัฒนาแอปจะต้องเพิ่มส่วนการค้นหาลงใน Android Manifest โดยประกาศตัวกรอง Intent ที่ตรงกับเบราว์เซอร์ที่รองรับแท็บที่กำหนดเอง
<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
เมื่อมาร์กอัปพร้อมใช้งานแล้ว โค้ดที่มีอยู่ซึ่งใช้ค้นหาเบราว์เซอร์ที่รองรับแท็บที่กำหนดเองจะทำงานตามที่คาดไว้
คำถามที่พบบ่อย
ถาม: โค้ดที่ค้นหาผู้ให้บริการแท็บที่กำหนดเองจะค้นหาแอปพลิเคชันที่จัดการhttps://
Intent ได้ แต่ตัวกรองข้อความค้นหาจะประกาศเฉพาะข้อความค้นหา android.support.customtabs.action.CustomTabsService
ไม่ควรประกาศคําค้นหาสําหรับhttps://
Intent
ตอบ: เมื่อประกาศตัวกรองข้อความค้นหา ระบบจะกรองการตอบกลับข้อความค้นหาไปยัง PackageManager ไม่ใช่ข้อความค้นหาเอง เนื่องจากเบราว์เซอร์ที่รองรับแท็บที่กำหนดเองจะประกาศการจัดการ CustomTabsService ระบบจึงไม่กรองเบราว์เซอร์เหล่านั้นออก ระบบจะกรองเบราว์เซอร์ที่ไม่รองรับแท็บที่กำหนดเองออก
บทสรุป
การเปลี่ยนแปลงทั้งหมดที่จําเป็นในการปรับการผสานรวมแท็บที่กําหนดเองที่มีอยู่ให้ทํางานกับ Android 11 หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับการผสานรวมแท็บที่กำหนดเองลงในแอป Android ให้เริ่มจากคู่มือการใช้งาน จากนั้นดูแนวทางปฏิบัติแนะนำเพื่อเรียนรู้เกี่ยวกับการผสานรวมที่ยอดเยี่ยม
โปรดแจ้งให้เราทราบหากมีคำถามหรือความคิดเห็น