Android10 分区存储的适配规则

 更新时间:2021年05月13日 08:41:27   作者:飞曼巴  
Android设备 在Sdk29己以上推出了分区存储,类似iOS沙箱。应用App 目标版本号为29或以上则需要适配分区存储,本文将具体的讲解适配规则

存储权限

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 分区存储的使用的资料请关注脚本之家其它相关文章!

相关文章

  • Android中Activity之间跳转和参数传递的实例

    Android中Activity之间跳转和参数传递的实例

    本篇文章主要介绍了Android中Activity之间跳转和参数传递的实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • Android线程管理之ActivityThread

    Android线程管理之ActivityThread

    线程通信、ActivityThread及Thread类是理解Android线程管理的关键。通过本文给大家介绍Android线程管理之ActivityThread 的相关知识,对android线程管理相关知识感兴趣的朋友一起学习吧
    2016-01-01
  • Android自定义单例AlertDialog详解

    Android自定义单例AlertDialog详解

    这篇文章主要为大家详细介绍了Android自定义单例AlertDialog的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 一些比较实用的 Android adb 命令分享

    一些比较实用的 Android adb 命令分享

    这篇文章主要介绍了一些比较实用的 Android adb 命令分享,本文讲解了查看设备、安装应用、卸载一个应用、启动一个页面、进入设备的shell界面等内容,需要的朋友可以参考下
    2015-02-02
  • Android条纹进度条的实现(调整view宽度仿进度条)

    Android条纹进度条的实现(调整view宽度仿进度条)

    这篇文章主要给大家介绍了关于Android实现条纹进度条的方法,主要是通过调整view宽度仿进度条,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友们下面来一起看看吧
    2018-09-09
  • Android中PackageManager使用详解

    Android中PackageManager使用详解

    PackageManger的主要职责是管理应用程序包,通过它可以获取应用程序信息,这篇文章主要给大家介绍了关于Android中PackageManager使用的相关资料,需要的朋友可以参考下
    2021-11-11
  • Service与Activity之间的通信(同一进程)

    Service与Activity之间的通信(同一进程)

    这篇文章主要介绍了Service与Activity之间的通信(同一进程)的相关资料,需要的朋友可以参考下
    2016-03-03
  • 浅析Kotlin使用infix函数构建可读语法流程讲解

    浅析Kotlin使用infix函数构建可读语法流程讲解

    这篇文章主要介绍了浅析Kotlin使用infix函数构建可读语法,我们在Kotlin中就多次使用A to B这样的语法结构构建键值对,包括Kotlin自带的mapOf()函数,这种语法结构的优点是可读性强
    2023-01-01
  • Android检测手机中存储卡及剩余空间大小的方法(基于Environment,StatFs及DecimalFormat)

    Android检测手机中存储卡及剩余空间大小的方法(基于Environment,StatFs及DecimalFormat

    这篇文章主要介绍了Android检测手机中存储卡及剩余空间大小的方法,基于Environment,StatFs及DecimalFormat实现该功能,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-01-01
  • Android开发中amera2 Preview使用详解

    Android开发中amera2 Preview使用详解

    这篇文章主要介绍了Android开发中amera2 Preview使用详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09

最新评论