而如果这个文件变成了一张图片,那你涉及到的就不仅仅是一个 I/O 操作了,还需要考虑如何更新 MediaStore,这样才可以在系统相册中。

刷新系统 Media 通常有如下几种方式:

  • 通过操作 MediaStore 类。
  • 发送广播更新 MediaStore。
  • 通过操作 MediaScannerConnection 类。

操作 MediaStore

MediaStore.Images.Media它提供了几个 inserImage () 方法,供我们向 MediaStore 中插入图片数据,并产生一个缩略图。

  /*** Insert an image and create a thumbnail for it.** @param cr The content resolver to use* @param source The stream to use for the image* @param title The name of the image* @param description The description of the image* @return The URL to the newly created image, or <code>null</code> if the image failed to be stored*              for any reason.*/public static final String insertImage(ContentResolver cr, Bitmap source,String title, String description) {ContentValues values = new ContentValues();values.put(Images.Media.TITLE, title);values.put(Images.Media.DESCRIPTION, description);values.put(Images.Media.MIME_TYPE, "image/jpeg");Uri url = null;String stringUrl = null;    /* value to be returned */try {url = cr.insert(EXTERNAL_CONTENT_URI, values);if (source != null) {OutputStream imageOut = cr.openOutputStream(url);try {source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);} finally {imageOut.close();}long id = ContentUris.parseId(url);// Wait until MINI_KIND thumbnail is generated.Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id,Images.Thumbnails.MINI_KIND, null);// This is for backward compatibility.Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F,Images.Thumbnails.MICRO_KIND);} else {Log.e(TAG, "Failed to create thumbnail, removing original");cr.delete(url, null, null);url = null;}} catch (Exception e) {Log.e(TAG, "Failed to insert image", e);if (url != null) {cr.delete(url, null, null);url = null;}}if (url != null) {stringUrl = url.toString();}return stringUrl;}

这个方法传递进去的是一个 Bitmap 对象,其余的 title 和 description 分别是图片文件的名称和一段描述。

广播可以更新 MediaStore

说到广播,在 Android 4.4 之前,是可以通过 ACTION_MEDIA_MOUNTED 广播,来通知系统刷新 MediaStore 的,不过假如你现在还在依赖这条广播,你会得到一个错误信息。

E/AndroidRuntime(23718): java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED from pid=23718, uid=10097

在 Android 4.4 之后,这个广播只能由系统进行广播,App 只能对该广播进行监听,在当前的系统分布环境下,这条路已经走不通了。
这样设计也很好理解,毕竟扫描全盘是非常的耗资源,所以系统肯定要把全盘扫描的权限拿在自己手里不开放出来,避免被第三方 App 滥用。
不过 Android 依然给我们提供了替代方案,那就是用 MediaScannerConnection 或者发送 ACTION_MEDIA_SCANNER_SCAN_FILE 广播。
接下来就来说说 ACTION_MEDIA_SCANNER_SCAN_FILE 这个广播。
通过广播刷新 MediaStore 的方式非常的简单,只需要指定文件路径和 Action 就好了。

val saveAs = "Your_Created_Image_File_Path"
val contentUri = Uri.fromFile(File(saveAs))
val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,contentUri)
sendBroadcast(mediaScanIntent)

正常情况下,它是没有问题的,不过假如你发现它不生效,就需要检查一下你文件的路径是否传递正确。
通过查看 MediaScannerReceiver 的源码,可以发现 onReceive() 方法中,针对 ACTION_MEDIA_SCANNER_SCAN_FILE 还有一个限制条件,那就是传递进去的文件绝对路径,必须是以 Environment.getExternalStorageDirectory() 方法的返回值开头。

操作 MediaScannerConnection 类

刷新 MediaStore 还有一个最通用也是我推荐的一个方法,那就是使用 MediaScannerConnection 进行操作。

不同于 MediaStore.Image.Media 和广播的方式,使用 MediaScannerConnection 不仅可以保存文件,还可以指定文件路径,最好的就是,它还支持刷新完成的回调。

如果我们对时序有要求,并且需要制定文件保存路径的话,最好的方式就是直接使用 MediaScannerConnection 类进行操作,并且这也应该是兼容最好的方式。

这里我们主要是利用 MediaScannerConnection 类的 scanFile() 方法进行触发扫描。
通过 scanFile() 方法,我们只需要制定一个待刷新的文件路径和对应的 MimeType 即可,它支持传递多个路径,也可就是支持批量扫描。

注意这里的 MimeType 是一定要填写的,并且不能写通配符 / 或 null,否则会导致刷新失败,通常我们保存的是一个图片的话,只需要传递 image/jpeg 即可。

最后一个参数, onScanCompletedListener 中可以监听我们扫描的结果,需要注意的是,假如这里扫描的是多个文件路径,它也会被回调多次。所以如果有什么在刷新之后的后续操作,就需要特殊处理一下(原因后面是说)。

MediaScannerConnection.scanFile(this, arrayOf(picFile.absolutePath), arrayOf("image/jpeg"), { path, uri ->Log.i("cxmyDev", "onScanCompleted : " + path)
})

测试:“系统相册里怎么看不到我刚保存的图片,是我操作不对吗?”

正确将图片保存到相册的方法相关推荐

  1. ios保存gif到相册_IOS开发入门之iOS GIF图片导入到相册处理方法

    本文将带你了解IOS开发入门之iOS GIF图片导入到相册处理方法,希望对大家学IOS有所帮助 iOS GIF图片导入到相册处理方法 通过路径转成data数据,写入本地相册就行了: Java代码   ...

  2. android本地图片如何显示到相册中,如何将本地图片保存到相册

    1.前言 我们都知道将图片保存到本地的操作,但是如何将本地的图片保存到相册.有几种不同的方法,下面分别讲述这几种方法. 2.调用系统方法 MediaStore.Images.Media.insertI ...

  3. 长按UIWebView上的图片保存到相册

    不知道各位对于这个需求要如何解决? 可能有些人会想到js与原生交互,js监听图片点击事件,然后将图片的url传递给原生App端,然后原生App将图片保存到相册,这样子麻烦吗?超麻烦.(1).js监听图 ...

  4. 教你实现微信公众号效果:长按图片保存到相册

    不知道各位对于这个需求要如何解决? 可能有些人会想到js与原生交互,js监听图片点击事件,然后将图片的url传递给原生App端,然后原生App将图片保存到相册,这样子麻烦吗?超麻烦.(1).js监听图 ...

  5. OpenGLES(八)GPUImage滤镜链与将滤镜修改后的图片保存到相册

    1.滤镜链 在一个复合滤镜中,多种滤镜效果处理时,通常都是图片 -> 设置顶点/纹理坐标 -> 滤镜效果处理 -> 帧缓冲区 -> 新的纹理 -> 滤镜效果处理 -> ...

  6. React-Native使用CameraRoll将图片保存到相册

    使用CameraRoll将图片保存到相册在ios和android上的实现有一些差别. 首先CameraRoll有一个CameraRoll.saveToCameraRoll(tag, [type]);方 ...

  7. 26.Android 下载图片保存到相册

    26.Android 下载图片保存到相册 Android 下载图片保存到相册 前言 实现思路 自定义Dialog 自定义Handler 自定义AsyncTask AndroidManifest配置权限 ...

  8. ios 获取沙河文件夹_沙盒路径获取以及图片保存到相簿的方法

    iphone沙盒(sandbox)中的几个目录获取方式: // 获取沙盒主目录路径 NSString *homeDir = NSHomeDirectory(); // 获取Documents目录路径 ...

  9. matlab中单独存图_Matlab中图片保存的四种方法

    Matlab 中图片保存的四种方法 matlab 的绘图和可视化能力是不用多说的, 可以说在业内是家喻户晓的. Matlab 提供了丰富 的绘图函数,比如 ez** 系类的简易绘图函数, surf . ...

最新文章

  1. des加密解密JAVA与.NET互通实例
  2. UVA11255 Necklace Burnside、组合
  3. oracle z中rowid,如何将索引块里面的rowid和表里面的rowid对应起来?
  4. 初识python你应该知道的6个知识点!
  5. RAID简介与示例演示
  6. 英伟达的“千人摩擦计划”:几千个智能体互相玩耍,学习跑酷更轻松
  7. 在线 SQL 数据库环境
  8. linux离线语音识别安装运行总结
  9. [转载] python内置函数 compile()
  10. schema约束和引入
  11. 创业之初需要准备的六个方面
  12. 出国读计算机专业好吗,计算机美国读研 - 美国留学读计算机专业好不好
  13. setup/teardown用法汇总
  14. 解决:provider:Named Pipes Provider error:40无法打开SQL Server的连接
  15. 2020年东北三省数学建模联赛赛题
  16. 在家也可以享受购物体验?AR+Scene 帮您实现商品3D展示和虚拟试戴
  17. Visio2013 取消箭头的自动连接
  18. QQ音乐PB级ClickHouse实时数据平台架构演进之路
  19. 成都睿铂|如何对倾斜摄影相机进行畸变校正
  20. [NOIP2017模拟]豆豆游戏

热门文章

  1. 华为m3现在还能用吗_现在买二手华为平板m3还能用吗?
  2. 人活着最重要的是开心,理财最重要的是回本
  3. 【bzoj4372】 烁烁的游戏【动态树分治】
  4. FFmpeg的HEVC解码器源代码简单分析:CTU解码(CTU Decode)部分-PU
  5. Windows下通过注册表修改某个类型文件的默认打开方式和文件图标
  6. 2018省赛第九届蓝桥杯真题C语言B组第十题题解 乘积最大
  7. 2019年安徽省大学生计算机博弈大赛,2019年辽宁省普通高等学校本科大学生计算机博弈竞赛在我校成功举行...
  8. 新手学CAD入门到精通,迅捷CAD图库大全免费下载!
  9. 用虚拟信用卡注册Google Play开发者账号
  10. 达梦8在VMware虚拟机麒麟系统下命令安装