#android #kotlin #android-contentresolver #android-10.0 #android-external-storage
#Android #kotlin #android-contentresolver #android-10.0 #android-external-storage
Вопрос:
В моем приложении 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)
Также пытался добавить a CATEGORY_OPENABLE
в intent. Ни одна из этих работ.
Итак, когда я отправляю намерение выбрать изображение из галереи, некоторые приложения из play Market возвращают мне Uri с файловой схемой, например: file:///storage/emulated/0/Download/sample.jpg
Когда я пытаюсь преобразовать его в растровое изображение (для настройки в ImageView), я получаю исключение EACCES (отказано в разрешении).
Я попытался прочитать его с помощью:
java.File Api
contentResolver.openInpuStream()
contentResolver.openFileDescriptor()
ImageDecoder
Ничего не помогает. Как я вижу, я не могу прочитать Uri с файловой схемой на Android 10 (нацеленный на 29 sdk) без флага requestlegacyexternalstorage, включенного в моем манифесте.
Если я ошибаюсь, пожалуйста, помогите мне разобраться, как это прочитать.
Загадочная вещь в том, что эмулятор Android 11 с приложением, ориентированным на 29 sdk, МОЖЕТ считывать Uri такого типа без флага requestlegacyexternalstorage.
И да, я предоставил разрешения на ЧТЕНИЕ / ЗАПИСЬ в EXTERNAL_STORAGE.
Комментарии:
1. Пожалуйста, начните свой пост с блока кода, в котором используется код для используемого намерения.
2.
file:///storage/emulated/.../image.jpeg
Пожалуйста, укажите полный путь.3.
s i can see i can not read Uri with a file scheme on android 10
Да, вы можете, но это зависит от полного пути. Вот почему я спросил,4. Действительно: Android 11 менее строгий. Тогда у вас будет большой доступ. Google сделал шаг назад.
5. Такие приложения из play marked используют что-то вроде getRealPathFromUr() или являются старыми приложениями для просмотра файлов.. В основном эта функция недоступна на Android 10, но, по-видимому, они запросили разрешение на устаревшее хранилище или придумали какой-то код для определения пути к файлу. К сожалению, не используется на Android 10. Виноваты авторы этих приложений. (Вы можете отправить их по почте). Пожалуйста, назовите их!
Ответ №1:
некоторые приложения из play Market возвращают мне 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
plus use android:requestLegacyExternalStorage="true"
для согласованности между версиями Android.
Ответ №2:
Это отлично работает для меня (я тестировал его на Android 8, 10, 11 с targeting 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));
}