Android 11 針對應用程式與使用者在裝置上安裝的其他應用程式互動的方式,導入了相關異動。如要進一步瞭解這些異動,請參閱 Android 說明文件。
如果使用自訂 Tabs 的 Android 應用程式指定 SDK 級別 30 以上,可能需要進行一些變更。本文將說明這些應用程式可能需要的變更。
在最簡單的情況下,您可以使用一行程式碼啟動自訂分頁,如下所示:
new CustomTabsIntent.Builder().build()
.launchUrl(this, Uri.parse("https://www.example.com"));
應用程式只要使用這項功能啟動應用程式,甚至加入 UI 自訂項目 (例如變更工具列顏色、新增動作按鈕),就不需要在應用程式中進行任何變更。
偏好原生應用程式
不過,如果您遵循最佳做法,可能需要進行一些變更。
第一個相關的最佳做法是,如果已安裝可處理意圖的應用程式,應用程式應優先使用原生應用程式處理意圖,而非自訂分頁。
Android 11 以上版本
Android 11 推出了新的 Intent 標記 FLAG_ACTIVITY_REQUIRE_NON_BROWSER
,這是嘗試開啟原生應用程式的建議方式,因為它不需要應用程式宣告任何套件管理員查詢。
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 在啟動時避免使用瀏覽器。
如果找不到可處理此意圖的原生應用程式,系統會擲回 ActivityNotFoundException
。
Android 11 之前
雖然應用程式可能指定 Android 11 或 API 級別 30,但先前的 Android 版本無法解讀 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 查詢支援一般 http
意圖的應用程式。這些應用程式可能是瀏覽器。
接著,請查詢應用程式,以便處理我們要啟動的特定網址。這會傳回瀏覽器和原生應用程式設定,以便處理該網址。
接著,從第二個清單中移除第一個清單中的所有瀏覽器,這樣就只剩下原生應用程式。
如果清單為空白,表示沒有原生處理常式,因此會傳回 false。否則,我們會啟動原生處理常式的意圖。
全面整合使用
我們需要確保在每個情況下都使用正確的方法:
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 資訊清單中新增查詢專區,宣告與支援自訂分頁的瀏覽器相符的意圖篩選器。
<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
標記完成後,用於查詢支援自訂分頁的瀏覽器的現有程式碼就會正常運作。
常見問題
問:尋找自訂分頁提供者的程式碼會針對可處理 https://
意圖的應用程式執行查詢,但查詢篩選器只會宣告 android.support.customtabs.action.CustomTabsService
查詢。您不應該宣告 https://
意圖的查詢嗎?
答:宣告查詢篩選器時,它會將對 PackageManager 的查詢回應篩除,而非查詢本身。由於支援 Custom Tabs 的瀏覽器會宣告處理 CustomTabsService,因此不會遭到篩除。系統會篩除不支援自訂分頁的瀏覽器。
結論
這些就是將現有自訂分頁整合功能調整為與 Android 11 搭配運作所需的所有變更。如要進一步瞭解如何將自訂分頁整合至 Android 應用程式,請先參閱實作指南,然後查看最佳做法,瞭解如何建構一流的整合作業。
如有任何問題或意見,歡迎與我們聯絡!