为何FileProvider无法在所有Android设备上正常工作?
解决FileProvider拍照部分设备崩溃的问题
你的代码存在几个关键问题,导致部分设备点击相机确认按钮时崩溃,逐一修复即可:
1. 禁止忽略文件创建/FileProvider初始化异常
内部try块直接ignored所有异常,会掩盖目录不存在、权限不足等问题,相机启动后因无法写入指定文件而崩溃。必须移除空catch,至少添加日志记录或终止流程提示用户。
2. 替换废弃的公共存储目录,改用应用私有外部存储
Android 10(API 29)及以上,Environment.getExternalStoragePublicDirectory已废弃,且公共存储的写入权限限制越来越严,部分相机应用无法写入公共目录的Uri。改用应用私有外部存储目录,既不需要额外权限,也更安全:
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
3. 确保文件父目录存在
创建文件前必须检查并创建父目录,否则相机无法写入文件:
if (!storageDir.exists()) { storageDir.mkdirs(); }
4. 显式授予Uri临时权限
部分相机应用需要显式的Uri读写权限,给Intent添加权限标记:
cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
5. 避免pictureImagePath空值崩溃
如果文件创建失败,不要继续启动相机,否则后续pictureImagePath为空,在onActivityResult里会触发空指针异常。
6. 移除assert,改用安全的非空判断
assert data != null在开启断言的设备上会直接崩溃,换成普通的非空判断:
if (data != null) { Bundle extras = data.getExtras(); if (extras != null) { bitmap = (Bitmap) extras.get("data"); } }
修改后的完整代码示例
takePicture方法:
private void takePicture() { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 确保相机应用存在 if (cameraIntent.resolveActivity(getPackageManager()) == null) { Toast.makeText(this, getString(R.string.camera_not_recog), Toast.LENGTH_SHORT).show(); return; } File photoFile = null; try { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imageFileName = timeStamp + ".jpg"; // 改用应用私有外部存储 File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); if (!storageDir.exists()) { storageDir.mkdirs(); } photoFile = new File(storageDir, imageFileName); pictureImagePath = photoFile.getAbsolutePath(); Uri outputFileUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", photoFile); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); // 显式授予权限 cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, "无法创建拍照文件", Toast.LENGTH_SHORT).show(); return; } // 只有成功创建文件才启动相机 someActivityResultLauncher.launch(cameraIntent); }
ActivityResultCallback:
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { Intent data = result.getData(); try { if (pictureImagePath != null) { File imgFile = new File(pictureImagePath); if (imgFile.exists()) { bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath()); } else if (data != null) { Bundle extras = data.getExtras(); if (extras != null) { bitmap = (Bitmap) extras.get("data"); } } } else if (data != null) { Bundle extras = data.getExtras(); if (extras != null) { bitmap = (Bitmap) extras.get("data"); } } } catch (Exception e) { e.printStackTrace(); if (data != null) { Bundle extras = data.getExtras(); if (extras != null) { bitmap = (Bitmap) extras.get("data"); } } } finally { startActivity(new Intent(this, CameraActivity.class)); } } });
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

