Search code examples
androidmediastoreandroid-10.0

Media Store insert DATE_TAKEN is always null


I'm using the MediaStore api to add a image to the gallery. The insert works, but when I query the image afterwards the datetaken=null.

Here is how I'm using MediaStore:

 private suspend fun saveImageToGallery(
        context: Context,
        bitmap: Bitmap,
        imageName: String
): Uri? = withContext(Dispatchers.IO) {
    try {
        val contentResolver = context.contentResolver

        val values = ContentValues().apply {
            put(MediaStore.Images.Media.DISPLAY_NAME, imageName)
            put(MediaStore.Images.Media.DESCRIPTION, imageName)
            put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
            put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000)
            put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.Images.Media.IS_PENDING, 1)
            }
        }
        // Insert file into MediaStore
        val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
        } else {
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }
        val galleryFileUri = contentResolver.insert(collection, values)
                ?: return@withContext null

        // Save file to uri from MediaStore
        contentResolver.openOutputStream(galleryFileUri).use {
            bitmap.compress(Bitmap.CompressFormat.JPEG, 80, it)
        }

        // Now that we're finished, release the "pending" status, and allow other apps to view the image.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            values.clear()
            values.put(MediaStore.Images.Media.IS_PENDING, 0)
            contentResolver.update(galleryFileUri, values, null, null)
        }
        return@withContext galleryFileUri
    } catch (ex: Exception) {
        Log.e("MSTEST", "Saving progress pic to gallery failed", ex)
        return@withContext null
    }
}

Here is a link to a project to reproduce the issue https://github.com/jakob-grabner/Media-Store-Example


Solution

  • DATE_TAKEN is documented to be "The time the media item was taken." and to deliver on that API description, they populate it based on the "DateTimeOriginal" Exif metadata field. If the file being scanned doesn't have this metadata, they can't accurately determine when the file was captured, so DATE_TAKEN is set to NULL to avoid misleading data. So one has to add exif data to populate the DATE_TAKEN field in the MediaStore.

            // Add exif data
            contentResolver.openFileDescriptor(galleryFileUri, "rw")?.use {
                // set Exif attribute so MediaStore.Images.Media.DATE_TAKEN will be set
                ExifInterface(it.fileDescriptor)
                    .apply {
                        setAttribute(
                            ExifInterface.TAG_DATETIME_ORIGINAL,
                            exifDateFormatter.format(Date())
                        )
                        saveAttributes()
                    }
            }