Mon. May 6th, 2024

In Android, runtime permissions refer to the permissions that an app must request from the user while the app is running in order to access sensitive data or perform certain actions. These permissions are introduced in Android 6.0 (API level 23) as a part of the Android Runtime (ART) permission model, which allows users to have more control over the permissions granted to apps.

Before Android 6.0, users had to grant all permissions at the time of installation. With runtime permissions, apps only request permissions when they are actually needed, improving user privacy and control. Here’s how runtime permissions work:

  1. Permission Groups: Permissions are grouped based on their functionality, such as location, camera, contacts, etc.
(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_CODE); }
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == CAMERA_PERMISSION_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission granted, proceed with using the camera } else { // Permission denied, handle accordingly } } }
(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { // Permission is already granted, proceed with using the camera } else { // Request permission from the user }

It’s important to note that you should provide clear explanations to the user about why your app needs the requested permissions. Users are more likely to grant permissions if they understand why they are necessary.

Also, starting from Android 10 (API level 29), some permissions like location access have more nuanced options, such as allowing access only while the app is in use, and users can choose to grant permissions in those specific contexts.

Keep in mind that Android’s permission model might have evolved since my knowledge cutoff in September 2021, so be sure to refer to the official Android documentation for the most up-to-date information.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">


        <Button
            android:id="@+id/check_permission"
            android:layout_width="match_parent"
            android:layout_centerInParent="true"
            android:layout_height="wrap_content"
            android:text="Check Permission"/>
        <Button
            android:id="@+id/request_permission"
            android:layout_below="@+id/check_permission"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Request Permission"/>
</LinearLayout>

MainActivity.kt

package com.androindian.perminssions

import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle

import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.view.View
import android.widget.Button

import android.annotation.SuppressLint
import android.app.AlertDialog
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity





class MainActivity : AppCompatActivity() {
        private var view: View? = null
        private val PERMISSION_REQUEST_CODE = 200

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val check_permission = findViewById<View>(R.id.check_permission) as Button
            val request_permission = findViewById<View>(R.id.request_permission) as Button

            check_permission.setOnClickListener {
                if (checkPermission()) {
                    Toast.makeText(this, "Permission already granted.", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, "Please request permission.", Toast.LENGTH_SHORT).show()
                }
            }

            request_permission.setOnClickListener {

               if (!checkPermission()) {
                requestPermission()
            } else {
                Toast.makeText(this, "Permission already granted.", Toast.LENGTH_SHORT).show()
            }
            }
        }





        private fun checkPermission(): Boolean {
            val result =
                ContextCompat.checkSelfPermission(this@MainActivity, android.Manifest.permission.ACCESS_FINE_LOCATION)
            val result1 = ContextCompat.checkSelfPermission(applicationContext,android.Manifest.permission.CAMERA)
            return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED
        }

        private fun requestPermission() {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CAMERA),
                PERMISSION_REQUEST_CODE
            )
        }

        @SuppressLint("MissingSuperCall")
        override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<String>,
            grantResults: IntArray
        ) {
            when (requestCode) {
                PERMISSION_REQUEST_CODE -> if (grantResults.size > 0) {
                    val locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED
                    val cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED
                    if (locationAccepted && cameraAccepted)

                                Toast.makeText(this@MainActivity,"Permission Granted, Now you can access location data and camera.",Toast.LENGTH_SHORT).show()
                     else {
                        Toast.makeText(this@MainActivity,"Permission Denied, You cannot access location data and camera.",Toast.LENGTH_SHORT).show()

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            if (shouldShowRequestPermissionRationale(android.Manifest.permission.ACCESS_FINE_LOCATION)) {
                                showMessageOKCancel(
                                    "You need to allow access to both the permissions"
                                ) { dialog, which ->
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                        requestPermissions(
                                            arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CAMERA),
                                            PERMISSION_REQUEST_CODE
                                        )
                                    }
                                }
                                return
                            }
                        }
                    }
                }
            }
        }

        private fun showMessageOKCancel(message: String, okListener: DialogInterface.OnClickListener) {
            AlertDialog.Builder(this@MainActivity)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show()
        }

}


androidmanifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:ignore="CoarseFineLocation">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
        tools:ignore="CoarseFineLocation"/>
    <uses-permission android:name="android.permission.CAMERA"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.Perminssions"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

By Rajashekar

I’m (Rajashekar) a core Android developer with complimenting skills as a web developer from India. I cherish taking up complex problems and turning them into beautiful interfaces. My love for decrypting the logic and structure of coding keeps me pushing towards writing elegant and proficient code, whether it is Android, PHP, Flutter or any other platforms. You would find me involved in cuisines, reading, travelling during my leisure hours.

Leave a Reply

Your email address will not be published. Required fields are marked *