Android 13下使用MediaStore.ACTION_VIDEO_CAPTURE录制视频崩溃问题
Android 13使用MediaStore.ACTION_VIDEO_CAPTURE崩溃的解决方案
问题现象
在Android 13系统中调用MediaStore.ACTION_VIDEO_CAPTURE录制视频时,应用崩溃,抛出空指针异常:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.content.ContentValues.put(java.lang.String, java.lang.Long)' on a null object reference at com.android.camera.VideoModule.saveVideo(VideoModule.java:1263) at com.android.camera.VideoModule.stopVideoRecording(VideoModule.java:1513) at com.android.camera.VideoModule.onStopVideoRecording(VideoModule.java:656) at com.android.camera.VideoModule.onShutterButtonClick(VideoModule.java:697) at com.android.camera.ShutterButton.performClick(ShutterButton.java:190) at android.view.View.performClickInternal(View.java:7483) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:29334) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
原有代码在Android 6-12上正常运行,核心实现为通过FileProvider生成Uri并传入MediaStore.EXTRA_OUTPUT:
Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takePictureIntent -> // Ensure that there's a camera activity to handle the intent takePictureIntent.resolveActivity(packageManager)?.also { // Create the File where the photo should go val videoFile: File? = try { createVideoFile() } catch (ex: IOException) { // Error occurred while creating the File null } // Continue only if the File was successfully created videoFile?.also { val videoUri: Uri = FileProvider.getUriForFile( this@MainActivity, "com.cameralbum.fileprovider", it ) takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri) startActivityForResult(takePictureIntent, REQUEST_TAKE_VIDEO) } } }
问题原因
Android 13对媒体Intent的处理逻辑做了调整:系统相机应用在接收ACTION_VIDEO_CAPTURE的EXTRA_OUTPUT参数时,若传入的是FileProvider生成的Uri,会无法正确初始化ContentValues对象,进而触发空指针异常。旧版本系统对这种Uri的兼容性更好,不会出现该问题。
解决方案
改用MediaStore直接生成视频存储Uri,替代FileProvider的方式,同时保留对旧版本系统的兼容逻辑:
1. 生成适配的视频Uri
创建方法根据系统版本生成对应的Uri,Android 13及以上使用MediaStore插入媒体记录,以下版本沿用原有FileProvider逻辑:
private fun getVideoCaptureUri(): Uri? { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { val contentValues = ContentValues().apply { put(MediaStore.Video.Media.DISPLAY_NAME, "录制视频_${System.currentTimeMillis()}.mp4") put(MediaStore.Video.Media.MIME_TYPE, "video/mp4") put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES + "/MyAppVideos") } contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues) } else { try { createVideoFile()?.let { file -> FileProvider.getUriForFile(this@MainActivity, "com.cameralbum.fileprovider", file) } } catch (e: IOException) { null } } }
2. 修改调用逻辑
替换原有的Uri生成代码,确保传入符合系统要求的Uri到录制Intent:
Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takeVideoIntent -> takeVideoIntent.resolveActivity(packageManager)?.also { getVideoCaptureUri()?.let { uri -> takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri) // 可选:设置视频质量参数,1为高质量 takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1) startActivityForResult(takeVideoIntent, REQUEST_TAKE_VIDEO) } } }
3. 权限适配
- Android 13及以上:无需申请
WRITE_EXTERNAL_STORAGE权限,通过MediaStore插入媒体文件时系统会自动处理权限。 - 旧版本系统:仍需在Manifest中声明
WRITE_EXTERNAL_STORAGE权限,并在运行时申请。
补充说明
- 自定义存储位置可通过
MediaStore.Video.Media.RELATIVE_PATH指定,系统会自动创建对应目录(示例中为Movies/MyAppVideos)。 - 录制完成后,可直接通过传入的Uri访问视频文件,无需额外转换文件路径。
内容的提问来源于stack exchange,提问作者Lev T.
相关产品推荐
相关产品推荐

