Meminta Izin Aplikasi

Setiap aplikasi Android berjalan dalam sandbox dengan akses terbatas. Jika harus menggunakan resource atau informasi di luar sandbox miliknya, aplikasi harus meminta izin yang sesuai. Untuk mendeklarasikan bahwa aplikasi Anda memerlukan izin, cantumkan izin dalam manifes aplikasi lalu minta pengguna untuk menyetujui setiap izin pada waktu proses (di Android 6.0 dan lebih tinggi).

Halaman ini menjelaskan tentang cara menggunakan Library Dukungan Android untuk memeriksa dan meminta izin. Framework Android menyediakan metode yang serupa dengan Android 6.0 (API level 23), tetapi dengan library dukungan, penyediaan kompatibilitas dengan versi Android lama menjadi lebih mudah.

Menambahkan izin ke manifes

Pada semua versi Android, untuk mendeklarasikan bahwa aplikasi Anda memerlukan izin, letakkan elemen <uses-permission> dalam manifes aplikasi, sebagai turunan dari elemen <manifest> tingkat atas. Misalnya, aplikasi yang perlu mengakses internet akan memiliki baris berikut dalam manifes:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.example.snazzyapp">

        <uses-permission android:name="android.permission.INTERNET"/>
        <!-- other permissions go here -->

        <application ...>
            ...
        </application>
    </manifest>
    

Perilaku sistem setelah Anda mendeklarasikan izin bergantung pada seberapa sensitif izin tersebut. Beberapa izin dianggap "normal" sehingga sistem langsung mengizinkannya pada saat penginstalan. Izin lainnya dianggap "berbahaya" sehingga pengguna harus mengizinkan akses aplikasi secara eksplisit. Untuk informasi selengkapnya tentang berbagai jenis izin, lihat Tingkat perlindungan.

Memeriksa izin

Jika aplikasi membutuhkan izin berbahaya, Anda harus memeriksa apakah Anda memiliki izin tersebut setiap kali melakukan operasi yang membutuhkannya. Mulai dari Android 6.0 (API level 23), pengguna bisa mencabut izin dari aplikasi apa pun kapan saja, bahkan meskipun aplikasi menargetkan level API yang lebih rendah. Jadi, meskipun aplikasi menggunakan kamera kemarin, aplikasi tidak bisa menganggap izin tersebut masih dimilikinya hari ini.

Untuk memeriksa apakah Anda memiliki izin, panggil metode ContextCompat.checkSelfPermission(). Sebagai contoh, cuplikan berikut menunjukkan cara memeriksa apakah aktivitas memiliki izin untuk menulis ke kalender:

Kotlin

    if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR)
            != PackageManager.PERMISSION_GRANTED) {
        // Permission is not granted
    }
    

Java

    if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR)
            != PackageManager.PERMISSION_GRANTED) {
        // Permission is not granted
    }
    

Jika aplikasi memiliki izin, metode akan mengembalikan PERMISSION_GRANTED, dan aplikasi dapat melanjutkan operasi. Jika aplikasi tidak memiliki izin, metode akan mengembalikan PERMISSION_DENIED, dan aplikasi harus meminta izin ke pengguna secara eksplisit.

Meminta izin

Ketika aplikasi menerima PERMISSION_DENIED dari checkSelfPermission(), Anda harus meminta izin tersebut dari pengguna. Android menyediakan beberapa metode yang dapat digunakan untuk meminta izin, seperti requestPermissions(), sebagaimana ditunjukkan dalam cuplikan kode di bawah ini. Memanggil metode ini akan menampilkan dialog Android standar yang tidak dapat disesuaikan.

Tampilan yang akan dilihat oleh pengguna bergantung pada versi perangkat Android serta versi target aplikasi, seperti yang dijelaskan dalam Ringkasan Izin.

Menjelaskan mengapa aplikasi membutuhkan izin

Dalam situasi tertentu, Anda ingin membantu pengguna untuk memahami mengapa aplikasi Anda memerlukan izin. Misalnya, jika meluncurkan aplikasi fotografi, pengguna mungkin tidak akan terkejut jika aplikasi meminta izin untuk menggunakan kamera, tetapi mereka mungkin tidak paham mengapa aplikasi juga menginginkan akses ke lokasi atau kontak pengguna. Sebelum aplikasi meminta izin, Anda harus mempertimbangkan untuk memberikan penjelasan kepada pengguna. Perlu diingat bahwa Anda tidak boleh membingungkan pengguna dengan penjelasan Anda; jika terlalu panjang, pengguna mungkin merasa aplikasi tersebut cukup sulit lalu menghapusnya.

Satu pendekatan yang mungkin Anda gunakan adalah memberikan penjelasan hanya jika pengguna telah menolak permintaan izin tersebut. Android menyediakan sebuah metode utilitas, shouldShowRequestPermissionRationale(), yang menghasilkan nilai true jika pengguna telah menolak permintaan, dan menghasilkan nilai false jika pengguna telah menolak izin dan memilih opsi Jangan tanya lagi dalam dialog permintaan izin, atau jika kebijakan perangkat melarang izin tersebut.

Jika pengguna tetap mencoba untuk menggunakan fungsi yang memerlukan izin tetapi terus menolak permintaan izinnya, kemungkinan mereka tidak memahami mengapa aplikasi memerlukan izin untuk menyediakan fungsionalitas tersebut. Dalam situasi seperti ini, memberikan penjelasan akan menjadi solusi yang tepat.

Saran lebih lanjut tentang cara membuat pengalaman pengguna yang baik ketika meminta izin disediakan dalam Praktik Terbaik Izin Aplikasi.

Meminta izin yang dibutuhkan

Jika belum memiliki izin yang dibutuhkan, aplikasi Anda harus memanggil salah satu metode requestPermissions() untuk meminta izin yang tepat. Aplikasi meneruskan izin yang diinginkan dan kode permintaan bilangan bulat yang Anda tentukan untuk mengidentifikasi permintaan izin ini. Metode ini berfungsi secara asinkron. Metode langsung mengembalikan hasil, dan setelah pengguna merespons permintaan, sistem akan memanggil metode callback aplikasi dengan hasilnya, meneruskan kode permintaan seperti yang diteruskan oleh aplikasi ke requestPermissions().

Kode berikut ini memeriksa apakah aplikasi memiliki izin untuk membaca kontak pengguna. Jika tidak, kode akan memeriksa apakah penjelasan tentang alasan diperlukannya izin harus ditunjukkan, dan jika tidak memerlukan penjelasan, izin akan diminta:

Kotlin

    // Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED) {

        // Permission is not granted
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
                Manifest.permission.READ_CONTACTS)) {
            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
        } else {
            // No explanation needed, we can request the permission.
            ActivityCompat.requestPermissions(thisActivity,
                    arrayOf(Manifest.permission.READ_CONTACTS),
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS)

            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    } else {
        // Permission has already been granted
    }
    

Java

    // Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED) {

        // Permission is not granted
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
                Manifest.permission.READ_CONTACTS)) {
            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
        } else {
            // No explanation needed; request the permission
            ActivityCompat.requestPermissions(thisActivity,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);

            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    } else {
        // Permission has already been granted
    }
    

Permintaan yang ditunjukkan oleh sistem menjelaskan grup izin yang perlu diakses oleh aplikasi Anda, bukan izin khusus.

Catatan: Saat aplikasi memanggil requestPermissions(), sistem akan menampilkan kotak dialog standar kepada pengguna. Aplikasi Anda tidak bisa mengonfigurasi atau mengubah kotak dialog tersebut. Jika perlu memberikan informasi atau penjelasan kepada pengguna, Anda harus melakukannya sebelum memanggil requestPermissions(), seperti yang dijelaskan dalam Menjelaskan mengapa aplikasi memerlukan izin.

Menangani respons permintaan izin

Ketika pengguna merespons permintaan izin aplikasi, sistem akan memanggil metode onRequestPermissionsResult() aplikasi Anda, yang meneruskan respons pengguna kepadanya. Aplikasi harus mengganti metode tersebut untuk mengetahui apakah izin telah diberikan. Callback menerima kode permintaan yang sama seperti yang Anda teruskan ke requestPermissions(). Misalnya, jika suatu aplikasi meminta akses READ_CONTACTS, aplikasi mungkin memiliki metode callback sebagai berikut:

Kotlin

    override fun onRequestPermissionsResult(requestCode: Int,
            permissions: Array<String>, grantResults: IntArray) {
        when (requestCode) {
            MY_PERMISSIONS_REQUEST_READ_CONTACTS -> {
                // If request is cancelled, the result arrays are empty.
                if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                } else {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return
            }

            // Add other 'when' lines to check for other
            // permissions this app might request.
            else -> {
                // Ignore all other requests.
            }
        }
    }
    

Java

    @Override
    public void onRequestPermissionsResult(int requestCode,
            String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                } else {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request.
        }
    }
    

Kotak dialog yang ditampilkan oleh sistem menjelaskan grup izin yang perlu diakses aplikasi Anda; izin khususnya tidak dicantumkan. Misalnya, jika Anda meminta izin READ_CONTACTS, kotak dialog sistem hanya akan mengatakan bahwa aplikasi Anda memerlukan akses ke kontak perangkat. Pengguna hanya perlu memberikan izin satu kali untuk setiap grup izin. Jika aplikasi Anda meminta izin lain dalam grup tersebut (yang tercantum dalam manifes aplikasi), sistem akan otomatis memberikannya. Ketika Anda meminta izin tersebut, sistem akan memanggil metode callback onRequestPermissionsResult() dan meneruskan PERMISSION_GRANTED dengan cara yang sama seperti jika pengguna telah secara eksplisit mengizinkan permintaan melalui kotak dialog sistem.

Catatan: Aplikasi Anda masih harus secara eksplisit meminta setiap izin yang dibutuhkan, meskipun pengguna telah memberikan izin lain dalam grup yang sama. Selain itu, pengelompokan izin ke dalam grup dapat berubah dalam rilis Android mendatang. Kode tidak boleh bergantung pada asumsi bahwa izin tertentu ada atau tidak ada dalam grup yang sama.

Misalnya, anggaplah Anda mencantumkan READ_CONTACTS dan WRITE_CONTACTS dalam manifes aplikasi. Jika Anda meminta READ_CONTACTS dan pengguna memberikan izin, lalu Anda meminta WRITE_CONTACTS, sistem akan langsung memberi Anda izin itu tanpa berinteraksi dengan pengguna.

Jika pengguna menolak permintaan izin, aplikasi Anda harus melakukan tindakan yang tepat. Misalnya, aplikasi mungkin menampilkan dialog yang menjelaskan mengapa tindakan yang diminta pengguna tidak bisa dilakukan karena membutuhkan izin tersebut.

Ketika sistem meminta pengguna untuk memberikan izin, pengguna memiliki opsi untuk memberi tahu sistem agar tidak meminta izin tersebut lagi. Dalam situasi ini, setiap kali aplikasi menggunakan requestPermissions() untuk meminta izin tersebut lagi, sistem akan langsung menolaknya. Sistem memanggil metode callback onRequestPermissionsResult() dan meneruskan PERMISSION_DENIED dalam cara yang sama seperti jika pengguna telah secara eksplisit menolak permintaan Anda lagi. Metode ini juga akan menghasilkan nilai false jika kebijakan perangkat melarang aplikasi untuk memiliki izin tersebut. Artinya, ketika memanggil requestPermissions(), Anda tidak boleh beranggapan bahwa interaksi langsung dengan pengguna telah terjadi.

Untuk memberikan pengalaman pengguna terbaik saat meminta izin aplikasi, lihat juga Praktik Terbaik Izin Aplikasi.

Mendeklarasikan izin berdasarkan level API

Untuk mendeklarasikan izin pada perangkat yang mendukung izin waktu proses saja, yaitu perangkat yang menjalankan Android 6.0 (API level 23) atau lebih tinggi, sertakan tag uses- permission-sdk-23, bukan tag uses-permission.

Saat menggunakan salah satu tag ini, Anda bisa menetapkan atribut maxSdkVersion untuk menetapkan bahwa, pada perangkat dengan versi yang lebih tinggi, izin tertentu tidak diperlukan.

Referensi lainnya

Untuk informasi tambahan tentang izin, baca artikel berikut:

Untuk mempelajari cara meminta izin selengkapnya, download sampel aplikasi berikut: