Set file name and extension when saving a video to Android's MediaStore

Viewed 876

I need something really simple - I have an mp4 file that my app recorded and I want to insert it to the MediaStore to the user's video collection. Here is my code, including the recommended ways of dealing with the new Scoped Storage:

// 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
}

However, after this function call the file with name video_1.mp4 becomes something like 1589077991588.3gp, so both the name and the extension are different (my device is Android 9). MediaStore.MediaColumns.DATA is deprecated. How can I fix this?

1 Answers

Late to the party, but just stumbled accross this issue and was looking for an answer here. And while trying around, I think I found a solution: Updating the MediaStore.Video.Media.DISPLAY_NAME after inserting the video data has done the trick (on Android 8, i.e.).

So while the above code worked for Android 10 and above, for Android 9 and below I've added to update the title after writing the content to the stream.

// [...] 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)
}

So it seems that on Android < 10 devices the display-name and title get overwritten when inserting the data via the contentResolver.openOutputStream.

Related