Android保存图片到系统图库并通知系统相册刷新

1.场景

  在android开发中保存应用的图片并插入到系统图库同时通知相册刷新的功能,做完后发现在部分手机上出现虽然图片保存成功了,但是相册却找不到图片的问题,查找文件夹图片也已经存在,可就是在相册里刷新不出来。

2.思路

2.1.保存图片的方法

public static File saveImage(Bitmap bmp) {File appDir = new File(Environment.getExternalStorageDirectory(), "zzs");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();}
}

  以上代码便是将Bitmap保存图片到指定的路径/sdcard/Boohee/下,文件名以当前系统时间命名,但是这种方法保存的图片没有加入到系统图库中

2.2.调用系统提供的插入图库的方法

MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "title", "description");

  调用以上系统自带的方法会把bitmap对象保存到系统图库中,但是这种方法无法指定保存的路径和名称,上述方法的title、description参数只是插入数据库中的字段,真实的图片名称系统会自动分配。看似上述这种方法就是我们要用到的方法,但是可惜的调用上述放法插入图库的方法图片并没有立刻显示在图库中,而我们需要立刻更新系统图库以便让用户可以立刻查看到这张图片。

2.3.调用系统提供的插入图库的方法

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

  上面那条广播是扫描整个sd卡的广播,如果你sd卡里面东西很多会扫描很久,在扫描当中我们是不能访问sd卡,所以这样子用户体现很不好,所以下面我们还有如下的方法:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File("/sdcard/Boohee/image.jpg"))););

  或者还有如下方法:

final MediaScannerConnection msc = new MediaScannerConnection(mContext, new MediaScannerConnectionClient() {     public void onMediaScannerConnected() {     msc.scanFile("/sdcard/Boohee/image.jpg", "image/jpeg");     }     public void onScanCompleted(String path, Uri uri) {     Log.v(TAG, "scan completed");     msc.disconnect();     }     
});

上面代码的图片路径不管是通过自己写方法还是系统插入图库的方法都可以很容易的获取到。

2.4.终极完美解决方案

  如果我想把图片保存到指定的文件夹,同时又需要图片出现在图库里呢?sdk还提供了这样一个方法:

MediaStore.Images.Media.insertImage(getContentResolver(), "image path", "title", "description");

  上述方法的第二个参数是image path,这样的话就有思路了,首先自己写方法把图片指定到指定的文件夹,然后调用上述方法把刚保存的图片路径传入进去,最后通知图库更新。

3.解决办法

(1)创建文件路径可选择Environment.getExternalStorageDirectory(),也就是(/storage/emulated/0/com.xx.xxx.xxx/),之前有问题的版本使用的是context.getExternalFilesDir(null)也就是(/storage/sdcard/Android/data/com.xxx.xxx/),部分手机相册无法找到此路径或者没有权限

    // 首先保存图片File appDir;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {//android11以后appDir = getExternalFilesDir(null);}else {appDir = new File(Environment.getExternalStorageDirectory(), "zzs");  }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();}

(2)保存的方法添加写入的动态权限,把文件插入到系统图库

      //把文件插入到系统图库try {MediaStore.Images.Media.insertImage(this.getContentResolver(),file.getAbsolutePath(), fileName, null);} catch (FileNotFoundException e) {e.printStackTrace();}

(3) 通知图库更新,使用MediaStore插入到系统相册,使用广播Intent.ACTION_MEDIA_SCANNER_SCAN_FILE通知相册刷新

       // 通知图库更新if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {String path = file.getAbsolutePath();Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);Uri uri = Uri.fromFile(new File(path));intent.setData(uri);sendBroadcast(intent);} else {String relationDir = file.getParent();File file1 = new File(relationDir);sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.fromFile(file1.getAbsoluteFile())));}

完整代码

 public void saveImageToGallery(Context context, Bitmap bmp) {// 首先保存图片File appDir;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {//android11以后appDir = getExternalFilesDir(null);}else {appDir = new File(Environment.getExternalStorageDirectory(), "zzs");  }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(this.getContentResolver(),file.getAbsolutePath(), fileName, null);} catch (FileNotFoundException e) {e.printStackTrace();}// 通知图库更新if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {String path = file.getAbsolutePath();Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);Uri uri = Uri.fromFile(new File(path));intent.setData(uri);sendBroadcast(intent);} else {String relationDir = file.getParent();File file1 = new File(relationDir);sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.fromFile(file1.getAbsoluteFile())));}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/651418.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应急消防应用步入“繁花”时代,卓翼智能消防无人机顺势而行大有可为

近日,北京卓翼智能科技有限公司(以下简称“卓翼智能”)宣布完成超亿元B轮融资,融资金额高达2.5亿元。这个“智能无人系统”黑马品牌,凭什么出圈?重点发力在哪些领域呢?今天,带你走进…

2726. 使用方法链的计算器

说在前面 🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。 题目描述 设计一个类 Calculator 。该类应提供加法、减法、乘法、除法和乘方等数学运算功能。同时&am…

设计模式-生成器设计模式

什么是生成器设计模式 众所周知我们设计代码的时候要将代码设计出模块化的,一个功能是一个模块,那么生成器设计模式,是将一个类再度进行了一个拆分,让一个类的内部进行了单一职责化,其实我们在平时开发的时候就会不经…

分布式id-Leaf算法

一、介绍 由美团开发,开源项目链接:https://github.com/Meituan-Dianping/Leaf Leaf同时支持号段模式和snowflake算法模式,可以切换使用。ID号码是趋势递增的8byte的64位数字,满足上述数据库存储的主键要求。 Leaf的snowflake模…

交叉导轨为何要保持日常清洁?

在工业自动化的发展中,交叉导轨因其具有精度高、高刚性、高耐磨性等特点,在数控技术的发展中得到了越来越多的使用,对于交叉导轨来说,保持日常清洁对其性能和寿命具有重要意义。 1、防止灰尘和杂质的侵入:交叉导轨在机…

嵌入式学习第十一天

1.数组和指针的关系: 1.一维数组和指针的关系: int a[5] {1, 2, 3, 4, 5}; int *p NULL; p &a[0]; p a; 数组的数组名a是指向数组第一个元素的一个指针常量 a &a[0] a 的类型可以理解为 int * 有两种情况除…

五步安装和配置CLion的ESP-IDF开发框架

记录CLion安装和配置ESP-IDF开发框架 真无语了,弄了半天多,近一天,这里弄那里弄。记录一下,万一后面还要踩坑呢! 弄一早上components的编写和使用(想用别人的components),下午弄开…

Java基础-实现猜数字小游戏

1. 实现控制台的猜数字游戏。游戏运行时产生一个1~100之间的随机数字; 2. 要求用户从控制台输入数字,若输入的数字比随机数小,则提示太小了;若输入的数字比随机数大,则提示太大了,若输入的数字与随机数相同…

JavaScript学习-原型和原型链

原型和原型链 示例代码 //创建一个Person类 class Person {constructor(name) {this.name name;}drink() {console.log(喝水);} } //创建一个Teacher类,继承Person class Teacher extends Person {constructor(name, subject) {super(name);this.subject subjec…

软件测试活动中,如何评估测试范围?

前言 大家好,我是chowley,今天来讲一讲——如何评估软件测试范围 在软件开发的不同阶段,评估测试范围是确保测试活动有效性和效率的关键步骤。测试范围的明确定义有助于确定测试目标、提高测试覆盖率,并确保在有限的时间内实现最…

动手学深度学习8 Softmax回归+损失函数+图片分类

Softmax回归损失函数图片分类 1. Softmax回归--分类问题2. 三个常用损失函数1. 均方损失 L2 Loss2. 绝对值损失函数 L1 Loss3. 两个结合 HUber’s Robust Loss 3. 图片分类数据集4. Softmax回归从零开始实现5. Softmax回归简洁实现6. QA 1. Softmax回归–分类问题 真实y只有一个…

vue项目中路由懒加载的三种方式

1 . vue异步组件技术 异步加载 vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 . 但是,这种情况下一个组件生成一个js文件 /* vue异步组件技术 */ { path: /home, name: home, component: resolve > require([/components/home],resolve) }, { path…

基于java+jsp+ssh的毕业生就业信息管理系统

🍅文末获取源码联系🍅 👇🏻 精彩项目推荐订阅👇🏻 不然下次找不到哟 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮…

ShardingSphere之ShardingJDBC客户端分库分表下

目录 ShardingJDBC实战 STANDARD标准分片策略 COMPLEX_INLINE复杂分片策略 CLASS_BASED自定义分片策略 HINT_INLINE强制分片策略 ShardingJDBC实战 上篇已经将需要用到的类、数据库表都准备好了,本篇主要介绍分片配置文件。 STANDARD标准分片策略 如果按照上篇文…

golang版本使用令牌桶算法来实现限流的策略

代码 package mainimport ("fmt""sync""time" )// 令牌桶结构体 type TokenBucket struct {tokens chan struct{}rate time.Duration// 桶容量limit int }// 创建令牌桶 func NewTokenBucket(rate time.Duration, limit int) *TokenBucket {r…

纳斯达克户外大屏背景配什么颜色效果最好-大舍传媒

纳斯达克户外大屏背景配什么颜色效果最好 引言 纳斯达克大屏是世界闻名的户外广告媒体之一,通过高清大屏呈现的广告内容吸引了众多目光。大舍传媒作为纳斯达克大屏的提供商和运营商之一,致力于创造最佳的视觉效果来吸引观众的注意力。在纳斯达克大屏投…

C语言“++”和“--”运算符需要注意些什么?

一、问题 “”和“--”运算符经常被应⽤,使⽤这两种运算符需要注意些什么? 二、解答 在使用C语言中的自增()和自减(--)运算符时,需要注意以下几点: 1、运算规则 运算符有两种形式&…

cs2系统提升思路

思路/战术 > 道具 > 练枪 思路/战术 通用的思路 > 针对性学习每一张图的思路 注意,休闲中人数较多,战术的体现不多,不要休闲打习惯了适应不了竞技 地图理解 / 分析 根据地形分析攻防 (比如dust2,所有道路…

HCIA学习作业四

要求: 1、AR3还回为3.3.3.0/24 2、其他基于192.168.1.0/24进行合理划分 3、AR1和AR2均存在两个环回 4、整个网络运行RIP v2 但是不能直接宣告AR3的环回 5、全网可达,保障更新安全,尽量减少路由条目,避免环路 拓扑图&#xf…

EXP脚本编写

EXP脚本的编写与POC脚本编写一样,只需要修改_attack部分,替换成漏洞 利用的脚本即可。要利用Flask漏洞,需要用到Python的特性。关于如何在Jinja2模 板中执行Python代码,官方给出的方法是在模板环境中注册函数就可以进行调 用。 J…