4

我需要一些非常简单的东西 - 我有一个我的应用程序录制的 mp4 文件,我想将它插入 MediaStore 到用户的视频收藏中。这是我的代码,包括处理新范围存储的推荐方法:

// fileToExpose is in internal storage with a name like video_1.mp4
fun copyVideoFileToMediaStore(fileToExpose: File, context: Context): Boolean {
    val resolver = context.contentResolver

    val volume = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) MediaStore.VOLUME_EXTERNAL_PRIMARY else MediaStore.VOLUME_EXTERNAL
    val videoCollection = MediaStore.Video.Media.getContentUri(volume)

    val videoDetails = ContentValues().apply {
        put(MediaStore.Video.Media.DISPLAY_NAME, fileToExpose.name)
        put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
        put(MediaStore.Video.Media.TITLE, name)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            put(MediaStore.Video.Media.IS_PENDING, 1)
        }
    }

    val videoContentUri = resolver.insert(videoCollection, videoDetails) ?: return false

    resolver.openFileDescriptor(videoContentUri, "w", null).use { pfd ->
        pfd ?: return false
        fileToExpose.inputStream().use { input ->
            FileOutputStream(pfd.fileDescriptor).use { output ->
                input.copyTo(output)
            }
        }
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        videoDetails.clear()
        videoDetails.put(MediaStore.Video.Media.IS_PENDING, 0)
        resolver.update(videoContentUri, videoDetails, null, null)
    }

    return true
}

但是,在这个函数调用之后,文件名video_1.mp4变成了类似1589077991588.3gp的,所以名称和扩展名都不同(我的设备是 Android 9)。MediaStore.MediaColumns.DATA已弃用。我怎样才能解决这个问题?

4

1 回答 1

1

聚会迟到了,但偶然发现了这个问题,并在这里寻找答案。在尝试时,我想我找到了一个解决方案:在插入视频数据MediaStore.Video.Media.DISPLAY_NAME 后更新已经完成了这个技巧(在 Android 8 上,即)。

因此,虽然上述代码适用于 Android 10 及更高版本,但对于 Android 9 及更低版本,我已添加以在将内容写入流后更新标题。

// [...] example as above, here we are after the `resolver.openFileDescriptor` section
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    videoDetails.clear()
    videoDetails.put(MediaStore.Video.Media.IS_PENDING, 0)
    resolver.update(videoContentUri, videoDetails, null, null)
} else {
    // On Android <= 9 we need to update the display name after writing the data to ensure the DISPLAY_NAME is correctly set
    videoDetails.clear()
    videoDetails.put(MediaStore.Video.Media.DISPLAY_NAME, fileToExpose.name)
    resolver.update(videoContentUri, videoDetails, null, null)
}

因此,在 Android < 10 设备上,通过contentResolver.openOutputStream.

于 2021-01-08T10:55:17.747 回答