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 支持。
解决方法是实际上忽略警告,因为它只是提供信息,因此无害。通过将 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 权限。
标志requestLegacyExternalStorage在Android 11 (API 30)中没有任何作用,它被完全忽略,并且没有解决方法。
WRITE_EXTERNAL_STORAGE 在 Android 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 倍。
尝试将其添加到您的清单中:
<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" />
使用文件 API ?
基于@PerracoLabs 回复,以下更改将使您的应用程序在运行的设备上运行
文件:“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 来源:
在进行文件操作之前,不要忘记授予运行时权限。 - Android-10 及以下版本需要。不要为 Android-11 请求运行时权限,而是为 Android-10 及更低版本请求运行时权限。
将用户导航到应用程序权限页面,以允许他使用以下代码启用文件权限(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));
}
正如 @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
}
添加行:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
并将以下代码添加到
AndroidManifest.xml
:
android:requestLegacyExternalStorage="true"
将 maxSdkVersion 设置为 32
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32"
tools:ignore="ScopedStorage" />