I'm trying to request the permissions that my app needs but I can't get the permission window to appear. Here is my composable :
@Composable
fun IntroScreen(
introViewModel: IntroViewModel = hiltViewModel(),
navController: NavController
){
val requestPermissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissionsMap ->
permissionsMap.forEach { (permission, isGranted) ->
Log.i("tag", "Permission: $permission, Granted: $isGranted")
}
}
val permissions = introViewModel.permissions
val permissionsState by introViewModel.permissionsState.collectAsState()
Column(
modifier = Modifier
.fillMaxWidth(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
){
Button(onClick = {
Log.i("tag", "Permissions state: ${permissionsState.joinToString(separator = ", ")}")
val allPermissionsGranted = permissionsState.all { it }
Log.i("tag", "All permissions granted: $allPermissionsGranted")
if (!allPermissionsGranted) {
// Request permissions
Log.i("tag", "Requesting permissions inside if statement: ${permissions.joinToString(", ")}")
requestPermissionLauncher.launch(permissions)
} else {
Log.i("tag", "All permissions already granted")
}
}, shape = Shapes.small) {
Text(text = "Ask Permissions")
}
}
Here is my view model:
@HiltViewModel
class IntroViewModel @Inject constructor(private val context: Context, introInteractor:IntroInteractor):ViewModel(){
private val _permissionsState = MutableStateFlow(emptyList<Boolean>())
val permissionsState: StateFlow<List<Boolean>> get() = _permissionsState
val permissions = arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_ADVERTISE,
Manifest.permission.POST_NOTIFICATIONS,
Manifest.permission.CAMERA,
Manifest.permission.INTERNET
)
init {
updatePermissionsState()
}
fun updatePermissionsState() {
val permissionsStateList = permissions.map { permission ->
ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
}
_permissionsState.value = permissionsStateList
}
}
I made the code as simple as I could. And all the logged statement returns the expected results. The Internet, bluetooth and bluetooth permissions are true and the rest are false. I tried removing the ones that are true, but I didn't get the window to appear. My code reaches the "requestPermissionLauncher.launch(permissions)" and the parameters for the launch() are correct. Why can't I get the window to appear?
This is the log result inside my if statement before my launcher: "Requesting permissions inside if statement: android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_FINE_LOCATION, android.permission.ACCESS_BACKGROUND_LOCATION, android.permission.BLUETOOTH, android.permission.BLUETOOTH_ADMIN, android.permission.BLUETOOTH_SCAN, android.permission.BLUETOOTH_ADVERTISE, android.permission.POST_NOTIFICATIONS, android.permission.CAMERA, android.permission.INTERNET ".
N.B.: I'm testing on a real Galaxy A14 and my manifest file is :
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false"/>
After spending few hours got the root cost of the issue , that is ACCESS_BACKGROUND_LOCATION
permission.
From here
ACCESS_BACKGROUND_LOCATION
permission shouldn't be requested before the general location permission was granted (ACCESS_FINE_LOCATION
orACCESS_COARSE_LOCATION
). Otherwise, the system will just ignore the request.
so create separate ACCESS_BACKGROUND_LOCATION
permission launcher and run after success of (ACCESS_FINE_LOCATION
or ACCESS_COARSE_LOCATION
)
More details Background location access checklist