Android分区存储到底该怎么做

文章目录

    • 一、Android存储结构
    • 二、什么是分区存储?
    • 三、私有目录和公有目录
    • 三、存储权限和分区存储有什么关系?
    • 四、我们应该该怎么做适配?
      • 4.1、利用File进行操作
      • 4.2、使用MediaStore操作数据库

一、Android存储结构

Android存储分为内部存储外部存储

在这里插入图片描述

二、什么是分区存储?

看下面的未使用分区存储时的结构图,App私有目录就是上面说的内部存储,共享存储空间就是上面说的外部存储

在这里插入图片描述

分区存储就是在外部存储中的这些文件夹不能随便放了,必须相应的文件类型存到相应的目录中才可以。比如图片文件只能放到Picture目录或者DCIM目录中,就不能放到Movies或者Music中了,否则就会报错崩溃。

在这里插入图片描述

这里提一句,Download目录可以放任何类型的文件,这个目录没有类型限制。

在这里插入图片描述

Android10以前,外部存储中的所有文件虽然有分类目录,但是不管文件是什么类型都可以随便存放,比如mp3音频文件可以放到Movies目录中或者Picture目录中。

对于Android10,Google第一次添加了分区存储方案,这是作为的一个过渡版本,并且Google在Android10上添加了一个属性让你来选择是否使用分区存储方案 ,就是在Manifest中配置的:android:requestLegacyExternalStorage="true",默认是false,即开启分区存储。

从Android11开始,Google强制使用分区存储,也就是说requestLegacyExternalStorage这个属性不再起作用了。

三、私有目录和公有目录

data目录下的可以理解为就是内部存储中的私有目录。
sdcard目录下的就作为公有目录,没有分区存储时,如果要访问里面的文件就需要权限。

在这里插入图片描述

如果使用了分区存储,要注意在sdcard目录中,也有私有目录和公有目录的概念。
在sdcard中的data目录下,可以看到应用的包名,这就是外部存储中的私有目录,访问这里面的文件不需要权限,只有访问Android目录外的文件才需要权限。并且卸载应用还会被删除。

在这里插入图片描述

三、存储权限和分区存储有什么关系?

存储权限也跟Android版本有关,我们很容易把它和分区存储的概念搞在一起弄的晕头转向,其实并没有什么关系,所以我们讲分区存储不需要考虑要什么什么权限,那是另外一回事。

四、我们应该该怎么做适配?

对于Android10以前(不包含Android10),没有分区存储的概念,并且我们操作文件都是用File对象。
对于Android10,我们有两种选择,即可以使用分区存储,也可以不使用。
对于Android10以后(不包含Android10),强制分区存储了,我们操作文件就需要用MediaStore来操作数据库才行。

4.1、利用File进行操作

这个就不过多进行介绍,随便百度都有很多。

4.2、使用MediaStore操作数据库

  1. 我们操作的数据库文件其实就存在内部存储的私有目录中:/data/data/com.android.providers.media
    我们可以将数据库导出利用数据库工具查看(需要root),里面有个files表,可以看到很多字段,这些字段就对应我们着我们平常代码中所写的:Media.DATAMedia.DISPLAY_NAMEMedia.DURATION等等,我们可以根据保存的文件类型以及自己的需求来选择需要的字段。

在这里插入图片描述

  1. 同时可以看到每种类型的文件目录也都有相应的字段,不管是文件夹目录还是文件在数据库中都会有一条数据相对应。

在这里插入图片描述

  1. 使用分区存储后,我们操作文件都需要注意相应的文件类型。
    例如MediaStore中的三种类型媒体:音频,视频,图片。
    每种类型都分别有三种Uri:内部存储,外部存储,可移动存储(这个不用太关心)。
        MediaStore.ImagesMediaStore.VideoMediaStore.Audio
        MediaStore.Images.Media.INTERNAL_CONTENT_URI//content//media/internal/image/mediaMediaStore.Images.Media.EXTERNAL_CONTENT_URI//content//media/external/image/mediaMediaStore.Images.Media.getContentUri(volumeName)//content//media/<volumeName>/image/mediaMediaStore.Video.Media.INTERNAL_CONTENT_URI//content//media/internal/video/mediaMediaStore.Video.Media.EXTERNAL_CONTENT_URI//content//media/external/video/mediaMediaStore.Video.Media.getContentUri(volumeName)//content//media/<volumeName>/video/mediaMediaStore.Audio.Media.INTERNAL_CONTENT_URI//content//media/internal/audio/mediaMediaStore.Audio.Media.EXTERNAL_CONTENT_URI//content//media/external/audio/mediaMediaStore.Audio.Media.getContentUri(volumeName)//content//media/<volumeName>/audio/media

当然MediaStore也还有其他类型,目前一共有五个。
在这里插入图片描述

  1. 我们操作数据库文件每次用到的就是一个Uri,比如说我要插入一张图片,执行完下面这个方法,就可以直接在相册中查看到你添加的图片了。
    private fun insertImage() {val displayName = "test.jpg"val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URIval values = ContentValues()//根据文件类型和自己的需求选择字段,比如图片这里就必须要指定MIME_TYPEvalues.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, displayName)values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/jpg")values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)val imageUri = contentResolver.insert(uri, values)//到这里创建的算是一个文件夹,如果通过下面的代码写入数据后就会变成图片文件if (imageUri != null) {try {val bitmap = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)val outputStream = contentResolver.openOutputStream(imageUri)if (outputStream != null) {bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)outputStream.close()}ToastUtil.showToast(this, "添加图片成功")} catch (e: Exception) {e.printStackTrace()}} else {ToastUtil.showToast(this, "操作失败")}}
  1. 简单的查询操作,比如查询上面添加的那张图片。
    private fun query(): Uri? {val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI//查询条件,根据DISPLAY_NAMEval selection = MediaStore.Images.Media.DISPLAY_NAME + "=?"val args: Array<String> = arrayOf("test.jpg")val projection: Array<String> = arrayOf(MediaStore.Images.Media._ID)//数据库查询val cursor = contentResolver.query(uri, projection, selection, args, null)return if (cursor != null && cursor.moveToFirst()) {val queryUri = ContentUris.withAppendedId(uri, cursor.getLong(0))cursor.close()ToastUtil.showToast(this, "查询成功:$queryUri")queryUri} else {ToastUtil.showToast(this, "查询失败")null}}
  1. 简单的删除操作,注意删除操作前需要先通过查询得到相应的uri。
    private fun delete() {//先查询后删除val uri = query()if (uri != null) {contentResolver.delete(uri, null, null)}}
  1. 简单的修改操作,跟删除一样,也需要先通过查询得到相应的uri。
    private fun update() {//先查询后修改val uri = query()if (uri != null) {//修改的字段val contentResolver = ContentValues()contentResolver.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "修改后的图片.jpg")//操作数据库getContentResolver().update(uri, contentResolver, null, null)}}
  1. 总结一下操作数据库,其实就3步:拿到uri,构建字段条件,执行。拿插入图片来举例。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/757715.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

支付宝手机网站支付,微信扫描二维码支付

支付宝手机网站支付 支付宝文档 响应示例 <form name"punchout_form" method"post" action"https://openapi.alipay.com/gateway.do?charsetUTF-8&methodalipay.trade.wap.pay&formatjson&signERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE…

MySQL 数据库设计范式

第一范式&#xff08;1NF&#xff09; 每一列都是不可分割的原子数据项第二范式&#xff08;2NF&#xff09; 在1NF的基础上&#xff0c;非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖) 1.函数依赖A->B&#xff0c;如果通过A属性(属性组)的值…

Transformer学习【从零理解】

Transformer 一、整体框架 二、Encoder 1.输入部分: &#xff08;1&#xff09;Embedding&#xff1a;将输入的词转换为对应的词向量。 &#xff08;2&#xff09;位置编码&#xff1a;因为保证输出时&#xff0c;顺序不会打乱&#xff0c;所以要加入时序信息即位置编码。 公…

如何避免AI网红经济泡沫?警惕细分行业的AI转型而不是转行

一、AI泡沫预防针 要避免AI相关新概念催生的网红经济泡沫&#xff0c;可以从多个角度采取措施&#xff1a; 1. **理性投资**&#xff1a; - 投资者应对AI项目和网红经济中的企业进行深入研究&#xff0c;了解其真实的技术实力、商业模式的可行性和盈利能力&#xff0c;而非…

初识GO语言

是由google公司推出的一门编程语言&#xff0c;12年推出的第一个版本 Go的特点 Go为什么能在最近的IT领域炙手可热 集python简洁&C语言的性能于一身 21世纪的C语言 顺应容器化时代的到来 区块链的崛起 学习一门编程语言可以划分为下面这三个步骤 安装 编译器 or 解…

JAVA多线程之synchronized锁

文章目录 1. 临界区2. synchronized使用2.1 不加锁实现2.2 synchronized加锁2.3 面向对象的改进2.4 方法上加synchronized2.5 线程安全 3. Monitor3.1 Java对象头3.2 Monitor工作流程3.3 字节码角度 4. synchronized原理4.1 轻量级锁4.2 锁膨胀4.3 偏向锁4.3.1 偏向锁过程4.3.2…

【链表】Leetcode 2. 两数相加【中等】

两数相加 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c; 并且每个节点只能存储 一位 数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外&#xff0c;这两个数都不…

Redis数据结构对象中的对象共享、对象的空转时长

对象共享 概述 除了用于实现引用计数内存回收机制之外&#xff0c;对象的引用计数属性还带有对象共享的作用。 在Redis中&#xff0c;让多个键共享同一个值对象需要执行以下两个步骤: 1.将数据库键的值指针指向一个现有的值对象2.将被共享的值对象的引用计数增一 目前来说…

pytorch 实现线性回归(Pytorch 03)

一 从零实现线性回归 1.1 生成训练数据 原始 计算公式&#xff0c; 我们先使用该公式生成一批数据&#xff0c;然后使用 结果数据去计算 计算 w1, w2 和 b。 %matplotlib inline import random import torch from d2l import torch as d2ldef synthetic_data(w, b, num_ex…

基于springboot+vue的餐饮管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Java学习笔记21——使用JDBC访问MySQL数据库

JDBC&#xff08;Java Database Connectivity&#xff0c;Java数据库连接&#xff09;是应用程序编程借口&#xff08;API&#xff09;&#xff0c;描述了一套访问关系数据库的标准Java类库。可以在程序中使用这些API&#xff0c;连接到关系数据库&#xff0c;执行SQL语句&…

IDEA Git恢复DropCommit删除的提交

刚刚Dorp commit了&#xff0c;本地代码也被删除了&#xff0c;如何恢复呢&#xff0c; 从项目中登录git&#xff0c;找到刚刚的commit代码&#xff0c;如下所示&#xff1a;输入命令git reflog 复制代码&#xff0c;到idea中&#xff0c;打开GIt&#xff0c;找到RESET HEAD, …

初始 Navicat BI 工具

早前&#xff0c;海外 LearnBI online 博主 Adam Finer 对 Navicat Charts Creator 这款 BI&#xff08;商业智能&#xff09;工具进行了真实的测评。今天&#xff0c;我们来看下他对 Navicat BI 工具的初始之感&#xff0c;希望这能给用户一些启发与建议。LearnBI online 作为…

《计算机考研精炼1000题》为你考研之路保驾护航

创作背景 在这个充满挑战与竞争的时代&#xff0c;每一位考生在备战研究生考试的过程中&#xff0c;都希望通过更多符合考纲要求的练习题来提高自己的知识和技能。为了满足这一需求&#xff0c;我们精心策划和编辑了这本《计算机考研精炼1000题》。在考研政治和考研数学领域&a…

springboot283图书商城管理系统

图书商城管理系统 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本图书商城管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理…

耳机壳UV树脂制作私模定制耳塞需要什么样的设备和技术?

制作私模定制耳塞需要使用到一些特定的设备和技术&#xff0c;包括但不限于以下内容&#xff1a; 耳模制作工具&#xff1a;用于获取用户耳型的耳模制作工具&#xff0c;如硅胶、橡皮泥等。需要使用熟练的手法和技术&#xff0c;确保耳模的准确性和稳定性。UV树脂&#xff1a;…

社交变革:探索Facebook的魔力

社交媒体平台的崛起已经改变了我们与世界的交互方式&#xff0c;而Facebook作为其中的巨头&#xff0c;其影响力和魔力更是不可忽视。本文将深入探讨Facebook如何引领社交变革&#xff0c;并探索其背后的魔力所在。 连接世界的纽带 Facebook的独特之处在于它作为一个社交平台&…

「滚雪球学Java」:安全(章节汇总)

&#x1f3c6;本文收录于「滚雪球学Java」专栏&#xff0c;专业攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎大家关注&&收藏&#xff01;持续更新中&#xff0c;up&#xff01;up&#xff01;up&#xff01;&#xf…

【视频异常检测】Diversity-Measurable Anomaly Detection 论文阅读

Diversity-Measurable Anomaly Detection 论文阅读 Abstract1. Introduction2. Related Work3. Diversity-Measurable Anomaly Detection3.1. The framework3.2. Information compression module3.3. Pyramid deformation module3.4. Foreground-background selection3.5. Trai…

JavaScript实现简单的表单验证

关键代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…