0

This error occurs ONLY when an image was choosed from Photo Picker on android 13 (on versions without Photo Picker all works!).

What does code:

User picks image from Photo Picker.

Get image's uri and save file in body, there all is working too:

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
}

But when body is sending as multipart,

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); 
....

a warning was shown in logCat:

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

and then retrofit/okhttp throws exception.

Retrofit version "com.squareup.retrofit2:retrofit:2.9.0"

Permissions in AndroidManifest, which are given before picking image:

<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"/>

And android:requestLegacyExternalStorage="true" in <application> too.

Asking permissions:

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

Can I get and send that image without using MANAGE_EXTERNAL_STORAGE permission? Because application distributes via Google Play and is not files manager or something like that. Maybe I should copy file in app's internal files dir or what?

Yoko999
  • 21
  • 1
  • 6

1 Answers1

0

Well, found solution: grant read uri permission

  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) {
        ...
      }
    }
  }
Yoko999
  • 21
  • 1
  • 6