Android 分区存储之图片处理

Android 10 开始 启动了分区存储,在开发的时候,就需要进行一些适配,以下是需要适配的一下方法

1.  项目中使用了 选择图片功能,所以选择了  https://github.com/zhihu/Matisse 

2. 图片展示:

    采用了分区存储,之前的 通过path 展示图片的时候,会发现图片无法展示了(除了自己app的存储内的文件)

    所有在选择图片的回来后,不使用 path 而是使用 Uri

		   Set<MimeType> s = new HashSet<>();
           s.add(MimeType.PNG);
           s.add(MimeType.JPEG);
           Matisse.from(ImagePickerActivity.this)
                  .choose(s)
                  .countable(false)
                  .maxSelectable(1)
                  .thumbnailScale(1)
                  .imageEngine(new PicassoEngine())
                  .showPreview(false) // Default is `true`
                  .showSingleMediaType(true)
                  .forResult(121);

返回的时候,注意返回 Uri

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 121 && resultCode == RESULT_OK) {
            List<Uri> imagePaths = Matisse.obtainResult(data);
        }
    }

通过uri 使用Glide 加载图片就可以。

 

3. 如果只有 path 要去查 图片的 Uri 咋办呢?

    public static Uri getImageContentUri(String path) {
        Cursor cursor = MyApplication.getApplication().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=? ",
                new String[]{path}, null);
        if (cursor != null && cursor.moveToFirst()) {
            int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
            Uri baseUri = Uri.parse("content://media/external/images/media");
            return Uri.withAppendedPath(baseUri, "" + id);
        } else {
            // 如果图片不在手机的共享图片数据库,就先把它插入。
            if (new File(path).exists()) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, path);
                return MyApplication.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            } else {
                return null;
            }
        }
    }

4. 如果需要操作这个图片转bitmap又咋办呢?

    可以通过Uri 转bitmap ,但是 对于稍大的图片 会很卡,甚至出现 OOM,所有我舍弃了这个方法,采用了,将图片通过复制到app 的存储路径,再进行随心所欲的操作

@SuppressLint("NewApi")
    public static File copyFile(final Uri uri) {
        File file = null;
        if(uri == null) return file;
        //android10以上转换
        if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
            file = new File(uri.getPath());
        } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
            //把文件复制到沙盒目录
            ContentResolver contentResolver = MyApplication.getApplication().getContentResolver();
            String displayName = System.currentTimeMillis()+ Math.round((Math.random() + 1) * 1000)
                    +"."+ MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri));

            try {
                InputStream is = contentResolver.openInputStream(uri);
                File cache = new File(MyApplication.getApplication().getExternalCacheDir().getAbsolutePath(), displayName);
                FileOutputStream fos = new FileOutputStream(cache);
                FileUtils.copy(is, fos);
                file = cache;
                fos.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;

    }

上述代码中

getExternalCacheDir().getAbsolutePath()

是将文件复制到  

 /storage/emulated/0/Android/data/xxxxx/cache

此处可根据需求进行改动

注意:在调用FileUtiles.copy 时需要注意 

Build.VERSION.SDK_INT < Build.VERSION_CODES.Q

如果版本是10 以下,就可以直接 使用 

Bitmap bitmap = BitmapFactory.decodeFile(imagePath);  // file转bitmap

如果是 10 以上,还需要判断,是不是 在自己app 的文件夹内,true,直接  使用   file 转bitmap

                                                                                                    fase   调用复制,再使用 file 转bitmap

 

 

5. 现在有个需求,需要将图片插入相册咋办呢?

 @SuppressLint("NewApi")
    public static String bitmapToFileToAl(Context context, Bitmap bmp) {
        Long mImageTime = System.currentTimeMillis();
        String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS")
                .format(new Date(mImageTime));
        final ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES
                + File.separator + "cck"); //Environment.DIRECTORY_SCREENSHOTS:截图,图库中显示的文件夹名。"dh"
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp);
        values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
        values.put(MediaStore.MediaColumns.DATE_ADDED, mImageTime / 1000);
        values.put(MediaStore.MediaColumns.DATE_MODIFIED, mImageTime / 1000);
        values.put(MediaStore.MediaColumns.DATE_EXPIRES, (mImageTime + DateUtils.DAY_IN_MILLIS) / 1000);
        values.put(MediaStore.MediaColumns.IS_PENDING, 1);

        ContentResolver resolver = context.getContentResolver();
        final Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        try {
            // First, write the actual data for our screenshot
            try (OutputStream out = resolver.openOutputStream(uri)) {
                if (!bmp.compress(Bitmap.CompressFormat.PNG, 100, out)) {
                    throw new IOException("Failed to compress");
                }
            }
            // Everything went well above, publish it!
            values.clear();
            values.put(MediaStore.MediaColumns.IS_PENDING, 0);
            values.putNull(MediaStore.MediaColumns.DATE_EXPIRES);
            resolver.update(uri, values, null, null);
            return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath() + "\\cck\\" + timeStamp + ".png";
        } catch (IOException e) {
            resolver.delete(uri, null);
            Log.d("Exception", e.toString());
        }
        return "";
    }

6. 另外   

  

 android:requestLegacyExternalStorage="true"
 android:preserveLegacyExternalStorage="true"

 

 

总结:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值