Here is the answer I would have like to find : When using CameraX, EXIF data is automatically set but not GPS EXIF tags because :
- permissions are needed to access location
- there are several ways to get the location and that the different options have a different impact on battery drain so it is good to have control.
- it can take a long time to get GPS location (10s with assisted GPS and up to 10mn not assisted).
Here is the function that I call inside the onImageSaved() callback :
fun setCurrentLocationInExif(context: Context, uri : Uri, fusedLocationClient : FusedLocationProviderClient){ // check location permissions if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ) { throw(Exception("no location found")) } else { // get location (a new one if older than 60s) val locRequest = CurrentLocationRequest.Builder().setMaxUpdateAgeMillis(60000).build() fusedLocationClient.getCurrentLocation(locRequest, null) .addOnSuccessListener { location: Location? -> // Got last known location. In some rare situations this can be null. In that case we do not go further if (location != null){ Log.d(TAG, "latitude=${location.latitude}") Log.d(TAG, "longitude=${location.longitude}") val uriFd = context.contentResolver.openFileDescriptor(uri, "rw") if (uriFd != null) { val uriExif = ExifInterface(uriFd.fileDescriptor) uriExif.setGpsInfo(location) uriExif.saveAttributes() uriFd.close() } else{ throw(Exception("Cannot find file for uri=$uri")) } } } } }
The call in onImageSaved :
override fun onImageSaved(output: ImageCapture.OutputFileResults){ setCurrentLocationInExif(requireContext(), output.savedUri!!, fusedLocationClient) }
Where fusedLocationClient is defined in my Main Activity onCreate after a lateinit (you will need to activate Play Services/location services in your gradle.build(app) :
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)