Android(API33)下用Kotlin+VideoView读取本地视频的问题
Android 13(API 33)本地视频播放权限与路径问题
我正在开发一款平板端Android应用(基于API 33/Android 13),功能是根据选择播放对应视频。目前能正常播放res/raw目录下的.mp4视频,但由于需要存储约50个单文件25MB左右的视频,且设备运行时无网络,希望将视频存到本地设备中。之前找到的10多年前的解决方案太晦涩,现在有几个关键问题:
当前播放raw目录视频的代码
val workPackage = intent.getParcelableExtra("work_package",WorkModel::class.java) if(workPackage != null){ val resId = resources.getIdentifier(workPackage.Video, "raw", packageName) val packageName = "android.resource://" + getPackageName() + "/" + resId val uri = Uri.parse(packageName) videoView.setVideoURI(uri) val mediaController = MediaController(this) videoView.setMediaController(mediaController) videoView.start() }
核心疑问
1. 访问Google Files或Google Drive中的视频
如果视频存储在Google Files或Google Drive中,该如何访问?仅仅修改URI即可吗?
2. 权限申请问题
我查了存储相关的官方文档,需要在应用清单中声明权限。我仅需要读取权限,是不是只需要声明uses-permission-sdk-23?
3. 存储路径疑问
Google Files或Google Drive的绝对文件系统路径是什么?有没有更适合存储这类视频的本地位置?
后续测试更新
更新1:尝试使用内部存储Movies目录
我将视频放入内部存储的Movies目录,文件路径为/storage/emulated/0/Movies/crystal.mp4,但尝试以下代码均无法播放:
// 写法1 videoView.setVideoPath("/storage/emulated/0/Movies/crystal.mp4")
// 写法2 val packageName = Environment.getExternalStorageDirectory().path + "/storage/emulated/0/Movies/crystal.mp4" val uri = Uri.parse(packageName)
// 写法3 val packageName = Environment.getExternalStorageDirectory().path + "/Movies/crystal.mp4" val uri = Uri.parse(packageName)
更新2:文件存在但无法读取
用file.exists()检查时,路径显示文件存在(进入if分支):
val packageName = "android.resource://" + getPackageName() + "/" + R.raw.crystal val filePath = "/storage/emulated/0/Movies/crystal.mp4" val file = File(filePath) if (file.exists()) { // 播放res/raw下的crystal,已知可正常播放 val uri = Uri.parse(packageName) videoView.setVideoURI(uri) } else { // 已知会失败 videoView.setVideoPath("/crystal.mp4") }
但用file.canRead()检查时进入了else分支:
val packageName = "android.resource://" + getPackageName() + "/" + R.raw.crystal val filePath = "/storage/emulated/0/Movies/crystal.mp4" val file = File(filePath) if (file.canRead()) { // 播放res/raw下的crystal,已知可正常播放 val uri = Uri.parse(packageName) videoView.setVideoURI(uri) } else { // 已知会失败 videoView.setVideoPath("/crystal.mp4") }
这说明路径正确但无法读取视频文件,原因是什么?
更新3:确认文件存在但不可读
用嵌套判断进一步测试:
val filePath = "/storage/emulated/0/Movies/crystal.mp4" val file = File(filePath) if (file.exists()) { if (file.canRead()) { val asdf = "android.resource://" + getPackageName() + "/" + R.raw.crystal val uri = Uri.parse(asdf) // 存在且可读则播放crystal videoView.setVideoURI(uri) } else { val asdf = "android.resource://" + getPackageName() + "/" + R.raw.testvid val uri = Uri.parse(asdf) // 存在但不可读则播放testvid videoView.setVideoURI(uri) } } else { val asdf = "android.resource://" + getPackageName() + "/" + R.raw.testvid1 val uri = Uri.parse(asdf) // 不存在则播放testvid1 videoView.setVideoURI(uri) }
结果播放了testvid,再次确认路径存在但文件无法读取。
更新4:文件夹可读写,文件不行
将路径修改为仅指向文件夹/storage/emulated/0/Movies/后,file.exists()和file.canRead()均返回true。是不是代码仅检查了文件夹的权限,而非文件本身?
内容的提问来源于stack exchange,提问作者VeronicaV
相关产品推荐
相关产品推荐

