In this article, we will talk about:
-What is the API & How it works. -JSON & XML. -The volley library and how to apply it in the app. -Callbacks(just an overview) -We will make a simple weather app using Java to show you how to deal with the API in details.
As we know, the letters API refers to "Application Program Interface", it is a service provided by a remote server.
In our app we will use Metaweather.com to get a list of data for the coming days of the week.
The API server provides a set of URLs that return pure data responses
JSON VS XML
The API servers always communicates with its clients in text massages formatted in JSON or XML.
-That is a code written in JSON:
"minutely": [
{
"dt": 1653491400,
"precipitation": 0
},
{
"dt": 1653491460,
"precipitation": 0
},
{
"dt": 1653491520,
"precipitation": 0
},
{
"dt": 1653491580,
"precipitation": 0
},
{
"dt": 1653491640,
"precipitation": 0
},
{
"dt": 1653491700,
"precipitation": 0
}
]
This tutorial will show you how to create a REST client in Android, let's go (^^)
Clients can be a mobile app, web app, watches and any other type of program you can imagine.
(1)Create a new project with Java in Android Studio.
(2)Create the layout using XML.
```<?xml version="1.0" encoding="utf-8"?>
<Button
android:id="@+id/btnGitCityID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GetCityID"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnGetWeatherByCityID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="Weather By ID"
app:layout_constraintStart_toEndOf="@+id/btnGitCityID"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteY="0dp" />
<Button
android:id="@+id/GetWeatherByCityName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Weather By Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.789"
app:layout_constraintStart_toEndOf="@+id/btnGetWeatherByCityID"
tools:layout_editor_absoluteY="0dp"
tools:ignore="MissingConstraints" />
<EditText
android:id="@+id/editTextCityName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="44dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="City Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.383"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnGetWeatherByCityID" />
<ListView
android:id="@+id/List"
android:layout_width="409dp"
android:layout_height="590dp"
android:layout_marginTop="0dp"
app:layout_constraintTop_toBottomOf="@+id/editTextCityName"
tools:layout_editor_absoluteX="2dp"
tools:ignore="MissingConstraints" />
/>
**(3)In the main Activity, We will initialize the views.
**
public class MainActivity extends AppCompatActivity {
Button GetCityID,GetWeatherByID,GetWeatherByCityName;
EditText ETCityName;
ListView list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GetCityID=findViewById(R.id.btnGitCityID);
GetWeatherByID=findViewById(R.id.btnGetWeatherByCityID);
GetWeatherByCityName=findViewById(R.id.GetWeatherByCityName);
ETCityName=findViewById(R.id.editTextCityName);
list=findViewById(R.id.List);} }
(4) Go to the Volley library documents.
-Add the dependency to the build gradle file in the app.
-Let's discover the section in the documents called " send a simple request" from this link:to the documentation
-In the docs, you surely notice that the library need to add an internet permission to the add.
-So, go to the manifest file and add the Internet permission attribute.
Come back with me to the Android studio(^^)
(5)In the main activity, we will work on the First button ```btnGitCityID
-Add a click listener to it and on the On click()
method, copy the code in the volley docs to the Main Activity.
``` GetCityID.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
String url = "https://www.metaweather.com/api/location/search/?query=london";
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
Toast.makeText(MainActivity.this,response,Toast.LENGTH_SHORT).show();
public void onResponse(JSONObject response) {
String cityId;
try {
JSONObject CityInfo = response.getJSONObject("0");
cityId=CityInfo.getString("woeid");
} catch (JSONException e) {
throw new RuntimeException(e);
}
Toast.makeText(MainActivity.this,"The city ID is:"+cityId.toString(),Toast.LENGTH_SHORT).show();
}
}, @Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this,"ERROR",Toast.LENGTH_SHORT).show();
}
});
queue.add(jsonObjectRequest);
-Be careful, the previous code has an Error!
Note: If you want to get an JSONobject from the API, so you have to make a standard request, Have a look at the code from here
Just take a minute as break before continue reading.
We will make a lot of edits to refactor the code and make each module of it independent part, so it will be readable, easy to maintain and less complex.
Singleton Pattern
Singleton is a class that where only one instance of the class can exist.
-If you have many requests occur at the same time, Singleton will handle them all.
(6)Make a new class called "MySingleton".
(7)Copy the code in this document and paste in the new class.
-Make small edits on it.
public class MySingleton {
private static MySingleton instance;
private RequestQueue requestQueue;
private static Context ctx;
private MySingleton(Context context) {
ctx = context;
requestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context) {
if (instance == null) {
instance = new MySingleton(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}
To make the code more better, we will separate the methods that control the buttons, in another class called
**(8) In the weatherDataService class, we will create a method for each button, firstly we will focus on the
button.**
-As you see, we separated the button in a separate method called
``` public void getCityID(String cityName, VolleyResponseListener volleyResponseListener){
// RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
String url = QUERY_FOR_CITY_ID +cityName;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONObject CityInfo = response.getJSONObject("0");
cityId=CityInfo.getString("woeid");
} catch (JSONException e) {
throw new RuntimeException(e);
}
// Toast.makeText(context,"The city ID is:"+cityId.toString(),Toast.LENGTH_SHORT).show();
volleyResponseListener.onResponse(cityId);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// Toast.makeText(context,"ERROR",Toast.LENGTH_SHORT).show();
volleyResponseListener.onError("Something going wrong!");
}
});
MySingleton.getInstance(context).addToRequestQueue(jsonObjectRequest);
//return cityId;
}
*Don't worry about the volley response term that you may not know much about it, i will explain it in details.*
# If you run the app, an **Asyncronous problem** will appear.
To know more about this problem, you should study deeper the threads topic
I recommend [this source](https://youtu.be/9NyGOrztWjE) to study it.
**(9)To solve this problem, we need to use* "Callbacks"***
*A callback* : is a way to schedule a method call to occur when another method finishes its task.
(10)We will use [this code](https://stackoverflow.com/questions/33535435/how-to-create-a-proper-volley-listener-for-cross-class-volley-method-calling) from Stackover to solve the problem.
(11)Make an interface in the WeatherDataService class.
public interface VolleyResponseListener { void onError(String message);
void onResponse(String cityId);
}
```
Finally, the First button is working well, follow these steps or add small steps to them to complete the rest of the buttons, see you soon in another Article.
Summary:
We talked in this Article about some concepts you should study more about it. These concepts are like: Callbacks, Singleton pattern, REST APIs, Refactoring.
I recommend "Head first object oriented analysis and design" book to have the mindset of the clean coder, so you can know about the refactoring in details.
That is the code on my Githup.
To have a look at my another great apps, visit my behance here
All my Accounts in one place, Click here to showmy linktree.