Android MultiPart Image and Files Upload using Retrofit 2

1.  We need to add dependencies for the Retrofit and Retrofit GSON converter library.

implementation \'com.squareup.retrofit2:retrofit:2.3.0\'
implementation \'com.squareup.retrofit2:converter-gson:2.3.0\'

2. We need to add Internet and Storage permission in our AndroidManifest.xml file.

<uses-permission android:name=\"android.permission.INTERNET\"/>
<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>

3. Our main layout has included which has two buttons one upload image and set into the imageView and as well as the image path sends to the database and then submit for sending image and text to the server.

\"\"
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"
    xmlns:app=\"http://schemas.android.com/apk/res-auto\"
    xmlns:tools=\"http://schemas.android.com/tools\"
    android:layout_width=\"match_parent\"
    android:layout_height=\"match_parent\"
    android:orientation=\"vertical\"
    android:focusableInTouchMode=\"true\"
    android:focusable=\"true\"
    tools:context=\".PostRecipesActivity\">

    <ScrollView
        android:layout_width=\"match_parent\"
        android:layout_height=\"match_parent\"
        android:scrollbars=\"none\"
        android:layout_margin=\"15dp\">
   <LinearLayout
        android:layout_width=\"match_parent\"
        android:layout_height=\"match_parent\"
        android:orientation=\"vertical\">

   <TextView
            android:layout_width=\"wrap_content\"
            android:layout_height=\"wrap_content\"
            android:text=\"ADD NEW RECIPES\"
            android:textSize=\"10pt\"
            android:textColor=\"@color/colorPrimaryDark\"/>

          <TextView
            android:layout_width=\"match_parent\"
            android:layout_height=\"1dp\"
            android:background=\"@color/Grey\"
            android:layout_marginTop=\"10dp\"/>
         <LinearLayout
            android:layout_width=\"match_parent\"
            android:layout_height=\"wrap_content\"
            android:orientation=\"vertical\"
            android:background=\"@drawable/customborder\"
            android:layout_marginTop=\"20dp\">
         <LinearLayout
            android:layout_width=\"match_parent\"
            android:layout_height=\"300dp\"
            android:orientation=\"vertical\"
            android:gravity=\"center\"
            android:background=\"#E0E0E0\">
           <ImageView
               android:id=\"@+id/imageView\"
               android:layout_width=\"match_parent\"
               android:layout_height=\"match_parent\"
               android:scaleType=\"fitXY\"
               android:src=\"@drawable/recipe_icon\"/>
         </LinearLayout>
           <TextView
                android:layout_width=\"match_parent\"
                android:layout_height=\"1dp\"
                android:background=\"@color/colorDarkYellow\"
                android:layout_marginBottom=\"50dp\"/>
       </LinearLayout>
      <LinearLayout
            android:id=\"@+id/layout_browsefile\"
            android:layout_width=\"match_parent\"
            android:layout_height=\"wrap_content\"
            android:orientation=\"vertical\"
            android:gravity=\"center\"
            android:background=\"@color/colorDarkYellow\"
            android:layout_marginTop=\"15dp\">
        <TextView
            android:layout_width=\"wrap_content\"
            android:layout_height=\"wrap_content\"
            android:text=\"BROWSE FILE\"
            android:textColor=\"@color/colorWhite\"
            android:textSize=\"10pt\"
            android:textStyle=\"bold\"
            android:padding=\"10dp\"/>
        </LinearLayout>
        <TextView
            android:layout_width=\"wrap_content\"
            android:layout_height=\"wrap_content\"
            android:text=\"Enter The Recipe Title\"
            android:textSize=\"8pt\"
            android:textColor=\"@color/colorPrimaryDark\"
            android:layout_marginTop=\"30dp\"/>
        <EditText
            android:id=\"@+id/recipe_name\"
            android:layout_width=\"match_parent\"
            android:layout_height=\"wrap_content\"
            android:hint=\"Full Name\"
            android:padding=\"10dp\"
            android:layout_marginTop=\"5dp\"
            android:background=\"@drawable/customborder\"/>
         <TextView
            android:layout_width=\"wrap_content\"
            android:layout_height=\"wrap_content\"
            android:text=\"Add Description\"
            android:textSize=\"8pt\"
            android:textColor=\"@color/colorPrimaryDark\"
            android:layout_marginTop=\"10dp\"/>
         <EditText
            android:id=\"@+id/recipe_description\"
            android:layout_width=\"match_parent\"
            android:layout_height=\"100dp\"
            android:gravity=\"start\"
            android:inputType=\"textMultiLine\"
            android:hint=\"Enter Description here...\"
            android:padding=\"10dp\"
            android:layout_marginTop=\"5dp\"
            android:background=\"@drawable/customborder\"/>
          <LinearLayout
            android:id=\"@+id/submit\"
            android:layout_width=\"match_parent\"
            android:layout_height=\"wrap_content\"
            android:orientation=\"vertical\"
            android:gravity=\"center\"
            android:background=\"@color/colorDarkYellow\"
            android:layout_marginTop=\"20dp\"
            android:layout_marginBottom=\"20dp\">
             <TextView
                android:layout_width=\"wrap_content\"
                android:layout_height=\"wrap_content\"
                android:text=\"SUBMIT\"
                android:textColor=\"@color/colorWhite\"
                android:textSize=\"10pt\"
                android:textStyle=\"bold\"
                android:padding=\"10dp\"/>
        </LinearLayout>
 </LinearLayout>
    </ScrollView>
</LinearLayout>

4. Now we are creating a Model ServerResponse .java class with message fields.

public class ServerResponse{

    @SerializedName(\"success\")
    boolean success;
    @SerializedName(\"message\")
    String message;   

    String getMessage() {
        return message;
    }

   boolean getSuccess() {
        return success;
    }

}

5. Next we have defined a Retrofit interface class with Multipart as the type to upload the image.

public interface ApiConfig {
static String BASE_URL=\"https://your base url/\";
    @Multipart
    @POST(\"/images/upload\") 
    Call<ServerResponse> uploadImage(@Part MultipartBody.Part image);
   or 
   @POST
   Call<Object> uploadImage(@Url String url, @Part MultipartBody.Part image);
}

***@POST usually use to join base url and after base url the extend url join here. We can write here as well as you can parse url from main java class also. 

6. Create MainActivity.java and Paste the following lines

public class MainActivity extends AppCompatActivity {  

    ImageView imageView;
  
    LinearLayout layout_browsefile;
    Bitmap bitmap;
    private static final int REQUEST_CODE_READ_EXTERNAL_PERMISSION = 2;
    String image_name;
    String imagePath;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      
        imageView = (ImageView) findViewById(R.id.imageView);
    
        layout_browsefile = (LinearLayout) findViewById(R.id.layout_browsefile);
        
        
         layout_browsefile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent galleryIntent = new Intent(Intent.ACTION_PICK,
                            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    startActivityForResult(galleryIntent, 0);
                }
            });

      }
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        try {
            // When an Image is picked
            if (requestCode == 0 && resultCode == RESULT_OK && null != data) {
                // Get the Image from data
                Uri selectedImage = data.getData();
                String selectedFilePath = FilePath.getPath(this,selectedImage);
                String[] filePathColumn = {MediaStore.Images.Media.DATA};
                Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
                assert cursor != null;
                cursor.moveToFirst();
                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                imagePath = cursor.getString(columnIndex);
//                str1.setText(mediaPath);
                // Set the Image in ImageView for Previewing the Media
                imageView.setImageBitmap(BitmapFactory.decodeFile(selectedFilePath));
                cursor.close();
                uploadImage();
            } // When an Video is picked
        } catch (Exception e) {
            Toast.makeText(this, \"Something went wrong\", Toast.LENGTH_LONG).show();
        }
    }
    }
  private void uploadImage() {
        final ProgressDialog pd = new ProgressDialog(this);
        pd.setMessage(\"Uploading Image...\");
        pd.setCancelable(false);
        pd.show();
        //creating a file
        File file = new File(imagePath);
        //creating request body for file
        RequestBody requestFile = RequestBody.create(MediaType.parse(\"multipart/form-data\"), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData(\"uploaded_file\", file.getName(), requestFile);
//        RequestBody descBody = RequestBody.create(MediaType.parse(\"text/plain\"), desc);
        Log.e(\"requestFile\",requestFile.toString());
        //The gson builder
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();
        //creating retrofit object
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiConfig.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(getUnsafeOkHttpClient())
                .build();
        //creating our api
        ApiConfig api = retrofit.create(ApiConfig.class);
        //creating a call and calling the upload image method
        Call call = api.editUser(\"Your URL\",body);
        //finally performing the call
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, retrofit2.Response response) {
                Log.e(\"response\",new Gson().toJson(response.body()));
                    try {
                       
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                pd.dismiss();
            }
            @Override
            public void onFailure(Call call, Throwable t) {
//                Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
                pd.dismiss();
                Log.e(\"response_failure\",t.toString());
            }
        });
    }
   
}

***In this process you can upload not only image but any kind of files to the server.