10. Using Android Networking APIs

Applications written with networking components are far more dynamic and content-rich than those that are not. Applications leverage the network for a variety of reasons: to deliver fresh and updated content, to enable social networking features of an otherwise standalone application, to offload heavy processing to high-powered servers, and to allow for data storage beyond what the user can achieve on the device.

Deciding how much networking support your application should contain is part of the application design process—something we talk more about in Chapter 18, “The Mobile Software Development Process.”

Those accustomed to Java networking will find the java.net package familiar. There are also some helpful Android utility classes for various types of network operations and protocols. This chapter focuses on Hypertext Transfer Protocol (HTTP), the most common protocol for networked mobile applications.

Accessing the Internet (HTTP)

The most common way to transfer data to and from the network is to use HTTP. You can use HTTP to encapsulate almost any type of data and to secure the data with Secure Sockets Layer (SSL), which can be important when you transmit data that falls under privacy requirements. Also, most common ports used by HTTP are typically open from the phone networks.

Tip

Recall that as part of the Android Software Development Kit (SDK) License Agreement, developers agree to a number of best practices when it comes to network applications. If you plan to use network support in your application, you might want to review these points within the contract to ensure that your application complies with the agreement.

Reading Data from the Web

Reading data from the Web can be extremely simple. For example, if all you need to do is read some data from a Web site and you have the web address of that data, you can leverage the URL class (available as part of the java.net package) to read a fixed amount of text from a file on a web server, like this:

image


First, a new URL object is created with the URL to the data we want to read. A stream is then opened to the URL resource. From there, we read the data and close the InputStream. Reading data from a server can be that simple.

However, remember that because we work with a network resource, errors can be more common. Our phone might not have network coverage; the server might be down for maintenance or disappear entirely; the URL might be invalid; and network users might experience long waits and timeouts.

This method might work in some instances, for example if your application has lightweight, noncritical network features, but it’s not particularly elegant. In many cases, you might want to know more about the data before reading from it from the URL. For instance, you might want to know how big it is.

Finally, for networking to work in any Android application, permission is required. Your application needs to have the following statement in its AndroidManifest.xml file:

<uses-permission
    android:name="android.permission.INTERNET"/>


Using HttpURLConnection

We can use the HttpURLConnection object to do a little reconnaissance on our URL before we transfer too much data. HttpURLConnection retrieves some information about the resource referenced by the URL object, including HTTP status and header information.

Some of the information you can retrieve from the HttpURLConnection includes the length of the content, content type, and date-time information so that you can check to see if the data changed since the last time you accessed the URL.

Here is a short example of how to use HttpURLConnection to query the same URL previously used:

image


The log lines demonstrate a few useful methods with the HttpURLConnection class. If the URL content is deemed appropriate, you can then call http.getInputStream() to get the same InputStream object as before. From there, reading from the network resource is the same, but more will be known about the resource.

Note

Android ships with Apache Foundation’s HTTPClient v4 (http://hc.apache.org/), which has substantial changes from previous versions. You can find more information about protocol interaction within the org.apache.http package.

Parsing XML from the Network

A large portion of data transmitted between network resources is stored in a structured fashion in Extensible Markup Language (XML). In particular, RSS feeds are provided in a standardized XML format and many web services provide data using these feeds.

Android SDK provides a variety of XML utilities. We dabbled with the XML Pull Parser in Chapter 5, “Managing Application Resources.” We also covered the various SAX and DOM support available in Chapter 9, “Using Android Data and Storage APIs.”

Parsing XML from the network is similar to parsing an XML resource file or a raw file on the file system. Android provides a fast and efficient XML Pull Parser, which is a parser of choice for networked applications.

The following code demonstrates how to use the XML Pull Parser to read an XML file from flickr.com and extract specific data from within it. A TextView called status is assigned before this block of code is executed and displays the status of the parsing operation.

image

image


After the URL is created, the next step is to retrieve an XmlPullParser instance from the XmlPullParserFactory. A Pull Parser has a main method that returns the next event. The events returned by a Pull Parser are similar to methods used in the implementation of a SAX parser handler class. Instead, though, the code is handled iteratively. This method is more efficient for mobile use.

In this example, the only event that we check for is the START_TAG event, signifying the beginning of an XML tag. Attribute values are queried and compared. This example looks specifically for image URLs within the XML from a flickr feed query. When found, a log entry is made.

You can check for the following XML Pull Parser events:

START_TAG: Returned when a new tag is found (that is, <tag>)

TEXT: Returned when text is found (that is, <tag>text</tag> where text has been found)

END_TAG: Returned when the end of tag is found (that is, </tag>)

END_DOCUMENT: Returned when the end of the XML file has been reached

Additionally, the parser can be set to validate the input. Typically, parsing without validation is used when under constrained memory environments, such as a mobile environment. Compliant, nonvalidating parsing is the default for this XML Pull Parser.

Using Threads for Network Calls

The style of networking presented so far causes the UI thread it runs on to block until the operation finishes. For small tasks, this might be acceptable. However, when timeouts or additional processing is added, such as parsing XML, you want to move these time-intensive operations away from the main UI thread by launching a worker new thread. This provides a smoother experience for the user.

The following code demonstrates how to launch a new thread that connects to a remote server, retrieves and parses some XML, and posts a response back to the UI thread to change a TextView:

image

image


For this example, an anonymous Thread object will do. We create it and call its start() method immediately. However, now that code runs on a separate thread, the user interface updates must be posted back to the main thread. This is done by using a Handler object on the main thread and creating Runnable objects that execute to call setText() on the TextView widget named status.

The rest of the code remains the same as in the previous examples. Executing both the parsing code and the networking code on a separate thread allows the user interface to continue to behave in a responsive fashion while the network and parsing operations are done behind the scenes, resulting in a smooth and friendly user experience. This also allows for handling of interim actions by the user, such as canceling the transfer. You can accomplish this by implementing the Thread to listen for certain events and check for certain flags.

Displaying Images from a Network Resource

Now that we covered how you can use a separate thread to parse XML, let’s take our example a bit deeper and talk about working with nonprimitive data types.

Continuing with the previous example of parsing for image locations from a flickr feed, let’s display some images from the feed. The following example reads the image data and displays it on the screen, demonstrating another way that network resources can be used:

image


You can find this block of code within the parser thread, as previously described. After the image source and title of the image have been determined, a new Runnable object is queued for execution on a separate image handling thread. The thread is merely a queue that receives the anonymous Runnable object created here and executes it at least 10 seconds after the last one, resulting in a slideshow of the images from the feed.

Caution

Although the preceding code is sound for local resources and URLs, for sources over slow connections, it might not work properly. This is a known issue with the Android SDK caused by a buffering issue with loading large bitmaps over slow connections. There is a relatively straightforward workaround that is found in the code provided for this chapter.

As with the first networking example, a new URL object is created and an InputStream retrieved from it. A Drawable object is needed to assign to the ImageSwitcher. Then we use the BitmapFactory.decodeStream() method, which takes an InputStream.

Finally, from this Runnable object, which runs on a separate queuing thread, spacing out image drawing, another anonymous Runnable object posts back to the main thread to actually update the ImageSwitcher with the new image. Figure 10.1 shows what the screen might look like showing decoding status and displaying the current image.

Figure 10.1. Screen showing a flickr image and decoding status of feed.

image

Although all this continues to happen while the feed from flickr.com is decoded, certain operations are slower than others. For instance, while the image is decoded or drawn on the screen, a distinct hesitation is noticeable in the progress of the decoding. This is to be expected on current mobile devices because most have only a single thread of execution available for applications. Careful design is needed to provide a reasonably smooth and responsive experience to the user.

Retrieving Android Network Status

The Android SDK provides utilities for gathering information about the current state of the network. This is useful to determine if a network connection is even available before trying to use a network resource. The ConnectivityManager class provides a number of methods to do this. The following code determines if the mobile (cellular) network is available and connected. In addition, it determines the same for the WiFi network:

image


First, an instance of the ConnectivityManager object is retrieved with a call to the getSystemService() method, available as part of your application Context. Then this instance retrieves NetworkInfo objects for both TYPE_WIFI and TYPE_MOBILE (for the cellular network). These objects are queried for their availability but can also be queried at a more detailed status level to learn exactly what state of connection (or disconnection) the network is in. Figure 10.2 shows the typical output for the emulator in which the mobile network is simulated but WiFi isn’t available.

Figure 10.2. Typical network status of the Android SDK emulator.

image

If the network is available, that does not necessarily mean the server that the network resource is on is available. However, a call to the ConnectivityManager method requestRouteToHost() can answer this question. This way, the application can give the user better feedback when there are network problems.

Tip

Use the emulator networking settings to simulate various types of cellular networks, from GSM to HSDPA data rates. Additionally, you can control the latency of the network to be similar to that of the cellular networks. Although this is useful for testing how your application behaves in good conditions for the chosen network type, it can’t simulate the real behavior of the network out in the field when the user is in bad coverage, goes on an elevator, or is on a train rapidly losing and reacquiring network coverage. Only physical handset testing can truly reveal these results.

For your application to read the status of the network, it needs explicit permission. The following statement is required to be in its AndroidManifest.xml file:

<uses-permission
    android:name="android.permission.ACCESS_NETWORK_STATE"/>


Browsing the Web with WebView

Applications that get data from the Web often end up displaying that data on the screen. Instead of customizing various screens with widgets, an application can just use the WebView widget, which uses the WebKit rendering engine, to draw HTML data on the screen. This data can be HTML pages on the Web, as with our example, or it can be locally sourced.

Here is an example of how to use a WebView widget to draw HTML.

image


The corresponding layout file section for this follows:

image


You do not need additional code to load the referenced web page on the screen. The call to the setInitialScale() method scales the view to 30 percent of the original size. For pages that specify absolute sizes, scaling the view is necessary to see the entire page on the screen. Some text might become too small to read though, so testing and page design changes, if under your control, might be required for a good user experience.

The WebView widget allows the user to navigate within the page and click on links. Clicking on links, by default, loads the default web browser on the system. Two classes, in particular, can help modify the behavior of the viewer and gather useful information from it. One of them is the WebViewClient class, which allows the application to listen for certain WebView status events, such as when a page is loading, when a form is submitted, and when a new URL is about to be loaded. The following is an example of how to handle the onPageFinished() method to draw the title of the page on the screen:

image


When the page finishes loading, as indicated by the call to onPageFinished(), a call to the getTitle() method of the WebView allows the title to be retrieved for use. The result of this call is shown in Figure 10.3.

Figure 10.3. WebView used to draw a web page at 30 percent with title showing.

image

Second, you can use the WebChromeClient class in a similar way to the WebViewClient. However, WebChromeClient is specialized for the sorts of items that will be drawn outside the region in which the web content is drawn, typically known as browser chrome. It also includes some callbacks for certain JavaScript calls, such as onJsBeforeUnload(), to confirm navigation away from a page.

The following code demonstrates interactivity from the user. An EditText and Button widget are added below the WebView and the Button handler is implemented as follows:

image


Calling the loadUrl() method again, as shown, is all that is needed to cause the WebView widget to download another HTML page for display, as shown in Figure 10.4. From here, a generic web browser can be built in to any application, but often restrictions will be applied so that the user is restricted to browsing relevant HTML documents (such as the application’s home server).

Figure 10.4. WebView with EditText allowing the user to enter an arbitrary web URL.

image

Whether you use WebView to display the main user interface of your application or use it sparingly to draw such things as help pages, there are circumstances where it might be the ideal widget for the job to save coding time, especially when compared to a custom screen design. Leveraging the power of the open source engine, WebKit, WebView can provide a powerful, standards-based HTML viewer for applications. Support for WebKit is widespread because it is used in various desktop browsers, including Safari and Google Chrome, and a variety of mobile browsers, including those on the Apple iPhone and Nokia S60.

Summary

Networking on the Android platform is standardized, using a combination of powerful yet familiar technologies and libraries such as java.net and WebKit. Although the implementation of networking features within applications is generally straightforward, mobile application developers need to plan for less stable connectivity than one might expect in a home or office network setting—connectivity depends on the location of the users and their device.

Integrating networking features into your mobile application needs to be considered at the design level. Users demand responsive applications, so time-intensive operations should not block from the main UI thread. Finally, don’t forget to handle application lifecycle events smoothly with network activities.

References and More Information

Java.net package information: http://developer.android.com/reference/java/net/package-summary.html

Android.net package information: http://developer.android.com/reference/android/net/package-summary.html

Android XML Pull Parser: http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html

More information on XML Pull Parsing: www.xmlpull.org/

WebKit Open Source Project: http://webkit.org/

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.243.130