Android 图片保存到相册不显示的解决方案(兼容Android 10及更高版本)

 更新时间:2021年04月22日 08:56:00   作者:东慕雨  
这篇文章主要介绍了Android 图片保存到系统相册不显示的解决方案,帮助大家更好的理解和学习使用Android开发,感兴趣的朋友可以了解下

前言

写了一个demo,简单逻辑就是:在一个图片上添加一行文字或者是水印,并且保存到系统相册,也就是我们手机上的图库。前面编辑图片添加水印都没有问题,到后面保存到系统相册出现了问题:显示不出来图片。

问题

在 Android 10 之前保存系统相册的三步骤:

  • 保存图片到手机
  • 把图片插入到手机图库
  • 发广播更新

代码如下:

public static void savePhotoAlbum(Context context, Bitmap bmp) {
    // 首先保存图片
    File appDir = new File(Environment.getExternalStorageDirectory(), "Boohee");
    if (!appDir.exists()) {
        appDir.mkdir();
    }
    String fileName = System.currentTimeMillis() + ".jpg";
    File file = new File(appDir, fileName);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        bmp.compress(CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
	}
    
    // 其次把文件插入到系统图库
    try {
        MediaStore.Images.Media.insertImage(context.getContentResolver(),
				file.getAbsolutePath(), fileName, null);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    // 最后通知图库更新
    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));
}

出现的问题:图片不显示,也就是说没有更新到系统图库中。

细心的小伙伴会发现,上段代码有两处地方废弃的方法:

 MediaStore.Images.Media.insertImage(context.getContentResolver(),
				file.getAbsolutePath(), fileName, null);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));

解决问题

下面是解决上面的问题,并兼容 Android10 版本:

    /**
     * 添加水印并保存到系统相册
     */
    private void imgMerge() {
        new Thread(() -> {
            try {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
                File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "newFile.jpg");
                if (!file.exists()) {
                    file.createNewFile();
                }
                //添加水印文字位置。
                Bitmap newBitmap = addTextWatermark(bitmap, "测试demo示例");
                //保存到系统相册
                savePhotoAlbum(newBitmap, file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
    
    /**
     * 保存到相册
     *
     * @param src  源图片
     * @param file 要保存到的文件
     */
    private void savePhotoAlbum(Bitmap src, File file) {
        if (isEmptyBitmap(src)) {
            return;
        }
        //先保存到文件
        OutputStream outputStream;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(file));
            src.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
            if (!src.isRecycled()) {
                src.recycle();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //再更新图库
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, file.getName());
            values.put(MediaStore.MediaColumns.MIME_TYPE, getMimeType(file));
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
            ContentResolver contentResolver = getContentResolver();
            Uri uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,  values);
            if (uri == null) {
                return;
            }
            try {
                outputStream = contentResolver.openOutputStream(uri);
                FileInputStream fileInputStream = new FileInputStream(file);
                FileUtils.copy(fileInputStream, outputStream);
                fileInputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            MediaScannerConnection.scanFile(
                    getApplicationContext(),
                    new String[]{file.getAbsolutePath()},
                    new String[]{"image/jpeg"},
                    (path, uri) -> {
                        // Scan Completed
                    });
        }
    }

发送广播和插入MediaProvider两种方式添加图片到相册,这两种方式已经官方废弃了。在 Android 10版本以及更高版本使用上面的方法,才能有效解决不显示图片的问题。

做个记录!

以上就是Android 图片保存到系统相册不显示的解决方案(兼容Android 10及更高版本)的详细内容,更多关于Android 图片保存到相册不显示的资料请关注脚本之家其它相关文章!

相关文章

  • Android HttpURLConnection.getResponseCode()错误解决方法

    Android HttpURLConnection.getResponseCode()错误解决方法

    在使用HttpURLConnection.getResponseCode()的时候直接报错是IOException错误,一直想不明白,同一个程序我调用了两次,结果有一个链接一直OK,另一个却一直报这个错误
    2013-06-06
  • android自定义ImageView仿图片上传示例

    android自定义ImageView仿图片上传示例

    本篇文章主要介绍了android自定义ImageView仿图片上传,具有一定的参考价值,有兴趣的可以了解一下。
    2017-01-01
  • Android实现滑动折叠Header全流程详解

    Android实现滑动折叠Header全流程详解

    这篇文章主要介绍了Android实现滑动折叠Header,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-11-11
  • Android最基本的异步网络请求框架

    Android最基本的异步网络请求框架

    这篇文章主要为大家详细介绍了Android最基本的异步网络请求框架,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • Flutter通过Container实现时间轴效果

    Flutter通过Container实现时间轴效果

    时间轴是前端UI经常用到的效果,本文讲解下Flutter如何通过Container实现,感兴趣的朋友可以了解下
    2021-05-05
  • Android 版本、权限适配相关总结

    Android 版本、权限适配相关总结

    针对 Android 6.0 (API 23)已以上版本,Google 增强全新的权限,应用程序在使用敏感权限(如拍照、查阅联系人或存储)时需要先征求用户必须赢得用户同意。
    2021-05-05
  • Android可自定义神奇动效的卡片切换视图实例

    Android可自定义神奇动效的卡片切换视图实例

    今天小编就为大家分享一篇关于Android可自定义神奇动效的卡片切换视图实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • Android在WebView中调用系统下载的方法

    Android在WebView中调用系统下载的方法

    这篇文章主要为大家详细介绍了Android在WebView中调用系统下载的简单使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Android中切换到主线程执行的方法

    Android中切换到主线程执行的方法

    这篇文章主要介绍了Android中切换到主线程执行的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Android Listview点赞问题关于图片重复问题

    Android Listview点赞问题关于图片重复问题

    最近在开发android方面的项目时,遇到很多问题,下面小编以listview 与 baseadapter结合使用为例,给大家分享下关于点赞的的时候 图片重复问题的解决方法,一起看看吧
    2016-11-11

最新评论