androidgeolocationgpsandroid-10.0android-exifinterface

Android ExifInterface longitude & latitude missing after android 10


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!


Solution

  • 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.