Android 4.3 Jelly Bean(API 18)Content URI引发相机录制崩溃求助
解决Android 4.3 Jelly Bean(API18)相机录视频时
data.getData()空指针问题 这个问题在Android 4.3这类旧版本系统里非常常见——系统自带的相机应用在你指定录制视频的输出目标后,并不会通过onActivityResult的data参数返回视频的URI,直接调用data.getData()自然就会触发NullPointerException,导致应用崩溃。
下面是最可靠的解决方案,核心思路是提前指定视频的保存路径,不用依赖返回的data参数:
步骤1:创建用于保存视频的临时文件
先写一个方法来生成唯一的视频文件,避免文件名冲突:
private File createVideoFile() throws IOException { // 用时间戳生成唯一文件名 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String videoFileName = "RECORD_" + timeStamp + "_"; // 存在应用私有电影目录,API19+无需额外权限,API18仍需WRITE_EXTERNAL_STORAGE File storageDir = getExternalFilesDir(Environment.DIRECTORY_MOVIES); return File.createTempFile(videoFileName, ".mp4", storageDir); }
步骤2:启动相机时指定输出路径
启动相机Intent的时候,通过MediaStore.EXTRA_OUTPUT把刚才创建的文件对应的URI传进去,告诉相机直接把视频写到这个文件里:
private static final int VIDEO_CAPTURE_REQUEST = 1; private Uri mSavedVideoUri; // 保存提前创建的视频URI private void launchCameraForVideo() { Intent videoCaptureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); // 先检查设备是否有相机应用 if (videoCaptureIntent.resolveActivity(getPackageManager()) != null) { File videoFile = null; try { videoFile = createVideoFile(); } catch (IOException e) { // 处理文件创建失败的情况,比如弹出提示 Toast.makeText(this, "无法创建视频文件", Toast.LENGTH_SHORT).show(); e.printStackTrace(); return; } if (videoFile != null) { mSavedVideoUri = Uri.fromFile(videoFile); videoCaptureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mSavedVideoUri); // 可以额外设置视频质量、时长等参数 videoCaptureIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 30); // 最长30秒 startActivityForResult(videoCaptureIntent, VIDEO_CAPTURE_REQUEST); } } else { Toast.makeText(this, "未找到相机应用", Toast.LENGTH_SHORT).show(); } }
步骤3:修改onActivityResult逻辑
不再从data里取URI,直接用我们提前保存的mSavedVideoUri:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == VIDEO_CAPTURE_REQUEST) { if (resultCode == RESULT_OK) { // 录制成功,直接使用mSavedVideoUri处理视频 if (mSavedVideoUri != null) { // 示例:打印视频路径 Log.d("VideoRecord", "视频已保存至:" + mSavedVideoUri.getPath()); // 这里可以添加播放、上传等逻辑 } } else if (resultCode == RESULT_CANCELED) { // 用户取消录制,清理临时文件 if (mSavedVideoUri != null) { File tempVideo = new File(mSavedVideoUri.getPath()); if (tempVideo.exists()) { tempVideo.delete(); } } Toast.makeText(this, "录制已取消", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "录制失败", Toast.LENGTH_SHORT).show(); } } }
必要的权限配置
在AndroidManifest.xml里添加相机和存储权限(适配API18):
<!-- 相机权限(可选,若应用必须依赖相机则设为required="true") --> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> <!-- API18及以下需要外部存储写入权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
为什么这个方案有效?
Android 4.3及更早的系统中,相机应用的设计逻辑是:当你通过EXTRA_OUTPUT指定了输出目标后,相机不会将视频URI封装到返回的Intent data中,而是直接将视频文件写入你指定的路径。所以我们完全不需要依赖data参数,直接使用提前创建的URI即可避免空指针问题。
内容的提问来源于stack exchange,提问作者andios
相关产品推荐
相关产品推荐

