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

仅在OnePlus 8Pro上出现的Android FileProvider相机崩溃问题求助

问题分析

崩溃核心原因是FileProvider的配置未覆盖临时文件所在路径,仅在OnePlus 8Pro上触发——该设备对/data/local/tmp/external/目录的权限或路径映射有特殊处理,导致FileProvider无法识别此路径属于已配置的根目录。

从日志可见,mFileTemp指向的路径是/data/local/tmp/external/xxx.jpg,但此路径不在当前FileProvider的file_paths.xml配置范围内,调用FileProvider.getUriForFile()时直接抛出IllegalArgumentException。另外,当前代码仅捕获IOException,未处理该非法参数异常,这是崩溃直接暴露的原因之一。

解决方案

1. 补全异常捕获逻辑

先拦截未处理的异常,避免崩溃直接影响用户:

private fun startCamera() {
    if (!iniTempFile()) return
    val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    try {
        mImageCaptureUri = null
        val state = Environment.getExternalStorageState()
        if (Environment.MEDIA_MOUNTED == state) {
            mImageCaptureUri = FileProvider.getUriForFile(
                requireContext(),
                "com.xxxx.yyyy.provider",  
                mFileTemp
            )
        }
        if (mImageCaptureUri != null) {
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri)
            cameraIntent.putExtra("return-data", true)
            resultLauncherCamera.launch(cameraIntent)
        } else {
            Toast.makeText(requireContext(),"Error al intentar guardar imagen",Toast.LENGTH_SHORT).show()
        }
    } catch (ex: IOException) {
        Log.d(NewFoodFragment.TAG,"Error Creating File:${ex.localizedMessage}")
    } catch (ex: IllegalArgumentException) {
        // 捕获FileProvider路径配置异常
        Log.e(NewFoodFragment.TAG,"FileProvider path config error:${ex.localizedMessage}")
        Toast.makeText(requireContext(),"Error al configurar almacenamiento",Toast.LENGTH_SHORT).show()
    }
}

2. 调整FileProvider配置覆盖临时路径

找到res/xml/file_paths.xml(无则创建),添加对目标临时目录的映射:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 保留原有配置,比如外部存储根目录 -->
    <external-path name="external_files" path="."/>
    <!-- 添加tmp/external目录的映射 -->
    <root-path name="root_tmp" path="/data/local/tmp/external/"/>
</paths>

注:root-path在Android 7.0+允许使用,若厂商有限制,可尝试用相对路径映射:<files-path name="tmp_external" path="/../tmp/external/"/>

3. 优化临时文件创建逻辑(推荐)

避免依赖系统级临时目录,改用App专属存储目录(兼容性更强,符合Android规范):
修改iniTempFile()方法,将临时文件创建在App外部缓存目录:

private fun iniTempFile(): Boolean {
    try {
        // 优先用外部缓存目录,无权限则用内部缓存
        val cacheDir = requireContext().getExternalCacheDir() ?: requireContext().cacheDir
        mFileTemp = File(cacheDir, "${System.currentTimeMillis()}.jpg")
        mFileTemp.createNewFile()
        return true
    } catch (e: IOException) {
        Log.e(NewFoodFragment.TAG, "Failed to create temp file: ${e.localizedMessage}")
        return false
    }
}

同时在file_paths.xml中添加缓存目录配置:

<external-cache-path name="external_cache" path="."/>

4. 针对性适配OnePlus设备(备选)

若必须保留原路径逻辑,可通过设备品牌判断调整路径:

val isOnePlus = Build.BRAND.equals("oneplus", ignoreCase = true)
val tempDir = if (isOnePlus) {
    // 针对OnePlus切换到App专属临时目录
    File(requireContext().getExternalFilesDir(null), "tmp")
} else {
    File("/data/local/tmp/external")
}
// 创建临时文件
mFileTemp = File(tempDir, "${UUID.randomUUID()}.jpg")

内容的提问来源于stack exchange,提问作者Mario Alvarez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 16:30:28