Android保存自定义路径的图片的一些问题
首先是權限的問題
在android 10以后,權限進一步更新,導致我們所保存的文件的路徑會進一步縮減,目前大部分的存儲目錄就這幾個
1、應用的內部存儲空間(這個路徑下只有當前APP能訪問數據,其他APP是無法訪問的):
目錄路徑即:data/data/包名 ,這個是在APP創建之后就會生成的,默認存儲的圖片會保存到這里,但是,這里的圖片,在圖庫(就是android的手機相冊)是訪問不到的,因為app(相冊)是無法訪問其他APP的私有目錄
2、共享存儲:
共享就是Android公開共享的文件夾,拿圖片來說的話 就是兩個文件夾 一個是DCIM目錄, 一個Pictures目錄,存放的圖片可以放在這兩個地方
(注:KitKat之后的版本不再支持用戶對外置SDcard(Secondary Storage)的寫入等操作,如果用戶想要將文件等copy到手機中,則只能存儲到內部存儲器中,而無法存儲到外置sdcard中)。外部存儲有9大共有目錄(表中第一條是外部存儲路徑):
Environment.getExternalStorageDirectory()
目錄文件路徑:/storage/sdcard/0
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS)
目錄文件路徑:/storage/sdcard/0/Alarms
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
目錄文件路徑:/storage/sdcard/0/DCIM
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS
目錄文件路徑:/storage/sdcard/0/Download
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
目錄文件路徑:/storage/sdcard/0/Movies
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
目錄文件路徑:/storage/sdcard/0/Music
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS)
目錄文件路徑:/storage/sdcard/0/Notifications
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
目錄文件路徑:/storage/sdcard/0/Pictures
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS)
目錄文件路徑:/storage/sdcard/0/Podcasts
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES)
目錄文件路徑:/storage/sdcard/0/Ringtones
然后就是保存圖片的代碼,這個百度很多,就不過多說明了,放上一個在Android 10以上用的代碼:
//保存圖片是否成功標識private final int SAVE_IMAGE_SUCCESS = 1;private final int SAVE_IMAGE_ERROR = 2;/*** 對于圖片進行截圖,然后保存到SD卡中* 這里可以用異步操作,最好使用異步操作,因為會有耗時操作*/private void saveBitmap() {//判斷版本LogUtil.e("當前手機版本:" + Build.VERSION.SDK_INT);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {saveImage(bitmap);} else {// setImageToNine(bitmap);}bitmap.recycle();} /*** 保存圖片,在SDK 10以及10以上 的圖片使用** @param bitmap*/private void saveImage(Bitmap bitmap) {//存儲的路徑String imageSaveFilePath = Environment.DIRECTORY_DCIM + File.separator + "com.demo"; // String imageSaveFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "com.demo";LogUtil.e("存儲的路徑:" + imageSaveFilePath);//新建文件夾mkDir(imageSaveFilePath);// 文件名String mImageFileName = DateFormat.format("yyyyMMdd_hhmmss", new Date()).toString();// 文件路徑String mImageFilePath = imageSaveFilePath + File.separator + mImageFileName + ".png";ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.MediaColumns.TITLE, mImageFileName);contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, mImageFileName);contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");contentValues.put(MediaStore.MediaColumns.DATE_TAKEN, mImageFileName);//應用下的絕對路徑contentValues.put(MediaStore.MediaColumns.DATA, mImageFilePath);//該媒體項在存儲設備中的相對路徑,該媒體項將在其中保留contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, imageSaveFilePath);Uri uri = null;OutputStream outputStream = null;ContentResolver localContentResolver = getContentResolver();try {uri = localContentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);outputStream = localContentResolver.openOutputStream(uri);//將bitmap圖片保存到Uri對應的數據節點中bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);outputStream.flush();outputStream.close();mHandler.obtainMessage(SAVE_IMAGE_SUCCESS, mImageFilePath).sendToTarget();} catch (Exception e) {e.printStackTrace();if (uri != null) {localContentResolver.delete(uri, null, null);}mHandler.obtainMessage(SAVE_IMAGE_ERROR, e.toString()).sendToTarget();} finally {bitmap.recycle();try {if (outputStream != null) {outputStream.close();}} catch (IOException e) {e.printStackTrace();}}}//創建文件夾public static void mkDir(String dirPath) {String[] dirArray = dirPath.split("/");String pathTemp = "";for (int i = 1; i < dirArray.length; i++) {pathTemp = pathTemp + "/" + dirArray[i];File newF = new File(dirArray[0] + pathTemp);if (!newF.exists()) {newF.mkdir();}}}private Handler mHandler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(@NonNull Message msg) {String dataObj = (String) msg.obj;LogUtil.e("保存的結果:" + dataObj);if (msg.what == SAVE_IMAGE_SUCCESS) {Toast.makeText(BeautyActivity.this, "保存的地址:" + dataObj, Toast.LENGTH_SHORT).show();} else {Toast.makeText(BeautyActivity.this, "保存失敗:" + dataObj, Toast.LENGTH_SHORT).show();}return false;}});接下來的就是遇到的問題了
1、代碼執行,但是掃描不成功,圖庫還是無法查看
getBaseContext().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(dataObj))));
這個問題是在10以下版本出現的: 保存到其他目錄,但是圖庫中不顯示的問題,可以使用以下代碼試試,代碼已經測試過了
//發送通知,告知圖片庫更新圖片ContentValues videoValues = new ContentValues();videoValues.put(MediaStore.Images.Media.TITLE, imageName);//imageName 圖片名稱videoValues.put(MediaStore.Images.Media.MIME_TYPE, "image/png");videoValues.put(MediaStore.Images.Media.DATA, savePathFile.getAbsolutePath()); //圖片路徑getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, videoValues);還有一種實現圖庫更新的方式,這種方式有點小問題,詳情看注釋
//把文件插入到系統圖庫 但是在圖庫中會多一張圖片,一張是原存放路徑的地方的圖片,一張是Pictures路徑下的圖片 MediaStore.Images.Media.insertImage(getContentResolver(), savePathFile.getAbsolutePath(), imageName, null);2、android 10 以上的路徑問題
//存儲的路徑String imageSaveFilePath = Environment.DIRECTORY_DCIM + File.separator + "com.demo"; // String imageSaveFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "com.demo";這兩個的路徑的差別
前者是 'DCIM/com.demo'
后者的路徑有 '/storage/emulated/0/DCIM/com.demo'
關于后者在上面的代碼運行時,會出現一個BUG:
'java.lang.IllegalArgumentException: Primary directory (invalid) not allowed for content://media/external/images/media; allowed directories are [DCIM, Pictures]'
提示說:內容的主要目錄(無效):mediaexternalimagesmedia;允許的目錄為[DCIM,圖片]
但是換成前者代碼 就不會有這個問題, 關于這個問題,目前還沒有找到答案,如果有答案的大佬看到 可以給我言, 感謝!!!
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Android保存自定义路径的图片的一些问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Multi GET API
- 下一篇: mysql存储过程输入参数拆分_一文看懂