前言
在上一篇中我們已經講述了AndroidQ(10)分區(qū)存儲適配,包括如何在私有目錄創(chuàng)建文件及文件夾、公共目錄下創(chuàng)建文件夾及文件、公有目錄下讀取文件、刪除文件等重要功能。
本篇文章將以開發(fā)中的實際情況出發(fā),講述在AndroidQ中如何將圖片下載到公共目錄,簡單來說就是如何將文件圖片復制到另一個文件夾下。
觸發(fā)場景:gilde已經將圖片緩存在本地,獲取圖片所在的gilde緩存路徑,將圖片復制到自己指定的目錄~
網絡下載圖片同理復制圖片,只是傳入不同類型的輸入輸出流而已~
相關系列文章
- AndroidQ(10)分區(qū)存儲完美適配
- AndroidQ(10)分區(qū)存儲完美適配之圖片(文件)上傳
- AndroidQ(10)分區(qū)存儲完美適配之圖片(文件)下載保存本地
- AndroidQ(10)分區(qū)存儲完美適配之圖片壓縮并保存
實際操作上手
必要參數(shù):原文件地址、需要復制的本地uri
-
根據(jù)系統(tǒng)版本獲取不同的文件路徑
- AndroidQ以下,可以使用
File API操作
/** * AndroidQ以下 * 創(chuàng)建圖片緩存路徑 * * @param fileName 名稱 包含文件類型 * @return 返回file類型 */ public static File getImageFileCache (String fileName) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { return null; } //創(chuàng)建項目圖片公共緩存目錄 File file = new File(Environment.getExternalStorageDirectory()+ File.separator + Environment.DIRECTORY_PICTURES + File.separator + "testAndroidQ" + File.separator + "images";); if (! file.exists()) { file.mkdirs(); } //創(chuàng)建對應圖片的緩存路徑 return new File(file + File.separator + fileName); }- AndroidQ以上, 使用
MediaStore生成對應文件圖片緩存路徑。不支持File API直接訪問本地文件,如果使用會報無權限訪問異常。
/** * AndroidQ以上保存圖片到公共目錄 * * @param imageName 圖片名稱 * @param imageType 圖片類型 * @param relativePath 緩存路徑 */ private static Uri insertImageFileIntoMediaStore (String imageName, String imageType, String relativePath) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { return null; } if (TextUtils.isEmpty(relativePath)) { return null; } Uri insertUri = null; ContentResolver resolver = context.getContentResolver(); //設置文件參數(shù)到ContentValues中 ContentValues values = new ContentValues(); //設置文件名 values.put(MediaStore.Images.Media.DISPLAY_NAME, imageName); //設置文件描述,這里以文件名代替 values.put(MediaStore.Images.Media.DESCRIPTION, imageName); //設置文件類型為image/* values.put(MediaStore.Images.Media.MIME_TYPE, "image/" + imageType); //注意:MediaStore.Images.Media.RELATIVE_PATH需要targetSdkVersion=29, //故該方法只可在Android10的手機上執(zhí)行 values.put(MediaStore.Images.Media.RELATIVE_PATH, relativePath); //EXTERNAL_CONTENT_URI代表外部存儲器 Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; //insertUri表示文件保存的uri路徑 insertUri = resolver.insert(external, values); return insertUri; } - AndroidQ以下,可以使用
-
通過兩個路徑地址生成對應的輸入輸出流
主要方式獲取
ContentResolver.openOutputStream(insertUri)
public static boolean copyFile (String sourceFilePath, final Uri insertUri) {
if (insertUri == null) {
return false;
}
ContentResolver resolver = context.getContentResolver();
InputStream is = null;//輸入流
OutputStream os = null;//輸出流
try {
os = resolver.openOutputStream(insertUri);
if (os == null) {
return false;
}
File sourceFile = new File(sourceFilePath);
if (sourceFile.exists()) { // 文件存在時
is = new FileInputStream(sourceFile); // 讀入原文件
//輸入流讀取文件,輸出流寫入指定目錄
return copyFileWithStream(os, is);
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 利用輸入輸出流邊讀邊寫,將文件(圖片)寫入指定路徑
private static boolean copyFileWithStream (OutputStream os, InputStream is) {
if (os == null || is == null) {
return false;
}
int read = 0;
while (true) {
try {
byte[] buffer = new byte[1444];
while ((read = is.read(buffer)) != - 1){
os.write(buffer, 0, read);
os.flush();
}
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
AndroidQ以下獲取文件輸入輸出流就不貼代碼了,注意區(qū)分就好啦~
加載本地圖片
我們項目中使用的是Glide加載,故示例代碼中也使用Glide。
GlideApp.with(context).load(imageUri);
如果AndroidQ之前使用file://類型加載,兼容10可以采用file轉uri的方式,都可以通過uri加載圖片。
圖片上傳
注意:
在AndroidQ中公有目錄訪問文件,
File API都無法訪問,即:file://本地path操作文件,本地加載圖片、上傳、下載都不支持,只能通過uri來操作如果下載圖片到公共目錄,無需再發(fā)送廣播通知圖片更新;
MediaStore.Images.Media.RELATIVE_PATH需要targetSdkVersion=29,故該方法只可在Android10的手機上執(zhí)行,如果在小于29的系統(tǒng)下調用RELATIVE_PATH會報錯:
android.database.sqlite.SQLiteException: table files has no column named relative_path (code 1 SQLITE_ERROR)
數(shù)據(jù)庫中插入無法找到relative_path字段
本篇代碼適用于文件讀寫、復制、保存圖片到本地等等功能,靈活掌握ContentResolver
后續(xù)會繼續(xù)對AndroidQ分區(qū)存儲實際操作做總結,歡迎關注~
大佬點個贊再走唄~