Menggunakan Tab Khusus dengan Android 11

Android 11 memperkenalkan perubahan pada cara aplikasi dapat berinteraksi dengan aplikasi lain yang telah diinstal pengguna di perangkat. Anda dapat membaca perubahan tersebut lebih lanjut di dokumentasi Android.

Jika aplikasi Android yang menggunakan Tab Kustom menargetkan SDK level 30 atau yang lebih tinggi, beberapa perubahan mungkin diperlukan. Artikel ini membahas perubahan yang mungkin diperlukan untuk aplikasi tersebut.

Dalam kasus yang paling sederhana, Tab Khusus dapat diluncurkan dengan satu baris seperti ini:

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

Aplikasi yang meluncurkan aplikasi menggunakan pendekatan ini, atau bahkan menambahkan penyesuaian UI seperti mengubah warna toolbar, menambahkan tombol tindakan tidak perlu melakukan perubahan apa pun dalam aplikasi.

Memilih Aplikasi Native

Namun, jika Anda mengikuti praktik terbaik, beberapa perubahan mungkin diperlukan.

Praktik terbaik pertama yang relevan adalah aplikasi harus memilih aplikasi native untuk menangani intent, bukan Tab Kustom jika aplikasi yang mampu menanganinya diinstal.

Di Android 11 dan yang lebih baru

Android 11 memperkenalkan tanda Intent baru, FLAG_ACTIVITY_REQUIRE_NON_BROWSER, yang merupakan cara yang direkomendasikan untuk mencoba membuka aplikasi native, karena tidak mengharuskan aplikasi mendeklarasikan kueri pengelola paket apa pun.

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;
    }
}

Solusinya adalah mencoba meluncurkan Intent dan menggunakan FLAG_ACTIVITY_REQUIRE_NON_BROWSER untuk meminta Android menghindari browser saat diluncurkan.

Jika aplikasi native yang mampu menangani Intent ini tidak ditemukan, ActivityNotFoundException akan ditampilkan.

Sebelum Android 11

Meskipun aplikasi dapat menargetkan Android 11, atau API level 30, versi Android sebelumnya tidak akan memahami tanda FLAG_ACTIVITY_REQUIRE_NON_BROWSER, jadi kita perlu mengkueri Package Manager dalam kasus tersebut:

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;
}

Pendekatan yang digunakan di sini adalah membuat kueri Package Manager untuk aplikasi yang mendukung intent http umum. Aplikasi tersebut kemungkinan adalah browser.

Kemudian, buat kueri untuk aplikasi yang menangani item untuk URL tertentu yang ingin kita luncurkan. Tindakan ini akan menampilkan penyiapan browser dan aplikasi native untuk menangani URL tersebut.

Sekarang, hapus semua browser yang ditemukan di daftar pertama dari daftar kedua, dan kita hanya akan memiliki aplikasi native.

Jika daftar kosong, kita tahu tidak ada pengendali native dan menampilkan nilai salah. Jika tidak, kita akan meluncurkan intent untuk pengendali native.

Menggabungkan semuanya

Kita harus memastikan penggunaan metode yang tepat untuk setiap kesempatan:

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 memberikan informasi yang kita butuhkan. Jika sama dengan atau lebih besar dari 30, Android akan mengetahui FLAG_ACTIVITY_REQUIRE_NON_BROWSER dan kita dapat mencoba meluncurkan aplikasi native dengan pendekatan baru. Jika tidak, kita akan mencoba meluncurkan dengan pendekatan lama.

Jika peluncuran aplikasi native gagal, kita akan meluncurkan Tab Khusus.

Ada beberapa boilerplate yang terlibat dalam praktik terbaik ini. Kami berupaya untuk mempermudahnya dengan mengaitkan kompleksitas dalam library. Nantikan update untuk library dukungan android-browser-helper.

Mendeteksi browser yang mendukung Tab Khusus

Pola umum lainnya adalah menggunakan PackageManager untuk mendeteksi browser mana yang mendukung Custom Tabs di perangkat. Kasus penggunaan umum untuk hal ini adalah menetapkan paket pada Intent untuk menghindari dialog disambiguasi aplikasi atau memilih browser yang akan dihubungkan saat terhubung ke layanan Tab Khusus.

Saat menargetkan API level 30, developer harus menambahkan bagian kueri ke Manifes Android mereka, yang mendeklarasikan filter intent yang cocok dengan browser dengan dukungan Custom Tabs.

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

Dengan markup yang diterapkan, kode yang ada yang digunakan untuk membuat kueri browser yang mendukung Tab Kustom akan berfungsi seperti yang diharapkan.

Pertanyaan Umum (FAQ)

T: Kode yang mencari penyedia Tab Kustom membuat kueri untuk aplikasi yang dapat menangani intent https://, tetapi filter kueri hanya mendeklarasikan kueri android.support.customtabs.action.CustomTabsService. Bukankah kueri untuk intent https:// harus dideklarasikan?

J: Saat mendeklarasikan filter kueri, filter akan memfilter respons terhadap kueri ke PackageManager, bukan kueri itu sendiri. Karena browser yang mendukung Tab Kustom mendeklarasikan penanganan CustomTabsService, browser tersebut tidak akan difilter. Browser yang tidak mendukung Tab Khusus akan difilter.

Kesimpulan

Itulah semua perubahan yang diperlukan untuk menyesuaikan integrasi Tab Kustom yang ada agar berfungsi dengan Android 11. Untuk mempelajari lebih lanjut cara mengintegrasikan Tab Kustom ke dalam aplikasi Android, mulai dengan panduan penerapan, lalu lihat praktik terbaik untuk mempelajari cara membuat integrasi kelas satu.

Beri tahu kami jika ada pertanyaan atau masukan.