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