I'm trying to create an app that allows the user to select a file and display the GPS long/lat found in the photo EXIF metadata.
I can get the GPS long/lat if the user selects an image from the recent tab or Downloads tab(example uri: content://com.android.providers.media.documents/document/image%3A1000000018).
However, when the user selects an image from storage(example uri: content://com.android.externalstorage.documents/document/primary%3ADownload%2FPhilip%20Island.jpg), I get all EXIF data except GPS long/lat which comes as nan or 0/1.
I have requested READ_EXTERNAL_STORAGE and ACCESS_MEDIA_LOCATION both in the manifest and during runtime. I've also tried the following:
Uri selecteduri = data.getData();
Cursor cursor = getContentResolver().query(selecteduri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
String[] parts = cursor.getString(0).split(":");
Uri photoUri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, parts[1]);
}
The only way I've gotten it to work so far is by constructing the file path using the URI(using a very hacky method), which we shouldn't do for obvious reasons. This is my code right now:
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@SuppressLint("Recycle")
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
Uri selecteduri = data.getData();
InputStream stream = null;
try {
stream = getContentResolver().openInputStream(selecteduri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
ExifInterface exifInterface = null;
try {
exifInterface = new ExifInterface(stream);
} catch (IOException e) {
e.printStackTrace();
}
float[] output = new float[2];
exifInterface.getLatLong(output);
System.out.println("Uri: : " + selecteduri);
System.out.println("Lat: " + output[0]);
System.out.println("Long: " + output[1]);
System.out.println("Lat: " + exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
private ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
if (isGranted &&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION) == PackageManager.PERMISSION_GRANTED) {
openImagePicker();
}
});
public void openImagePicker() {
Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
photoPickerIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION |
Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
someActivityResultLauncher.launch(createChooser(photoPickerIntent, "My Title"));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissionLauncher.launch(Manifest.permission.ACCESS_MEDIA_LOCATION);
}
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.ACCESS_MEDIA_LOCATION) == PackageManager.PERMISSION_GRANTED) {
openImagePicker();
}
}
What am I missing here? Thanks!
You should convert the saf uri to a mediastore uri first.
Uri uri = MediaStore.getMediaUri(selectedUri);
will do the trick.
Sorry, out of mind i do not know the right name, but Android Studio will suggest the right one.