Android保存自定义路径的图片的一些问题

解决11保存到相册的问题:android 11 版本下图片的保存方式改变以及保存图片到相册_笑忘书客的博客-CSDN博客_android11保存图片到相册

首先是权限的问题
在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() {
        @Override
        public 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);
1
2
3
4
5
6
7
还有一种实现图库更新的方式,这种方式有点小问题,详情看注释

    //把文件插入到系统图库  但是在图库中会多一张图片,一张是原存放路径的地方的图片,一张是Pictures路径下的图片        
   MediaStore.Images.Media.insertImage(getContentResolver(), savePathFile.getAbsolutePath(), imageName, null);
1
2
2、android 10 以上的路径问题
    //存储的路径
        String imageSaveFilePath = Environment.DIRECTORY_DCIM + File.separator + "com.demo";
//       String imageSaveFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "com.demo";
1
2
3
这两个的路径的差别
前者是 '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,图片]

但是换成前者代码 就不会有这个问题, 关于这个问题,目前还没有找到答案,如果有答案的大佬看到 可以给我言, 感谢!!!
————————————————
版权声明:本文为CSDN博主「 暝七夜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_17806439/article/details/116752361

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值