Android 11 wprowadził zmiany w sposobie interakcji aplikacji z innymi aplikacjami zainstalowanymi na urządzeniu przez użytkownika. Więcej informacji o tych zmianach znajdziesz w dokumentacji Androida.
Jeśli aplikacja na Androida korzystająca z niestandardowych kart jest kierowana na pakiet SDK w poziomie 30 lub wyższym, może być konieczne wprowadzenie pewnych zmian. W tym artykule omawiamy zmiany, które mogą być potrzebne w przypadku tych aplikacji.
W najprostszym przypadku karty niestandardowe można uruchomić za pomocą pojedynczego wiersza kodu:
new CustomTabsIntent.Builder().build()
.launchUrl(this, Uri.parse("https://www.example.com"));
Aplikacje uruchamiające inne aplikacje za pomocą tego podejścia lub nawet dodające do interfejsu takie funkcje jak zmiana koloru paska narzędzi czy dodanie przycisku akcji nie muszą wprowadzać żadnych zmian w aplikacji.
Preferowanie aplikacji natywnych
Jeśli jednak zastosujesz sprawdzone metody, może być konieczne wprowadzenie pewnych zmian.
Pierwsza sprawdzona metoda to taka, że aplikacje powinny preferować aplikację natywną do obsługi intencji zamiast karty niestandardowej, jeśli zainstalowana jest aplikacja, która może ją obsługiwać.
Android 11 lub nowszy
Android 11 wprowadza nową flagę intencji FLAG_ACTIVITY_REQUIRE_NON_BROWSER
, która jest zalecanym sposobem otwierania natywnej aplikacji, ponieważ nie wymaga od niej deklarowania żadnych zapytań menedżera pakietów.
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;
}
}
Rozwiązaniem jest spróbowanie uruchomienia intencjonalnie i użycie FLAG_ACTIVITY_REQUIRE_NON_BROWSER
, aby poprosić Androida o uniknięcie uruchamiania przeglądarek.
Jeśli nie zostanie znaleziona natywna aplikacja, która może obsłużyć ten zamiar, zostanie wywołana funkcja ActivityNotFoundException
.
Przed Androidem 11
Mimo że aplikacja może być kierowana na Androida 11 lub poziom API 30, poprzednie wersje Androida nie będą rozumieć flagi FLAG_ACTIVITY_REQUIRE_NON_BROWSER
, więc w takich przypadkach musimy użyć zapytania do menedżera pakietów:
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;
}
W tym przypadku wysyłamy zapytanie do Menedżera pakietów o aplikacje obsługujące ogólny zamiar http
. Te aplikacje to prawdopodobnie przeglądarki.
Następnie wyszukaj aplikacje, które obsługują itenty dla konkretnego adresu URL, który chcemy uruchomić. W zwrotnej wartości otrzymasz zarówno przeglądarki, jak i natywne aplikacje skonfigurowane do obsługi tego adresu URL.
Teraz usuń z drugiej listy wszystkie przeglądarki znalezione na pierwszej liście. Pozostaną tylko aplikacje natywne.
Jeśli lista jest pusta, wiemy, że nie ma żadnych natywnych obsługi, i zwracamy wartość false. W przeciwnym razie uruchamiamy intent dla natywnego modułu obsługi.
Podsumowanie
Musimy używać odpowiedniej metody w każdej sytuacji:
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
zawiera informacje, których potrzebujemy. Jeśli jest równa lub większa niż 30, Android zna wartość FLAG_ACTIVITY_REQUIRE_NON_BROWSER
i możemy spróbować uruchomić aplikację natywną przy użyciu nowego podejścia. W przeciwnym razie spróbujemy uruchomić kampanię, korzystając ze starego podejścia.
Jeśli uruchomienie aplikacji natywnej się nie uda, uruchomimy karty niestandardowe.
Ta sprawdzona metoda zawiera pewne elementy szablonowe. Pracujemy nad uproszczeniem tego procesu poprzez umieszczenie złożoności w bibliotece. Śledź informacje o aktualizacjach biblioteki pomocy android-browser-helper.
Wykrywanie przeglądarek obsługujących karty niestandardowe
Innym typowym wzorcem jest użycie menedżera pakietów do wykrywania przeglądarek, które obsługują karty niestandardowe na urządzeniu. Typowymi zastosowaniami są: ustawienie pakietu w intencji, aby uniknąć okna rozróżniania aplikacji, lub wybór przeglądarki, z którą chcesz się połączyć, gdy łączysz się z usługą kart niestandardowych.
Aby kierować reklamy na urządzenia z Androidem na poziomie interfejsu API 30, deweloperzy muszą dodać do pliku manifestu Androida sekcję zapytań, w której należy zadeklarować filtr intencji pasujący do przeglądarek obsługujących karty niestandardowe.
<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
Po zastosowaniu znaczników dotychczasowy kod używany do wysyłania zapytań do przeglądarek obsługujących niestandardowe karty będzie działał zgodnie z oczekiwaniami.
Najczęstsze pytania
Pytanie: kod, który wyszukuje dostawców kart niestandardowych, wysyła zapytania do aplikacji, które mogą obsługiwać intencje https://
, ale filtr zapytań deklaruje tylko zapytanie android.support.customtabs.action.CustomTabsService
. Czy nie powinno być zadeklarowane zapytania o intencje https://
?
Odp.: deklarując filtr zapytania, możesz odfiltrować odpowiedzi na zapytanie do PackageManagera, a nie samo zapytanie. Ponieważ przeglądarki obsługujące karty niestandardowe deklarują obsługę CustomTabsService, nie będą odfiltrowywane. Przeglądarki, które nie obsługują kart niestandardowych, zostaną odfiltrowane.
Podsumowanie
To wszystkie zmiany wymagane do dostosowania dotychczasowej integracji z kartami niestandardowymi do pracy z Androidem 11. Aby dowiedzieć się więcej o integrowaniu kart niestandardowych z aplikacją na Androida, zacznij od przewodnika po wdrożeniu, a potem zapoznaj się ze sprawdzonymi metodami, aby dowiedzieć się, jak stworzyć integrację najwyższej jakości.
Jeśli masz pytania lub uwagi, daj nam znać.