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

MediaStore.ACTION_VIDEO_CAPTURE在诺基亚G10无法写入完整视频字节如何解决

问题修复方案

你遇到的是诺基亚G10预装相机应用的兼容性问题,核心原因有两点:

  1. 你给Intent加的FLAG_GRANT_WRITE_URI_PERMISSION仅对Intent的data字段生效,对EXTRA_OUTPUT携带的Uri不生效,该设备的相机应用没有拿到自定义路径的完整写入权限,导致文件写入到一半被中断
  2. 该设备相机应用写入自定义路径的视频时,没有完整写入视频尾部的索引元数据(moov原子),导致播放器只能读取到前面的帧

修复步骤

1. 修正Uri权限授予逻辑

不要依赖Intent的flag自动授权,手动给所有匹配拍照Intent的相机应用授予Uri的读写权限

2. 修正FileProvider的SDK版本判断

原代码判断SDK_INT > N_MR1(API25)才用FileProvider,Android 7.0(API24)就已经禁止Uri.fromFile的跨进程传递,需要调整判断条件

3. 添加录制完成后的兜底复制逻辑

如果自定义路径的文件损坏,直接将相机默认输出的视频复制到你的自定义目录,完全规避相机写入自定义路径的兼容性问题

4. 优化FileProvider配置

避免暴露整个存储根目录,减少权限风险


修正后的代码

调用录制Intent的代码

Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takeVideoIntent ->
    val resolvedActivities = activity!!.packageManager.queryIntentActivities(takeVideoIntent, 0)
    if (resolvedActivities.isNotEmpty()) {
        val videoUri = getFileUri(activity!!, filePath)
        // 手动给所有匹配的相机应用授予Uri读写权限
        resolvedActivities.forEach { resolveInfo ->
            val packageName = resolveInfo.activityInfo.packageName
            activity!!.grantUriPermission(
                packageName,
                videoUri,
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
            )
        }
        takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri)
        takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0)
        takeVideoIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 60)
        startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE)
    }
}

修正后的getFileUri方法

fun getFileUri(activity: Activity, filePath: File): Uri {
    // Android 7.0及以上统一使用FileProvider
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        FileProvider.getUriForFile(
            activity,
            BuildConfig.APPLICATION_ID + ".provider",
            filePath
        )
    } else {
        Uri.fromFile(filePath)
    }
}

优化后的FileProvider paths配置

替换原有paths配置,把your_custom_folder改成你实际的存储文件夹名即可

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!-- 仅暴露你需要用到的自定义目录,不要暴露整个根目录 -->
    <external-files-path name="app_video_folder" path="your_custom_folder/" />
</paths>

onActivityResult兜底处理逻辑

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == Activity.RESULT_OK) {
        val targetFile = filePath // 你的自定义路径文件
        // 检查文件是否正常,10秒低清视频至少大于2MB,可根据你的画质调整阈值
        if (targetFile.length() < 2 * 1024 * 1024) {
            // 文件损坏,从相机默认输出的Uri复制到自定义路径
            data?.data?.let { defaultUri ->
                contentResolver.openInputStream(defaultUri)?.use { inputStream ->
                    FileOutputStream(targetFile).use { outputStream ->
                        inputStream.copyTo(outputStream)
                    }
                }
                // 复制完成后可删除系统默认存储的视频
                contentResolver.delete(defaultUri, null, null)
            }
        }
        // 收回之前授予的Uri权限
        val videoUri = getFileUri(this, filePath)
        revokeUriPermission(videoUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
    }
}

内容的提问来源于stack exchange,提问作者Rizwan Rasheed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:54:02