2

I am using com.google.accompanist:accompanist-permissions:0.25.1 in my project. I am trying to request bluetooth permission in runtime which is requesting. I want to know how user know that permission is disable permanently.

Manifest.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">

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission
        android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" />
    <uses-permission
        android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" />
    <uses-permission
        android:name="android.permission.BLUETOOTH_SCAN"
        android:usesPermissionFlags="neverForLocation"
        tools:targetApi="s" />
    <!-- Needed only if your app makes the device discoverable to Bluetooth devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <!-- Needed only if your app communicates with already-paired Bluetooth devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-feature android:name="android.hardware.bluetooth" android:required="false"/>

    <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:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Permission"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.Permission">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

MainActivity.kt

package com.vivek.permission

import android.Manifest
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import com.vivek.permission.ui.theme.PermissionTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            PermissionTheme {
                // A surface container using the 'background' color from the theme
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(MaterialTheme.colorScheme.background)
                ) {
                    ExampleScreenWithAccompanist()
                }
            }
        }
    }
}

val permissionsList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    listOf(
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADMIN,
        Manifest.permission.BLUETOOTH_SCAN,
        Manifest.permission.BLUETOOTH_CONNECT,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
} else {
    listOf(
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADMIN,
        Manifest.permission.ACCESS_COARSE_LOCATION,
    )
}

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ExampleScreenWithAccompanist() {
    val multiplePermissionsState = rememberMultiplePermissionsState(permissions = permissionsList)
    Text(text = "we need your permission", color = Color.White)
    when {
        multiplePermissionsState.allPermissionsGranted -> {
            Text(text = " Permission Granted", color = Color.White)
        }
        multiplePermissionsState.shouldShowRationale -> {
            Text(text = " Permission ShouldShowRationale", color = Color.White)
        }
        !multiplePermissionsState.allPermissionsGranted && !multiplePermissionsState.shouldShowRationale -> {
            Text(
                text = "Permission permanently denied ,you can enable it by going to app setting",
                color = Color.White
            )
        }
    }

    Button(onClick = { multiplePermissionsState.launchMultiplePermissionRequest() }) {
        Text(text = "Give permission", color = Color.White)
    }
}

My 3 when statement run when user install first time the application. So how can i handle properly..

Kotlin Learner
  • 3,995
  • 6
  • 47
  • 127

1 Answers1

0

Try:

// MainActivity.kt

package com.vivek.permission

import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.vivek.permission.ui.theme.PermissionTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            PermissionTheme {
                // A surface container using the 'background' color from the theme
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(MaterialTheme.colorScheme.background)
                ) {
                    ExampleScreenWithAccompanist()
                }
            }
        }
    }
}

val permissionsList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    listOf(
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADMIN,
        Manifest.permission.BLUETOOTH_SCAN,
        Manifest.permission.BLUETOOTH_CONNECT,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
} else {
    listOf(
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADMIN,
        Manifest.permission.ACCESS_COARSE_LOCATION,
    )
}

@Composable
fun ExampleScreenWithAccompanist() {
    val requestPermissionLauncher =
        registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
            permissions.entries.forEach {
                if (it.value) {
                    Text(text = " Permission Granted", color = Color.White)
                } else {
                    Text(
                        text = "Permission permanently denied ,you can enable it by going to app setting",
                        color = Color.White
                    )
                }
            }
        }

    Button(onClick = { requestPermissionLauncher.launch(permissionsList.toTypedArray()) }) {
        Text(text = "Give permission", color = Color.White)
    }
}

Explanation: In the above code, I have used the registerForActivityResult() function to register the activity result. The registerForActivityResult() function takes two parameters, the first one is the ActivityResultContracts.RequestMultiplePermissions() and the second one is the lambda function. The lambda function takes the Map<String, Boolean> as a parameter. The Map<String, Boolean> contains the permission name as a key and the permission status as a value. The permission status is true if the permission is granted and false if the permission is denied.


You can show the rational message when the user has denied the permission and the shouldShowRequestPermissionRationale() function returns true. The shouldShowRequestPermissionRationale() function returns true if the user has denied the permission and the user has not selected the “Don’t ask again” checkbox. The following code shows how to show the rational message.

if (ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        // You can use the API that requires the permission.
    }
    else {
        if (ActivityCompat.shouldShowRequestPermissionRationale(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            )
        ) {
            // You can show the rational message.
        } else {
            // You can directly ask for the permission.
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                1
            )
        }
    }
Tibic4
  • 3,709
  • 1
  • 13