Kotlin开发Android保险柜应用 删除文件后仍在选择器显示引发崩溃
问题根因
你删除公共存储的源文件时仅调用了File.delete(),Android系统的MediaStore媒体库不会自动感知普通文件删除操作,仍会保留该文件的索引记录。系统文件选择器默认读取MediaStore的索引数据而非实时扫描磁盘,因此已删除文件会继续显示,选中后因为实际文件不存在触发崩溃。
可行解决方案
方案1:删除文件时同步更新MediaStore索引
替换原有代码中直接调用from.delete()的逻辑,用兼容多版本的删除方法同时更新媒体库:
你原有代码里private fun deleteSourceFile(context: Context, sourceFile: File): Boolean { if (!sourceFile.exists()) return false return try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10及以上通过MediaStore删除,自动更新索引 val contentUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL) val selection = "${MediaStore.Files.FileColumns.DATA} = ?" val args = arrayOf(sourceFile.absolutePath) context.contentResolver.delete(contentUri, selection, args) > 0 } else { // 低版本先删除文件,再通知系统扫描更新媒体库 val deleteSuccess = sourceFile.delete() if (deleteSuccess) { MediaScannerConnection.scanFile(context, arrayOf(sourceFile.absolutePath), null, null) } deleteSuccess } } catch (e: Exception) { e.printStackTrace() false } }from.delete()的位置替换为调用上述方法即可:if (!isInterrupted!!) { Log.d(TAG, "copyFile: Not Interupted") deleteSourceFile(this, from) // 替换原有from.delete() }方案2:增加选中文件的前置校验,避免崩溃
在系统文件选择器返回结果后,先校验文件合法性,不要直接走后续拷贝逻辑:// 拿到文件选择器返回的路径后先执行校验 val targetFile = File(selectedFilePath) if (!targetFile.exists() || !targetFile.isFile || !targetFile.canRead()) { Toast.makeText(this, "所选文件已失效,请重新选择", Toast.LENGTH_SHORT).show() return // 终止后续逻辑 } // 校验通过再执行拷贝/移动操作可选优化:修复原有拷贝代码的已知问题
原有代码中val lenghtOfFile: Int = inStream.available()获取文件总长度的方式不准确,大文件场景会导致进度计算错误,建议替换为val lenghtOfFile = from.length(),同时建议用Kotlin的use扩展自动管理流的关闭,避免异常场景下流泄露。
内容的提问来源于stack exchange,提问作者Vamsi Reddy
相关产品推荐
相关产品推荐

