Средство выбора галереи возвращает Uri с файловой схемой на Android 10, как это читать?

Мое приложение имеет targetSdkVersion = 29 (новая политика хранения с ограниченными возможностями) и не имеет флага requestlegacyexternalstorage, включенного в манифесте (я не хочу его включать).

Способы, которыми я пытался составить намерение:

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);

Также пробовал это

val galleryIntent = Intent(Intent.ACTION_PICK).apply {
    type = PICK_INTENT_TYPE
}
flowInterruptBlocker?.blockFlowInterruption()
startActivityForResult(galleryIntent, GALLERY_INTENT_REQUEST_CODE)

Также пробовал добавить CATEGORY_OPENABLE к намерению. Ни одна из этих работ.

Итак, когда я отправляю намерение выбрать изображение из галереи, некоторые приложения с игрового рынка возвращают мне Uri с файловой схемой, например: file: ///storage/emulated/0/Download/sample.jpg

Когда я пытаюсь преобразовать его в растровое изображение (для установки в imageView), я получаю исключение EACCES (Permission denied).

Я попытался прочитать это с помощью:

java.File Api

contentResolver.openInpuStream()

contentResolver.openFileDescriptor()

ImageDecoder

Ничего не помогает. Как я вижу, я не могу читать Uri с файловой схемой на Android 10 (таргетинг на 29 SDK) без флага requestlegacyexternalstorage, включенного в моем манифесте.

Если я ошибаюсь, пожалуйста, помогите мне понять, как это читать.

Загадочная вещь в том, что эмулятор Android 11 с таргетингом на приложения 29 sdk МОЖЕТ читать этот тип Uri без флага requestlegacyexternalstorage.

И да, я предоставил разрешения READ / WRITE_EXTERNAL_STORAGE.


person Efimov Aleksandr    schedule 08.10.2020    source источник
comment
Пожалуйста, начните свой пост с блока кода, в котором используется код для используемого намерения.   -  person blackapps    schedule 08.10.2020
comment
file:///storage/emulated/.../image.jpeg Укажите полный путь.   -  person blackapps    schedule 08.10.2020
comment
s i can see i can not read Uri with a file scheme on android 10 Да, можно, но это зависит от полного пути. Вот почему я спросил,   -  person blackapps    schedule 08.10.2020
comment
Действительно: Android 11 менее строг. Тогда у вас будет большой доступ. Google сделал шаг назад.   -  person blackapps    schedule 08.10.2020
comment
Такие приложения из игры с пометкой используют что-то вроде getRealPathFromUr () или являются старыми приложениями File Explorer. В основном эту функцию нельзя использовать на Android 10, но, по-видимому, они запросили разрешение на устаревшее хранилище или придумали некоторый код для определения пути к файлу. К сожалению, не работает на Android 10. В этом виноваты авторы этих приложений. (Вы можете отправить их по почте). Назовите их, пожалуйста!   -  person blackapps    schedule 08.10.2020
comment
@blackapps Спасибо за внимание. Я добавил код намерения, представив пример uri, который я не могу открыть. Не могли бы вы предоставить некоторую информацию о меньших ограничениях Android 11. Спасибо   -  person Efimov Aleksandr    schedule 08.10.2020
comment
На Android 11 можно будет использовать этот файл uri.   -  person blackapps    schedule 08.10.2020


Ответы (2)


некоторые приложения с игрового рынка возвращают мне Uri с файловой схемой, например: file: ///storage/emulated/0/Download/sample.jpg

Некоторые приложения написаны неопытными разработчиками.

Если я ошибаюсь, пожалуйста, помогите мне понять, как это читать.

На Android 10 вы не сможете прочитать это Uri без android:requestLegacyExternalStorage="true".

Загадочная вещь в том, что эмулятор Android 11 с таргетингом на приложения 29 sdk МОЖЕТ читать этот тип Uri без флага requestlegacyexternalstorage.

Функция необработанных путей, представленная в Android 11, означает, что READ_EXTERNAL_STORAGE снова работает нормально. Итак, рекомендуемый подход - запросить READ_EXTERNAL_STORAGE плюс использовать android:requestLegacyExternalStorage="true" для согласованности между версиями Android.

person CommonsWare    schedule 09.10.2020

У меня это отлично работает (я тестировал его на Android 8, 10, 11 с таргетингом sdk 29). Не требует android:requestLegacyExternalStorage="true" и каких-либо разрешений.

private static Bitmap readImage(Uri uri, Context context){
   InputStream inputStream = context.getContentResolver().openInputStream(uri);
   Bitmap res = BitmapFactory.decodeStream(inputStream);
   inputStream.close();
   return res;
}

и вы используете это так:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
       
    if(data == null || data.getClipData().size() == 0)
       return;

    myImageView.setImageBitmap(readImage(data.getClipData().getItemAt(0).getUri(), this));
                    
}
person Jan Rozenbajgier    schedule 22.04.2021