Overview
In this tutorial We will show you how to create a simple Android application for User CREATE, READ, UPDATE, DELETE with Android Studio. This app will send the CRUD requests to the RESTFul Web Service using Retrofit 2 HTTP Client.Follow the steps mentioned below to develop this application.
Video Tutorial
Project Structure
Review CRUD RESTFul Webservices
The following images show the creation of CRUD API using RESTFul Webservices call in Postman.Hostname: localhost(My LAN IP Address: 169.254.35.189)
GET All User API
Request Method: GET
URL: http://169.254.35.189:8080/demo/user/
POST Add User API
Request Method: POST
URL: http://169.254.35.189:8080/demo/add/
PUT Update User API
Request Method: PUT
URL: http://169.254.35.189:8080/demo/update/3
DELETE User API
Request Method: DELETE
URL: http://169.254.35.189:8080/demo/delete/3
Create Android Project with Android Studio
Open Android Studio create a new project with an empty activity called MainActivity. Find the steps to create the Android Project.Add Gradle dependencies and permission
Add the following dependencies to your build.gradle file.
implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'com.google.code.gson:gson:2.6.1'build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 26 defaultConfig { applicationId "com.jackrutorial.androidretrofit2crud" 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 { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'com.google.code.gson:gson:2.6.1' }Add the permission to access internet in the AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET" />AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jackrutorial.androidretrofit2crud"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".UserActivity" android:parentActivityName=".MainActivity" > <!-- Parent activity meta-data to support 4.0 and lower --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity" /> </activity> </application> </manifest>
User Model
Create a new package to src/main/java with the name com.jackrutorial.androidretrofit2crud.model.Create a User class under com.jackrutorial.androidretrofit2crud.model package and write the following code in it.
package com.jackrutorial.androidretrofit2crud.model; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; public class User { @SerializedName("id") @Expose private int id; @SerializedName("name") @Expose private String name; public User() { } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Retrofit Interface
UserService
Create a new package to src/main/java with the name com.jackrutorial.androidretrofit2crud.remote.Create a UserService interface under com.jackrutorial.androidretrofit2crud.remote package. In this interface, we'll define GET, POST, PUT, DELETE method that perform HTTP requests with @GET, @POST, @PUT, @DELETE annotations and write the following code in it.
package com.jackrutorial.androidretrofit2crud.remote; import com.jackrutorial.androidretrofit2crud.model.User; import java.util.List; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; public interface UserService { @GET("user/") Call<List<User>> getUsers(); @POST("add/") Call<User> addUser(@Body User user); @PUT("update/{id}") Call<User> updateUser(@Path("id") int id, @Body User user); @DELETE("delete/{id}") Call<User> deleteUser(@Path("id") int id); }
RetrofitClient
Create a RetrofitClient class under com.jackrutorial.androidretrofit2crud.remote package and write the following code in it.package com.jackrutorial.androidretrofit2crud.remote; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class RetrofitClient { private static Retrofit retrofit = null; public static Retrofit getClient(String url){ if(retrofit == null){ retrofit = new Retrofit.Builder().baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } }
APIUtils
Create a ApiUtils class under com.jackrutorial.androidretrofit2crud.remote package and write the following code in it.package com.jackrutorial.androidretrofit2crud.remote; public class APIUtils { private APIUtils(){ }; public static final String API_URL = "http://169.254.35.189:8080/demo/"; public static UserService getUserService(){ return RetrofitClient.getClient(API_URL).create(UserService.class); } }
Adjust activity
Change the activity_main.xml layout to the following.<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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.jackrutorial.androidretrofit2crud.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <Button android:id="@+id/btnAddUser" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Add User" android:background="#BA55D3" android:textColor="#ffffff" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" /> <Button android:id="@+id/btnGetUsersList" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Fetch users" android:background="#32CD32" android:textColor="#ffffff" android:layout_marginBottom="5dp" /> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content"> </ListView> </LinearLayout> </android.support.constraint.ConstraintLayout>Change MainActivity activity code to the following.
package com.jackrutorial.androidretrofit2crud; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ListView; import com.jackrutorial.androidretrofit2crud.model.User; import com.jackrutorial.androidretrofit2crud.remote.APIUtils; import com.jackrutorial.androidretrofit2crud.remote.UserService; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class MainActivity extends AppCompatActivity { Button btnAddUser; Button btnGetUsersList; ListView listView; UserService userService; List<User> list = new ArrayList<User>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("Retrofit 2 CRUD Demo"); btnAddUser = (Button) findViewById(R.id.btnAddUser); btnGetUsersList = (Button) findViewById(R.id.btnGetUsersList); listView = (ListView) findViewById(R.id.listView); userService = APIUtils.getUserService(); btnGetUsersList.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //get users list getUsersList(); } }); btnAddUser.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, UserActivity.class); intent.putExtra("user_name", ""); startActivity(intent); } }); } public void getUsersList(){ Call<List<User>> call = userService.getUsers(); call.enqueue(new Callback<List<User>>() { @Override public void onResponse(Call<List<User>> call, Response<List<User>> response) { if(response.isSuccessful()){ list = response.body(); listView.setAdapter(new UserAdapter(MainActivity.this, R.layout.list_user, list)); } } @Override public void onFailure(Call<List<User>> call, Throwable t) { Log.e("ERROR: ", t.getMessage()); } }); } }
Create User Activity
- Right Click the app folder choose File > New > Activity > Empty Activity
- Name the new activity "UserActivity".
- Click Finish.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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.jackrutorial.androidretrofit2crud.UserActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/txtUId" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="ID" android:textSize="20dp" android:layout_marginTop="5dp" /> <EditText android:id="@+id/edtUId" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="number" /> <TextView android:id="@+id/txtUUsername" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="USER NAME" android:textSize="20dp" android:layout_marginTop="5dp" /> <EditText android:id="@+id/edtUsername" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btnSave" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Save" android:background="#32CD32" android:textColor="#ffffff" android:layout_marginBottom="5dp" /> <Button android:id="@+id/btnDel" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Delete User" android:background="#FF0000" android:textColor="#ffffff" /> </LinearLayout> </android.support.constraint.ConstraintLayout>Change UserActivity activity code to the following.
package com.jackrutorial.androidretrofit2crud; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.jackrutorial.androidretrofit2crud.model.User; import com.jackrutorial.androidretrofit2crud.remote.APIUtils; import com.jackrutorial.androidretrofit2crud.remote.UserService; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class UserActivity extends AppCompatActivity { UserService userService; EditText edtUId; EditText edtUsername; Button btnSave; Button btnDel; TextView txtUId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user); setTitle("Users"); getSupportActionBar().setDisplayHomeAsUpEnabled(true); txtUId = (TextView) findViewById(R.id.txtUId); edtUId = (EditText) findViewById(R.id.edtUId); edtUsername = (EditText) findViewById(R.id.edtUsername); btnSave = (Button) findViewById(R.id.btnSave); btnDel = (Button) findViewById(R.id.btnDel); userService = APIUtils.getUserService(); Bundle extras = getIntent().getExtras(); final String userId = extras.getString("user_id"); String userName = extras.getString("user_name"); edtUId.setText(userId); edtUsername.setText(userName); if(userId != null && userId.trim().length() > 0 ){ edtUId.setFocusable(false); } else { txtUId.setVisibility(View.INVISIBLE); edtUId.setVisibility(View.INVISIBLE); btnDel.setVisibility(View.INVISIBLE); } btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { User u = new User(); u.setName(edtUsername.getText().toString()); if(userId != null && userId.trim().length() > 0){ //update user updateUser(Integer.parseInt(userId), u); } else { //add user addUser(u); } } }); btnDel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { deleteUser(Integer.parseInt(userId)); Intent intent = new Intent(UserActivity.this, MainActivity.class); startActivity(intent); } }); } public void addUser(User u){ Call<User> call = userService.addUser(u); call.enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if(response.isSuccessful()){ Toast.makeText(UserActivity.this, "User created successfully!", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<User> call, Throwable t) { Log.e("ERROR: ", t.getMessage()); } }); } public void updateUser(int id, User u){ Call<User> call = userService.updateUser(id, u); call.enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if(response.isSuccessful()){ Toast.makeText(UserActivity.this, "User updated successfully!", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<User> call, Throwable t) { Log.e("ERROR: ", t.getMessage()); } }); } public void deleteUser(int id){ Call<User> call = userService.deleteUser(id); call.enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if(response.isSuccessful()){ Toast.makeText(UserActivity.this, "User deleted successfully!", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<User> call, Throwable t) { Log.e("ERROR: ", t.getMessage()); } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return true; } return super.onOptionsItemSelected(item); } }
Create User Adapter
Create a UserAdapter class under com.jackrutorial.androidretrofit2crud package and write the following code in it.
package com.jackrutorial.androidretrofit2crud; import android.content.Context; import android.content.Intent; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import com.jackrutorial.androidretrofit2crud.model.User; import java.util.List; public class UserAdapter extends ArrayAdapter<User> { private Context context; private List<User> users; public UserAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull List<User> objects) { super(context, resource, objects); this.context = context; this.users = objects; } @Override public View getView(final int pos, View convertView, ViewGroup parent){ LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rowView = inflater.inflate(R.layout.list_user, parent, false); TextView txtUserId = (TextView) rowView.findViewById(R.id.txtUserId); TextView txtUsername = (TextView) rowView.findViewById(R.id.txtUsername); txtUserId.setText(String.format("#ID: %d", users.get(pos).getId())); txtUsername.setText(String.format("USER NAME: %s", users.get(pos).getName())); rowView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //start Activity User Form Intent intent = new Intent(context, UserActivity.class); intent.putExtra("user_id", String.valueOf(users.get(pos).getId())); intent.putExtra("user_name", users.get(pos).getName()); context.startActivity(intent); } }); return rowView; } }Create the list_user.xml file under res/layout/ folder to the following.
Click on app > res > layout > Right Click on layout. Select New > XML > Layout XML File. In the dialog that appears, enter list_user as name for the file. Then change the list_user.xml layout to the following.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/txtUserId" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="3dp" /> <TextView android:id="@+id/txtUsername" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="3dp" /> </LinearLayout>
Run this application with the Android Emulator
You can run this app from an Android Studio project. Or you can run this app that's been installed on the emulator as you would run any app on a device. To start the emulator and run this app in your project.- Open Android Studio project and click Run.
- In the Select Deployment Target dialog, select an existing emulator definition, and then click OK.
- If you don’t see a definition you want to use, click Create New Virtual Device to launch the AVD Manager. After you define a new AVD, in the Select Deployment Target dialog, click OK.
- If you want to use this emulator definition as the default for your project, select Use same selection for future launches.
Fetch Users Screen |
Add User Screen |
Update and Delete User Screen |