仅在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
相关产品推荐
相关产品推荐

