Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Mengonfigurasi visibilitas paket berdasarkan kasus penggunaan

Dokumen ini memberikan beberapa contoh kasus penggunaan umum saat aplikasi berinteraksi dengan aplikasi lain. Setiap bagian menyediakan panduan tentang cara mengelola visibilitas paket ke dalam aplikasi yang diinstal lainnya, yang diperlukan untuk mempertimbangkan apakah aplikasi Anda menargetkan Android 11 (API level 30) atau yang lebih tinggi.

Saat aplikasi Anda menargetkan Android 11 atau yang lebih tinggi dan menggunakan intent untuk memulai aktivitas di aplikasi lain, pendekatan yang paling mudah adalah memanggil intent tersebut dan menangani pengecualian ActivityNotFoundException jika tidak ada aplikasi yang tersedia.

Jika sebagian aplikasi Anda bergantung pada mengetahui apakah panggilan ke startActivity() dapat berhasil, seperti menampilkan UI, tambahkan elemen ke elemen <queries> dari manifes aplikasi Anda. Biasanya, elemen baru ini adalah elemen <intent>.

Membuka URL

Bagian ini menjelaskan cara membuka URL di aplikasi yang menargetkan Android 11 atau yang lebih tinggi. Ikuti salah satu contoh dalam subbagian berikut, bergantung pada cara aplikasi Anda membuka URL.

Membuka URL di browser atau aplikasi lain

Untuk membuka URL, gunakan intent yang berisi tindakan intent ACTION_VIEW, seperti yang dijelaskan di bagian tentang cara memuat URL web. Setelah Anda memanggil startActivity() menggunakan intent ini, salah satu hal berikut akan terjadi:

  • URL akan terbuka di aplikasi browser web.
  • URL akan terbuka di aplikasi yang mendukung URL sebagai deep link.
  • Dialog disambiguisasi muncul, yang memungkinkan pengguna memilih aplikasi mana yang membuka URL.
  • ActivityNotFoundException terjadi karena tidak ada aplikasi yang diinstal di perangkat yang dapat membuka URL. (Ini tidak biasa.)

    Sebaiknya aplikasi Anda menangkap dan menangani ActivityNotFoundException jika terjadi.

Karena metode startActivity() tidak dipengaruhi oleh perilaku visibilitas paket sistem, Anda tidak perlu menambahkan elemen <queries> ke manifes aplikasi Anda.

Periksa apakah browser tersedia

Dalam beberapa kasus, aplikasi Anda mungkin ingin memverifikasi bahwa setidaknya ada satu browser yang tersedia di perangkat, atau bahwa browser tertentu adalah browser default, sebelum berupaya membuka URL. Dalam hal ini, sertakan elemen <intent> berikut sebagai bagian dari elemen <queries> dalam manifes Anda:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="https" />
</intent>

Saat Anda memanggil queryIntentActivities() dan meneruskan intent web sebagai argumen, daftar yang ditampilkan akan menyertakan aplikasi browser yang tersedia dalam beberapa kasus. Daftar tersebut tidak menyertakan aplikasi browser jika pengguna secara default telah mengonfigurasi URL agar terbuka di aplikasi non-browser.

Membuka URL di Tab Khusus

Tab Khusus memungkinkan aplikasi menyesuaikan tampilan dan nuansa browser. Anda dapat membuka URL di Tab Khusus tanpa perlu menambahkan atau mengubah elemen <queries> dalam manifes aplikasi.

Namun, Anda mungkin ingin memeriksa apakah perangkat memiliki browser yang mendukung Tab Khusus, atau memilih browser tertentu untuk diluncurkan dengan Tab Khusus menggunakan CustomTabsClient.getPackageName(). Dalam kasus tersebut, sertakan elemen <intent> berikut sebagai bagian dari elemen <queries> dalam manifes Anda:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>

Mengizinkan aplikasi non-browser menangani URL

Meskipun aplikasi Anda dapat membuka URL menggunakan Tab Khusus, sebaiknya Anda mengizinkan aplikasi non-browser untuk membuka URL tertentu jika memungkinkan. Untuk menyediakan kemampuan ini di aplikasi Anda, coba lakukan panggilan ke startActivity() menggunakan intent yang menetapkan tanda intent FLAG_ACTIVITY_REQUIRE_NON_BROWSER. Jika sistem memunculkan ActivityNotFoundException, aplikasi Anda dapat membuka URL di Tab Khusus.

Jika intent menyertakan tanda ini, panggilan ke startActivity() menyebabkan ActivityNotFoundException ditampilkan saat salah satu kondisi berikut terjadi:

  • Panggilan ini akan meluncurkan aplikasi browser secara langsung.
  • Panggilan tersebut akan menampilkan dialog disambiguisasi kepada pengguna, ketika satu-satunya opsi adalah aplikasi browser.

Cuplikan kode berikut menunjukkan cara memperbarui logika Anda untuk menggunakan tanda intent FLAG_ACTIVITY_REQUIRE_NON_BROWSER:

Kotlin

try {
    val intent = Intent(ACTION_VIEW, Uri.parse(url)).apply {
        // The URL should either launch directly in a non-browser app (if it's
        // the default), or in the disambiguation dialog.
        addCategory(CATEGORY_BROWSABLE)
        flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER
    }
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Only browser apps are available, or a browser is the default.
    // So you can open the URL directly in your app, for example in a
    // Custom Tab.
    openInCustomTabs(url)
}

Java

try {
    Intent intent = new Intent(ACTION_VIEW, Uri.parse(url));
    // The URL should either launch directly in a non-browser app (if it's the
    // default), or in the disambiguation dialog.
    intent.addCategory(CATEGORY_BROWSABLE);
    intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER);
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // Only browser apps are available, or a browser is the default.
    // So you can open the URL directly in your app, for example in a
    // Custom Tab.
    openInCustomTabs(url);
}

Menghindari dialog disambiguisasi

Jika Anda tidak ingin menampilkan dialog disambiguisasi yang mungkin dilihat pengguna saat mereka membuka URL, dan lebih memilih untuk menangani URL sendiri dalam situasi ini, Anda dapat menggunakan intent yang menetapkan tanda intent FLAG_ACTIVITY_REQUIRE_DEFAULT.

Jika intent menyertakan tanda ini, panggilan ke startActivity() akan menyebabkan ActivityNotFoundException ditampilkan saat panggilan itu akan menampilkan dialog disambiguisasi kepada pengguna.

Jika intent menyertakan tanda ini dan tanda intent FLAG_ACTIVITY_REQUIRE_NON_BROWSER, panggilan ke startActivity() menyebabkan ActivityNotFoundException ditampilkan saat salah satu kondisi berikut terjadi:

  • Panggilan ini akan meluncurkan aplikasi browser secara langsung.
  • Panggilan tersebut akan menampilkan dialog disambiguisasi kepada pengguna.

Cuplikan kode berikut menunjukkan cara menggunakan tanda FLAG_ACTIVITY_REQUIRE_NON_BROWSER dan FLAG_ACTIVITY_REQUIRE_DEFAULT secara bersamaan:

Kotlin

val url = URL_TO_LOAD
try {
    // In order for this intent to be invoked, the system must directly launch a
    // non-browser app.
    val intent = Intent(ACTION_VIEW, Uri.parse(url).apply {
        addCategory(CATEGORY_BROWSABLE)
        flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REQUIRE_NON_BROWSER or
                FLAG_ACTIVITY_REQUIRE_DEFAULT
    }
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // This code executes in one of the following cases:
    // 1. Only browser apps can handle the intent.
    // 2. The user has set a browser app as the default app.
    // 3. The user hasn't set any app as the default for handling this URL.
    openInCustomTabs(url)
}

Java

String url = URL_TO_LOAD;
try {
    // In order for this intent to be invoked, the system must directly launch a
    // non-browser app.
    Intent intent = new Intent(ACTION_VIEW, Uri.parse(url));
    intent.addCategory(CATEGORY_BROWSABLE);
    intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REQUIRE_NON_BROWSER |
            FLAG_ACTIVITY_REQUIRE_DEFAULT);
    startActivity(intent);
} catch (ActivityNotFoundException e) {
    // This code executes in one of the following cases:
    // 1. Only browser apps can handle the intent.
    // 2. The user has set a browser app as the default app.
    // 3. The user hasn't set any app as the default for handling this URL.
    openInCustomTabs(url);
}

Membuka file

Jika aplikasi Anda menangani file atau lampiran, seperti memeriksa apakah perangkat dapat membuka file tertentu, biasanya paling mudah untuk mencoba memulai aktivitas yang dapat menangani file tersebut. Untuk melakukannya, gunakan intent yang menyertakan tindakan intent ACTION_VIEW dan URI yang merepresentasikan file tertentu. Jika tidak ada aplikasi yang tersedia di perangkat, aplikasi Anda dapat menangkap ActivityNotFoundException. Dalam logika penanganan pengecualian, Anda dapat menampilkan error atau mencoba menangani file sendiri.

Jika aplikasi Anda harus mengetahui terlebih dahulu apakah aplikasi lain dapat membuka file tertentu, sertakan elemen <intent> dalam cuplikan kode berikut sebagai bagian dari elemen <queries> dalam manifes Anda. Sertakan jenis file jika Anda sudah mengetahui jenis file tersebut pada waktu kompilasi.

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <!-- If you don't know the MIME type in advance, set "mimeType" to "*/*". -->
  <data android:mimeType="application/pdf" />
</intent>

Selanjutnya, Anda dapat memeriksa apakah aplikasi tersedia dengan memanggil resolveActivity() menggunakan intent Anda.

Memberikan akses URI

Catatan: Rekomendasi ini berlaku untuk semua aplikasi, terlepas dari hal berikut:

  • Versi SDK target aplikasi Anda.
  • Apakah aplikasi Anda mengespor penyedia kontennya atau tidak.

Agar aplikasi yang menargetkan Android 11 atau yang lebih tinggi dapat mengakses URI konten, intent aplikasi Anda harus mendeklarasikan izin akses URI dengan menetapkan setidaknya salah satu tanda intent berikut: FLAG_GRANT_READ_URI_PERMISSION dan FLAG_GRANT_WRITE_URI_PERMISSION.

Pada Android 11 dan yang lebih tinggi, izin akses URI memberikan kemampuan berikut kepada aplikasi yang menerima intent:

  • Membaca dari, atau menulis ke, data yang diwakili URI konten, berdasarkan izin URI yang diberikan.
  • Mendapatkan visibilitas ke dalam aplikasi yang berisi penyedia konten yang cocok dengan otoritas URI. Aplikasi yang berisi penyedia konten mungkin berbeda dari aplikasi yang mengirimkan intent.

Cuplikan kode berikut menunjukkan cara menambahkan tanda intent izin URI sehingga aplikasi lain yang menargetkan Android 11 atau yang lebih tinggi dapat melihat data di URI konten:

Kotlin

val shareIntent = Intent(Intent.ACTION_VIEW).apply {
    flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    data = CONTENT_URI_TO_SHARE_WITH_OTHER_APP
}

Java

Intent shareIntent = new Intent(Intent.ACTION_VIEW);
shareIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setData(CONTENT_URI_TO_SHARE_WITH_OTHER_APP);

Membuat sharesheet kustom

Jika memungkinkan, gunakan sharesheet yang disediakan oleh sistem. Atau, sertakan elemen <intent> berikut sebagai bagian dari elemen <queries> dalam manifes Anda:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.SEND" />
  <!-- Replace with the MIME type that your app works with, if needed. -->
  <data android:mimeType="image/jpeg" />
</intent>

Jika tidak, proses pembuatan sharesheet dalam logika aplikasi Anda, seperti panggilan ke queryIntentActivities(), tidak akan berubah dibandingkan dengan versi Android sebelumnya.

Tampilkan tindakan pemilihan teks kustom

Saat pengguna memilih teks di aplikasi Anda, toolbar pemilihan teks menampilkan kumpulan operasi yang mungkin dilakukan pada teks yang dipilih. Jika toolbar ini harus menampilkan tindakan kustom dari aplikasi lain, sertakan elemen <intent> berikut sebagai bagian dari elemen <queries> dalam manifes Anda:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.PROCESS_TEXT" />
  <data android:mimeType="text/plain" />
</intent>

Menghubungkan ke mesin text-to-speech

Jika aplikasi Anda berinteraksi dengan mesin text-to-speech (TTS), sertakan elemen <intent> berikut sebagai bagian dari elemen <queries> dalam manifes Anda:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.intent.action.TTS_SERVICE" />
</intent>

Menghubungkan ke layanan pengenalan ucapan

Jika aplikasi berinteraksi dengan layanan pengenalan ucapan, termasuk elemen <intent> berikut sebagai bagian dari elemen <queries> di manifes Anda:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.speech.RecognitionService" />
</intent>

Menghubungkan ke layanan browser media

Di aplikasi browser media klien, sertakan elemen <intent> berikut sebagai bagian dari elemen <queries> dalam manifes Anda:

<!-- Place inside the <queries> element. -->
<intent>
  <action android:name="android.media.browse.MediaBrowserService" />
</intent>

Menampilkan baris data kustom untuk kontak

Aplikasi dapat menambahkan baris data kustom ke Penyedia Kontak. Agar aplikasi kontak dapat menampilkan data kustom ini, aplikasi harus dapat melakukan hal berikut:

  1. Membaca file contacts.xml dari aplikasi lain.
  2. Memuat ikon yang sesuai dengan jenis MIME kustom.

Jika aplikasi Anda adalah aplikasi kontak, sertakan elemen <intent> berikut sebagai bagian dari elemen <queries> dalam manifes Anda:

<!-- Place inside the <queries> element. -->
<!-- Allows the app to read the "contacts.xml" file from the other apps. -->
<intent>
  <action android:name="android.accounts.AccountAuthenticator" />
</intent>
<!-- Allows the app to load an icon corresponding to the custom MIME type. -->
<intent>
  <action android:name="android.intent.action.VIEW" />
  <data android:scheme="content" android:host="com.android.contacts"
        android:mimeType="vnd.android.cursor.item/*" />
</intent>

Mendeklarasikan kebutuhan visibilitas paket dalam library

Jika Anda mengembangkan library Android, Anda dapat mendeklarasikan kebutuhan visibilitas paket dengan menambahkan elemen <queries> di file manifes AAR. Elemen <queries> ini memiliki fungsionalitas yang sama seperti elemen yang dapat dideklarasikan oleh aplikasi dalam manifesnya sendiri.

Jika library Anda melibatkan komunikasi dengan aplikasi "host", seperti menggunakan layanan terikat, sertakan elemen <package> yang menentukan nama paket aplikasi host:

<!-- Place inside the <queries> element. -->
<package android:name=PACKAGE_NAME />

Dengan menyertakan deklarasi ini, Anda dapat memeriksa apakah aplikasi host sudah diinstal dan berinteraksi dengannya, misalnya dengan memanggil bindService(). Aplikasi pemanggil yang menggunakan library Anda otomatis dapat dilihat oleh aplikasi host sebagai hasil dari interaksi ini.