Android 11 導入了變更,讓應用程式與使用者裝置上安裝的其他應用程式互動。請參閱 Android 說明文件,進一步瞭解這些變更。
如果 Android 應用程式使用自訂分頁指定 SDK 級別 30 以上,你可能須進行調整。本文將介紹這些應用程式可能需要進行的異動。
在最簡單的情況下,使用者可以用單行文字啟動「自訂分頁」,如下所示:
new CustomTabsIntent.Builder().build()
.launchUrl(this, Uri.parse("https://www.example.com"));
如果應用程式使用這個方法啟動應用程式,甚至是新增 UI 自訂項目 (例如變更工具列顏色、新增動作按鈕),也不必在應用程式中進行任何變更。
優先使用原生應用程式
但如果您遵循最佳做法,可能就要做出一些調整。
第一個相關的最佳做法是,如果應用程式能夠處理該意圖,就應優先使用原生應用程式處理意圖,而不應使用「自訂分頁」。
Android 11 以上版本
Android 11 推出了新的意圖旗標 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
旗標,因此在以下情況下,我們必須查詢套件管理員:
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;
}
這裡的做法是向套件管理員查詢支援一般 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 偵測哪些瀏覽器支援自訂分頁。這種做法的常見用途是在意圖上設定套件,以避免在連線至自訂分頁服務時造成應用程式混淆對話方塊,或選擇連線瀏覽器。
如果指定 API 級別 30,開發人員需要在 Android 資訊清單新增查詢區段,同時宣告符合支援自訂分頁瀏覽器的意圖篩選器。
<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
標記就緒後,用於查詢支援自訂分頁的瀏覽器的「現有程式碼」就可正常運作。
常見問題
問:這個程式碼會尋找自訂分頁供應商,查詢可處理 https://
意圖的應用程式,但查詢篩選器只會宣告 android.support.customtabs.action.CustomTabsService
查詢。不應該宣告 https://
意圖嗎?
答:宣告查詢篩選器時,系統會篩選 PackageManager 查詢的回應,而非查詢本身。支援自訂分頁的瀏覽器會宣告處理 CustomTabsService,因此不會遭到篩除。系統會篩除不支援自訂分頁的瀏覽器。
結論
為配合 Android 11 調整現有「自訂分頁」的整合方式,這些為必要變更。如要進一步瞭解如何將自訂分頁整合至 Android 應用程式,請先參閱實作指南,再參閱最佳做法,瞭解如何建構一流整合功能。
如有任何問題或意見,歡迎與我們聯絡。