Not surprisingly, Android platform for developing a variety of ways to make use of Internet access. Some provide high-level access, such as components integrated WebKit browser. If you want, you can skip all the way and use sockets. In between, you can make use of the API-both on the phone and from a third party offers you access to specific protocols: HTTP, XMPP, SMTP, ...
The emphasis of this program is to form a higher level of access - WebKit components, discussed in previous chapter, and the Internet access API, discussed in this chapter. Because of the active programmers, we should try to reuse existing components wherever possible considering taking over our own protocol.
Internet permission
INTERNET
permission in AndroidManifest.xml
. So, you must always remember to add this line above <application>
tag before start working with Internet:
<uses-permission android:name="android.permission.INTERNET"/>
HTTP Operations via HttpURLConnection
HttpURLConnection
class instead. This API is more efficient because it reduces network use through transparent compression and response caching, and minimizes power consumption. That mean, the package help us to connecting to Internet is still java.net
that available in JDK.When using it, we can setup a
HttpURLConnection
from an URL
object, get an InputStream
which on Internet and parsing it based on it's datatype (Bitmap, JSON, XML, ...).Moreover, interacting with Internet process are always declared and done in a background thread (see "Dealing with Threads" post to see more details), unless, you will be crashed with
NetworkOnMainThreadException
error.In next part, I will present the way to get Bitmaps or JSON formatted strings from an
URL
.Getting Image from URL on Internet
Bitmap
type by using BitmapFactory
to decode it. This whole process is done in an AsyncTask
as follows:
GetImageTask.java
As you see in the package info.devexchanges.internet;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.Toast;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class GetImageTask extends AsyncTask<Void, Void, Bitmap> {
private final String IMAGE_URL = "http://i.imgur.com/ur4Ye8R.jpg";
private MainActivity activity;
private ProgressDialog progressDialog;
private HttpURLConnection connection;
public GetImageTask(MainActivity activity) {
this.activity = activity;
progressDialog = ProgressDialog.show(activity, "Connecting...", "Downloading Image...", true);
}
@Override
protected Bitmap doInBackground(Void... params) {
try {
//get Image from URL by URLConnection
URL url = new URL(IMAGE_URL);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
//InputStream and decode to Bitmap
InputStream input = connection.getInputStream();
Bitmap bmp = BitmapFactory.decodeStream(input);
return bmp;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
connection.disconnect();
}
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
progressDialog.dismiss(); //dismiss progress bar when task finished!
if (bitmap == null) {
Toast.makeText(activity, "Wrong Link!", Toast.LENGTH_SHORT).show();
} else {
//call back data to UI thread
activity.getBackBitmap(bitmap);
}
}
}
AsyncTask
code, after it finish this work, calling back data to UI thread in onPostExecute()
by invoke getBackBitmap()
method. So, go to your Activity
code and add this:
public void getBackBitmap(Bitmap bitmap) {
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(bitmap);
}
execute()
, we can invoke an AsyncTask
instance:
new GetImageTask(MainActivity.this).execute();
Note: With downloading images from Internet, there are many external libraries to make your work easier. See this post to learning about Picasso and UniversalImageLoader.
Get JSON from an URL
InputStream
response is a string with JSON format. So, we must use a BufferedReader
object to read all lines. This AsyncTask
will be similar:
GetJSONTask.java
With JSON_URL link above, the response JSON data will be like this:
package info.devexchanges.internet;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class GetJSONTask extends AsyncTask<Void, Void, String> {
private HttpURLConnection urlConnection;
private final String JSON_URL = "http://api.openweathermap.org/data/2.5/weather?q=hanoi,vn&appid=2de143494c0b295cca9337e1e96b00e0";
private MainActivity activity;
private ProgressDialog progressDialog;
public GetJSONTask(MainActivity activity) {
this.activity = activity;
progressDialog = ProgressDialog.show(activity, "Connecting...", "Downloading JSON...", true);
}
@Override
protected String doInBackground(Void... params) {
StringBuilder result = new StringBuilder();
try {
URL url = new URL(JSON_URL);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
}catch( Exception e) {
e.printStackTrace();
}
finally {
urlConnection.disconnect();
}
return result.toString();
}
@Override
protected void onPostExecute(String result) {
progressDialog.dismiss(); //dismiss dialog
activity.parsingJSONResponse(result); //call back data to UI thread
}
}
{
"coord": {
"lon": 105.85,
"lat": 21.03
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04d"
}
],
"main": {
"temp": 287.85,
"pressure": 1024.05,
"humidity": 89,
"temp_min": 287.85,
"temp_max": 287.85
},
"sys": {
"message": 0.0082,
"country": "VN",
"sunrise": 1453160172,
"sunset": 1453199888
},
"id": 1561096,
"name": "Xóm Pho",
"cod": 200
}
JSONObjects
, JSONArrays
based on each element name:
// parsing json and set the custom dialog components - text, image and button
try {
JSONObject jsonObject = new JSONObject(jsonString);
//get location
JSONObject locationObject = jsonObject.getJSONObject("coord");
location.setText("[ " + locationObject.getString("lon") + ", " + locationObject.getString("lat") + " ]");
//get temperature, humidity and pressure
JSONObject tempObject = jsonObject.getJSONObject("main");
temperature.setText(tempObject.getString("temp") + " Kelvin");
humidity.setText(tempObject.getString("humidity") + "%");
pressure.setText(tempObject.getString("pressure") + "Pa");
//get city name
city.setText(jsonObject.getString("name"));
} catch (JSONException e) {
e.printStackTrace();
}
MainActivity.java
And it's layout:
package info.devexchanges.internet;
import android.app.Dialog;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
private View btnGetJSON;
private View btnGetImage;
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGetImage = findViewById(R.id.btn_img);
btnGetJSON = findViewById(R.id.btn_json);
imageView = (ImageView) findViewById(R.id.image);
btnGetImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new GetImageTask(MainActivity.this).execute();
}
});
btnGetJSON.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new GetJSONTask(MainActivity.this).execute();
}
});
}
public void getBackBitmap(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
public void parsingJSONResponse(String jsonString) {
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog_weather);
dialog.setTitle(getString(R.string.notice));
dialog.setCancelable(true);
TextView temperature = (TextView) dialog.findViewById(R.id.temperature);
TextView humidity = (TextView) dialog.findViewById(R.id.humidity);
TextView pressure = (TextView) dialog.findViewById(R.id.pressure);
TextView location = (TextView) dialog.findViewById(R.id.location);
TextView city = (TextView) dialog.findViewById(R.id.city);
// parsing json and set the custom dialog components - text, image and button
try {
JSONObject jsonObject = new JSONObject(jsonString);
//get location
JSONObject locationObject = jsonObject.getJSONObject("coord");
location.setText("[ " + locationObject.getString("lon") + ", " + locationObject.getString("lat") + " ]");
//get temperature, humidity and pressure
JSONObject tempObject = jsonObject.getJSONObject("main");
temperature.setText(tempObject.getString("temp") + " Kelvin");
humidity.setText(tempObject.getString("humidity") + "%");
pressure.setText(tempObject.getString("pressure") + "Pa");
//get city name
city.setText(jsonObject.getString("name"));
} catch (JSONException e) {
e.printStackTrace();
}
//showing dialog
dialog.show();
}
}
activity_main.xml
The dialog layout (display when parsing JSON complete):
<?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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<Button
android:id="@+id/btn_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/get_image" />
<Button
android:id="@+id/btn_json"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/get_json" />
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="@dimen/activity_horizontal_margin"
android:contentDescription="@string/app_name" />
</LinearLayout>
dialog_weather.xml
After running, we can see this screen:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/country" />
<TextView
android:id="@+id/city"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_green_light" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/location" />
<TextView
android:id="@+id/location"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_blue_dark" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/temperature"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/temperature"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_orange_dark" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/humidity"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/humidity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_purple" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:text="@string/pressure" />
<TextView
android:id="@+id/pressure"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.65"
android:textColor="@android:color/holo_red_dark" />
</LinearLayout>
</LinearLayout>
When an
AsyncTask
is running:After downloading image finished:
After downloading/parsing JSON:
NOTE: Source code of this project now available on @Github.
Parsing XML data?
HttpURLConnection
and parsing data response by XMLPullParser
, DOM
or SAX
. The data can be like this:
<current>
<city id="1561096" name="Xóm Pho">
<coord lon="105.85" lat="21.03"/>
<country>VN</country>
<sun rise="2016-01-18T23:36:12" set="2016-01-19T10:38:09"/>
</city>
<temperature value="289.006" min="289.006" max="289.006" unit="kelvin"/>
<humidity value="88" unit="%"/>
<pressure value="1025.91" unit="hPa"/>
<wind>
<speed value="2.67" name="Light breeze"/>
<gusts/>
<direction value="37.001" code="NE" name="NorthEast"/>
</wind>
<clouds value="88" name="overcast clouds"/>
<visibility/>
<precipitation mode="no"/>
<weather number="804" value="overcast clouds" icon="04d"/>
<lastupdate value="2016-01-19T01:50:51"/>
</current>
XMLPullParser
), read it HERE to learn about xml parsing.Web service in Android
By default SDK, Android is not preinstalled SOAP or XML-RPC client API. SOAP web service can be connecting through k-soap2 library. and connecting to REST web service by using Volley. (See my previous post about Volley to deep understand it).
You can read a simple example of web service consuming at this POST. Moreover, usually, the responding data is much complicated, so, you can read "Parsing Soap Object response" post to learn how to consuming the SOAP web service.