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

网友投稿 936 2022-05-29

文章目录

一、分区存储模式下使用 MediaStore 插入图片

二、分区存储模式下使用 MediaStore 查询图片

三、相关文档资料

Android 分区存储系列博客 :

【Android 文件管理】应用可访问的存储空间 ( 存储空间分类 | 存储空间访问权限 | 分区存储 )

【Android 文件管理】分区存储 ( 分区存储机制 和 文件索引数据 )

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

一、分区存储模式下使用 MediaStore 插入图片

在上一篇博客 【Android 文件管理】分区存储 ( MediaStore 文件操作 ) 中 , 创建了一个文本文件 , 并向其写出一个字符串 ;

创建文件时注意 , 使用 MediaStore 向

" external.db " 数据库

中插入了文件数据 , 只是生成了文件索引 , 如果不向文件中写出数据 ,

并不会真正的创建文件

; 插入数据后 ,

依据返回的 android.net.Uri 类型打开输出流 ,

然后通过该输出流写出数据 ,

文件创建完成 ;

图片创建流程 :

首先 , 获取

操作数据库的 Uri ;

// 操作 external.db 数据库 // 获取 Uri 路径 var uri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI

1

2

3

其次 ,

构造插入数据库的 ContentValues 数据结构

, 设置的 “external.db” 数据库中的 “files” 数据表的各个字段与 MediaStore 中的常量对应关系如下 :

MediaStore.Downloads.RELATIVE_PATH :

relative_path

MediaStore.Downloads.DISPLAY_NAME :

display_ame

MediaStore.Downloads.TITLE :

tittle

MediaStore.Downloads.MIME_TYPE :

mime_type

// 将要新建的文件的文件索引插入到 external.db 数据库中 // 需要插入到 external.db 数据库 files 表中, 这里就需要设置一些描述信息 var contentValues: ContentValues = ContentValues() // 设置插入 external.db 数据库中的 files 数据表的各个字段的值 // 设置存储路径 , files 数据表中的对应 relative_path 字段在 MediaStore 中以常量形式定义 contentValues.put(MediaStore.Downloads.RELATIVE_PATH, "${Environment.DIRECTORY_MOVIES}/image") // 设置文件名称 contentValues.put(MediaStore.Downloads.DISPLAY_NAME, "image.jpg") // 设置文件标题, 一般是删除后缀, 可以不设置 contentValues.put(MediaStore.Downloads.TITLE, "image") // 设置 MIME_TYPE contentValues.put(MediaStore.Downloads.MIME_TYPE, "image/jpg")

1

2

3

4

5

6

7

8

9

10

11

12

13

再次 , 获取该上下文对应的 ContentResolver , 调用 insert 方法 , 将上述构建的 ContentValues 插入到数据库中 , 返回 Uri ;

// uri 表示操作哪个数据库 , contentValues 表示要插入的数据内容 var insert: Uri = contentResolver.insert(uri, contentValues)!!

1

2

最后 , 根据插入数据返回的 Uri , 打开输出流 , 然后向输出流中写出图片数据 ;

// 向 Download/hello/hello.jpg 文件中插入数据 var os: OutputStream = contentResolver.openOutputStream(insert)!! var bitmap: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.icon) bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os) os.close()

1

2

3

4

5

图片数据写出完成 , 输出流正式关闭 , 图片创建成功 ;

创建完成后 , 可以在 " Device Explorer " 面板中显示新创建的图片 ;

关于 图片 MIME_TYPE :

图片文件创建 与 文本文件创建 唯一的区别就是需要设置 MIME_TYPE 字段 , 根据传入的图片格式设置不同的 mimetype , 如 : 传入 jpeg 图片 , 则设置字段值为 “image/jpg” ;

保存图片文件时 , 传入的 MIME_TYPE 为 “image/jpg” , 如果传错了 , 写成 “vedio/mp3” , 创建文件时不会抛出异常 , 但是使用该文件时会出错 ;

图片创建部分代码示例 :

/** * 创建图片文件 * 在 Download 目录下创建 hello.txt */ fun createImageFile(){ // 操作 external.db 数据库 // 获取 Uri 路径 var uri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI // 将要新建的文件的文件索引插入到 external.db 数据库中 // 需要插入到 external.db 数据库 files 表中, 这里就需要设置一些描述信息 var contentValues: ContentValues = ContentValues() // 设置插入 external.db 数据库中的 files 数据表的各个字段的值 // 设置存储路径 , files 数据表中的对应 relative_path 字段在 MediaStore 中以常量形式定义 contentValues.put(MediaStore.Downloads.RELATIVE_PATH, "${Environment.DIRECTORY_MOVIES}/image") // 设置文件名称 contentValues.put(MediaStore.Downloads.DISPLAY_NAME, "image.jpg") // 设置文件标题, 一般是删除后缀, 可以不设置 contentValues.put(MediaStore.Downloads.TITLE, "image") // 设置 MIME_TYPE contentValues.put(MediaStore.Downloads.MIME_TYPE, "image/jpg") // uri 表示操作哪个数据库 , contentValues 表示要插入的数据内容 var insert: Uri = contentResolver.insert(uri, contentValues)!! // 向 Download/hello/hello.jpg 文件中插入数据 var os: OutputStream = contentResolver.openOutputStream(insert)!! var bitmap: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.icon) bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os) os.close() }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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

23

24

25

26

27

28

29

30

31

32

33

34

二、分区存储模式下使用 MediaStore 查询图片

首先 , 根据查询的位置 , 获取其对应的数据库操作 Uri ; 这里获取外置 SD 卡 Pictures 目录对应的 Uri 对象 ;

// 获取外置 SD 卡 Pictures 对应的 Uri 对象 var externalContentUri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

1

2

然后 , 使用 SQLite 查询机制 , 查询对应图片的 Uri ; 查询 Pictures 目录下的 image.jpg 图片 ;

// 拼接查询语句 var selection: String = "${MediaStore.Images.Media.DISPLAY_NAME}=?"; // 查询语句参数 var selectionArgs: Array = arrayOf("image.jpg"); // 查询 SQLite 数据库 var cursor = contentResolver.query( // 指定要查询的 Uri externalContentUri, // 指定要查询的列 null, // 指定查询语句 selection, // 指定查询参数 selectionArgs, // 排序规则 null )

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

最后 , 通过 Cursor 查询数据表中各个字段的信息 , 如 id 字段 , relative_path 相对路径字段 , data 绝对路径字段 , _display_name 文件名称字段 ;

// 先获取该图片在数据库中的 id , 然后通过 id 获取 Uri if (cursor != null && cursor.moveToFirst()){ // 获取第 0 行 _id 所在列的值 var id = cursor.getLong( // 获取 _id 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID) ) var path = cursor.getString( // 获取 relative_path 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media.RELATIVE_PATH) ) var name = cursor.getString( // 获取 _display_name 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME) ) // 绝对路径 var absolutePath = cursor.getString( // 获取 data 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) ) // 通过 _id 字段获取图片 Uri var uri = ContentUris.withAppendedId(externalContentUri, id); Log.i(TAG, "查询到的 Uri = $uri , 路径 = $path , 文件名称 = $name , 绝对路径 = $absolutePath") // 关闭游标 cursor.close() }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

查询文件代码示例 :

/** * 查询所有的图片 */ fun queryImages(){ // 获取外置 SD 卡 Pictures 对应的 Uri 对象 var externalContentUri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; // 拼接查询语句 var selection: String = "${MediaStore.Images.Media.DISPLAY_NAME}=?"; // 查询语句参数 var selectionArgs: Array = arrayOf("image.jpg"); // 查询 SQLite 数据库 var cursor = contentResolver.query( // 指定要查询的 Uri externalContentUri, // 指定要查询的列 null, // 指定查询语句 selection, // 指定查询参数 selectionArgs, // 排序规则 null ) // 先获取该图片在数据库中的 id , 然后通过 id 获取 Uri if (cursor != null && cursor.moveToFirst()){ // 获取第 0 行 _id 所在列的值 var id = cursor.getLong( // 获取 _id 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID) ) var path = cursor.getString( // 获取 relative_path 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media.RELATIVE_PATH) ) var name = cursor.getString( // 获取 _display_name 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME) ) // 绝对路径 var absolutePath = cursor.getString( // 获取 data 所在列的索引 cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) ) // 通过 _id 字段获取图片 Uri var uri = ContentUris.withAppendedId(externalContentUri, id); Log.i(TAG, "查询到的 Uri = $uri , 路径 = $path , 文件名称 = $name , 绝对路径 = $absolutePath") // 关闭游标 cursor.close() } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

执行打印的结果 :

查询到的 Uri = content://media/external/images/media/42 , 路径 = Pictures/image/ , 文件名称 = image.jpg , 绝对路径 = /storage/emulated/0/Pictures/image/image.jpg

1

注意 : 该文件的

Uri 是 " content://media/external/images/media/42 " ,

绝对路径是 " /storage/emulated/0/Pictures/image/image.jpg " ;

Uri 最后的 42 数字 , 就是在 " external.db " 数据库中 files 数据表中该 image.jpg 文件对应的 _id 字段数据 ;

绝对路径

在 Android 11 的 分区存储机制 中不能用来做任何操作 , 否则会产生崩溃 ;

对文件的操作 , 如 : 访问图片 , 删除图片 等操作 , 必须使用 Uri 进行操作 ;

三、相关文档资料

Android 文件处理参考文档 :

数据和文件存储概览 : https://developer.android.google.cn/training/data-storage

访问应用专属文件 : https://developer.android.google.cn/training/data-storage/app-specific#kotlin

保存到共享的存储空间 : https://developer.android.google.cn/training/data-storage/shared

管理存储设备上的所有文件 : https://developer.android.google.cn/training/data-storage/manage-all-files

分享文件 : https://developer.android.google.cn/training/secure-file-sharing

应用安装位置 : https://developer.android.google.cn/guide/topics/data/install-location

Android 存储用例和最佳做法 : https://developer.android.google.cn/training/data-storage/use-cases

FileProvider : https://developer.android.google.cn/reference/androidx/core/content/FileProvider

博客源码 :

GitHub : https://github.com/han1202012/File

CSDN : https://download.csdn.net/download/han1202012/18932254

Android 数据库

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:安利几个实用的Python库,超好用!
下一篇:软件测试常用工具总结(测试管理、单元测试、接口测试、自动化测试、性能测试、负载测试...)
相关文章