OPPO与Realme设备调用相机拍照时出现空指针异常求助
OPPO/Realme设备拍照时
java.io.File.getAbsolutePath()空指针问题解决 问题根源
- Activity重建导致成员变量丢失:OPPO/Realme定制的相机应用启动时,可能触发当前Activity被系统销毁并重建,原本的成员变量
mediaFile会被重置为null,在onActivityResult调用时触发空指针。 - 存储路径适配不足:部分机型对外部公共目录的访问限制更严格,或路径拼接错误导致文件对象未正确初始化。
- 缺少空值校验:代码中直接调用
mediaFile.getAbsolutePath(),未做null判断。
解决方案
1. 持久化文件路径,避免Activity重建丢失
在Activity销毁前保存文件路径,重建时恢复:
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mediaFile != null) { outState.putString("camera_image_path", mediaFile.getAbsolutePath()); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout); // 恢复保存的文件路径 if (savedInstanceState != null) { String savedPath = savedInstanceState.getString("camera_image_path"); if (savedPath != null) { mediaFile = new File(savedPath); } } }
2. 适配Android版本的存储路径
针对Android 10+的分区存储机制,改用应用私有目录(无需外部存储权限),同时优化路径创建逻辑:
private File getOutputMediaFile(int type) { File mediaStorageDir; // Android 10及以上使用应用私有外部目录 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { mediaStorageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "TEST"); } else { // Android 9及以下使用公共图片目录 mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "TEST"); } // 创建目录失败时打印日志排查 if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) { Log.e("CameraUtil", "无法创建图片存储目录"); return null; } if (type == MEDIA_TYPE_IMAGE) { String timestamp = String.valueOf(System.currentTimeMillis() / 1000); imageFileName = "JPEG_" + timestamp + ".jpg"; // 使用File构造函数拼接路径,避免手动拼接出错 mediaFile = new File(mediaStorageDir, imageFileName); return mediaFile; } return null; }
3. 完善权限与Intent配置
给相机Intent添加读写权限标记,确保相机应用能正常写入文件:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // 同时添加读写权限标记 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
4. 增加空值校验,避免崩溃
在onActivityResult中先判断文件是否存在,再执行后续逻辑:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) { if (resultCode == RESULT_OK) { if (mediaFile != null && mediaFile.exists()) { final String outputFilePath = mediaFile.getAbsolutePath(); // 处理拍照结果 } else { Log.e("CameraError", "拍照文件不存在或文件对象为空"); // 提示用户重新拍照 } } } }
5. 动态权限申请(Android 6.0 - Android 9)
确保已申请外部存储写入权限:
// 检查权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); } else { // 权限已获取,启动相机 startCamera(); } // 权限回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { startCamera(); } else { // 权限被拒绝,提示用户开启权限 } } }
内容的提问来源于stack exchange,提问作者Suchindra Kumar S
相关产品推荐
相关产品推荐

