Step by step simple example guide how to upload an image using Android Retrofit (Multipart-FormData)

 

 

Project source code link is available at the end the post.

 

What is Retrofit ?

We all know that doing HTTP efficiently makes your stuff load faster and saves bandwidth in mobile platforms. Retrofit is an open source library for Android and Java platforms to handle Http request asynchronously and synchronously.  Basically is a type-safe HTTP client who can handle all kind of network activities such as requests and responses.

 

let’s move to the next step.

 

Webservice for the Photo uploading

I wrote a simple web service request handler using php. I have a confident that if your  client side code is working for this web service, It should work for other web services too. Don’t use this code in your production because we should write proper web service in order to use in production level applications.

 

[code]

<?php

 

<?phperror_reporting(E_ALL);

ini_set(‘display_errors’, ‘off’); //turn on if you want to see the server errors and notifications.

$target_dir = “uploads/”;

$filename = $_POST[‘filename’];

$target_file = $target_dir . $filename;

if (file_exists($_FILES[“fileToUpload”][“tmp_name”])) {

if (move_uploaded_file($_FILES[“fileToUpload”][“tmp_name”], $target_file)) {

echo json_encode(array(“message” => “Upload Success.!”));

} else {

echo json_encode(array(“message” => “Upload Failed.!”));

}

} else {

echo json_encode(array(“message” => “No Files Found.!”));

}

 

?>

 

[/code]

 

I am passing two fields to the Webserive,

  1. File Name (Type : String).
  2. Image File (Type : File)

 

 

Test the Webservice using POSTMAN.

Postman is really a handy tool to test the web services. You can test the web service using their free tier. Download their PC Version or you can install Chrome plugin.  Download it and play now.!

 

 

 

 

Don’t forget to set content-type to “application/x-www-form-urlencoded” in headers section, when you test the web service via PostMan.

 

 

Create New Android Project

Create a simple Android Studio project and copy the following files. Don’t forget to sync the Gradle Build  file.

 

 

Add the Retrofit Libraries and Necessary classes to the project.

 

Make sure to add the latest released version to the [code]build.gradle[/code] file

 

This is my app module [code]build.gradle[/code] file

[code]

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "com.appsgit.retrofitexample"
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'

    // Retrofit Version is really really important. here its retrofit2 and 2.3.0 as of today
    compile 'com.squareup.retrofit2:retrofit:2.3.0'

    compile 'com.google.code.gson:gson:2.8.1'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'

    compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
}

[/code]

 

 

Create [code]ApiClient.java[/code] file and [code]ApiClientBuilder.java[/code] classes accordingly.

[code]

//ApiClient.java
package com.appsgit.retrofitexample.jsonclient;

import com.appsgit.retrofitexample.jsonclient.model.UserProfile;

import java.io.File;

import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;

/**
 * Created on 10/15/17.
 */

public interface ApiClient {

    @Multipart
    @POST("/appsgit-service/fileupload.php")
    Call<UserProfile> uploadImage(@Part("filename") RequestBody fileName, @Part MultipartBody.Part file);
}

[/code]

 

and the ApiClientBuilder class create the retrofit object. ApiClient builder class contains several important implementations. check the thoroughly.

[code]

//ApiClientBuilder.java
package com.appsgit.retrofitexample.jsonclient;

import com.google.gson.GsonBuilder;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiClientBuilder {

    public static final String BASE_URL = "https://appsgit.com";

    private static Retrofit retrofit = null;

    public static OkHttpClient.Builder httpClient;

    public static Retrofit getClient(String baseUrl) {

        //http logging interceptor will give us the information about web service call reqponse.
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);

        httpClient = new OkHttpClient.Builder();

        httpClient.readTimeout(60, TimeUnit.SECONDS);

        httpClient.connectTimeout(60, TimeUnit.SECONDS);

        httpClient.addInterceptor(logging);

        //We should add headers for the request.
        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
                Request original = chain.request();

                Request request = original.newBuilder()
                        .header("Content-Type", "application/x-www-form-urlencoded")
                        .method(original.method(), original.body())
                        .build();

                return chain.proceed(request);
            }
        });

        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()))
                .client(httpClient.build())
                .build();

        return retrofit;
    }


    public static ApiClient getMGClient() {

        return getClient(BASE_URL).create(ApiClient.class);
    }

}

[/code]

 

 

Create a Model class called [code]UserProfile.java[/code]

 

[code]

package com.appsgit.retrofitexample.jsonclient.model;

import java.io.File;

/**
 * Created on 10/16/17.
 */

public class UserProfile {

    String imageName;

    File image;

    String message;


    public String getImageName() {
        return imageName;
    }

    public UserProfile setImageName(String imageName) {
        this.imageName = imageName;
        return this;
    }

    public File getImage() {
        return image;
    }

    public UserProfile setImage(File image) {
        this.image = image;
        return this;
    }
}

[/code]

 

 

Create a service class to handle the Webservice.

 

[code]

package com.appsgit.retrofitexample.jsonclient.services;

import android.content.Context;

import com.appsgit.retrofitexample.jsonclient.ApiClient;
import com.appsgit.retrofitexample.jsonclient.ApiClientBuilder;
import com.appsgit.retrofitexample.jsonclient.model.UserProfile;
import com.appsgit.retrofitexample.utils.FileUtils;

import java.io.File;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;


public class UserService {

    String BASE_URL = "";

    public void saveUserImage(Context context, String photoName, File imageFile, Callback<UserProfile> callback) {

        // create upload service client
        ApiClient service = ApiClientBuilder.getMGClient();

        RequestBody requestFile =
                RequestBody.create(MediaType.parse(FileUtils.getFileExtension(imageFile.getAbsolutePath())), imageFile);

        // MultipartBody.Part is used to send also the actual file name
        MultipartBody.Part body =
                MultipartBody.Part.createFormData("fileToUpload", imageFile.getName(), requestFile);

        // add another part within the multipart request
        String imageName = photoName;
        RequestBody description =
                RequestBody.create(
                        okhttp3.MultipartBody.FORM, imageName);

        Call<UserProfile> result =  service.uploadImage(description, body);

        result.enqueue(callback);

    }

}

[/code]

 

Now call the [code]saveUserImage()[/code] method in your Main Activity.

 

[code]

service.saveUserImage(this, photnName, new File(mCurrentPhotoPath), new Callback<UserProfile>() {
    @Override
    public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
        showMessage("Image successfully uploaded to server.!");
    }

    @Override
    public void onFailure(Call<UserProfile> call, Throwable t) {
        showMessage("Upload Failed.!");
    }
});

[/code]

 

 

the [code]MainActivity.java[/code] is here,

[code]

package com.appsgit.retrofitexample.activities;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.appsgit.retrofitexample.R;
import com.appsgit.retrofitexample.jsonclient.model.UserProfile;
import com.appsgit.retrofitexample.jsonclient.services.UserService;
import com.appsgit.retrofitexample.utils.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {

    public static String TAG = MainActivity.class.getSimpleName();
    ImageView imageView;
    static final int REQUEST_IMAGE_CAPTURE = 1000;

    UserService service;

    String mCurrentPhotoPath;

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

        service = new UserService();

        if (getSupportActionBar() != null) {
            getSupportActionBar().hide();
        }

        imageView = (ImageView) findViewById(R.id.imageView);
    }

    public void selectImage(View view) {
        try {

            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

            // Create the File where the photo should go
            File photoFile = null;

            try {

                photoFile = FileUtils.createImageFile(this);
                mCurrentPhotoPath = photoFile.getAbsolutePath();

            } catch (IOException ex) {
                ex.printStackTrace();
            }

            if (photoFile != null) {

                //getUriForFile, which returns a content:// URI. For more recent apps targeting Android 7.0 (API level 24) and higher,
                //don't forget to change your package name
                Uri photoURI = FileProvider.getUriForFile(this,
                        "com.appsgit.retrofitexample.fileprovider",
                        photoFile);

                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
            }


        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void uploadImage(View view) {
        try {
            Log.d(TAG, "uploadImage: mCurrentPhotoPath " + mCurrentPhotoPath);

            if (mCurrentPhotoPath != null && !mCurrentPhotoPath.equals("")) {

                String photnName = "testimage.jpg";

                service.saveUserImage(this, photnName, new File(mCurrentPhotoPath), new Callback<UserProfile>() {
                    @Override
                    public void onResponse(Call<UserProfile> call, Response<UserProfile> response) {
                        showMessage("Image successfully uploaded to server.!");
                    }

                    @Override
                    public void onFailure(Call<UserProfile> call, Throwable t) {
                        showMessage("Upload Failed.!");
                    }
                });
            } else {
                showMessage("No Image found to be uploaded.");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, "onActivityResult: requestCode " + requestCode);
        Log.d(TAG, "onActivityResult: resultCode == RESULT_OK ? " + (resultCode == RESULT_OK));
        if (REQUEST_IMAGE_CAPTURE == requestCode && resultCode == RESULT_OK) {

           try {

               Bitmap imageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
               imageView.setImageBitmap(imageBitmap);

           } catch (Exception ex) {
               ex.printStackTrace();
           }
        }
    }

    public void showMessage(String message) {
        try {
            AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
            alertDialog.setTitle("Message");
            alertDialog.setMessage(message);
            alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            alertDialog.show();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

[/code]

 

 

and the Front UI code is here

[code]

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context="com.appsgit.retrofitexample.activities.MainActivity">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/buttonWrapper"
        android:layout_alignParentStart="true" />

    <LinearLayout
        android:id="@+id/buttonWrapper"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:orientation="vertical">


        <Button
            android:id="@+id/selectButton"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:text="Select Image"
            android:onClick="selectImage"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:id="@+id/uploadButton"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_margin="2dp"
            android:text="Upload Image"
            android:onClick="uploadImage" />


    </LinearLayout>

</RelativeLayout>

[/code]

 

 

Project Git Repo is here

If you have any issues testing or running this project, please let me know.

 

 

cheers.!

 

Add a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.