Android Upload Image To Server Using Retrofit Example PHP MySQL

android login registration using retrofit, android upload image to server using retrofit, android retrofit multipart upload image, android custom dialog with listview, android custom dialog with recyclerview

Hello and welcome to Android Upload Image To Server Using Retrofit Example.

In this tutorial, you will learn how to upload image using retrofit android to PHP MySQL server.

Retrofit will take care about http calls and data transaction between android and remote server.

For using multipart with retrofit you can check out Android Retrofit Multipart Image upload Example.

We need to write one PHP script that will accept the image into Base64String format.

See the Video

JSON from Server

See the below image. It is the json we are getting from the server after successful upload of image.

Android Upload Image To Server Using Retrofit
JSON after image has reached server

PHP Section

Make a new file and add the below code lines in it. Name of this file should be uploadRetrofit.php

<?php

include_once("config.php");

    //$json = json_decode(file_get_contents('php://input'),true);
    
    
   
    $name = $_POST["name"]; //within square bracket should be same as Utils.imageName & Utils.image
   
     $image = $_POST["image"];
 //$image = substr(explode(";",$image)[1], 7);
    $response = array();
 
    $decodedImage = base64_decode("$image");
 
    $return = file_put_contents("uploadedFiles/".$name.".JPG", $decodedImage);
 
    if($return !== false){
        $response['success'] = 1;
        $response['message'] = "Image Uploaded Successfully with Retrofit";
    }else{
        $response['success'] = 0;
        $response['message'] = "Image Uploaded Failed";
    }
 
    echo json_encode($response);
?>

Code for config.php is like the following

<?php
$host="localhost";
$user="your username";
$password="your password";
$db = "your db name";

$con = mysqli_connect($host,$user,$password,$db);

// Check connection
if (mysqli_connect_errno())
  {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  }else{  //echo "Connect"; 
  
   
   }

?>

Now create a new project in android studio.

Step 1. Basic Permissions

In this tutorial we need some permissions and also need to add three dependencies in gradle file.

So add the following lines in ANDROIDMANIFEST.xml file.

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

First line is about internet permission and other two are for read and to write files on external storage.

Now in your build.gradle(Module: app) file, add the below lines

 implementation 'com.karumi:dexter:5.0.0'
 implementation 'com.squareup.retrofit2:retrofit:2.5.0'
 implementation 'com.squareup.retrofit2:converter-scalars:2.5.0'

Here, first line will give us the right to use the dexter library in our project. This library will help us to simplify the runtime permissions process.

Second line will enable us to use retrofit library and third one will use scalar to convert JSON response into string format.

Step 2. Useful Interface

Make a new java class and give it a name like ImageInterface.java

Source code for ImageInterface.java is as the following

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface ImageInterface {

    String IMAGEURL = "https://demonuts.com/Demonuts/JsonTest/Tennis/";
    @FormUrlEncoded
    @POST("uploadRetrofit.php")
    Call<String> getUserLogin(
            @Field("name") String name,
            @Field("image") String image
    );

}

A string variable is containing the URL of the web service.

@POST(“uploadRetrofit.php”) is the name of the php script that we have already created.

 getUserLogin() method have two parameters. First one is the name of the image and second one is the image it self into Base64 String format.

Step 3. Final Code Lines

Now we are just left with activity_main.xml and MainActivity.java file

In your activity_main.xml file, write down the below code block

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#18cae6"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Select Image and upload to server" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Below image is uploaded to server using Retrofit"
        android:layout_marginTop="5dp"
        android:textSize="23sp"
        android:gravity="center"
        android:textColor="#000"/>

    <ImageView
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY"
        android:src="@mipmap/ic_launcher"
        android:id="@+id/iv"/>

</LinearLayout>

Above holds one Button, one text view and one image view.

When the user clicks the button, system will show him all the images of galley, from where he need to select any one.

Text view is saying like “below image is uploaded using retrofit.”

We will set the image in the image view which we will upload on the php mysql server.

Now in MainActivity.java file, fill the following code structure

import android.Manifest;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.DexterError;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.PermissionRequestErrorListener;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class MainActivity extends AppCompatActivity {

    private Button btn;
    private ImageView imageView;

    private final int GALLERY = 1;

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

        requestPermissions();

        btn = findViewById(R.id.btn);
        imageView = (ImageView) findViewById(R.id.iv);

        btn.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, GALLERY);
            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == this.RESULT_CANCELED) {
            return;
        }
        if (requestCode == GALLERY) {
            if (data != null) {
                Uri contentURI = data.getData();
                try {

                    Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), contentURI);
                    imageView.setImageBitmap(bitmap);

                     uploadImage(bitmap);

                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this, "Failed!", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    private void uploadImage(Bitmap bitmap){

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
        String encodedImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
        String imgname = String.valueOf(Calendar.getInstance().getTimeInMillis());

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ImageInterface.IMAGEURL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

        ImageInterface api = retrofit.create(ImageInterface.class);

        Log.d("helloo",encodedImage +"   >>"+imgname);
        Log.d("imggggg","   >>"+imgname);
        Call<String> call = api.getUserLogin(imgname,encodedImage);

        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.i("Responsestring", response.body().toString());
                //Toast.makeText()
                if (response.isSuccessful()) {
                    if (response.body() != null) {
                        Log.i("onSuccessimg", response.body().toString());

                        Toast.makeText(MainActivity.this, "Image Uploaded Successfully!!", Toast.LENGTH_SHORT).show();

                    } else {
                        Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
                    }
                }
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {

            }
        });
    }


    private void  requestPermissions(){
        Dexter.withActivity(this)
                .withPermissions(

                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_EXTERNAL_STORAGE)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        // check if all permissions are granted
                        if (report.areAllPermissionsGranted()) {
                            Toast.makeText(getApplicationContext(), "All permissions are granted by user!", Toast.LENGTH_SHORT).show();
                        }

                        // check for permanent denial of any permission
                        if (report.isAnyPermissionPermanentlyDenied()) {
                            // show alert dialog navigating to Settings

                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                }).
                withErrorListener(new PermissionRequestErrorListener() {
                    @Override
                    public void onError(DexterError error) {
                        Toast.makeText(getApplicationContext(), "Some Error! ", Toast.LENGTH_SHORT).show();
                    }
                })
                .onSameThread()
                .check();
    }


}

Looking at above code

In the onCreate() method, first of all compiler will call requestPermissions() method.

Below are the writings for requestPermissions() method.

 private void  requestPermissions(){
        Dexter.withActivity(this)
                .withPermissions(

                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_EXTERNAL_STORAGE)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        // check if all permissions are granted
                        if (report.areAllPermissionsGranted()) {
                            Toast.makeText(getApplicationContext(), "All permissions are granted by user!", Toast.LENGTH_SHORT).show();
                        }

                        // check for permanent denial of any permission
                        if (report.isAnyPermissionPermanentlyDenied()) {
                            // show alert dialog navigating to Settings

                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                }).
                withErrorListener(new PermissionRequestErrorListener() {
                    @Override
                    public void onError(DexterError error) {
                        Toast.makeText(getApplicationContext(), "Some Error! ", Toast.LENGTH_SHORT).show();
                    }
                })
                .onSameThread()
                .check();
    }

This method will ask for runtime permissions to the user. It will ask for read and write permissions.

We have also added internet permission in manifest file, but it is normal permission, so need to ask it here again.

Now, compiler will again go to onCreate() method. Below code will be run when the user clicks the button.

 btn.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, GALLERY);
            }
        });

Compiler will create one intent when the user clicks the button. This intent would be for ACTION_PICK. Meaning is that it will allow user to select image.

When the user selects the image, compiler will call onActivityResult() method.

Following is the code lines for onActivityResult() method,

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == this.RESULT_CANCELED) {
            return;
        }
        if (requestCode == GALLERY) {
            if (data != null) {
                Uri contentURI = data.getData();
                try {

                    Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), contentURI);
                    imageView.setImageBitmap(bitmap);

                     uploadImage(bitmap);

                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this, "Failed!", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

Compiler will first get the URI of the image from the selected data.

Then it will create the bitmap of the image.

After this, it will set the bitmap into the image view.

Finally, it will call the uploadImage() method.

Below is the code snippet for uploadImage() method.

  private void uploadImage(Bitmap bitmap){

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
        String encodedImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
        String imgname = String.valueOf(Calendar.getInstance().getTimeInMillis());

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ImageInterface.IMAGEURL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

        ImageInterface api = retrofit.create(ImageInterface.class);

        Log.d("helloo",encodedImage +"   >>"+imgname);
        Log.d("imggggg","   >>"+imgname);
        Call<String> call = api.getUserLogin(imgname,encodedImage);

        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.i("Responsestring", response.body().toString());
                //Toast.makeText()
                if (response.isSuccessful()) {
                    if (response.body() != null) {
                        Log.i("onSuccessimg", response.body().toString());

                        Toast.makeText(MainActivity.this, "Image Uploaded Successfully!!", Toast.LENGTH_SHORT).show();

                    } else {
                        Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
                    }
                }
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {

            }
        });
    }

Compiler will get the bitmap into the parameter of this method.

Using this bitmap, it will convert the image into the Base64 string format. A string variable “encodedImage” holds this base64 value.

A variable imgname will have the value of current millisecond as the name of the image in string format.

After this, compiler will create the object of the Retrofit class. Here, .baseUrl(Imagenterface.IMGURL) will give the URL to the retrofit.

api.getUserLogin(imgname, encodedImage) will make the http call to the remote server.

When the compiler gets the JSON response, it will call the onResponse() method.

Inside  onResponse() method, system will show one toast.

Download code for android upload image to server using retrofit

Click the below link.

https://github.com/demonuts/android-retrofit-upload-image-to-server