Android 文件管理】分區存儲 ( 創建與查詢圖片文件 )

      網友投稿 1137 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

      【Android 文件管理】分區存儲 ( 創建與查詢圖片文件 )

      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

      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庫,超好用!
      下一篇:軟件測試常用工具總結(測試管理、單元測試、接口測試、自動化測試、性能測試、負載測試...)
      相關文章
      亚洲人成在线播放网站岛国| 亚洲欧洲日韩不卡| 亚洲国产福利精品一区二区| 久久精品国产精品亚洲艾| 国产亚洲成人在线播放va| 亚洲成?v人片天堂网无码| 苍井空亚洲精品AA片在线播放| 国产亚洲欧美日韩亚洲中文色| 亚洲国产成人手机在线观看| 亚洲熟妇丰满xxxxx| 亚洲中文无码永久免| 亚洲中文无码mv| 亚洲AV综合永久无码精品天堂| 亚洲Aⅴ在线无码播放毛片一线天 亚洲avav天堂av在线网毛片 | 亚洲国产精品13p| 亚洲黄片毛片在线观看| 国产偷国产偷亚洲高清日韩 | 亚洲国产美女在线观看| 亚洲午夜精品国产电影在线观看| 亚洲另类小说图片| 一本色道久久88—综合亚洲精品| 亚洲精品无码国产片| 精品久久久久久亚洲综合网| 大胆亚洲人体视频| 亚洲熟妇av一区二区三区| 久久精品国产亚洲香蕉| 久久精品国产亚洲AV无码娇色| 亚洲白色白色永久观看| 亚洲成年网站在线观看| 亚洲国产精品成人午夜在线观看 | 亚洲欧美在线x视频| 亚洲精品一级无码中文字幕| 亚洲日韩精品无码一区二区三区| 亚洲国产成人片在线观看| 91嫩草私人成人亚洲影院| 亚洲精品亚洲人成在线播放| 亚洲精品美女久久7777777| 亚洲日韩中文在线精品第一| 亚洲精品蜜桃久久久久久| 亚洲色图在线播放| 国产精品亚洲片夜色在线|