READ_EXTERNAL_STORAGE 不适用于 Android 10

READ_EXTERNAL_STORAGE doesn't work on Android 10

我正在尝试将照片发送到服务器,但我无法仅在 Android 上访问照片 10. 发出 READ_EXTERNAL_STORAGE 请求,单击“允许”,在设置,允许访问存储。

清单

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

片段

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)
  }
}

文件路径显示在日志中。绝对的,像file:///emulated/0/...photo.jpg,很方便,因为你可以立即上传到服务器,但是毕加索和服务器不接受照片,或者更确切地说,它似乎不允许阅读(毕加索显示占位符由于一个错误)。此代码仅在您将 requestLegacyExternalStorage 添加到清单时才有效。然后一切立即正常,但此属性在 Android 11 中消失。我不知道为什么 10 Android 不起作用,尽管在 7、8、6 上使用测试设备一切正常。

//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
}

默认情况下,面向 Android 10 及更高版本的应用程序被授予对外部存储或范围存储的范围访问权限。此类应用无需请求任何与存储相关的用户权限即可查看外部存储设备中的文件 但是您可以在 activity xml 中添加以下 属性 以回退到旧行为。

android:requestLegacyExternalStorage="真"

但这将长期不可用。您必须根据新规范处理此问题以获取更多详细信息 https://developer.android.com/about/versions/10/privacy/changes

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

因此,将 android:requestLegacyExternalStorage="true" 添加到清单中的 <application> 元素。

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

在 Android 11+ 中,在很大程度上,READ_EXTERNAL_STORAGE 的工作方式与在 Android 9 及以下版本中的工作方式相同。不过,还有一些区域是禁区。

Google 希望您做的是停止考虑文件和文件系统,而是使用存储访问框架(例如,ACTION_OPEN_DOCUMENT)。