android - 使用 FileProvider 和 MediaScan,视频不会显示在 Android 24 上的照片中
问题描述
我有点卡在这个问题上,并且已经研究了一段时间,但没有运气。我有一个允许用户拍摄照片/视频的 android 应用程序。这些文件使用 FileProvider 存储在外部存储中。我一直在尝试(没有运气)让视频显示在照片应用程序中,但未能成功。Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 和 sendBroadcast 适用于图像,但不适用于视频。我知道视频正在被捕获,它们被保存在正确的位置,并且没有损坏(我可以使用 FileProvider 内容 Uri 在 VideoView 中播放它们)我还没有尝试将其更新到 Android 10,因为我的最低目标是 24我似乎无法让它为此工作。
创建 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 和 sendBroadcast 视频不显示。如果我使用 MediaScannerConnection 它不会出现。如果我使用内容 URI 手动插入内容解析器,它会显示在照片中,但视频不可播放且没有预览。如果我使用绝对路径手动插入内容解析器,它根本不会出现在照片中 下面是我用来拍摄视频并添加到 MediaStore 的代码
文件提供者
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
文件提供程序路径
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="Image" path="Image" />
<external-files-path name="Recording" path="Recording"/>
<external-files-path name="Video" path="Video"/>
</paths>
创建文件和调用 Intent 捕获视频的方法
private fun takeVideo() {
Intent(MediaStore.ACTION_VIDEO_CAPTURE).also{ videoIntent ->
val videoFile: File? = try{
createVideoFile()
}catch(ex: IOException){
Toast.makeText(mMainActivityHelper.contextProvider(), R.string.error_taking_photo, Toast.LENGTH_SHORT).show()
Log.w("OPENING_VIDEO_FILE", "Error opening video file with message = " + ex.message)
return
}
mFilePath = Uri.parse(videoFile?.absolutePath)
videoFile?.also{
videoIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
mFileUri = FileProvider.getUriForFile(mMainActivityHelper.contextProvider(), "FileProvider", it)
videoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri)
mMainActivityHelper.startActivityForResult(videoIntent, MainActivity.TAKE_VIDEO)
}
}
}
@Throws(IOException::class)
private fun createVideoFile(): File? {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val externalDir = mMainActivityHelper.externalFilesDirProvider(null)
val imagePath = File(externalDir, "NuNoteVideo")
if(!imagePath.exists())
imagePath.mkdir()
return File(imagePath.path, "MPEG_${timeStamp}" + ".mp4")
}
我尝试过的 OnActivityResult 代码都没有奏效。我尝试过使用内容 URI 和绝对路径,但没有成功
覆盖乐趣 onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data)
when{
requestCode == TAKE_VIDEO && resultCode == Activity.RESULT_OK->{
val cv = ContentValues(3).apply {
val absolutePath = myObjectWithThePath.mFilePath.toString()
val name = absolutePath.substring(absolutePath.lastIndexOf("/") + 1)
put(MediaStore.Video.Media.TITLE, name)
put(MediaStore.Video.Media.DISPLAY_NAME, name)
put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
put(MediaStore.Video.Media.DATE_ADDED, Date().time)
put(MediaStore.MediaColumns.DATA, absolutePath)
contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, this)
}
Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
val fileUri = myObjectWithThePath.mFileUri
if(fileUri != null) {
val f = File(fileUri)
mediaScanIntent.data = Uri.fromFile(f)
//mediaScanIntent.type = "video/mp4"
sendBroadcast(mediaScanIntent)
}
}
val f = File(myObjectWithThePath.mFilePath.toString())
MediaScannerConnection.scanFile(applicationContext, listOf(f.absolutePath).toTypedArray(), listOf("video/mp4").toTypedArray()){
path, uri ->
print(path)
print(uri) //This shows a URI if i use the absolute path but nothing shows up in the photos app. If i use content uri with FileProvider is null
}
我已经在 Stack 上查看了许多许多 anwsers,但没有任何效果。任何帮助是极大的赞赏
SDK-29 上的 MediaScanner 和 ScopedStorage
MediaStore.ACTION_VIDEO_CAPTURE 不在 Nougat 7.0 中保存视频
来自外部 SD 卡 Lollipop+ 的 ACTION_MEDIA_SCANNER_SCAN_FILE
使用 Android FileProvider 将照片和视频保存到图库
解决方案
发布更新。我通过在不提供文件路径的情况下创建视频来解决这个问题。这将在 DCIM 文件夹中创建视频。创建视频时,我保存 uri,并查询 uri 以确保它在应用程序的负载上仍然存在。不完全是我想要的,但它会起作用
推荐阅读
- flutter - 从随机小部件导航到使用整个屏幕的新小部件
- java - Java REST 客户端通过连接到 Nexus OSS 获得 403 Forbiden 错误
- c++ - 遇到零时划分数组
- applescript - 如何将 Ctrl+C 发送到除 AppleScript 中的当前选项卡之外的所有 iTerm2 选项卡?
- python - 如何将分类索引更新为 Pandas DataFrame(Python)中使用的类别?
- python - 接受 json 对象的 Python 函数返回 mongodb 查询对象
- time-series - 如何将 SARIMAX 模型拟合到大型数据集?目前非常慢
- html - 当我的导航栏响应时,图标显示在菜单项的顶部
- javascript - 无法在按钮单击 React.js 时重定向(使用上下文提供程序)
- python-3.x - 使用 python pathlib 查找上游目录的绝对路径