As you can see on my blog, I had 2 posts about SOAP web service, you should take a glance first:
- Consuming "temperature converting" web service on W3Schools (a simple SOAP web service for beginners).
- Parsing response XML Objects from SOAP web service (more complicated web service).
What is REST and why REST?
The alternative is building relatively complex conventions on top of HTTP. Often, this takes the shape of entire new XML-based languages. The most illustrious example is SOAP. You have to learn a completely new set of conventions, but you never use HTTP to its fullest power. Because REST has been inspired by HTTP and plays to its strengths, it is the best way to learn how HTTP works.
After an initial overview, we'll examine each of the HTTP building blocks: URLs, HTTP verbs and response codes. We'll also review how to use them in a RESTful way. Along the way, we'll illustrate the theory with an example application, which simulates the process of keeping track of data related to a company's clients through a web interface.
REST asks developers to use HTTP methods explicitly and in a way that’s consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping:
- To create a resource on the server, use POST.
- To retrieve a resource, use GET.
- To change the state of a resource or to update it, use PUT.
- To remove or delete a resource, use DELETE.
In this tutorial, I'm going to show you how to use the classes and methods available in the Android SDK to connect to remote web servers and interact with them using their REST APIs.
Enabling Internet Access
<uses-permission android:name="android.permission.INTERNET" />
Using GET request
AsyncTask
and in the main thread, invoking excute()
to start it:
private class GetDataTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... voids) {
//More code will be added here later
}
}
We will get data from URL, By using the openConnection()
method of the URL
class, you can quickly set up a connection to any REST endpoint. The return value of openConnection()
must be cast to an instance of either HttpURLConnection
or HttpsURLConnection
, depending on whether the endpoint is accessed over HTTP or HTTPS. Both HttpURLConnection
and HttpsURLConnection
allow you to perform operations such as adding request headers and reading responses.Setting up a connection with the GitHub API's root endpoint:
// Create URL
URL githubEndpoint = new URL("https://api.github.com/");
// Create connection
HttpsURLConnection myConnection = (HttpsURLConnection) githubEndpoint.openConnection();
The next important step is adding headers for your GET request. By using setRequestProperty()
method multiple times, you can add multiple headers for your request:
myConnection.setRequestProperty("User-Agent", "my-rest-app-v0.1");
myConnection.setRequestProperty("Accept", "application/vnd.github.v3+json");
myConnection.setRequestProperty("Contact-Me", "wandered.vip.007@example.com");
Now, we must read the response message from API. Once you have passed all the request headers, you can check if you have a valid response using the getResponseCode()
method of the HttpURLConnection
object. If the HttpURLConnection
class gets a redirect response code, such as 200, it handles it automatically and follows the redirect. Therefore, usually, you will not have to write any extra code to check for redirects.In case of no errors, you can now call the
getInputStream()
method to get a reference to the input stream of the connection. The response data from REST API usually is JSON, therefore, instead of reading from the InputStream
object directly, I suggest you create an InputStreamReader
for it. After that, you can use/parse JSON data in your way:
if (myConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {//HTTP_OK code is 200
InputStream responseBody = myConnection.getInputStream();
InputStreamReader responseBodyReader = new InputStreamReader(responseBody, "UTF-8");
BufferedReader streamReader = new BufferedReader(responseBodyReader);
StringBuilder responseStrBuilder = new StringBuilder();
//get JSON String
String inputStr;
while ((inputStr = streamReader.readLine()) != null)
responseStrBuilder.append(inputStr);
myConnection.disconnect();
return responseStrBuilder.toString();
} else {
Log.d("Main", "error in connection");
return "";
}
Remember to invoke myConnection.disconnect()
to close the HttpURLConnection
.For example, the JSON document returned by the root endpoint of GitHub's REST API with my account will be like this:
{
"current_user_url": "https://api.github.com/user",
"current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}",
"authorizations_url": "https://api.github.com/authorizations",
"code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}",
"emails_url": "https://api.github.com/user/emails",
"emojis_url": "https://api.github.com/emojis",
"events_url": "https://api.github.com/events",
"feeds_url": "https://api.github.com/feeds",
"followers_url": "https://api.github.com/user/followers",
"following_url": "https://api.github.com/user/following{/target}",
"gists_url": "https://api.github.com/gists{/gist_id}",
"hub_url": "https://api.github.com/hub",
"issue_search_url": "https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}",
"issues_url": "https://api.github.com/issues",
"keys_url": "https://api.github.com/user/keys",
"notifications_url": "https://api.github.com/notifications",
"organization_repositories_url": "https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}",
"organization_url": "https://api.github.com/orgs/{org}",
"public_gists_url": "https://api.github.com/gists/public",
"rate_limit_url": "https://api.github.com/rate_limit",
"repository_url": "https://api.github.com/repos/{owner}/{repo}",
"repository_search_url": "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}",
"current_user_repositories_url": "https://api.github.com/user/repos{?type,page,per_page,sort}",
"starred_url": "https://api.github.com/user/starred{/owner}{/repo}",
"starred_gists_url": "https://api.github.com/gists/starred",
"team_url": "https://api.github.com/teams",
"user_url": "https://api.github.com/users/{user}",
"user_organizations_url": "https://api.github.com/user/orgs",
"user_repositories_url": "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}",
"user_search_url": "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"
}
Using POST request
HttpURLConnection
object, you must use its setRequestMethod()
method. For example, the following code snippet opens a connection to an endpoint that belongs to httpbin.org and sets its HTTP method to POST
:
URL httpbinEndpoint = new URL("https://httpbin.org/post");
HttpsURLConnection myConnection = (HttpsURLConnection) httpbinEndpoint.openConnection();
myConnection.setRequestMethod("POST");
The POST
requests are used to send data to the server. By writing to the output stream of the connection, you can easily add any data to the body of the POST
request. However, before you do so, you must make sure that you call the setDoOutput
method of the HttpURLConnection
object and give true
to it:
String myData = "message=Hello";
myConnection.setDoOutput(true);
myConnection.getOutputStream().write(myData.getBytes());
After that, you can call the getInputStream()
method to get a reference to the input stream of the connection like the GET
method above:
if (myConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
Log.i("Main", "getresponse code 200: ");
// Get InputStream
InputStream is = myConnection.getInputStream();
// Convert the InputStream into a string
String charset = "UTF-8";
BufferedReader r = new BufferedReader(new InputStreamReader(is, charset));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
byte[] bytes = total.toString().getBytes();
return new String(bytes, Charset.forName(charset));
} else {
// Server returned HTTP error code.
Log.d("Main", "server error");
}
} catch (IOException e) {
e.printStackTrace();
}
With this example, you can get this JSON data response:
{
"args": {},
"data": "",
"files": {},
"form": {
"message": "Hello"
},
"headers": {
"Accept-Encoding": "gzip",
"Content-Length": "13",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Dalvik/2.1.0 (Linux; U; Android 6.0; Android SDK built for x86_64 Build/MASTER)"
},
"json": null,
"origin": "192.168.1.1",
"url": "https://httpbin.org/post"
}
As you can see in the form
object of JSON response, the message you've just post is Hello
.
Conclusions
HttpURLConnection
/HttpsURLConnection
in Android SDK to consume REST APIs. For the full code of this example, you can download by click the button below. It has 2 Activities
named HttpGetActivity
and HttpPostActivity
corresponding to 2 methods (GET and POST). This is the basic and official way to consume a REST web service. Moreover, if you think this way is hard, you should give third-party libraries like Retrofit or Volley with this work, these libraries provide lots of convenient methods that allow you to make your code more concise and readable, the fact that, most of Android developers are using them! I will have some posts about this topic soon!