Android WebView选择图片时提前生成重复CAPTURE_*.jpg文件问题求解
Android WebView 文件上传提前生成拍照冗余文件解决方案
问题根因
你当前代码在onShowFileChooser触发、弹出文件选择器时,就预先创建了相机拍照的输出文件,并且将其Uri传入相机Intent。只要系统相机组件被唤起(哪怕用户最终取消拍照、或者选择了相册图片),这个预先创建的空文件都会被保留,最终产生大量冗余的CAPTURE_*.jpg文件。
修复方案
在原有逻辑基础上增加冗余文件清理逻辑,同时适配高版本Android的分区存储规则,修改后代码如下:
// 先在类顶部定义FileProvider的authority,和你AndroidManifest里配置的一致 private const val FILE_PROVIDER_AUTHORITY = "${你的应用包名}.fileprovider" myWebView.webChromeClient = object : WebChromeClient() { override fun onShowFileChooser(webView: WebView, filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: FileChooserParams):Boolean { chooserCallback = filePathCallback // 预先创建拍照输出文件,API30+推荐使用应用专属目录,避免申请外部存储权限 val fileCamera = File( getExternalFilesDir(Environment.DIRECTORY_PICTURES), "CAPTURE_${System.currentTimeMillis()}.jpg" ) // 高版本Android要用FileProvider生成Uri,否则会报Uri暴露权限错误 chooserCamera = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { FileProvider.getUriForFile(this@YourActivity, FILE_PROVIDER_AUTHORITY, fileCamera) } else { Uri.fromFile(fileCamera) } val captureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, chooserCamera) // 给相机授予临时写入权限 captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) val imageIntent = Intent(Intent.ACTION_GET_CONTENT) imageIntent.addCategory(Intent.CATEGORY_OPENABLE) imageIntent.type = "image/*" val chooserIntent = Intent.createChooser(imageIntent, "Select Image") chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(captureIntent)) startActivityForResult(chooserIntent, requestChooser) return true } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == requestChooser) { // 先把预先创建的相机文件转成File对象,方便后续判断是否要删除 val cameraFile = chooserCamera?.path?.let { File(it) } when (resultCode) { Activity.RESULT_OK -> { val resultUri = if (data?.data == null) { // 用户确认使用拍摄的照片,保留文件 chooserCamera!! } else { // 用户选择了相册图片,删除没用的预创建相机文件 cameraFile?.takeIf { it.exists() }?.delete() data.data!! } chooserCallback?.onReceiveValue(arrayOf(resultUri)) } Activity.RESULT_CANCELED -> { // 用户取消选择,删除预创建的相机文件 cameraFile?.takeIf { it.exists() }?.delete() Toast.makeText(applicationContext, "No Image", Toast.LENGTH_SHORT).show() chooserCallback?.onReceiveValue(null) } } chooserCallback = null chooserCamera = null } }
额外配置说明
- 你需要在
AndroidManifest.xml中配置FileProvider,否则Android 7.0及以上设备会触发Uri暴露权限错误 - 如果确实需要把拍照的图片保存到公共相册目录,可在用户确认拍照后,再把应用专属目录下的图片复制到公共目录,不要直接在公共目录预创建文件
内容的提问来源于stack exchange,提问作者adyoi
相关产品推荐
相关产品推荐

