Возникает ошибка «Ошибка открытия: EFAULT (Неверный адрес)», когда okhttp пытается отправить выбранное изображение из PhotoPicker.

Эта ошибка возникает ТОЛЬКО в том случае, если изображение было выбрано из Photo Picker на Android 13 (в версиях без Photo Picker все работает!).

Что означает код:

Пользователь выбирает изображение из Photo Picker.

Получите uri изображения и сохраните файл в теле, там тоже все работает:

      File imgFile = FilesHelper.INSTANCE.getFileFromUri(this, imgUri); 
postBody.setPhoto(imgFile);
      @Throws(Exception::class)
fun getFileFromUri(context: Context, uri: Uri): File? {
    var path: String? = null
    if ("content".equals(uri.scheme, ignoreCase = true)) {
        path = getDataColumn(context, uri, null, null)
    } else if ("file".equals(uri.scheme, ignoreCase = true)) {
        path = uri.path
    }
    return if (!path.isNullOrEmpty()) File(path) else null
}

private fun getDataColumn(context: Context, uri: Uri, 
                          selection: String?, selectionArgs: Array<String?>?): String? {
    var cursor: Cursor? = null
    val column = MediaStore.Images.Media.DATA
    val projection = arrayOf(column)
    try {
        cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
        if (cursor != null && cursor.moveToFirst()) {
            val column_index = cursor.getColumnIndexOrThrow(column)
            return cursor.getString(column_index)
        }
    } finally {
        cursor?.close()
    }
    return null
}

Но когда тело отправляется как составное,

      final Map<String, RequestBody> multipart = new HashMap<>(2);
multipart.put("product",
            RequestBody.create(MediaType.parse("application/json"),
            BaseApplication.getGson().toJson(postBody)));
multipart.put("image\"; filename=\"%1.jpg\"",
            RequestBody.create(MediaType.parse("image/jpeg"),
            postBody.getPhoto())); // type File
....  
serverApi.sendBody(multipart); 
....

в logCat было показано предупреждение:

* /sdcard/.transforms/synthetic/picker/0/com.android.providers.media.photopicker/media/1000000019.jpg: open failed: EFAULT (Bad address)*

а затем Retrofit/okhttp выдает исключение.

Дооснащенная версия "com.squareup.retrofit2:retrofit:2.9.0"

Разрешения в AndroidManifest, которые предоставляются перед выбором изображения:

      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--Android 13 permissions-->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>

И android:requestLegacyExternalStorage="true"в <приложении> тоже.

Запрашиваем разрешения:

      if (VERSION.SDK_INT >= 33) arrayOf(Manifest.permission.READ_MEDIA_IMAGES) else arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)

Могу ли я получить и отправить это изображение без использования разрешения MANAGE_EXTERNAL_STORAGE? Потому что приложение распространяется через Google Play и не является файловым менеджером или чем-то в этом роде. Может быть, мне следует скопировать файл во внутреннюю папку приложения или что?

1 ответ

Что ж, найдено решение: предоставить разрешение на чтение URI.

        private void onImagePicked(Uri imgUri){
    if(imgUri!=null) {
      try {

        grantUriPermission(getPackageName(),imgUri,Intent.FLAG_GRANT_READ_URI_PERMISSION);

        File imgFile = FilesHelper.INSTANCE.getFileFromUri(this, imgUri);
        postBody.setPhoto(imgFile);
      } catch (Exception e) {
        ...
      }
    }
  }
Другие вопросы по тегам