Android10 分区存储的适配规则

目录
  • 存储权限
  • 内部存储 外部存储
  • 适配

存储权限

Android Q 仍然使用 READ_EXTRNAL_STORAGE 和 WRITE_EXTRNAL_STORAGE 作为存储相关运行时权限 但现在即使

获取了这些权限,访问外部存储也受到了限制,只能访问自身目录下的文件和公共体内的文件

内部存储 外部存储

内部存储 外部存储 备注
英文名称 Internal storage External storage
版本变更 不变 4.4之前,外部存储仅仅代表SD卡之类的移动存储设备,4.4之后包括内置的外部存储和SD卡(部分手机没有提供SD卡的卡槽,就只有内置的外部存储)
查看方法 用模拟器+adb shell 进入 或者是Android Studio Devices File Explorer 一般的文档管理App 都能看 用 su root 命令给模拟器加权限
组成成分 System/:存放系用数据 data/: 存放应用相关数据 vendor/:用于存放厂商客制化的数据等 私有存储区:android/ 文件夹下,是应用的私有存储区域 公共存储区域:Movie、Download、 DCIM、 Picture、Documents、Ringtones、Music、 Alarms
存储内容 db share preference files cache 等 开发者自己需要存储的数据 如视频文件、音频文件、或者一些表格 日志文件 内部存储小而且宝贵我们基本上不要操作它,需要存储的都存储在外部存储
获取路径方法 Environment.getDataDirectory() Context.getFileDir() Environment.getExternalStorageDirectory() (traget>=30,已废弃) Context.getExternalFilesDir() 基本上Context的方法获取的都是应用的私有存储路径 E nvironment的方法获取的都是根目录
应用卸载时 私有路径下的文件全部删除 即:data/user/0/packageName/ 私有路径下的文件全部删除 即:android/data/packageName/ 公共存储区域不变动

适配

  • 获取外部存储 文件夹
// 如果当前目录下没有 fileDirName 文件夹会自动创建
val file:File = context.getExternalFileDir("fileDirName") // fileDirName 文件夹名称
// /storage/emulated/0/Android/data/packageName/files/fileDirName
  • 创建外部存储 文件
  val appFileDirName = applicationContext.getExternalFilesDir("fileDirName")?.absolutePath
  val newFile = File(appFileDirName, "temp.txt")
  val fileWriter = FileWriter(newFile)
  fileWriter.write("test information")
  fileWriter.flush()
  fileWriter.close()
  • 创建外部存储公共目录下的文件路径
    /**
     * @param fileName 文件名称
     * @param relativePath 包含某个媒体下的子路径
     */
    fun insertFileIntroMediaStore(
        context: Context,
        fileName: String,
        relativePath: String
    ): Uri? {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            return null
        }
        val contentResolver = context.contentResolver
        val values = ContentValues()
        values.put(MediaStore.Downloads.DISPLAY_NAME, fileName)
        values.put(MediaStore.Downloads.MIME_TYPE, "text/plain")
        values.put(MediaStore.Downloads.RELATIVE_PATH, relativePath)
      	//验证存储空间的可用性
      	//由于外部存储空间位于用户可能能够移除的物理卷上,因此在尝试从外部存储空间读取应用专
      	//属数据或将应用专属数据写入外部存储空间之前,请验证该卷是否可访问。
      	//您可以通过调用 Environment.getExternalStorageState() 查询该卷的状态。如果返回的状态为 MEDIA_MOUNTED,那么您就可以在外部存储空间中读取和写入应用专属文件。如果返回的状态为 MEDIA_MOUNTED_READ_ONLY,您只能读取这些文件。
        val externalStorageState = Environment.getExternalStorageState()
        return if (externalStorageState.equals(Environment.MEDIA_MOUNTED)) {
            contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
        } else {
            contentResolver.insert(MediaStore.Downloads.INTERNAL_CONTENT_URI, values)
        }
    }

    /**
     * @param context 上下文
     * @param insertUri 存储Uri
     * @param inputStream 文件输出流
     */
    fun saveFile(context: Context, insertUri: Uri?, inputStream: InputStream?) {
        insertUri ?: return
        inputStream ?: return
        val resolver = context.contentResolver
        val out = resolver.openOutputStream(insertUri)
        var read: Int
        val buffer = ByteArray(1024)
        while (inputStream.read(buffer).also { read = it } != -1) {
            out?.write(buffer)
        }
        inputStream.close()
        out?.flush()
        out?.close()
    }

    /**
     * @param context 上下文
     * @param insertUri 存储Uri
     * @param sourceFile 资源文件
     */
    fun saveFile(context: Context, insertUri: Uri?, sourceFile: File?) {
        insertUri ?: return
        sourceFile ?: return
        val inputStream = FileInputStream(sourceFile)
        val resolver = context.contentResolver
        val out = resolver.openOutputStream(insertUri)
        var read: Int
        val buffer = ByteArray(1024)
        while (inputStream.read(buffer).also { read = it } != -1) {
            out?.write(buffer)
        }
        inputStream.close()
        out?.flush()
        out?.close()
    }
  • 读取外部存储 公共目录文件
    /**
     * 获取文件输出流 by uri
     * @param context 上下文
     * @param uri 文件路径
     */
    fun getInputStreamByUri(context: Context, uri: Uri?): InputStream? {
        uri ?: return null
        val openFileDescriptor = context.contentResolver.openFileDescriptor(uri, "r")
        return FileInputStream(openFileDescriptor?.fileDescriptor)
    }

以上就是Android10 分区存储的使用总结的详细内容,更多关于Android10 分区存储的使用的资料请关注我们其它相关文章!

(0)

相关推荐

  • AndroidQ分区存储权限变更及适配的实现

    分区存储 在Android Q中引入了分区储存功能,在外部存储设备中为每个应用提供了一个"隔离存储沙盒".其他应用无法直接访问应用的沙盒文件.由于文件是应用的私有文件,不再需要任何权限即可访问和保存自己的文件.此变更并有助于减少应用所需的权限数量,同时保证用户文件的隐私性. 权限变更 Android Q 更改了应用对设备外部存储设备中的文件(如:/sdcard )的访问方式.继续使用 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 权限,只

  • 详解Android10的分区存储机制(Scoped Storage)适配教程

    1. 简介 大家应该都有过这样的体会,手机用着用着里面就充斥着各种不懂的文件夹和文件.甚至是连已经删除的软件的文件夹还存在. 为什么会发生的这样的问题呢? 因为Google的缺席,导致Android生态野蛮生长,导致很多开发规范没有完全被落实. 为了解决这样的问题,Google决定重拳出击,提出了分区存储(Scoped Storage)机制,也叫沙盒存储机制. 那么什么是沙盒存储机制呢. 沙盒机制是一种安全机制,用于防止应用读取其他应用的数据. 每个应用程序都有自己的存储空间. 应用程序不能翻过

  • AndroidQ(10)分区存储完美适配方法

    前言 最近时间在做AndroidQ的适配,截止到今天AndroidQ分区存储适配完成,期间出现很多坑,目前网上的帖子大部分都是概述变更内容,接下来的几篇帖子都是对分区存储实际经验代码总结,填坑经验,特此记录一下,也为大家提供帮助. 本篇主要是对AndroidQ(10)分区存储适配具体实现 要点: Android Q文件存储机制修改成了沙盒模式 APP只能访问自己目录下的文件和公共媒体文件 对于AndroidQ以下,还是使用老的文件存储方式 这里需要注意:在适配AndroidQ的时候还要兼容Q系统

  • AndroidQ沙盒机制之分区存储适配

    为了让用户更好地控制自己的文件,Android Q更改了应用访问设备外部存储空间中文件的方式.Android Q用更精细的媒体特定权限来替换READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限,并且无需特定权限,应用即可访问自己在外部存储设备的文件. 1.针对应用私有文件的隔离存储沙盒 对于每个应用,Android Q 都会创建一个"隔离存储沙盒",以限制其他应用访问本应用在外部存储设备的文件.常见的外部存储设备是/sdcard.此定义具有两个优

  • Android10 分区存储的适配规则

    目录 存储权限 内部存储 外部存储 适配 存储权限 Android Q 仍然使用 READ_EXTRNAL_STORAGE 和 WRITE_EXTRNAL_STORAGE 作为存储相关运行时权限 但现在即使 获取了这些权限,访问外部存储也受到了限制,只能访问自身目录下的文件和公共体内的文件 内部存储 外部存储 内部存储 外部存储 备注 英文名称 Internal storage External storage 版本变更 不变 4.4之前,外部存储仅仅代表SD卡之类的移动存储设备,4.4之后包括

  • Android 10 适配攻略小结

    相比较去年写的Android 9适配,这次Android 10的内容有点多.没想到写了我整整两天,吐血中... 准备工作 老规矩,首先将我们项目中的 targetSdkVersion 改为 29. 1.Scoped Storage(分区存储) 说明 在Android 10之前的版本上,我们在做文件的操作时都会申请存储空间的读写权限.但是这些权限完全被滥用,造成的问题就是手机的存储空间中充斥着大量不明作用的文件,并且应用卸载后它也没有删除掉.为了解决这个问题,Android 10 中引入了 Sco

  • 安卓11适配攻略抢先看

    引言 近期,Google 发布了 Android 11的平台稳定版本.Android 11 将在确保用户隐私安全的前提下,更好地让用户畅享最新科技. 下图是 Android 11 发布整体流程的时间线: 个推深耕开发者领域,一直紧跟行业发展趋势,对Android 11的有关更新展开了深入研究.本文将从分区存储.应用包可见性.权限变化和新功能四个方面来谈谈 Android 11 新特性,以帮助开发者更快速.更便捷地上手适配Android新系统. 作者| 个推高级安卓开发工程师 一七 正文 分区存储

  • Oracle10个分区和Mysql分区区别详解

    Oracle10g分区常用的是:range(范围分区).list(列表分区).hash(哈希分区).range-hash(范围-哈希分区).range-list(列表-复合分区). Range分区:Range分区是应用范围比较广的表分区方式,它是以列的值的范围来做为分区的划分条件,将记录存放到列值所在的range分区中. 如按照时间划分,2010年1月的数据放到a分区,2月的数据放到b分区,在创建的时候,需要指定基于的列,以及分区的范围值. 在按时间分区时,如果某些记录暂无法预测范围,可以创建m

  • oracle表空间表分区详解及oracle表分区查询使用方法

    此文从以下几个方面来整理关于分区表的概念及操作:1.表空间及分区表的概念2.表分区的具体作用3.表分区的优缺点4.表分区的几种类型及操作方法5.对表分区的维护性操作.(1.) 表空间及分区表的概念表空间:是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表, 所以称作表空间. 分区表: 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区.表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间

  • 创建mysql表分区的方法

    表分区是最近才知道的哦 ,以前自己做都是分表来实现上亿级别的数据了,下面我来给大家介绍一下mysql表分区创建与使用吧,希望对各位同学会有所帮助.表分区的测试使用,主要内容来自于其他博客文章以及mysql5.1的参考手册mysql测试版本:mysql5.5.28mysql物理存储文件(有mysql配置的datadir决定存储路径)格式简介数据库engine为MYISAM frm表结构文件,myd表数据文件,myi表索引文件.INNODB engine对应的表物理存储文件innodb的数据库的物理

随机推荐