针对 Android 10 时的 WRITE_EXTERNAL_STORAGE

问题描述 投票:0回答:6

AS 中有关于

android.permission.WRITE_EXTERNAL_STORAGE
的 lint 警告。该警告表示,当针对 Android 10 及更高版本时,该权限将不再提供写入访问权限。删除上述权限仍然可以在内部存储文件夹
Pictures/MY_APP_NAME
中写入来保存图像,但它仅适用于Android 10(SDK 29)和/或更高版本(尚未在Android R上测试)。当我在较低版本(例如 Android M(SDK 23))上再次测试它时,保存图像停止工作,因此我决定返回
android.permission.WRITE_EXTERNAL_STORAGE
,因此警告再次出现。是否有可能 lint 只是误报,错误地诊断了不同情况下的问题?因为目前我的支持 SDK 从 21 开始,最新为 30,但 lint 仅指出在针对 Android 10(SDK 29)时不再需要它,并且没有考虑回顾项目的最低 SDK 支持。

android android-permissions
6个回答
135
投票

解决方法是实际上忽略警告,因为它只是提供信息,因此无害。通过将 maxSdkVersion 设置为 28 无需再担心。

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />

请注意,使用其他答案中所述的 android:requestLegacyExternalStorage 标志并不是解决方案,只是一个临时补丁,在 Android 11 (API 30) 和未来版本

中将不再起作用。

更新,澄清一些开发者在评论中表现出的疑问和困惑:

  • 如果在 Android 10 (API 29) 中使用 requestLegacyExternalStorage 标志,则照常请求 WRITE_EXTERNAL_STORAGE 权限。

  • 标志requestLegacyExternalStorageAndroid 11 (API 30)中没有任何作用,它被完全忽略,并且没有解决方法。

  • WRITE_EXTERNAL_STORAGEAndroid 11 (API 30) 中不会授予任何权限,它根本不执行任何操作,因此在 API 11 中,您需要将 maxSdkVersion 设置为 29

  • 如果在 Android 10 (API 29) 中您也没有使用 requestLegacyExternalStorage,则将 maxSdkVersion 设置为 28 而不是 29

  • Android 11 (API 30) 开始,旧的 File API 可以再次使用,但“仅”在访问公共“共享存储”文件夹(DCIM、音乐等)或您的应用程序“私有”时使用“ 目录。对于其他位置,需要DocumentFile API。

  • 考虑到文件 API 现在在 Android 11 (API 30) 中要慢得多,因为已被重构为本质上成为包装器。这是为了强制仅在允许的位置使用它。因此,它不再是一个快速的系统文件 API,而只是一个在内部将工作委托给 MediaStore 的包装器。在 Android 11 或更高版本中使用 File API 时,您应该考虑性能损失,因为根据 Android 团队的说法,它会比直接访问 MediaStore 慢 2 到 3 倍。


30
投票

尝试将其添加到您的清单中:

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true" //Add this Line
android:label="@string/app_name">

 ---------<Activity, Sevices or Recivers>----------

</application>

并再次删除

READ_EXTERNAL_STORAGE
权限:

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

27
投票

使用文件 API ?

基于@PerracoLabs 回复,以下更改将使您的应用程序在运行的设备上运行

  1. Android-9 及以下
  2. Android-10
  3. Android-11及以上版本

文件:“AndroidManifest.xml”

<!-- Without this folders will be inaccessible in Android-11 and above devices -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<!-- Without this entry storage-permission entry will not be visible under app-info permissions list Android-10 and below -->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29"
tools:ignore="ScopedStorage"/>

<!-- Without this entry the folders will remain in-accessible in Android-10, even if WRITE_EXTERNAL_STORAGE as above is present. -->
<application
    android:requestLegacyExternalStorage="true"/>

Java 来源:

  1. 在进行文件操作之前,不要忘记授予运行时权限。 - Android-10 及以下版本需要。不要为 Android-11 请求运行时权限,而是为 Android-10 及更低版本请求运行时权限。

  2. 将用户导航到应用程序权限页面,以允许他使用以下代码启用文件权限(Android-11 及更高版本支持所需):

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && false == Environment.isExternalStorageManager()) {
         Uri uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID);
         startActivity(new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri));
     }
    

15
投票

正如 @PerracoLabs 所回答的,该警告仅供参考。如果你一开始就阅读他的答案会更好。 https://stackoverflow.com/a/65477206/6055194

我使用

WRITE_EXTERNAL_STORAGE
权限仅用于将.pdf文件下载到
Downloads
和应用程序“私有”目录
通过使用
DownloadManager
(这很重要,如果你阅读@PerracoLabs答案下的讨论,你就可以理解为什么)。因此,我刚刚为此权限添加了 SDK 的最大级别,并忽略了范围存储的标记。

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />

附注如果

tools
标签无法识别,那么您必须通过将
xmlns:tools="http://schemas.android.com/tools"
添加到 AndroidManifest.xml 来声明它,如下所示。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.app.my">

但您必须注意,在

onRequestPermissionsResult
及更高版本(API 29+)之后,将不会调用
Build.VERSION_CODES.Q
函数。 所以只有低于29的API才需要调用请求权限
WRITE_EXTERNAL_STORAGE

所以你可以像这样添加检查写入外部存储功能(Kotlin)。

   private fun hasWriteStoragePermission(): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            return true
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(activity!!, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(
                        arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                        REQUEST_PERMISSIONS_CODE_WRITE_STORAGE
                )

                return false
            }
        }

        return true
    }

1
投票

添加行:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>

并将以下代码添加到

AndroidManifest.xml

 android:requestLegacyExternalStorage="true"

0
投票

maxSdkVersion 设置为 32

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="32"
    tools:ignore="ScopedStorage" />
© www.soinside.com 2019 - 2024. All rights reserved.