Overview
In this part of the project, we will use the simple REST API that we created in Part 1 to display the data on Android UI.
Prerequisites
Android Studio >3.0: You can download Android Studio here.
If you get stuck at any stage, you can download all the source files for this project here.
Step 1: Create a New Android Project
We’re going to call this application MyRESTProject, but feel free to give it any other name of your choice. Enter a unique package name and set the target SDK to Android 5.0.
This Project will have only a single Activity and will be based on a empty Activity template.
Step 2: Edit your manifest.xml file
The only permission we need is Internet permission. We need this in order to make API calls over the internet connection. Add the following line to your Manifest.xml file.
<uses-permission android:name="android.permission.INTERNET"/>
To keep this tutorial simple, we're only going to support Portrait Mode for our app.
After making the changes for Internet permission and support for portrait mode only, your manifest code should look something like this:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.myrestproject"><uses-permission android:name="android.permission.INTERNET" /><applicationandroid: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=".Record"></activity></application></manifest>
Step 3: Edit the activity_main.xml layout
Edit activity_main.xml by adding one TextView tag and one EditText tag to get user Input, in our case; RollNo. And a button which when clicked will call the API we have created to validate the student’s RollNo.
<?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.myrestproject.MainActivity"android:background="@color/colorPrimary"><EditTextandroid:id="@+id/editText"android:layout_width="150dp"android:layout_height="42dp"android:layout_marginBottom="8dp"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="8dp"android:hint="2017CA48"android:inputType="text"android:textAlignment="center"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias="0.498" /><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="8dp"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="8dp"android:text="ENTER REGISTRATION NUMBER"app:layout_constraintBottom_toTopOf="@+id/editText"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="8dp"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="8dp"android:text="Show Record"android:onClick="onClick"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/editText" /></android.support.constraint.ConstraintLayout>
Step 4: Add new Layout File
In order to show the student data on the UI, we’ll create a new layout file and name it activity_record.xml.
Edit activity_record.xml file by adding several TextViews to display the following information about the student.
- Student’s RollNo
- Student’s Name
- Student’s College
- Student’s Contact information
- Student’s Marks
All this will be contained in constraint layout to adjust all the TextViews in an efficient manner.
Our Layout file should look like this after making the required changes.
<?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.myrestproject.Record"><TextViewandroid:id="@+id/Name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="44dp"android:ems="10"android:textAlignment="center"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.534"app:layout_constraintStart_toEndOf="@+id/Name1"app:layout_constraintTop_toBottomOf="@+id/ID_User" /><TextViewandroid:id="@+id/Mob"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="44dp"android:ems="10"android:textAlignment="center"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.503"app:layout_constraintStart_toEndOf="@+id/textView7"app:layout_constraintTop_toBottomOf="@+id/CollegeName" /><TextViewandroid:id="@+id/ID_User"android:layout_width="wrap_content"android:layout_height="0dp"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="76dp"android:ems="10"android:textAlignment="center"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toEndOf="@+id/Roll"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/CollegeName"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="40dp"android:ems="10"android:textAlignment="center"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.445"app:layout_constraintStart_toEndOf="@+id/textView6"app:layout_constraintTop_toBottomOf="@+id/Name" /><TextViewandroid:id="@+id/Marks"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="8dp"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="40dp"android:ems="10"android:textAlignment="center"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.407"app:layout_constraintStart_toEndOf="@+id/textView8"app:layout_constraintTop_toBottomOf="@+id/Mob"app:layout_constraintVertical_bias="0.031" /><TextViewandroid:id="@+id/Roll"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="8dp"android:layout_marginStart="24dp"android:layout_marginTop="56dp"android:text="Roll Number"app:layout_constraintBottom_toTopOf="@+id/Name1"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias="0.357" /><TextViewandroid:id="@+id/Name1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="24dp"android:layout_marginTop="44dp"android:text="Name of Student"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/ID_User" /><TextViewandroid:id="@+id/textView6"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="40dp"android:layout_marginStart="24dp"android:layout_marginTop="36dp"android:text="College Name"app:layout_constraintBottom_toTopOf="@+id/textView7"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/Name1"app:layout_constraintVertical_bias="0.538" /><TextViewandroid:id="@+id/textView7"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="44dp"android:layout_marginStart="24dp"android:text="Contact"app:layout_constraintBottom_toTopOf="@+id/textView8"app:layout_constraintStart_toStartOf="parent" /><TextViewandroid:id="@+id/textView8"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="164dp"android:layout_marginStart="24dp"android:text="Percentage"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toStartOf="parent" /></android.support.constraint.ConstraintLayout>
Step 5: Developing the Singleton class
If your application makes constant use of the network, it's probably most efficient to set up a single instance of a RequestQueue: a request dispatch queue with a thread pool of dispatchers. Calling add(Request) will enqueue the given Request for dispatch, resolving from either cache or network on a worker thread, and then delivering a parsed response on the main thread.
You can achieve this in various ways. The recommended approach is to use a third-party library called Volley and implement a singleton class that encapsulates RequestQueue and other Volley functionality. Another approach is to subclass Application and set up the RequestQueue in Application.onCreate(). But this approach is discouraged since a static singleton can provide the same functionality in a more modular way.
First, you need to install volley to your project. The easiest way to do so is to add the following line to dependencies of your app's build.gradle.
// /app/build.gradledependencies {...implementation 'com.android.volley:volley:1.1.1'}
Next, create a java class and name it as MySingleton.java. This class will encapsulate RequestQueues (StringRequest, JSONArrayRequest).
This class will have the following structure:
package com.myrestproject;import android.content.Context;import com.android.volley.Request;import com.android.volley.RequestQueue;import com.android.volley.toolbox.JsonArrayRequest;import com.android.volley.toolbox.JsonObjectRequest;import com.android.volley.toolbox.StringRequest;import com.android.volley.toolbox.Volley;public class MySingleton {private static MySingleton mySingleton;private RequestQueue requestQueue;private Context context;private MySingleton(Context context){this.context = context;requestQueue = getRequestQueue();}public RequestQueue getRequestQueue(){if(requestQueue==null){requestQueue = Volley.newRequestQueue(context.getApplicationContext());}return requestQueue;}public static synchronized MySingleton getInstance(Context context){if(mySingleton==null)mySingleton = new MySingleton(context);return mySingleton;}//RequestQueue for String Requestspublic void addToRequestQueue(StringRequest request){requestQueue.add(request);}//RequestQueue for JSON Requestspublic void addToJsonRequestQueue(JsonArrayRequest jsonArrayRequest){requestQueue.add(jsonArrayRequest);}}
Step 6: Write Code for Validation of Students Roll No.
For this tutorial, instead of using HttpUrlConnection and Handler Objects, we’ll use Volley Library.
Volley is an HTTP library that makes networking for Android apps easier and most importantly, faster.
Volley offers the following benefits:
- Scheduling of network requests.
- Supports Multiple concurrent network connections.
- Memory response caching with standard HTTP cache coherence.
- Support for request prioritization.
- Cancellation request API. You can cancel a single request, or you can set blocks or scopes of requests to cancel.
We’ll be making use of volley StringRequest class which accepts the following three parameters:
- Type of Request.
- URL to the resources (fully qualified).
- Callback Functions.
The Callback functions have some methods which have to be overridden, which are,
- onResponse() [Functionality to perform when response is received from the server]
- onErrorResponse() [Functionality to perform when there is an error]
- getparams() [This is used to add values to the body of the request sent]
In order to traverse from one activity to another, we’ll make use of Intent class.
Intents are asynchronous messages which allow application components to request functionality from other Android components. Intents allow you to interact with components from the same applications as well as with components contributed by other applications. We’ll put the RollNo of the Student to the Intent and pass it along to another activity where it can be used so that we don’t have to fetch the RollNo from the server.
MainActivity.java class should look like this:
package com.myrestproject;import android.app.ProgressDialog;import android.content.Intent;import android.content.SharedPreferences;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.AdapterView;import android.widget.Button;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.Toast;import com.android.volley.AuthFailureError;import com.android.volley.Request;import com.android.volley.Response;import com.android.volley.VolleyError;import com.android.volley.toolbox.StringRequest;import java.util.HashMap;import java.util.Map;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private EditText editText;private Button button;private ProgressDialog Progress;String StatusCode;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = findViewById(R.id.button);editText = findViewById(R.id.editText);Progress = new ProgressDialog(this);button.setOnClickListener(this);}@Overridepublic void onClick(View v) {Progress.show();try {//Add the URL you have got when you had run the “iisexpress-proxy” commandStringRequest request = new StringRequest(Request.Method.POST, "http://192.168.43.172:3000/api/values", new Response.Listener<String>() {@Overridepublic void onResponse(String s) {Progress.dismiss();//The server returns a fully qualified series of text, from which the Status Code is at index 13-16.StatusCode = s.substring(13,16);//If Status Code matches to “302”, i.e Student’s RollNo is available in the DBif (StatusCode.contains("302")) {Intent intent = new Intent(MainActivity.this, Record.class);intent.putExtra("ID", editText.getText().toString());startActivity(intent);}else if(StatusCode.contains("404")){Toast.makeText(MainActivity.this, "Not Found in Student Database",Toast.LENGTH_LONG).show();}else {Toast.makeText(MainActivity.this, "Unknown Error", Toast.LENGTH_LONG).show();}}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError volleyError) {Log.d("HAR",volleyError.toString());Progress.dismiss();}}) {@Overrideprotected Map<String, String> getParams() throws AuthFailureError {Map<String, String> parameters = new HashMap<>();parameters.put("ID", editText.getText().toString());return parameters;}};//Adding the request to the RequestQueueMySingleton.getInstance(this).addToRequestQueue(request);} catch (Exception ex) {Log.d("HAR",ex.toString());}}}
Step 7: Displaying Student’s details on the UI
After the Student’s RollNo is validated, then we have to show the details of that student on the next screen. For that purpose, let’s create another java class and name it at as Record.java
In this class, we’ll make use of volley JSONArrayRequest class as the record fetched from server will be in JSON format. JSON is also a kind of string which we’ll convert to JSONObject to get values corresponding to different keys in the JSON string.
The Record.java class will look like this:
package com.myrestproject;import android.app.ProgressDialog;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.widget.TextView;import android.widget.Toast;import com.android.volley.Response;import com.android.volley.VolleyError;import com.android.volley.toolbox.JsonArrayRequest;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;public class Record extends AppCompatActivity {private TextView ID_User;private TextView Name;private TextView College;private TextView Mob;private TextView Marks;private ProgressDialog Progress;String id;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_record);SetFields();Progress.show();callService();}private void SetFields(){Progress = new ProgressDialog(this);ID_User = findViewById(R.id.ID_User);Name = findViewById(R.id.Name);College = findViewById(R.id.CollegeName);Mob = findViewById(R.id.Mob);Marks = findViewById(R.id.Marks);//Extracting the Intent value from the previous activityid = getIntent().getStringExtra("ID");}private void callService(){JsonArrayRequest jsonArrayRequest = new JsonArrayRequest("http://192.168.43.172:3000/api/values/"+id, new Response.Listener<JSONArray>() {@Overridepublic void onResponse(JSONArray response1) {Progress.dismiss();JSONArray response = null;JSONObject json;String str = response1.toString();try {response = new JSONArray(str);} catch (JSONException e) {e.printStackTrace();}if(response!=null){try {json = response.getJSONObject(0);ID_User.setText(id);//Extracting values from JSONObject based on KeysName.setText(json.getString("sName"));College.setText(json.getString("collegeName"));Mob.setText(json.getString("mob"));Marks.setText(json.getString("percentage_marks"));}catch (Exception e){Log.e("HAR",e.toString());}}}},new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {Toast.makeText(Record.this, "Volley Error"+error.toString(), Toast.LENGTH_SHORT).show();}});MySingleton.getInstance(this).addToJsonRequestQueue(jsonArrayRequest);}}
After the completion of this tutorial, the final result should look like this:
Note: Before Running the Application, make sure your Android device and the system on which your Web API is running are on the same network.
After completing this tutorial, you have successfully learnt how to integrate an API with an android application.