Android Retrofit 2 Upload file to Server Tutotial
In previous tutorial, I had been tell you how to use retrofit 2 to retrieve data from the REST API. Able to let the user upload file to the server such as image is also a necessary requirement to create a mobile application. Multipart form-data is built for uploading the file to the server transmit by name/value pair, each pair represents by part. The difference with x-www-form-unlencoded send giant string query to the server, so its unable to upload the file. In a current tutorial, I will let you know how to use android retrofit 2 upload file to the server so you can get the image from the server.
Creating a New Project
1. Open Android Studio IDE in your computer.
2. Create a new project and Edit the Application name to “RetrofitUploadFileExample”.
(Optional) You can edit the company domain or select the suitable location for current project tutorial. Then click next button to proceed.
3. Select Minimum SDK (API 15:Android 4.0.3 (IceCreamSandwich). I choose the API 15 because many android devices currently are support more than API 15. Click Next button.
4. Choose “Empty Activity” and Click Next button
5. Lastly, press finish button.
Add new dependencies
Add dependencies for picasso and retrofit library. Picasso is to load the image in the application, so you don’t need to write huge code to load the image.
compile 'com.android.support:design:24.2.0' compile 'com.squareup.picasso:picasso:2.5.2' compile 'com.squareup.retrofit2:retrofit:2.0.2' compile 'com.squareup.retrofit2:converter-gson:2.0.2'
Add new permissions access
Go to your manifest file and Add the internet, access network and read external storage permissions in your application so it able to use them in your app.
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Create a new xml layout for content
This layout is the content of your main layout, i add two button which is upload and pick image.
<?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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.questdot.retrofituploadfileexample.MainActivity" tools:showIn="@layout/activity_main"> <ImageView android:id="@+id/imageView" android:adjustViewBounds="true" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/fab" android:layout_above="@+id/btnPick" /> <Button android:text="Upload" android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> <Button android:text="Pick Image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:onClick="showImagePopup" android:layout_centerHorizontal="true" android:id="@+id/btnPick" /> </RelativeLayout>
Edit mainactivity.xml layout
Go to your mainactivity layout and edit to the following source code.
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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:fitsSystemWindows="true" android:id="@+id/parentView" tools:context=".MainActivity" > <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> </android.support.design.widget.CoordinatorLayout>
Create a new Interface
Right click your package name and create a new class. After that, change your class to interface and edit to the source code below.
public interface FileApi { @Multipart @POST("upload.php") Call<Respond> uploadImage(@Part MultipartBody.Part file); }
Create a new Modal Class
Add a new class in your package and this class is get the respond of the url.
public class Respond { private String message; private Boolean error; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Boolean getError() { return error; } public void setError(Boolean error) { this.error = error; } }
Create a PHP file to upload
Add a new php file in your PHP IDE and it will perform upload file to the path you specify in the php code such as /image for the example below.
<?php $file_path = "image/"; if (isset($_FILES['uploaded_file']['name'])) { $file_path = $file_path . basename( $_FILES['uploaded_file']['name']); if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path)) { $response['message'] = 'File uploaded successfully'; $response['error'] = false; } else{ $response['error'] = true; $response['message'] = 'Could not move the file'; } } else { $response['error'] = true; $response['message'] = 'Not received any file'; } echo json_encode($response); ?>
Create a new RetroClient class
You need to enter your server URL in the ROOT_URL field so it will able to work later. The Upload file process is performed by the server.
public class RetroClient { private static final String ROOT_URL = "http://192.168.0.111/upload-file/"; public RetroClient() { } private static Retrofit getRetroClient() { return new Retrofit.Builder() .baseUrl(ROOT_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static FileApi getApiService() { return getRetroClient().create(FileApi.class); } }
Edit MainActivity.class
Edit your mainactivity class, this class to perform retrofit call from the URL. Copy and paste it to your own file. Android 6.0 and above required Read External and Write External Storage permission to access.
public class MainActivity extends AppCompatActivity { private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; ImageView imageView; String imagePath; Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); verifyStoragePermissions(MainActivity.this); toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); imageView = (ImageView) findViewById(R.id.imageView); Button button = (Button) findViewById(R.id.fab); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(imagePath!=null) uploadImage(); else Toast.makeText(getApplicationContext(),"Please select image", Toast.LENGTH_LONG).show(); } }); } private void uploadImage() { final ProgressDialog progressDialog; progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setMessage("loading..."); progressDialog.show(); FileApi service = RetroClient.getApiService(); File file = new File(imagePath); RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); MultipartBody.Part body = MultipartBody.Part.createFormData("uploaded_file", file.getName(), requestFile); Call<Respond> resultCall = service.uploadImage(body); resultCall.enqueue(new Callback<Respond>() { @Override public void onResponse(Call<Respond> call, Response<Respond> response) { progressDialog.dismiss(); // Response Success or Fail if (response.isSuccessful()) { if (response.body().getError()==true) Toast.makeText(getApplicationContext(),response.body().getMessage(),Toast.LENGTH_LONG).show(); else Toast.makeText(getApplicationContext(),response.body().getMessage(),Toast.LENGTH_LONG).show(); } else { Toast.makeText(getApplicationContext(),response.body().getMessage(),Toast.LENGTH_LONG).show(); } imageView.setImageDrawable(null); imagePath = null; } @Override public void onFailure(Call<Respond> call, Throwable t) { progressDialog.dismiss(); } }); } public void showImagePopup(View view) { final Intent galleryIntent = new Intent(); galleryIntent.setType("image/*"); galleryIntent.setAction(Intent.ACTION_PICK); final Intent chooserIntent = Intent.createChooser(galleryIntent, "Choose image"); startActivityForResult(chooserIntent, 100); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && requestCode == 100) { if (data == null) { Toast.makeText(getApplicationContext(),"Unable to pick image",Toast.LENGTH_LONG).show(); return; } Uri imageUri = data.getData(); imageView.setImageURI(imageUri); /* Uri selectedImageUri = data.getData(); String[] filePathColumn = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(selectedImageUri, filePathColumn, null, null, null); if (cursor != null) { cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]);*/ imagePath = getRealPathFromURI(imageUri); // Picasso.with(getApplicationContext()).load(new File(imagePath)) // .into(imageView); // Toast.makeText(getApplicationContext(),"Please reselect your image",Toast.LENGTH_LONG).show(); /* cursor.close(); } else { Toast.makeText(getApplicationContext(),"Unable to load image",Toast.LENGTH_LONG).show(); }*/ } } private String getRealPathFromURI(Uri contentUri) { String[] proj = { MediaStore.Images.Media.DATA }; CursorLoader loader = new CursorLoader(getApplicationContext(), contentUri, proj, null, null, null); Cursor cursor = loader.loadInBackground(); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String result = cursor.getString(column_index); cursor.close(); return result; } public static void verifyStoragePermissions(Activity activity) { // Check if we have write permission int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user ActivityCompat.requestPermissions( activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE ); } } }
Run Your Project
Finally, you can try the form data call in your android project, if success, it will automatically add the image in your server.
(Android Retrofit 2 Upload file to Server)
Source Code
Android
PHP
Hi Kristofer, I am not able to download your code. Is this app available on github
I’ve been exploring for a little bit for any high quality articles or weblog posts on this kind
of house . Exploring in Yahoo I finally stumbled upon this website.
Reading tjis info So i’m satisfied to show that I have an incredibly
just right uncanny feeling I discovered just what I needed.
I most undoubtedly will make sure to don?t omit this web site and provides it a look regularly.
Thanks for finally talkig about >Android Retrofit 2 Upload file to
Server Tutotial – QuestDot <Liked it!
Thank you forr any other excellent post. The place else could anybody get that kind of injformation iin such a perfect means of writing?
I have a presentation nex week, and I’m at the look ffor such information.
I was recommended this web site via my cousin. I’m not sure whether or not this put up is wriotten via him as nobody else know such specified approximatly my trouble.
You’re amazing! Thanks!
Wonderful gkods from you, man. I’ve undersstand ylur stuff previous too and you’re just too magnificent.
I actually like what you’veacquired here, certainly like what you are
stating andd the way in which you say it. You make
it entertaining and you still take care of to keep it sensible.
I can not wait to read much more from you. This is really a tremendous webb site.
It’s iin reality a nice and useful piece of information. I am happy that yyou simply shared this helpful info with us.
Please stay us informed like this. Thajk you for sharing.
;