Долгота и широта Android ExifInterface отсутствуют после Android 10

Я пытаюсь создать приложение, которое позволяет пользователю выбирать файл и отображать долготу/широту GPS, найденную в метаданных EXIF ​​фотографии.

Я могу получить долготу/широту GPS, если пользователь выбирает изображение на вкладке «Последние» или на вкладке «Загрузки» (пример uri: content://com.android.providers.media.documents/document/image%3A1000000018).

Однако, когда пользователь выбирает изображение из хранилища (пример uri: content://com.android.externalstorage.documents/document/primary%3ADownload%2FPhilip%20Island.jpg), я получаю все данные EXIF, кроме GPS long/lat, которые приходит как нан или 0/1.

Я запросил READ_EXTERNAL_STORAGE и ACCESS_MEDIA_LOCATION как в манифесте, так и во время выполнения. Я также пробовал следующее:

  • Флаг намерения ACTION_GET_CONTENT Intent.FLAG_GRANT_READ_URI_PERMISSION
  • uri = MediaStore.setRequireOriginal(uri);
  • Использование contentResolver для создания URI, как показано ниже:
 ​ 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]);  
}

Единственный способ заставить его работать до сих пор — это построить путь к файлу с использованием URI (используя очень хакерский метод), чего мы не должны делать по очевидным причинам. Это мой код прямо сейчас:

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();
    }
}

Что мне здесь не хватает? Спасибо!

Да, об этом часто сообщалось здесь. Чтобы получить эту информацию о местоположении, вам также необходимо запросить разрешение на определение местоположения. И, возможно, MANAGE_EXTERNAL_STORAGE. Новым для меня является то, что не все провайдеры удаляют теги местоположения.

blackapps 19.10.2022 06:48

Для первой схемы контента вы использовали ACTION_GET_CONTENT? Если да, предоставляет ли ACTION_OPEN_DOCUMENT ту же схему?

blackapps 19.10.2022 08:03

Я могу подтвердить то, что вы сказали. Интересный. Насколько мне известно, в документах этого нет. Так что выберите «Недавние» или «Изображения», и вы без проблем получите информацию о местоположении.

blackapps 19.10.2022 09:20

Интересный? Раздражающий! Требуется ACCESS_MEDIA_LOCATION для первой схемы контента, но я понятия не имею, какие разрешения необходимы для второй. MANAGE_EXTERNAL_STORAGE не помогает.

blackapps 19.10.2022 13:10

С помощью схемы file:// также можно прочитать lat,lon.

blackapps 19.10.2022 13:43

@blackapps, спасибо за предложения. Да, я использовал ACTION_GET_CONTENT. Пробовал MANAGE_EXTERNAL_STORAGE и ACTION_OPEN_DOCUMENT, все равно не работает. Спасибо за помощь!

Uvin Abeysinghe 03.11.2022 23:57
0
6
117
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сначала вы должны преобразовать saf uri в uri mediastore.

Uri uri = MediaStore.getMediaUri(selectedUri); 

будет делать свое дело.

Извините, я не знаю правильного имени, но Android Studio предложит правильное.

Другие вопросы по теме