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的更多相关文章

  1. Python 写了一个批量生成文件夹和批量重命名的工具

    Python 写了一个批量生成文件夹和批量重命名的工具 目录 Python 写了一个批量生成文件夹和批量重命名的工具 演示 功能 1. 可以读取excel内容,使用excel单元格内容进行新建文件夹, ...

  2. 记PHP下载大文件失败的一次坑

    说明 php提供文件的储存和下载,nginx作为web服务器,fpm做解析. 现象 当下载一个5M大小的图片时,总提示下载失败,或下载下来的文件不完整,仅显示部分图像(每次下载不一样) php下载相关 ...

  3. springboot项目下载文件功能中-切面-导致的下载文件失败的bug

    背景:使用spring提供的 ResponseEntity 和Resource结合,实现的下载文件功能 bug:Resource已经加载到了文件, 并且通过 ResponseEntity 构建了响应, ...

  4. 记一个SwipeMenuListView侧滑删除错乱的Bug

    做侧滑删除网上有很多方案,比如重写Listview实现滑动的监听,今天说下一个SwipeListView,这个是之前一个朋友在网上开源的一个封装组件,能够适用于多种情况,项目地址:https://gi ...

  5. 记一个全局变量"冒充"局部变量引起的bug

    看代码相当简单直观,觉得怎么都不会出错,可运行结果明明就是错了 - 对着vim摸着脑袋就是想不出哪里有问题,可去掉新加的代码,就又可以了. 没办法,只好祭出杀手锏:一行一行注释掉来观察... 反映问题 ...

  6. CSVWriter生成文件时writer.writeRecord();方法保存的文件末尾多一个空行

    一.问题,CSVWriter生成文件时使用writer.writeRecord();方法保存的文件末尾多一个空行,效果图如下: 目标结果:(去掉末尾空行) 二.关键代码如下(修改前代码): /** * ...

  7. 记-ItextPDF+freemaker 生成PDF文件---导致服务宕机

    摘要:已经上线的项目,出现服务挂掉的情况. 介绍:该服务是专门做打印的,业务需求是生成PDF文件进行页面预览,主要是使用ItextPDF+freemaker技术生成一系列PDF文件,其中生成流程有:解 ...

  8. 记Windows的一个存在了十多年的bug

    bug Windows有一个bug,持续了十多年,从Windows Visita开始(2007年),一直存在,直到Windows11(2021年)才修复(其实也不叫修复,后面我再具体说),而Windo ...

  9. 写入数据到Plist文件中时,第一次要创建一个空的数组,否则写入文件失败

    #pragma mark - 保存数据到本地Plist文件中 - (void)saveValidateCountWithDate:(NSString *)date count:(NSString *) ...

  10. Log4j使用笔记:每天生成一个日志文件、按日志大小生成文件

    其中TestLog4j.java如下: package cn.zhoucy.test; import org.apache.log4j.Logger; public class TestLog4j { ...

随机推荐

  1. Python学习之十_paramiko的简单学习

    Python学习之十_paramiko的简单学习 简介 pywinrm 是python用于连接访问windows的工具 paramiko 是python用于连接访问linux的工具 ansible等工 ...

  2. Windows 磁盘部分性能数据获取

    Windows 磁盘部分性能数据获取 摘要 每次晚上加班总有收获 这次发现了一个fio for windows版本的压测程序, 准备学习和使用一下. https://github.com/axboe/ ...

  3. Sysbench 开启超线程/关闭超线程以及容器运行数据库的性能损耗

    Sysbench 开启超线程/关闭超线程性能损耗 摘要 Stress-NG 测试完之后 突然想 使用sysbenchen也进行一次压测 验证一把 超线程对数据的性能影响. 压测命令 ./sysbenc ...

  4. Skia 编译及踩坑实践

    本文要点 •了解并入门 Skia.OpenGL 和 Vulkan •了解 Skia 在后端渲染上的坑点 前言 Skia 是什么 Skia 是一个开源 2D 图形库,提供可跨各种硬件和软件平台工作的通用 ...

  5. React中事件的绑定

    事件绑定 语法:on +事件名= { ()=>{ do something }} <!-- 点击事件 --> onClick={ () => { } } 注意的是:React采 ...

  6. hadoop实践01---hdfs分布式集群搭建与启动

    一.hdfs集群组成结构

  7. 【一】tensorflow【cpu/gpu、cuda、cudnn】全网最详细安装、常用python镜像源、tensorflow 深度学习强化学习教学

    相关文章: [一]tensorflow安装.常用python镜像源.tensorflow 深度学习强化学习教学 [二]tensorflow调试报错.tensorflow 深度学习强化学习教学 [三]t ...

  8. 19.0 Boost 基于ASIO网络编程技术

    Boost ASIO库是一个基于C++语言的开源网络编程库,该库提供了成熟.高效.跨平台的网络API接口,并同时支持同步与异步两种模式,ASIO库提供了多重I/O对象.异步定时器.可执行队列.信号操作 ...

  9. Swift中UITableViewDiffableDataSource的使用

    在 iOS 13 中 Apple 为 UITableView 和 UICollectionView 引入了 DiffableDataSource, 让开发者可以更简单高效的实现 UITableView ...

  10. 教你用JavaScript实现鼠标特效

    案例介绍 欢迎来的我的小院,我是霍大侠,恭喜你今天又要进步一点点了!我们来用JavaScript编程实战案例,做一个鼠标爱心特效.鼠标在页面移动时会出现彩色爱心特效.通过实战我们将学会createEl ...