Adding Latitude Longitude values to Image Metadata in Kotlin

Adding Latitude Longitude values to Image Metadata in Kotlin

This is one of the POC I was working on where I once a picture is taken, need to calculate the latitude longitude values and add it to the Image Metadata. There are already tutorials available for taking images, extracting latitude longitude and all, so will not be focusing on that, but what I will be focusing is on using ExifInterface and setting the Latitude, Longitude attributes to the metadata.

We will be using the metadata extractor library to read the metadata, so that we can verify if its visible or not.

implementation("com.drewnoakes:metadata-extractor:2.19.0")

This is the function I am using to the add the metadata

@RequiresApi(Build.VERSION_CODES.Q)
private fun addLocationMetadata(imageUri: Uri, latitude: Double, longitude: Double): File? {
    return try {
        val file = FileUtil.getFileFromImageUri(requireContext(), imageUri)
        val exifInterface = file?.let { ExifInterface(it) }

        exifInterface?.setAttribute(
            ExifInterface.TAG_GPS_LATITUDE,
            convertToDegreeMinutesSeconds(latitude)
        )
        exifInterface?.setAttribute(
            ExifInterface.TAG_GPS_LONGITUDE,
            convertToDegreeMinutesSeconds(longitude)
        )
        exifInterface?.saveAttributes()

        logImageMetadata(file)
        Log.d("TAG", "FIRST LOG OF METADATA DONE")
        file
    } catch (e: Exception) {
        e.printStackTrace()
// Handle exceptions that may occur during metadata modification
        Log.e("TAG", "Error modifying image metadata", e)
        null
    }
}

In this we are passing the image uri, latitude and longitude.

ExifInterface is class to handle image and audio files, EXIF stands for Exchangeable Image File Format. Exif has a multiple tags that we can read and write values on to. So we will be writing the latitude longitude to this using the .setAttribute()

With this there was one issue that I faced which was that, just passing the latitude and longitude as string does not work and when we log the metadata, it gives null, what actually with the help of my research, chatgpt and my senior was that we need to convert the latitude and longitude to degree, minutes and seconds format, the function for that has been defined as follows.

private fun convertToDegreeMinutesSeconds(coord: Double): String {
    val degrees = coord.toInt()
    val minutes = ((coord - degrees) * 60).toInt()
    val seconds = ((coord - degrees - minutes / 60.0) * 3600.0).toInt()

    return "$degrees/1,$minutes/1,$seconds/1"
}

This simple change allowed to add the latitude and longitude values to the ExifInterface.

The getFileFromImageUri function too is easily available with a quick google search, so will not be addressing saveTag() of the exifInterface not working was the problem I could not find solution to anywhere, so I have written this blog to address the problem and show one way of solving it.