Chapter 10 Networking/Web Service Using HTTP
1. Consuming web services using HTTP
<1>Downloading Binary Data
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="mirror.android.networing.Networing" > <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout>
package mirror.android.networing; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.widget.ImageView; public class Networing extends Activity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_networking); new DownloadImageTask().execute("http://www.mayoff.com/5-01cablecarDCP01934.jpg"); } private InputStream OpenHttpConnection(String urlString) throws IOException{ InputStream in = null; URL url = new URL(urlString); URLConnection conn = url.openConnection(); if (!(conn instanceof HttpURLConnection)) throw new IOException("Not an HTTP connection"); try{ HttpURLConnection httpConn = (HttpURLConnection)conn; httpConn.setAllowUserInteraction(false); httpConn.setInstanceFollowRedirects(true); httpConn.setRequestMethod("GET"); httpConn.connect(); if(httpConn.getResponseCode() == HttpURLConnection.HTTP_OK){ in = httpConn.getInputStream(); } } catch(Exception ex){ Log.d("Networking",ex.getLocalizedMessage()); throw new IOException("Error connecting"); } return in; } private Bitmap DownloadImage(String URL){ Bitmap bitmap = null; try{ InputStream in = OpenHttpConnection(URL); //Decode an input stream into a bitmap bitmap = BitmapFactory.decodeStream(in); in.close(); } catch(IOException e){ Log.d("NetworkingActivity", e.getLocalizedMessage()); } return bitmap; } //An asynchronous task is defined by a computation that runs on a background thread //and whose result is published on the UI thread. private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>{ @Override protected Bitmap doInBackground(String... urls) { return DownloadImage(urls[0]); } @Override protected void onPostExecute(Bitmap result) { ImageView imageView = (ImageView)findViewById(R.id.img); imageView.setImageBitmap(result); } } }
If you want to download a series of images asynchronously, you can modify the DownloadImageTask class as follows:
package mirror.android.networing; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.widget.ImageView; import android.widget.Toast; public class Networing extends Activity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_networking); imageView = (ImageView)findViewById(R.id.img); new DownloadImageTask().execute("http://www.mayoff.com/5-01cablecarDCP01934.jpg", "http://www.hartiesinfo.net/greybox/Cable_Car_Hartbeespoort.jpg", "http://www.fantom-xp.com/wallpapers/63/San_Francisco_-_Sunset.jpg"); } private InputStream OpenHttpConnection(String urlString) throws IOException{ InputStream in = null; URL url = new URL(urlString); URLConnection conn = url.openConnection(); if (!(conn instanceof HttpURLConnection)) throw new IOException("Not an HTTP connection"); try{ HttpURLConnection httpConn = (HttpURLConnection)conn; httpConn.setAllowUserInteraction(false); httpConn.setInstanceFollowRedirects(true); httpConn.setRequestMethod("GET"); httpConn.connect(); if(httpConn.getResponseCode() == HttpURLConnection.HTTP_OK){ in = httpConn.getInputStream(); } } catch(Exception ex){ Log.d("Networking",ex.getLocalizedMessage()); throw new IOException("Error connecting"); } return in; } private Bitmap DownloadImage(String URL){ Bitmap bitmap = null; try{ InputStream in = OpenHttpConnection(URL); //Decode an input stream into a bitmap bitmap = BitmapFactory.decodeStream(in); in.close(); } catch(IOException e){ Log.d("NetworkingActivity", e.getLocalizedMessage()); } return bitmap; } //An asynchronous task is defined by a computation that runs on a background thread //and whose result is published on the UI thread. private class DownloadImageTask extends AsyncTask<String, Bitmap, Long>{ //Perform a computation on a background thread. @Override protected Long doInBackground(String... urls) { long imageCount = 0; for(int i = 0; i < urls.length ; i++){ Bitmap imagesDownloded = DownloadImage(urls[i]); if(imagesDownloded != null){ imageCount ++; try{ Thread.sleep(3000); } catch(InterruptedException e){ e.printStackTrace(); } } //publish updates on the UI thread publishProgress(imagesDownloded); } return imageCount; } //Runs on the UI thread after publishProgress is invoked. @Override protected void onProgressUpdate(Bitmap... bitmap) { imageView.setImageBitmap(bitmap[0]); } //Runs on the UI thread after doInBackground finished @Override protected void onPostExecute(Long imageCount) { Toast.makeText(getApplication() , "Total " + imageCount + " images downloaded" , Toast.LENGTH_LONG).show(); } } }
When you run the preceding code, the images are downloaded in the background and displayed at an interval of three seconds. When the
last image has been downloaded, the Toast class displays the total number of images downloaded.
<2>Downloading Text Content
package mirror.android.networing; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.widget.ImageView; import android.widget.Toast; public class Networing extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_networking); new DownloadTextTask().execute("http://iheartquotes.com/api/v1/random?max_characters=256&max_lines=10"); } private InputStream OpenHttpConnection(String urlString) throws IOException{ InputStream in = null; URL url = new URL(urlString); URLConnection conn = url.openConnection(); if (!(conn instanceof HttpURLConnection)) throw new IOException("Not an HTTP connection"); try{ HttpURLConnection httpConn = (HttpURLConnection)conn; httpConn.setAllowUserInteraction(false); httpConn.setInstanceFollowRedirects(true); httpConn.setRequestMethod("GET"); httpConn.connect(); if(httpConn.getResponseCode() == HttpURLConnection.HTTP_OK){ in = httpConn.getInputStream(); } } catch(Exception ex){ Log.d("Networking",ex.getLocalizedMessage()); throw new IOException("Error connecting"); } return in; } private String DownloadText(String URL){ String readStrings = ""; try { InputStream in = OpenHttpConnection(URL); InputStreamReader isr = new InputStreamReader(in); int charReadNumber; char[] inputBuffer = new char[2000]; while((charReadNumber = isr.read(inputBuffer)) > 0){ String readString = String.valueOf(inputBuffer, 0 , charReadNumber); readStrings += readString; inputBuffer = new char[2000]; } in.close(); } catch (Exception e) { Log.d("Networking", e.getLocalizedMessage()); return ""; } return readStrings; } //An asynchronous task is defined by a computation that runs on a background thread //and whose result is published on the UI thread. private class DownloadTextTask extends AsyncTask<String, Void, String>{ //Perform a computation on a background thread. @Override protected String doInBackground(String... urls) { return DownloadText(urls[0]); } //Runs on the UI thread after doInBackground finished @Override protected void onPostExecute(String result) { Toast.makeText(getApplication(), result , Toast.LENGTH_LONG).show(); } } }
<3>Accessing Web Services Using the GET Method
So far, you have learned how to download images and text from the web. The previous section showed how to download some plain text
from a server. Very often, you need to download XML files and parse the contents (a good example of this is consuming web services).
Therefore, in this section you learn how to connect to a web service using the HTTP GET method. Once the web service returns a
result in XML, you extract the relevant parts and display its content using the Toast class.
http://services.aonaware.com/DictService/
This web method is from a dictionary web service that returns the defi nition of a given word. for example, look up "apple" in this dictionary
This web method takes a request in the following fomat:
GET /DictService/DictService.asmx/Define?word=string HTTP/1.1 Host: services.aonaware.com HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length
returns a response in the following format:
<?xml version=”1.0” encoding=”utf-8”?> <WordDefinition xmlns=”http://services.aonaware.com/webservices/”> <Word>string</Word> <Definitions> <Definition> <Word>string</Word> <Dictionary> <Id>string</Id> <Name>string</Name> </Dictionary> <WordDefinition>string</WordDefinition> </Definition>
<Definition> <Word>string</Word> <Dictionary> <Id>string</Id> <Name>string</Name> </Dictionary> <WordDefinition>string</WordDefinition> </Definition> </Definitions> </WordDefinition>
to obtain the definition of a word, you need to establish an HTTP connection to the web method and then parse the XML result that
is returned.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="mirror.android.getwebservice.NetworkingActivity" > <TextView android:id="@+id/tv_show" android:layout_width="wrap_content" android:layout_height="wrap_content"
//To set the scrollbars in the vertical direction; android:maxLines="30" android:scrollbars="vertical" android:text="@string/hello_world" /> </RelativeLayout>
package mirror.android.getwebservice; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.widget.ScrollerCompat; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.widget.TextView; import android.widget.Toast; public class NetworkingActivity extends Activity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_word_definition); textView = (TextView)findViewById(R.id.tv_show);
//To enable scroller textView.setMovementMethod(ScrollingMovementMethod.getInstance()); new AccessWebServiceTask().execute("apple"); } private InputStream OpenHttpConnection(String urlString) throws IOException{ InputStream in = null; URL url = new URL(urlString); URLConnection conn = url.openConnection(); if (!(conn instanceof HttpURLConnection)) throw new IOException("Not an HTTP connection"); try{ HttpURLConnection httpConn = (HttpURLConnection)conn; httpConn.setAllowUserInteraction(false); httpConn.setInstanceFollowRedirects(true); httpConn.setRequestMethod("GET"); httpConn.connect(); if(httpConn.getResponseCode() == HttpURLConnection.HTTP_OK){ in = httpConn.getInputStream(); } } catch(Exception ex){ Log.d("Networking",ex.getLocalizedMessage()); throw new IOException("Error connecting"); } return in; } private String WordDefinition(String word){ InputStream in = null; String strDefinition = ""; try {
//
//1.obtain a Document(DOM) object from an XML file(XML result returned by web service) in = OpenHttpConnection("http://services.aonaware.com/DictService/DictService.asmx/Define?word=" + word); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(in); doc.getDocumentElement().normalize(); //Log.d("Mirror_DOC",doc.toString());
//2.find all the elements with the <Definition> tag // retrieve all the <Definition> elements NodeList definitionElements = doc.getElementsByTagName("Definition"); //Log.d("Mirror_definitionElements",definitionElements.toString() + ", its length is: " + definitionElements.getLength());
//3.definition of a word is contained within the <WordDefinition> elment, then proceed to extract all the definitions // iterate through each <Definition> elements for (int i = 0; i < definitionElements.getLength(); i++) { Node itemNode = definitionElements.item(i); if(itemNode.getNodeType() == Node.ELEMENT_NODE){ // convert the definition node into an Element Element definitionElement = (Element)itemNode; //get all the <WordDefinition> elements under the <Definition> element NodeList wordDefinitionElements = (definitionElement).getElementsByTagName("WordDefinition"); //NodeList wordDefinitionElements = definitionElement.
//4.The text content of the <WordDefinition> element contains the defi nition of a word, //iterate through each <Worddefinition> elements for (int j = 0; j < wordDefinitionElements.getLength(); j++) { // convert a <WordDefinition> node into an Element Element wordDefinitionElement = (Element)wordDefinitionElements.item(j); // get all the child nodes under the <WordDefinition> element NodeList textNodes = ((Node)wordDefinitionElement).getChildNodes(); strDefinition += ((Node)textNodes.item(0)).getNodeValue() + ". \n"; } } } } catch (Exception e) { Log.d("NetworkingActivity", e.getLocalizedMessage()); } return strDefinition; } private class AccessWebServiceTask extends AsyncTask<String, Void, String> { protected String doInBackground(String... urls) { return WordDefinition(urls[0]); } protected void onPostExecute(String result) { //Toast.makeText(getBaseContext(), result, Toast.LENGTH_LONG).show(); textView.setText(result); } } }
Logcat : 5 definitions for the "apple" .