You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 08:15:03