Android MediaStore 安卓保存图片各版本适配Q及以上

使用方法  

保存当前view到相册  
MediaStoreUtils.saveBitmap(activity,ConvertUtils.view2Bitmap(view"需要保存的图片"));

保存drawable资源图片到相册

Bitmap bitmap=BitmapFactory.decodeResource(resources,R.drawable.t1)
MediaStoreUtils.saveBitmap(activity,bitmap);

1. MediaStore工具类

public class MediaStoreUtils {
    //读取
    public static void queryImages(@NotNull Activity activity) {
        String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            //检查权限
            if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(activity, new String[]{permission}, 10086);
                return;
            }
        }
        queryAllImages(activity);
    }

    private static ArrayList queryAllImages(Context context) {
        Uri externalContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        String[] projection;
        Uri.Builder appendId = new Uri.Builder();

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.RELATIVE_PATH};
        } else {
            projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.DATA};
        }
        Cursor cursor = context.getContentResolver().query(externalContentUri, projection, null, null, null);

        ArrayList<Uri> uris = new ArrayList<Uri>();
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                do {
                    appendId = ContentUris.appendId(externalContentUri.buildUpon(), cursor.getLong(0));
                    if (appendId != null) {
                        uris.add(appendId.build());
                        Log.d("SMG", appendId.build().toString());
                    }
                    String string1 = cursor.getString(1);
                    Log.d("SMG", string1);
                    String string2 = cursor.getString(2);
                    Log.d("SMG", string2);
                } while (cursor.moveToNext());
            }
            cursor.close();
        }
        return uris;
    }
    //保存
    public static void saveImages(@NotNull Activity activity, @NotNull final Bitmap bitmap) {
        String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            //检查权限
            if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(activity, new String[]{permission}, 10086);
                return;
            }
        }

        try {
            saveMedia(activity, bitmap, Environment.DIRECTORY_PICTURES, "ASUKA", "xxx.jpg", "image/JPEG", "");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //type:Environment.DIRECTORY_PICTURES
    private static void saveMedia(Context context, Bitmap bitmap, String dirType, String relativeDir, String filename, String mimeType, String description) throws IOException {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            //首先保存
            File saveDir = Environment.getExternalStoragePublicDirectory(dirType);
            saveDir = new File(saveDir, relativeDir);
            if (!saveDir.exists() && !saveDir.mkdirs()) {
                try {
                    throw new Exception("create directory fail!");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            Log.d("SMG", saveDir.getAbsolutePath());
            File outputFile = new File(saveDir, filename);
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(outputFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);
            bos.flush();
            bos.close();
            //把文件插入到系统图库(直接插入到Picture文件夹下)
//        MediaStore.Images.Media.insertImage(
//            context.contentResolver, outputFile.absolutePath, outputFile.name, ""
//        )
            //最后通知图库更新
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(outputFile)));
        } else {
            String path = EmptyUtils.isNotEmpty(relativeDir) ? Environment.DIRECTORY_PICTURES + File.separator + relativeDir : Environment.DIRECTORY_PICTURES;
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
            contentValues.put(MediaStore.Images.Media.DESCRIPTION, description);
            contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, path);
            contentValues.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
            //contentValues.put(MediaStore.Images.Media.IS_PENDING,1)

            Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            Uri insertUri = context.getContentResolver().insert(external, contentValues);

            OutputStream fos = (OutputStream) null;
            if (insertUri != null) {
                try {
                    fos = context.getContentResolver().openOutputStream(insertUri);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
                fos.flush();
                fos.close();
            }
        }
    }


    /**
     * Android Q以下版本,删除文件需要申请WRITE_EXTERNAL_STORAGE权限。通过MediaStore的DATA字段获得媒体文件的绝对路径,然后使用File相关API删除
     * <p>
     * Android Q以上版本,应用删除自己创建的媒体文件不需要用户授权。删除其他应用创建的媒体文件需要申请READ_EXTERNAL_STORAGE权限。
     * 删除其他应用创建的媒体文件,还会抛出RecoverableSecurityException异常,在操作或删除公共目录的文件时,需要Catch该异常,由MediaProvider弹出弹框给用户选择是否允许应用修改或删除图片/视频/音频文件
     */
    public static void deletePicture(@NotNull Activity activity, @NotNull Uri imageUri) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            String[] projection = new String[]{MediaStore.Images.Media.DATA};
            Cursor cursor = activity.getContentResolver().query(imageUri, projection,
                    null, null, null);
            if (cursor != null) {
                int columnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
                if (columnIndex > -1) {
                    File file = new File(cursor.getString(columnIndex));
                    file.delete();
                }
            }
            if (cursor != null) {
                cursor.close();
            }
        } else {
            try {
                activity.getContentResolver().delete(imageUri, null, null);
            } catch (RecoverableSecurityException e1) {
                //捕获 RecoverableSecurityException异常,发起请求
                try {
                    ActivityCompat.startIntentSenderForResult(activity, e1.getUserAction().getActionIntent().getIntentSender(),
                            10086, null, 0, 0, 0, null);
                } catch (IntentSender.SendIntentException e) {
                    e.printStackTrace();
                }

            }
        }
    }

}

2.   view2Bitmap 跟bitmap2Bytes转换工具类

public final class ConvertUtils {

    /**
     * 毫秒时间戳转合适时间长度
     *
     * @param millis    毫秒时间戳
     *                  <p>小于等于0,返回null</p>
     * @param precision 精度
     *                  <ul>
     *                  <li>precision = 0,返回null</li>
     *                  <li>precision = 1,返回天</li>
     *                  <li>precision = 2,返回天和小时</li>
     *                  <li>precision = 3,返回天、小时和分钟</li>
     *                  <li>precision = 4,返回天、小时、分钟和秒</li>
     *                  <li>precision &gt;= 5,返回天、小时、分钟、秒和毫秒</li>
     *                  </ul>
     * @return 合适时间长度
     */
    @SuppressLint("DefaultLocale")
    public static String millis2FitTimeSpan(long millis, int precision) {
        if (millis <= 0 || precision <= 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        String[] units = {"天", "小时", "分钟", "秒", "毫秒"};
        int[] unitLen = {86400000, 3600000, 60000, 1000, 1};
        precision = Math.min(precision, 5);
        for (int i = 0; i < precision; i++) {
            if (millis >= unitLen[i]) {
                long mode = millis / unitLen[i];
                millis -= mode * unitLen[i];
                sb.append(mode).append(units[i]);
            }
        }
        return sb.toString();
    }


    /**
     * bitmap转byteArr
     *
     * @param bitmap bitmap对象
     * @param format 格式
     * @return 字节数组
     */
    public static byte[] bitmap2Bytes(final Bitmap bitmap, final Bitmap.CompressFormat format) {
        if (bitmap == null) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        /**
         * Bitmap.CompressFormat format 图像的压缩格式;
         * int quality 图像压缩率,0-100。 0 压缩100%,100意味着不压缩;
         * OutputStream stream 写入压缩数据的输出流;
         */
        bitmap.compress(format, 100, baos);
        return baos.toByteArray();
    }

    /**
     * byteArr转bitmap
     *
     * @param bytes 字节数组
     * @return bitmap
     */
    public static Bitmap bytes2Bitmap(final byte[] bytes) {
        return (bytes == null || bytes.length == 0) ? null : BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }

    /**
     * drawable转bitmap
     *
     * @param drawable drawable对象
     * @return bitmap
     */
    public static Bitmap drawable2Bitmap(final Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            if (bitmapDrawable.getBitmap() != null) {
                return bitmapDrawable.getBitmap();
            }
        }
        Bitmap bitmap;
        if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
            bitmap = Bitmap.createBitmap(1, 1,
                    drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        } else {
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
                    drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        }
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    }

    /**
     * bitmap转drawable
     *
     * @param bitmap bitmap对象
     * @return drawable
     */
    public static Drawable bitmap2Drawable(final Bitmap bitmap, Context context) {
        return bitmap == null ? null : new BitmapDrawable(context.getResources(), bitmap);
    }

    /**
     * drawable转byteArr
     *
     * @param drawable drawable对象
     * @param format   格式
     * @return 字节数组
     */
    public static byte[] drawable2Bytes(final Drawable drawable, final Bitmap.CompressFormat format) {
        return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format);
    }

    /**
     * byteArr转drawable
     *
     * @param bytes 字节数组
     * @return drawable
     */
    public static Drawable bytes2Drawable(final byte[] bytes, Context context) {
        return bytes == null ? null : bitmap2Drawable(bytes2Bitmap(bytes),context);
    }

    /**
     * view转Bitmap
     *
     * @param view 视图
     * @return bitmap
     */
    public static Bitmap view2Bitmap(final View view) {
        if (view == null) {
            return null;
        }
        Bitmap bmp = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bmp);
        Drawable bgDrawable = view.getBackground();
        if (bgDrawable != null) {
            bgDrawable.draw(canvas);
        } else {
            canvas.drawColor(Color.WHITE);
        }
        view.draw(canvas);

        // 缩小图片
        Matrix matrix = new Matrix();
        matrix.postScale(1.0f, 1.0f); //长和宽放大缩小的比例
        bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);

        return bmp;
    }

    public static Bitmap stringToBitmap(String string){
        //将字符串转换成Bitmap类型
        Bitmap bitmap=null;
        try {
            byte[]bitmapArray;
            bitmapArray=Base64.decode(string, Base64.DEFAULT);
            bitmap=BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bitmap;
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易寻资料

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值