You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:05:42