数据存储简述

名称 作用 详细说明
应用专属存储空间 存储应用专属的文件 专属存储空间可以在内部存储和外部存储为用户开辟专属的目录,可以用来存储其它用户不能访问的文件,可以通过File api访问,应用被卸载后文件同时被删除,访问不需要权限
共享存储 存储所有应用共享的数据 存储您的应用打算与其他应用共享的文件,包括媒体、文档和其他文件,可以使用MediaStoreapi访问,应用卸载数据仍然存在,访问需要申请存储权限

外部存储空间的使用

使用外部专属存储空间

android4.4-android9的版本之中,应用被分配了外部专属存储空间,这个空间无需权限即可访问,如果应用想访问其它应用的外部专属存储空间(分区存储),那么需要申请存储权限。

android10以上的版本中,应用的外部存储空间成为了应用的私有空间,任何应用不可以访问其它应用的专属存储空间

  1. 特性

外部专属存储空间位于应用的外部存储中,我们可以在不申请权限的情况下访问外部专属存储空间,外部专属存储空间可以在应用卸载后被删除,专属空间目录媒体文件通常不应该被相册等媒体应用收录(也就是说相册中不会展示这个目录下的图片)(我们自定义的图片选择器也不应该扫描这个目录下的图片)

在低于 android10 的版本中,这个目录是对所有应用可见的

  1. 访问方式

获取目录路径:

  • getExternalFilesDir(""):/storage/emulated/0/Android/data/com.ananananzhuo.storage10demo/files

  • getExternalFilesDirs():获取目录下所有文件的列表

  1. 使用 demo
 val file = File(getExternalFilesDir(""),"安安安安安卓.txt")val fos = FileOutputStream(file)fos.write("公众号:安安安安安卓".toByteArray(Charsets.UTF_8))fos.close()

上面的代码中会在外部专属存储目录(/storage/emulated/0/Android/data/com.ananananzhuo.storage10demo/files)下创建一个安安安安安卓.txt的文件,这里我们没有声明和申请任何权限。执行代码后去看文件选择器中的展示如下:

在外部存储中访问非私有目录则必须声明申请权限
下面我们写一个反面案例

  1. 代码
 ItemData(title = "访问外部存储空间",{val file = File(Environment.getExternalStorageDirectory().absolutePath)val fileAn = File(file,"安安安.txt")logEE(file.absolutePath)val fos = FileOutputStream(fileAn)fos.write("公众号:安安安安安卓".toByteArray(Charsets.UTF_8))fos.close()})
  1. 运行后崩溃日志
    提示没有权限

将媒体文件存储在外部专属存储目录的媒体文件夹中

将图片存储到图片文件夹中

  1. 代码
val picFile = getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.apply {if (!exists()) {mkdirs()}}val file = File(picFile,"pic.jpg")FileOutputStream(file).apply {write(12)flush()close()}
  1. 结果

成功存储文件

媒体文件夹还有其他选项:

  • Environment.DIRECTORY_MOVIES
  • Environment.DIRECTORY_DOWNLOADS
  • Environment.DIRECTORY_DOCUMENTS
  • Environment.DIRECTORY_SCREENSHOTS

存储媒体的时候我们应该尽量使用 Environment 中的字符串常量获取媒体文件目录

android10 以上版本能否使用 Environment.getExternalStorageDirectory 存取文件

高于android10的版本无法使用getExternalStorageDirectory api操作文件,因为 api 已经被删除,低于android10可以继续使用该 api

那么高于android10的版本我们应该如何访问这部分的文件呢?别急,后续的共享存储会详细说明

  1. 代码

  1. 效果图

android10以上版本如何获取sd卡中普通目录的图片

我们可以通过SAF在android11以上版本获取普通目录图片(即非专属目录,非共享目录的图片)

本例中的方法不适用于android10以下系统版本(强行使用会崩溃

  1. 代码
 override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_directory_scan11)findViewById<Button>(R.id.btn_secletdirectory).setOnClickListener {val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)intent.addCategory(Intent.CATEGORY_OPENABLE)intent.type = "image/jpeg"startActivityForResult(intent, 100)//跳转系统浏览器}}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)data?.data?.let {iv.setImageURI(it)//通过url处理图片}}
  1. 效果

内部存储

使用 openFileOutput 和 openFileInput 操作内部存储

将一个文件存储到内部存储的 files 目录下

  1. 代码
openFileOutput("安安安安卓openfileoutput.txt", MODE_PRIVATE).apply {write("openFileOutput方法输入流".toByteArray(Charsets.UTF_8))flush()close()
}
  1. 执行后文件查看

openFileInput 方法和 openFileOutput 一样的使用方式

fileList 获取内部存储全部文件路径

  1. 代码
ItemData(title = "获取目录中所有文件路径",{fileList().forEach {logEE("文件路径:$it")}})
  1. 输出日志
E/安安安安卓: 文件路径:安安安安卓openfileoutput.txt

getCacheDir 获取内部存储缓存文件

内部存储缓存中的文件可能会在应用被卸载后被删除,也可能在未卸载前被删除(内部存储空间不足的情况)。所以我们使用内部存储空间缓存文件的时候需要先判断文件是否存在

context.getCacheDir()

共享存储空间(android10 以上版本)

媒体

android10以上将媒体文件文件按类型保存在公共目录上,可以使用 MediaStore 访问媒体文件

以下表格列举所有共享媒体文件类型

媒体类型 位置 备注
图片 存储在 Pictures 和 DICM 目录中,系统将这些文件存放在 MediaStore.Images 中
视频 存储 DICM、Movies、Pictures 目录中,系统将这些文件添加到 MediaStore.VIDEO 表中
音频文件 存储在 Alarms、Audiobooks、Music、Notifications、Podcasts、Ringtones 目录中,系统将这些文件添加到 MediaStore.Audio 表中
下载文件 存储在 Download 目录下,系统将这些文件添加到 MediaStore.Download 表中 低于 android10 的版本中不可用
文件集合 存在于 MediaStore.Files 表中 如果使用了分区存储,这个集合只会显示本应用创建的照片、视频、音频文件

开启分区存储权限,媒体的处理

如果应用使用分区存储,您需要在应用的清单中声明 ACCESS_MEDIA_LOCATION 权限,然后在运行时申请此权限。申请方法后面会讲

编写一个相册

  1. 首先需要获取共享存储中所有的图片地址,代码如下
 private fun getGallaryData(): MutableList<Image> {val cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,null, null, null, "${MediaStore.Images.Media.DISPLAY_NAME} ASC")val tempdatas = mutableListOf<Image>()cursor?.use {val idColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media._ID)val nameColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)while (it.moveToNext()) {val id = it.getLong(idColumn)val contentUrl =ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)val name = it.getString(nameColumn)val image = Image(contentUrl, "")tempdatas.add(image)logEE("文件名:${contentUrl.path}")}it.close()}return tempdatas}
  1. 在协程中获取图片 uri,并展示到适配器上
private fun initData() {lifecycleScope.launch(Dispatchers.IO) {datas.addAll(getGallaryData())withContext(Dispatchers.Main) {recycle.adapter?.notifyDataSetChanged()}}}
  1. 效果

关于android11版本MANAGE_EXTERNAL_STORAGE权限

android10的版本是不能访问所有文件的,可能google也意识到这是不合理的,所以在android11的版本上重新支持了所有文件的访问

android11的系统版本上,如果想扫描应用的所有文件,那么可以声明MANAGE_EXTERNAL_STORAGE权限

MANAGE_EXTERNAL_STORAGE权限需要使用Intent进行权限申请,会跳转到一个系统页面确认权限

需要说明的是:这种方式可以访问共享存储中的文件,但是不可以访问专属存储目录中的文件(Android/data)

如下方法可以判断是否拥有MANAGE_EXTERNAL_STORAGE权限

Environment.isExternalStorageManager()

声明权限方式如下:

  1. manifest中声明权限
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
  1. 申请权限代码
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
}
  1. 实现效果

其它

权限方面

  • 使用使用共享存储空间访问其它应用创建的应用需要申请存储权限,自己应用本次安装创建的文件不需要申请权限。

  • 如果应用target版本大于 9,那么我们仅应该在<=9 的版本中进行权限申请,可以通过如下配置设置:

maxSdkVersion

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"android:maxSdkVersion="28" />
  • 如果应用使用了存储兼容功能,那么仍然需要访问存储权限

存储兼容指的就是我们准备升级android10但是暂时不想使用分区存储

开启使用存储兼容只需要在 manifest 中 application 标签声明如下配置即可:

android:requestLegacyExternalStorage="true"

切换媒体文件待处理状态

如果应用操作可能非常耗时(例如写入文件),那么在我们操作文件期间应该避免让其他应用有处理文件的机会。我们可以通过将 ContentValue.put(MediaStore.Audio.Media.IS_PENDING, 1) 标记的值设为 1 来获取此独占访问权限。这样就只有我们的的应用可以操作该文件,直到我们的应用将 IS_PENDING 的值改回 0。

照片中的位置信息

相册中的照片可能会包含敏感信息,例如位置信息,这个信息默认是不允许用户进行查看的,如果想查看需要申请 ACCESS_MEDIA_LOCATION权限

关注公众号学习更多知识

【android】关于android10-11存储的一些知识相关推荐

  1. android增加内置存储分区,详解Android10的分区存储机制(Scoped Storage)适配教程

    1. 简介 大家应该都有过这样的体会,手机用着用着里面就充斥着各种不懂的文件夹和文件.甚至是连已经删除的软件的文件夹还存在. 为什么会发生的这样的问题呢? 因为google的缺席,导致android生 ...

  2. 解锁 Android 手机的11大有效技巧

    想了解如何在没有密码或图案的情况下解锁 Android 智能手机吗?按照以下 10 大最佳技巧解锁 Android 手机. 人们很可能会在智能手机上应用屏幕锁定图案或密码以保护隐私.为防止其他人访问您 ...

  3. 【Android 文件管理】分区存储 ( 创建与查询图片文件 )

    文章目录 一.分区存储模式下使用 MediaStore 插入图片 二.分区存储模式下使用 MediaStore 查询图片 三.相关文档资料 Android 分区存储系列博客 : [Android 文件 ...

  4. 【Android 文件管理】分区存储 ( MediaStore 文件操作 )

    文章目录 一.动态权限申请 二.MediaStore 操作文件 三.完整代码示例 1.MainActivity 核心代码 2.build.gradle 构建脚本 3.清单文件 五.相关文档资料 特别注 ...

  5. Android 系统(43)----Andropid 基础知识

    谈谈你对android系统(体系)架构的理解 Linux操作系统为核心,从下往上,依赖关系. 应用程序层:包括系统应用以及第三方应用. 应用程序框架:提供应用开发所必须的一些API框架,是软件复用的重 ...

  6. Android内、外存储 易混淆点剖析(/mnt/sdcard、/storage/sdcard0、/storage/emulated/0等区别)

    向原创者致敬!自己感觉好转载了! 说起Android"内部存储",对于开发者而言可以毫不犹豫地脱口而出,不就是/data/data目录嘛,也不尽然,/data/user/0/又如何 ...

  7. android 访问存储卡,Android:无法访问存储在SD卡中的文件

    我正在研究一个读取存储在SD卡(内部/数据/本地)中的.txt文件的应用程序.我遇到的问题是,它似乎可以访问文件路径,但它不能访问文件本身(尽管它具有读取和写入权限),但会引发FileNotFound ...

  8. [ Android 五种数据存储方式之一 ] —— SharedPreferences存储数据

    SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数. 主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceS ...

  9. android模拟器的数据存放,Android模拟器在哪里存储SQLite数据库?

    Android模拟器在哪里存储SQLite数据库? 我正在开发一个将数据存储在SQLite数据库中的Android应用程序. 我的问题是,当您使用模拟器时,此数据库文件存储在文件系统中的哪个位置? 我 ...

  10. 【Android 文件管理】分区存储 ( 修改与删除图片文件 )

    文章目录 一.分区存储模式下使用 MediaStore 修改图片 二.分区存储模式下使用 MediaStore 删除图片 三.相关文档资料 Android 分区存储系列博客 : [Android 文件 ...

最新文章

  1. 使用CNN分类签名和文本图像
  2. MYSQL WHERE语句
  3. Git复习(十二)之命令专场
  4. redis分布式缓存php,基于redis分布式缓存实现
  5. 写一个函数的程序,判断是否是浮点数
  6. 字体Times New Roman
  7. 三天学好ADO(转)
  8. python 删除文件 通配符_python 实现删除文件或文件夹实例详解
  9. 用c语言枚举计算坐标,来个c++枚举有效范围计算器
  10. Fixcel电子表格——报表模块(一)
  11. C#------如何获取本机IP地址
  12. GB 50007-2011《建筑地基基础设计规范》高清电子版
  13. 教你如何设置让Excel窗口总是在最前面
  14. js 将图片置灰_将图片转换成黑白(灰色)的css和js的方法
  15. 关于jupyter notebook闪退问题【我真真的够了,大家以后不要乱捣鼓电脑了,绝了】
  16. RK3399教程:wifi驱动调试技巧
  17. 苏州木渎计算机课程培训,苏州木渎H5/web全栈开发培训
  18. 无线MESH自组网系统
  19. vite+ts+elementplus运行正常打包报错
  20. Kafuka面试(整合Kafka两种模式区别)

热门文章

  1. “留得五湖明月在,不愁无处下金钩“太经典,分享一下
  2. 【java】本地客户端内嵌浏览器1 - Swing、SWT、DJNativeSwing、javaFX
  3. android系统计步修改,安卓手机计步软件怎么修改步数 无需root轻松修改步数
  4. 运动计步app开发的功能分析
  5. Axure RP 9 下载、汉化及最新授权码
  6. Java应用分层(阿里巴巴Java开发手册)
  7. atat(mcsqs)建立相对稳定的高熵合金模型
  8. 华为机顶盒E6108 V9-V9U-V92-V97免拆机-刷机固件及教程
  9. win10使用Switchhost显示无修改权限
  10. Java实现的餐厅点餐系统源码Java点餐系统Java点餐系统Java网上订餐系统Java在线订餐系统