记一个 Andorid 生成文件失败的bug
Android生成文件失败:java.lang.IllegalStateException:Failed to build unique file: /storage/emulated/0/...
1.问题来源
App 调用相机拍照,中间有一些处理过程,然后将这张照片插入系统图片数据库中。
MediaStore.Images.Media.insertImage(getContentResolver(), photoPath, null, null);
很长一段时间,这段代码都运行的好好的,可是突然有一天,测试妹妹报告一个bug,拍照之后,保存图片失败了,并且在 Gallery 中也看不到这张图片。
幸运地是,专业的测试妹妹,抓到了Log,很快找到了错误地方:
E DatabaseUtils: Writing exception to parcel
E DatabaseUtils: java.lang.IllegalStateException: Failed to build unique file: /storage/emulated/0/Pictures/Image.jpg bucket_display_name=Pictures volume_name=external_primary date_modified=null date_expires=null _display_name=Image.jpg mime_type=image/jpeg _data=/storage/emulated/0/Pictures/Image.jpg _size=null is_trashed=0 is_pending=0 bucket_id=-1617409521 relative_path=Pictures/
E DatabaseUtils: at com.android.providers.media.MediaProvider.ensureFileColumns(MediaProvider.java:2624)
E DatabaseUtils: at com.android.providers.media.MediaProvider.ensureUniqueFileColumns(MediaProvider.java:2368)
E DatabaseUtils: at com.android.providers.media.MediaProvider.updateInternal(MediaProvider.java:5265)
E DatabaseUtils: at com.android.providers.media.MediaProvider.update(MediaProvider.java:4953)
E DatabaseUtils: at android.content.ContentProvider$Transport.update(ContentProvider.java:457)
E DatabaseUtils: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:230)
E DatabaseUtils: at android.os.Binder.execTransactInternal(Binder.java:1159)
E DatabaseUtils: at android.os.Binder.execTransact(Binder.java:1123)
W MediaStore: Failed to insert image
W MediaStore: java.lang.IllegalStateException: Failed to build unique file: /storage/emulated/0/Pictures/Image.jpg bucket_display_name=Pictures volume_name=external_primary date_modified=null date_expires=null _display_name=Image.jpg mime_type=image/jpeg _data=/storage/emulated/0/Pictures/Image.jpg _size=null is_trashed=0 is_pending=0 bucket_id=-1617409521 relative_path=Pictures/
W MediaStore: at android.os.Parcel.createExceptionOrNull(Parcel.java:2381)
W MediaStore: at android.os.Parcel.createException(Parcel.java:2357)
W MediaStore: at android.os.Parcel.readException(Parcel.java:2340)
W MediaStore: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:190)
W MediaStore: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
W MediaStore: at android.content.ContentProviderProxy.update(ContentProviderNative.java:649)
W MediaStore: at android.content.ContentResolver.update(ContentResolver.java:2356)
W MediaStore: at android.content.ContentResolver.update(ContentResolver.java:2318)
W MediaStore: at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:2097)
W MediaStore: at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:2059)
2.问题分析
显然这个异常并不是我们 App 中定义的,从日志可以看到程序执行到 MediaStore.Images.Media.insertImage() 方法出现异常了,异常是 MediaProvider.ensureFileColumns 抛出的,关键字是 Failed to build unique file 。
那只能查找源码了。在源码中搜 MediaProvider 的 ensureFileColumns 方法中,的确看到抛出了上述异常。

可以看到,这个一样应该是 FileUtils.buildUniqueFile() 或者 FileUtils.buidlNonUniqueFile() 方法抛出的。查看源码,我们发现是在 FileUtils.buildUniqueFile() 调用 FileUtils.buildUniqueFileWithExtension() 方法,抛出了异常。

看下这个方法大致就可以明白,同一名称的文件会被系统在默认添加(1...)等数字用以标识,例如我有一个aa.txt文件,当我要再次生成aa.txt时,系统会帮我生成aa (1).txt文件,再生成则是aa (2).txt。当括号中的名称数量大于32(含32,也就是说同一文件名的数量超过33个时)后就抛异常。
至此,破案了。
我们在调用
MediaStore.Images.Media.insertImage(getContentResolver(), photoPath, null, null);
方法时,第三个参数,插入数据库的文件的名称,传的 null, 系统会默认生成一个文件名,Image.jpg, 再次插入的则为 Image(1).jpg...
3.修改方案
修改方案明了了,只需要再插入系统数据库时,指定文件名。并且要尽量保持唯一。看来,系统接口设计很严谨,接口中每一个参数都是有意义的,比如该第四个参数,description,文件的描述,最好也要赋值。
记一个 Andorid 生成文件失败的bug的更多相关文章
- Python 写了一个批量生成文件夹和批量重命名的工具
Python 写了一个批量生成文件夹和批量重命名的工具 目录 Python 写了一个批量生成文件夹和批量重命名的工具 演示 功能 1. 可以读取excel内容,使用excel单元格内容进行新建文件夹, ...
- 记PHP下载大文件失败的一次坑
说明 php提供文件的储存和下载,nginx作为web服务器,fpm做解析. 现象 当下载一个5M大小的图片时,总提示下载失败,或下载下来的文件不完整,仅显示部分图像(每次下载不一样) php下载相关 ...
- springboot项目下载文件功能中-切面-导致的下载文件失败的bug
背景:使用spring提供的 ResponseEntity 和Resource结合,实现的下载文件功能 bug:Resource已经加载到了文件, 并且通过 ResponseEntity 构建了响应, ...
- 记一个SwipeMenuListView侧滑删除错乱的Bug
做侧滑删除网上有很多方案,比如重写Listview实现滑动的监听,今天说下一个SwipeListView,这个是之前一个朋友在网上开源的一个封装组件,能够适用于多种情况,项目地址:https://gi ...
- 记一个全局变量"冒充"局部变量引起的bug
看代码相当简单直观,觉得怎么都不会出错,可运行结果明明就是错了 - 对着vim摸着脑袋就是想不出哪里有问题,可去掉新加的代码,就又可以了. 没办法,只好祭出杀手锏:一行一行注释掉来观察... 反映问题 ...
- CSVWriter生成文件时writer.writeRecord();方法保存的文件末尾多一个空行
一.问题,CSVWriter生成文件时使用writer.writeRecord();方法保存的文件末尾多一个空行,效果图如下: 目标结果:(去掉末尾空行) 二.关键代码如下(修改前代码): /** * ...
- 记-ItextPDF+freemaker 生成PDF文件---导致服务宕机
摘要:已经上线的项目,出现服务挂掉的情况. 介绍:该服务是专门做打印的,业务需求是生成PDF文件进行页面预览,主要是使用ItextPDF+freemaker技术生成一系列PDF文件,其中生成流程有:解 ...
- 记Windows的一个存在了十多年的bug
bug Windows有一个bug,持续了十多年,从Windows Visita开始(2007年),一直存在,直到Windows11(2021年)才修复(其实也不叫修复,后面我再具体说),而Windo ...
- 写入数据到Plist文件中时,第一次要创建一个空的数组,否则写入文件失败
#pragma mark - 保存数据到本地Plist文件中 - (void)saveValidateCountWithDate:(NSString *)date count:(NSString *) ...
- Log4j使用笔记:每天生成一个日志文件、按日志大小生成文件
其中TestLog4j.java如下: package cn.zhoucy.test; import org.apache.log4j.Logger; public class TestLog4j { ...
随机推荐
- Python学习之十_paramiko的简单学习
Python学习之十_paramiko的简单学习 简介 pywinrm 是python用于连接访问windows的工具 paramiko 是python用于连接访问linux的工具 ansible等工 ...
- Windows 磁盘部分性能数据获取
Windows 磁盘部分性能数据获取 摘要 每次晚上加班总有收获 这次发现了一个fio for windows版本的压测程序, 准备学习和使用一下. https://github.com/axboe/ ...
- Sysbench 开启超线程/关闭超线程以及容器运行数据库的性能损耗
Sysbench 开启超线程/关闭超线程性能损耗 摘要 Stress-NG 测试完之后 突然想 使用sysbenchen也进行一次压测 验证一把 超线程对数据的性能影响. 压测命令 ./sysbenc ...
- Skia 编译及踩坑实践
本文要点 •了解并入门 Skia.OpenGL 和 Vulkan •了解 Skia 在后端渲染上的坑点 前言 Skia 是什么 Skia 是一个开源 2D 图形库,提供可跨各种硬件和软件平台工作的通用 ...
- React中事件的绑定
事件绑定 语法:on +事件名= { ()=>{ do something }} <!-- 点击事件 --> onClick={ () => { } } 注意的是:React采 ...
- hadoop实践01---hdfs分布式集群搭建与启动
一.hdfs集群组成结构
- 【一】tensorflow【cpu/gpu、cuda、cudnn】全网最详细安装、常用python镜像源、tensorflow 深度学习强化学习教学
相关文章: [一]tensorflow安装.常用python镜像源.tensorflow 深度学习强化学习教学 [二]tensorflow调试报错.tensorflow 深度学习强化学习教学 [三]t ...
- 19.0 Boost 基于ASIO网络编程技术
Boost ASIO库是一个基于C++语言的开源网络编程库,该库提供了成熟.高效.跨平台的网络API接口,并同时支持同步与异步两种模式,ASIO库提供了多重I/O对象.异步定时器.可执行队列.信号操作 ...
- Swift中UITableViewDiffableDataSource的使用
在 iOS 13 中 Apple 为 UITableView 和 UICollectionView 引入了 DiffableDataSource, 让开发者可以更简单高效的实现 UITableView ...
- 教你用JavaScript实现鼠标特效
案例介绍 欢迎来的我的小院,我是霍大侠,恭喜你今天又要进步一点点了!我们来用JavaScript编程实战案例,做一个鼠标爱心特效.鼠标在页面移动时会出现彩色爱心特效.通过实战我们将学会createEl ...