I'm working a background remover app from an image and upon the background removal process, I am supposed to download it to the download's folder butI keep getting the exception that no such file name found. So i tried asking for runtime permissions before downloading and i am facing an issue where my Android app is not showing the requested permissions in the app settings. I've declared the android.permission.WRITE_EXTERNAL_STORAGE permission in my AndroidManifest.xml and am requesting it at runtime using ActivityCompat.requestPermissions.
Despite this, the app settings page doesn't list the permission as requested. I've tried the following:
My build.gradle (app) file has minSdk set to 24 and targetSdk set to 34 and in my AndroidManifest file i have set targetApi to 31 and I am testing it on my OnePlus 12R device.
In order to ask for runtime permissions I am using the following code :
private fun requestRuntimePermissions() {
when {
ContextCompat.checkSelfPermission(
this@ImageStaging,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED -> {
// You can use the API that requires the permission.
Log.d("PermGrant", "Permission already granted...")
}
ActivityCompat.shouldShowRequestPermissionRationale(
this@ImageStaging, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) -> {
val builder = AlertDialog.Builder(this@ImageStaging)
builder.setMessage("Permission to write is required to download the image to your storage...")
builder.setTitle("Permission Required").setCancelable(false).setPositiveButton("OK", DialogInterface.OnClickListener { dialog, which ->
ActivityCompat.requestPermissions(this@ImageStaging, arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE), writepermcode)
dialog.dismiss()
})
builder.setNegativeButton("Cancel", DialogInterface.OnClickListener { dialog, which ->
dialog.dismiss()
})
builder.show()
}
else -> {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
ActivityCompat.requestPermissions(this@ImageStaging, arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE), writepermcode)
}
}
}
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
writepermcode -> {
// If request is cancelled, the result arrays are empty.
if ((grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// Permission is granted. Continue the action or workflow
// in your app.
Toast.makeText(this@ImageStaging, "Permission Granted!", Toast.LENGTH_SHORT).show()
} else if (!ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Explain to the user that the feature is unavailable because
// the feature requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
val builder = AlertDialog.Builder(this@ImageStaging)
builder.setMessage("Permission to write is required to download the image to your storage...")
builder.setTitle("Permission Required").setCancelable(false).setPositiveButton("OK", DialogInterface.OnClickListener { dialog, which ->
val intent: Intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri: Uri = Uri.fromParts("package", packageName, null)
intent.setData(uri)
startActivity(intent)
dialog.dismiss()
})
builder.setNegativeButton("Cancel", DialogInterface.OnClickListener { dialog, which ->
dialog.dismiss()
})
builder.show()
}
return
}
// Add other 'when' lines to check for other
// permissions this app might request.
else -> {
// Ignore all other requests.
requestRuntimePermissions()
}
}
}
Upon running the app on my device i am expecting to see the app having requested at least a single external storage request, but i am getting the following output :
Handle permissions for android 13 and above.
private fun checkStoragePermission(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val audioPermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_MEDIA_AUDIO
)
val videoPermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_MEDIA_VIDEO
)
val imagePermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_MEDIA_IMAGES
)
return audioPermission == PackageManager.PERMISSION_GRANTED && videoPermission == PackageManager.PERMISSION_GRANTED && imagePermission == PackageManager.PERMISSION_GRANTED
} else {
val storagePermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
val courseLocationPermission = ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_EXTERNAL_STORAGE
)
return storagePermission == PackageManager.PERMISSION_GRANTED && courseLocationPermission == PackageManager.PERMISSION_GRANTED
}
}
And add these lines in manfest.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>