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

Android设备用Kotlin+VideoView播放SD卡视频失败求助

解决Android 13(API33)下播放SD卡视频失败的问题

核心问题分析

你遇到的问题主要来自三个方面:Android 13的权限变更、SD卡路径获取错误、Uri解析方式不正确,以下是针对性的解决步骤:


1. 权限适配Android 13规则

Android 13开始废弃READ_EXTERNAL_STORAGE权限,针对视频文件需使用READ_MEDIA_VIDEO权限,同时兼容低版本的话可以保留旧权限并限制最高适配版本:

<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- 兼容API32及以下版本 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

注意:危险权限需要在运行时主动请求,不能仅依赖Manifest声明。

2. 正确获取可移除SD卡路径

Environment.getExternalStorageDirectory()返回的是设备内部存储的公共目录,并非你插入的Micro SD卡路径。根据存储场景选择以下两种方式:

  • 应用私有SD卡目录(无需额外权限)
    如果视频放在SD卡中你的应用私有目录下,通过getExternalFilesDirs(null)获取路径,该方法返回的数组中,第二个元素即为SD卡的应用私有目录(存在SD卡时):

    val externalDirs = getExternalFilesDirs(null)
    if (externalDirs.size > 1 && externalDirs[1] != null) {
        val videoFile = File(externalDirs[1], "crystal.mp4")
        val uri = Uri.fromFile(videoFile)
        videoView.setVideoURI(uri)
        
        val mediaController = MediaController(this)
        videoView.setMediaController(mediaController)
        videoView.start()
    }
    

    这种方式属于应用私有存储,不需要请求媒体权限。

  • SD卡公共目录(需权限)
    如果视频放在SD卡公共目录(如Movies、Download),不能直接通过路径访问,需通过MediaStore查询对应的Content Uri:

    val projection = arrayOf(MediaStore.Video.Media._ID)
    val selection = "${MediaStore.Video.Media.DISPLAY_NAME} = ?"
    val selectionArgs = arrayOf("crystal.mp4")
    
    contentResolver.query(
        MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
        projection,
        selection,
        selectionArgs,
        null
    )?.use { cursor ->
        if (cursor.moveToFirst()) {
            val videoId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
            val uri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, videoId)
            
            videoView.setVideoURI(uri)
            val mediaController = MediaController(this)
            videoView.setMediaController(mediaController)
            videoView.start()
        }
    }
    

3. 修正Uri解析方式

直接用路径字符串调用Uri.parse()是错误的,Android 7及以上会触发FileUriExposedException,且无法正确识别SD卡文件。需使用Uri.fromFile()(仅适用于应用私有目录)或通过MediaStore获取标准的Content Uri。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:46:07