0

I am trying to upload an image with retrofit from my computer, android emulator or my phone but those 3 ways, it doesnt not work. I get A FileNotFoundException from a file of my computor and an invalid path on my phone or Android emulator.

I followed this tutorial : https://github.com/hidrodixtion/Example-Retrofit-Image-Upload/blob/master/app/src/main/java/com/projectbox/uploadfile/MainActivity.java#L11

And tried to solved my problem with this topic FileNotFoundException while uploading image using Retrofit

but it still doest now work.

here is my call :

    @Multipart
@POST("http://192.168.1.102:8181/test_postimage.php")
Call<ResponseBody> postImage(@Part MultipartBody.Part image);

and there my activity :

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_prestations);

        Button btn =findViewById(R.id.btn5);

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

        // Change base URL to your upload server URL.
        service = new Retrofit.Builder().baseUrl("http://192.168.0.234:3000").client(client).build().create(UserAccountServices.class);


            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent();
                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);
                    startActivityForResult(Intent.createChooser(intent, "Select Image"), PICK_IMAGE);
                }
            });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {

            Uri selectedImage = data.getData();
            String[] filePath = {MediaStore.Images.Media.DATA};
            Cursor c = getContentResolver().query(selectedImage, filePath,null, null, null);
            c.moveToFirst();
            int columnIndex = c.getColumnIndex(filePath[0]);
            String FilePathStr = c.getString(columnIndex);
            c.close();

            //MultipartBody.Part body = null;

            File file = new File(FilePathStr);
            RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
            MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), reqFile);

            retrofit2.Call<okhttp3.ResponseBody> req = service.postImage(body);
            req.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    Log.i("response image OK",response.body().toString());
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    t.printStackTrace();
                }
            });
        }
    }

I also add a debug screeen if it could help :enter image description here

Thanks for help.enter image description here

EDIT : I tried with your link and I get this code below :

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {

        Uri selectedImage = data.getData();

        File file = new File(selectedImage.getPath());
        RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), reqFile);

        retrofit2.Call<okhttp3.ResponseBody> req = service.postImage(body);
        req.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Log.i("response image OK",response.body().toString());
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                t.printStackTrace();
            }
        });
    }
}

}

But I m still getting a FileNotFoundException Error :

enter image description here

enter image description here

And Finally the error when I pick an image in my phone :

enter image description here

EDIT 2 : I am still looking for a solution and when I pick an image I the thoses weird paths maybe it comes from here but I do not know what.

            Uri selectedImage = data.getData();

        File file = new File("/document/image/stars.jpg");
        Log.i("image path ==> ",selectedImage.getPath());
        Log.i("image encoded path ==> ",selectedImage.getEncodedPath());
        RequestBody reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), reqFile);

those path :

enter image description here

EDIT 3 :

Now I have a permission denied :

enter image description here

ShikaZero
  • 23
  • 7
  • 1
    You already have the uri. No need of cursor manipulation here. Check this link https://stackoverflow.com/questions/2975197/convert-file-uri-to-file-in-android – Vivek Mishra Dec 05 '18 at 10:39

2 Answers2

0

As you are following a tutorial you may visit retrofit tutorial of Future Studio here: https://futurestud.io/tutorials/retrofit-getting-started-and-android-client, the best place to learn retrofit, and for exact your case visit this video

Bashir Fardoush
  • 184
  • 1
  • 10
0

After some investigations, I found the solution of the problem and I post it here for the newcomers on retrofit because there is a lot of misunderstood on internet of what I saw.

First of all I changed the listener as below:

          btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(galleryIntent, PICK_IMAGE);
            }
        });

We need to keep the cursor (the opposite of vivek mishra said) and we have to add a user request confirmation. I put all my code below and it works really well with android 8.0.

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == PICK_IMAGE && resultCode == RESULT_OK && data != null && data.getData() !=null) {

        if (ContextCompat.checkSelfPermission(this.getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            // Permission is not granted

            ActivityCompat.requestPermissions(PrestationsActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    REQUEST_EXTERNAL_STORAGE);
        }

        Uri selectedImage = data.getData();
        String[] filePath = {MediaStore.Images.Media.DATA};
        Cursor c = getContentResolver().query(selectedImage, filePath,null, null, null);
        c.moveToFirst();
        int columnIndex = c.getColumnIndex(filePath[0]);
        String FilePathStr = c.getString(columnIndex);
        c.close();


        File file = new File(FilePathStr);
        RequestBody reqFile = RequestBody.create(MediaType.parse(getContentResolver().getType(selectedImage)), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), reqFile);

        retrofit2.Call<okhttp3.ResponseBody> req = service.postImage(body);
        //Call<ResponseBody> req = service.postImage(body);
        req.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Log.i("response image OK",response.body().toString());
                Log.i("response image Type",response.body().contentType().toString());
                Log.i("response image Message",response.message());
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                t.printStackTrace();
            }
        });

        }
}

Hope it helps some devs.

ShikaZero
  • 23
  • 7