安卓11及以上版本读取本地文件的方法
前言
在安卓10.0及以上,系统新增了沙盒模式,进一步增强了用户的隐私性以及开发的规范性。但是在10.0时,我们可以在AndroidManifest.xml中添加 android:requestLegacyExternalStorage=“true” 的方式,把沙盒模式关闭继续使用9.0及以下的方式去读取本地文件。但是在11.0开始,该方式将不在起作用,我们就需要去适配沙盒模式。
本篇博客借鉴了郭霖大神的博客。郭霖YYDS
一、沙盒模式
什么是沙盒模式?详细可见官方文档数据和文件存储概览。
我从文档中总结了关于APP可使用的存储方式,包括data/data 内部存储目录、缓存目录、应用外部专属目录、Download共享目录等。
在我尝试去使用外部的Download目录时我发现一个问题:既然文档上说可以通过Downlaod共享目录去读取外部文件,那么是不是说任意的外部文件只要我放在Download中我都能读取呢? 结果很明显,我失败了(只能拿到应用本身创建、系统文件例如照片、视频等,其他APP产生的文件或外部手动导入的文件均拿不到)那么11.0以上我们怎么才能获取到本地想要的文件呢? 往下看。
二、开始黑科技
1.权限申请
代码如下(示例):
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
前两个读写权限就不说了,重点戏是第三个MANAGE_EXTERNAL_STORAGE 管理外部存储权限。
该权限属于特殊权限需要用户手动去设置中打开,代码如下。
private fun checkStorageManagerPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R ||
Environment.isExternalStorageManager()
) {
Toast.makeText(this, "已获得访问所有文件权限", Toast.LENGTH_SHORT).show()
} else {
val builder = AlertDialog.Builder(this)
.setMessage("本程序需要您同意允许访问所有文件权限")
.setPositiveButton("确定") { _, _ ->
val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
startActivity(intent)
}
builder.show()
}
}
代码中用 Environment.isExternalStorageManager() 来判断APP是否拥有该权限,若无此权限,则将页面手动跳转至设置页面,让用户手动打开该权限,如下图。
需要用户手动“授予所有文件的管理权限”打开,下面我么开始测试能否读取任意文件,并想9.0及以下用文件的绝对路径去操作该文件。
2.开始操作
代码如下(示例):
val rootPath =
getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath
Log.e(">>>", rootPath)
val listFiles = File(rootPath).listFiles()
listFiles?.forEach {
Log.e(">>>", it.name)
if (it.name == "test") {
Log.e(">>>", it.name)
it.listFiles()?.forEach { file ->
Log.e(">>>", file.name)
if (file.name == "1.jpg") {
startActivity(MainActivity2.getActivity(this, file.absolutePath))
finish()
}
}
}
我们在请求权限的if判断后,添加这些代码。去获取Download共享目录下所有的文件,并手动创建一个test的文件夹,并在其中还防止一张名为1.jpg的图片供MainActivity2放问并展示,如下图。
接下来我们执行代码,看看日志有没有把所有Download目录下所有文件打印出来。
可以看见Download目录下的所有文件我们都成功获取到了,并且也找到了test文件夹以及其中的1.jpg,如下图。说明APP拥有该权限后,沙盒模式将不在阻拦我们拿取任意文件。
总结
经过上面的一些简单测试,我们不难发现当我们申请 MANAGE_EXTERNAL_STORAGE 管理外部存储权限 后,完全可以当做之前外部存储的方式去读取,完美解决沙盒模式对拿取外部的非APP创建的文件的困扰。
PS.若小伙伴们需要把APP发布到谷歌商店中,慎重使用该权限,因为该权限本为浏览器或本地文件操作器类型的APP设计,所以一般APP申请该权限,谷歌可能不会同意。
最后文章或代码中若有问题,欢迎大家指正或在评论下一起探讨沙盒模式的相关问题。
相关文章
- Java服务器、android连接小票打印机打印(亲测可用)
- 卢益贵(码客):游戏高度可配置化(一)——通用数据引擎(data-e)及其在模块化游戏开发中的应用构想图解
- 微信开发者工具在C盘下User Data有啥用,能删掉吗?占用空间超大
- 【Spring框架】Spring概述及基本应用
- 微信小程序搭建流程
- Android 录屏 实现
- 微信小程序开发学习笔记
- Golang 实现http协议的心跳检测程序
- 微信小程序语言与web开发语言的区别
- Android Studio开发APP
- Android学习总结
- 微信小程序|基于小程序+云开发制作一个菜谱小程序
- E4A影视APP源码电视盒子酷点TV版4.5 后端对接苹果cms
- 堆结构的两个应用
- 10分钟搞定win11安卓子系统
- 【历史上的今天】3 月 9 日:AlphaGo 成名之战;Mac 电脑设计者诞生;谷歌收购 Writely
- 【SCL】for循环指令的应用&三层电梯模拟控制
- 手机忘记密码解锁的 6 大软件方法
- AndroidStudio案例——简单计算器
- Flutter IOS 新建打包发布全流程 2023 版