Korzystanie z kart niestandardowych w Androidzie 11

W Androidzie 11 wprowadzono zmiany dotyczące sposobu, w jaki aplikacje mogą wchodzić w interakcje z innymi aplikacjami zainstalowanymi na urządzeniu przez użytkownika. Więcej informacji na temat tych zmian znajdziesz w dokumentacji Androida.

Gdy aplikacja na Androida, która korzysta z kart niestandardowych, jest kierowana na pakiet SDK na poziomie 30 lub wyższym, konieczne może być wprowadzenie pewnych zmian. Z tego artykułu dowiesz się, jakie zmiany mogą być konieczne w przypadku tych aplikacji.

Najprościej karty niestandardowe można uruchomić z użyciem jednego wiersza, na przykład:

new CustomTabsIntent.Builder().build()
        .launchUrl(this, Uri.parse("https://www.example.com"));

Aplikacje uruchamiające aplikacje w ten sposób, a nawet modyfikować interfejs użytkownika, np. zmianę koloru paska narzędzi czy dodanie przycisku polecenia, nie muszą wprowadzać żadnych zmian w aplikacji.

Preferowanie aplikacji natywnych

Jeśli jednak zastosujesz się do sprawdzonych metod, konieczne może być wprowadzenie zmian.

Pierwszą sprawdzoną metodą jest to, że do obsługi intencji zamiast karty niestandardowej aplikacje powinny preferować aplikację natywną, jeśli jest to możliwe.

Na Androidzie 11 i nowszych

Android 11 wprowadza nową flagę intencji (FLAG_ACTIVITY_REQUIRE_NON_BROWSER), która jest zalecanym sposobem otwierania aplikacji natywnej, ponieważ nie wymaga deklarowania 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;
    }
}

Aby rozwiązać ten problem, spróbuj uruchomić intencję i użyć FLAG_ACTIVITY_REQUIRE_NON_BROWSER, aby poprosić Androida o unikanie przeglądarek przy uruchamianiu.

Jeśli aplikacja natywna, która obsługuje tę intencję, nie zostanie znaleziona, zostanie zgłoszony ActivityNotFoundException.

Przed Androidem 11

Mimo że aplikacja może być kierowana na Androida 11 lub poziom interfejsu API 30, poprzednie wersje Androida nie rozpoznają flagi FLAG_ACTIVITY_REQUIRE_NON_BROWSER. W takich przypadkach musimy wysłać zapytanie 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 wyślesz do menedżera pakietów zapytanie o aplikacje, które obsługują ogólną intencję http. Są to prawdopodobnie przeglądarki.

Następnie wyślij zapytanie o aplikacje obsługujące itenty dla konkretnego adresu URL, który chcesz uruchomić. Spowoduje to zwrócenie ustawień przeglądarek i aplikacji natywnych do obsługi tego adresu URL.

Teraz usuń z drugiej listy wszystkie przeglądarki z pierwszej listy. Zostanwimy tylko aplikacje natywne.

Jeśli lista jest pusta, wiemy, że nie ma natywnych modułów obsługi, i zwracamy „fałsz”. W przeciwnym razie uruchamiamy intencję dla natywnego modułu obsługi.

Podsumowanie

Musimy zastosować właściwą metodę 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 dostarcza nam potrzebnych informacji. Jeśli liczba jest równa lub większa niż 30, Android zna FLAG_ACTIVITY_REQUIRE_NON_BROWSER i możemy spróbować uruchomić aplikację nativa w nowej metodzie. W przeciwnym razie próbujemy uruchamiać starą metodę.

Jeśli uruchomienie aplikacji natywnej nie powiedzie się, uruchamiamy karty niestandardowe.

Sprawdzona metoda wiąże się z pewnymi schematami. Pracujemy nad uproszczeniem tego procesu, wyjmując złożoność biblioteki. Będziemy na bieżąco informować o aktualizacjach biblioteki pomocy android-browser-helper.

Wykrywanie przeglądarek, które obsługują karty niestandardowe

Innym typowym wzorcem jest użycie menedżera pakietów do wykrywania, które przeglądarki obsługują karty niestandardowe na urządzeniu. Typowe zastosowania tego rozwiązania to ustawienie pakietu w intencji, aby uniknąć okna ujednoznacznienia aplikacji, lub wybór przeglądarki, z którą ma się połączyć podczas łączenia z usługą kart niestandardowych.

Kierując reklamy na poziom 30 interfejsu API, deweloperzy muszą dodać do pliku manifestu Androida sekcję zapytań i zadeklarować filtr intencji, który pasuje do przeglądarek obsługujących karty niestandardowe.

<queries>
    <intent>
        <action android:name=
            "android.support.customtabs.action.CustomTabsService" />
    </intent>
</queries>

Gdy dodasz znaczniki, istniejący kod używany do wysyłania zapytań dotyczących przeglądarek obsługujących karty niestandardowe będzie działać zgodnie z oczekiwaniami.

Najczęstsze pytania

P: Kod, który wyszukuje dostawców kart niestandardowych, wyszukuje aplikacje, które mogą obsługiwać intencje https://, ale filtr zapytań deklaruje tylko zapytanie android.support.customtabs.action.CustomTabsService. Czy nie należy zadeklarować zapytania dotyczącego intencji https://?

O: Podczas zadeklarowania filtra zapytania zostaną odfiltrowane odpowiedzi na zapytanie kierowane do menedżera pakietów, a nie samo zapytanie. Przeglądarki, które obsługują karty niestandardowe, deklarują obsługę obiektu CustomTabsService, dlatego nie zostaną one odfiltrowane. Przeglądarki, które nie obsługują kart niestandardowych, są odfiltrowywane.

Podsumowanie

To wszystkie zmiany, które należy wprowadzić, aby dostosować istniejącą integrację kart niestandardowych do działania z Androidem 11. Aby dowiedzieć się więcej o integrowaniu kart niestandardowych z aplikacją na Androida, zacznij od przewodnika po implementacji, a następnie zapoznaj się ze sprawdzonymi metodami tworzenia integracji pierwszej klasy.

Jeśli masz jakieś pytania lub uwagi, daj nam znać.