Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

READ_EXTERNAL_STORAGE doesn't work on Android 10

I'm trying to send a photo to the server, but I can't access the photo ONLY on Android 10. Made a READ_EXTERNAL_STORAGE request, clicked "allow", in the settings, access to storage is allowed.

Manifest

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Fragment

private fun haveStoragePermission() =
    ActivityCompat.checkSelfPermission(requireActivity(), Manifest
       .permission.READ_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED

private fun requestPermission() {
  if (!haveStoragePermission()) {
     val permissions = arrayOf(
          Manifest.permission.READ_EXTERNAL_STORAGE
     )
     ActivityCompat.requestPermissions(requireActivity(), permissions, STORAGE_REQUEST_PERMISSION)
  }
}

The path to the file is displayed in logs. It's absolute, like file:///emulated/0/...photo.jpg , it is convenient, since you can immediately upload it to the server , but Picasso and server does not accept photos , or rather it does not seem to be allowed to read (Picasso displays placeholder due to an error). This code only works if you add requestLegacyExternalStorage to the manifest. Then everything works fine at once , but this attribute disappear in Android 11. I have no idea why exactly 10 Android doesn't work , although with test devices on 7, 8 , 6 everything is OK.

//Get images code
private fun getAllShownImagesPath(activity: Activity): ArrayList<String> {
    val listOfAllImages = ArrayList<String>()
    val uri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val projection = arrayOf(
        MediaColumns.DATA,
        MediaStore.Images.Media.BUCKET_DISPLAY_NAME
    )
    val cursor = activity.contentResolver.query(
        uri, projection, null,
        null,"${MediaStore.Images.Media.DATE_TAKEN} DESC"
    )
    val columnIndexData = cursor!!.getColumnIndexOrThrow(MediaColumns.DATA)
    while (cursor.moveToNext()) {
        val absolutePathOfImage = cursor.getString(columnIndexData)
        listOfAllImages.add("file://$absolutePathOfImage")
    }
    return listOfAllImages
}
like image 696
Janey Springs Avatar asked Jul 26 '20 09:07

Janey Springs


2 Answers

This code only works if you add requestLegacyExternalStorage to the manifest.

So, add android:requestLegacyExternalStorage="true" to the <application> element in the manifest.

Then everything works fine at once , but this attribute disappear in Android 11

In Android 11+, to a large extent, READ_EXTERNAL_STORAGE works as it did in Android 9 and below. There will be some more areas that are off-limits, though.

What Google would prefer that you do is to stop thinking in terms of files and the filesystem, and instead use the Storage Access Framework (e.g., ACTION_OPEN_DOCUMENT).

like image 146
CommonsWare Avatar answered Oct 07 '22 03:10

CommonsWare


By default, apps targeting Android 10 and higher are given scoped access into external storage, or scoped storage. Such apps can see the files within an external storage device without needing to request any storage-related user permissions But you can add following property in activity xml to fallback to old behavior.

android:requestLegacyExternalStorage="true"

<activity android:name="..... android:requestLegacyExternalStorage="true">

But this will not be available for long time. You have to handle this according to new specifications for more details https://developer.android.com/about/versions/10/privacy/changes

like image 33
alokHarman Avatar answered Oct 07 '22 02:10

alokHarman