打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android 保存图片到本地 兼容Android 10+
userphoto

2022.05.08 湖南省

关注


Android 保存图片到本地(兼容Android 10+)

图片保存在 DCIM 公开目录

大于 28 需使用 MediaStore

小于 29 直接 new FIle

public class ImageSaveUtil {

    /**

     * 保存图片到公共目录

     * 29 以下,需要提前申请文件读写权限

     * 29及29以上的,不需要权限

     * 保存的文件在 DCIM 目录下

     *

     * @param context 上下文

     * @param bitmap  需要保存的bitmap

     * @param format  图片格式

     * @param quality 压缩的图片质量

     * @param recycle 完成以后,是否回收Bitmap,建议为true

     * @return 文件的 uri

     */

    @Nullable

    public static Uri saveAlbum(Context context, Bitmap bitmap, Bitmap.CompressFormat format, int quality, boolean recycle) {

        String suffix;

        if (Bitmap.CompressFormat.JPEG == format)

            suffix = "JPG";

        else

            suffix = format.name();

        String fileName = System.currentTimeMillis() + "_" + quality + "." + suffix;

        if (Build.VERSION.SDK_INT < 29) {

            if (!isGranted(context)) {

                Log.e("ImageUtils", "save to album need storage permission");

                return null;

            }

            File picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

            File destFile = new File(picDir, fileName);

            if (!save(bitmap, destFile, format, quality, recycle))

                return null;

            Uri uri = null;

            if (destFile.exists()) {

                uri = Uri.parse("file://" + destFile.getAbsolutePath());

                Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);

                intent.setData(uri);

                context.sendBroadcast(intent);

            }

            return uri;

        } else {

            // Android 10 使用

            Uri contentUri;

            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

            } else

                contentUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI;

            ContentValues contentValues = new ContentValues();

            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);

            contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/*");

            contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/");

            // 告诉系统,文件还未准备好,暂时不对外暴露

            contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);

            Uri uri = context.getContentResolver().insert(contentUri, contentValues);

            if (uri == null) return null;

            OutputStream os = null;

            try {

                os = context.getContentResolver().openOutputStream(uri);

                bitmap.compress(format, quality, os);

                // 告诉系统,文件准备好了,可以提供给外部了

                contentValues.clear();

                contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);

                context.getContentResolver().update(uri, contentValues, null, null);

                return uri;

            } catch (Exception e) {

                e.printStackTrace();

                // 失败的时候,删除此 uri 记录

                context.getContentResolver().delete(uri, null, null);

                return null;

            } finally {

                try {

                    if (os != null)

                        os.close();

                } catch (IOException e) {

                    // ignore

                }

            }

        }

    }

    private static boolean save(Bitmap bitmap, File file, Bitmap.CompressFormat format, int quality, boolean recycle) {

        if (isEmptyBitmap(bitmap)) {

            Log.e("ImageUtils", "bitmap is empty.");

            return false;

        }

        if (bitmap.isRecycled()) {

            Log.e("ImageUtils", "bitmap is recycled.");

            return false;

        }

        if (!createFile(file, true)) {

            Log.e("ImageUtils", "create or delete file <$file> failed.");

            return false;

        }

        OutputStream os = null;

        boolean ret = false;

        try {

            os = new BufferedOutputStream(new FileOutputStream(file));

            ret = bitmap.compress(format, quality, os);

            if (recycle && !bitmap.isRecycled()) bitmap.recycle();

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            try {

                if (os != null)

                    os.close();

            } catch (IOException e) {

                // ignore

            }

        }

        return ret;

    }

    private static boolean isEmptyBitmap(Bitmap bitmap) {

        return bitmap == null || bitmap.isRecycled() || bitmap.getWidth() == 0 || bitmap.getHeight() == 0;

    }

    private static boolean createFile(File file, boolean isDeleteOldFile) {

        if (file == null) return false;

        if (file.exists()) {

            if (isDeleteOldFile) {

                if (!file.delete()) return false;

            } else

                return file.isFile();

        }

        if (!createDir(file.getParentFile())) return false;

        try {

            return file.createNewFile();

        } catch (IOException e) {

            return false;

        }

    }

    private static boolean createDir(File file) {

        if (file == null) return false;

        if (file.exists())

            return file.isDirectory();

        else

            return file.mkdirs();

    }

    private static boolean isGranted(Context context) {

        return (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE));

    }

}

————————————————

版权声明:本文为CSDN博主「OneGreenHand」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/a295268305/article/details/108880706

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android多媒体分析(二)MediaStore
适配Android10 拍照,相册,裁剪,上传图片
Android多媒体学习一:Android中Image的简单实例。
Android 基于Zxing的二维码扫描优化
适配小米华为手机等拍照后获取不到照片
如何获取多媒体文件信息
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服