[Android Software Development] michael.the.don:
[Ultimate Guide][Part 6-II-released][3/09/2011]Android App Development - From Scratch

PART VI-II

Introducing Adapters

Adapters are bridging classes that bind data to user-interface Views. The adapter is responsible for creating the child views used to represent each item and providing access to the underlying data. User-interface controls that support Adapter binding must extend the AdapterView abstract class. It’s possible to create your own AdapterView-derived controls and create new Adapter classes to bind them.

Introducing Some Android-Supplied Adapters

In many cases, you won’t have to create your own Adapter from scratch. Android supplies a set of Adapters that pump data into the native user-interface widgets. Because Adapters are responsible both for supplying the data and selecting the Views that represent each item, Adaptors can radically modify the appearance and functionality of the controls they’re bound to. The following list highlights two of the most useful and versatile native adapters:

❑ ArrayAdapter The ArrayAdapter is a generic class that binds Adapter Views to an array of objects. By default, the ArrayAdapter binds the toString value of each object to a TextView control defined within a layout. Alternative constructors llow you to use more complex layouts, or you can extend the class to use alternatives to Text View (such as populating an

ImageView or nested layout) by overriding the getView method.

❑ SimpleCursorAdapter The SimpleCursorAdapter binds Views to cursors returned from Content Provider queries. You specify an XML layout defi nition and then bind the value within each column in the result set, to a View in that layout.

Using Adapters for Data Binding

To apply an Adapter to an AdapterView-derived class, you call the View’s setAdapter method, passing in an Adapter instance, as shown in the snippet below:

ArrayList<String> myStringArray = new ArrayList<String>();

ArrayAdapter<String> myAdapterInstance;

int layoutID = android.R.layout.simple_list_item_1;

myAdapterInstance = new ArrayAdapter<String>(this, layoutID, myStringArray);

myListView.setAdapter(myAdapterInstance);

Using Internet Resources

With Internet connectivity and WebKit browser, you might well ask if there’s any reason to create native Internet-based applications when you could make a web-based version instead.

There are several benefits to creating thick- and thin-client native applications rather than relying on entirely web-based solutions:

❑ Bandwidth Static resources like images, layouts, and sounds can be expensive data consumers on devices with limited and often expensive bandwidth restraints. By creating a native application, you can limit the bandwidth requirements to only data updates.

❑ Caching Mobile Internet access has not yet reached the point of ubiquity. With a browserbased solution, a patchy Internet connection can result in intermittent application availability. A native application can cache data to provide as much functionality as possible without a live connection.

❑ Native Features Android devices are more than a simple platform for running a browser; they include location-based services, camera hardware, and accelerometers. By creating a native application, you can combine the data available online with the hardware features available on the device to provide a richer user experience.

Connecting to an Internet Resource

While the details of working with specific web services aren’t covered within this book, it’s useful to know the general principles of connecting to the Internet and getting an input stream from a remote data source. Before you can access Internet resources, you need to add an INTERNET uses-permission node to your application manifest, as shown in the following XML snippet:

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

The following skeleton code shows the basic pattern for opening an Internet data stream:

String myFeed = getString(R.string.my_feed);

try {

URL url = new URL(myFeed);

URLConnection connection = url.openConnection();

HttpURLConnection httpConnection = (HttpURLConnection)connection;

int responseCode = httpConnection.getResponseCode();

if (responseCode == HttpURLConnection.HTTP_OK) {

InputStream in = httpConnection.getInputStream();

[ ... Process the input stream as required ... ]

}

}

catch (MalformedURLException e) { }

catch (IOException e) { }

Android includes several classes to help you handle network communications. They are available in the java.net.* and android.net.* packages.

Leveraging Internet Resources

Android offers several ways to leverage Internet resources. At one extreme, you can use the WebView widget to include a WebKit-based browser control within an Activity. At the other extreme, you can use client-side APIs such as Google’s GData APIs to interact directly with server processes. Somewhere in between, you can process remote XML feeds to extract and process data using a Java-based XML parser such as SAX or javax. Detailed instructions for parsing XML and interacting with specific web services are outside the scope of this book. That said, the Earthquake example, included later in this chapter, gives a fully worked example of parsing an XML feed using the javax classes. If you’re using Internet resources in your application, remember that your users’ data connections depend on the communications technology available to them. EDGE and GSM connections are notoriously low bandwidth, while a Wi-Fi connection may be unreliable in a mobile setting. Optimize the user experience by limiting the quantity of data being transmitted, and ensure that your application is robust enough to handle network outages and bandwidth limitations.

Introducing Dialogs

Dialog boxes are a common UI metaphor in desktop and web applications. They’re used to help users answer questions, make selections, confirm actions, and read warning or error messages. An Android Dialog is a floating window that partially obscures the Activity that launched it.

There are three ways to implement a Dialog box in Android:

❑ Using a Dialog-Class Descendent As well as the general-purpose AlertDialog class, Android includes several specialist classes that extend Dialog. Each is designed to provide specific Dialog-box functionality. Dialog-class-based screens are constructed entirely within their calling Activity, so they don’t need to be registered in the manifest, and their life cycle is controlled entirely by the calling Activity.

❑ Dialog-Themed Activities You can apply the Dialog theme to a regular Activity to give it the appearance of a Dialog box.

❑ Toasts Toasts are special non-modal transient message boxes, often used by Broadcast Receivers and background services to notify users of events.

Introducing the Dialog Class

The Dialog class implements a simple floating window that is constructed entirely within an Activity. To use the base Dialog class, you create a new instance and set the title and layout as shown below:

Dialog d = new Dialog(MyActivity.this);

// Have the new window tint and blur the window it

// obscures.

Window window = d.getWindow();

window.setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,

WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

d.setTitle(“Dialog Title”);

d.setContentView(R.layout.dialog_view);

TextView text = (TextView)d.findViewById(R.id.dialogTextView);

text.setText(“This is the text in my dialog”);

The AlertDialog Class

The AlertDialog class is one of the most versatile Dialog implementations. It offers various options that let you construct screens for some of the most common Dialog-box use cases, including:

1.	Presenting a message to the user offering one to three options in the form of alternative buttons. This functionality is probably familiar to you if you¡¯ve done any desktop programming, where the buttons presented are usually a selection of OK, Cancel, Yes, or No.

2.	. Offering a list of options in the form of check buttons or radio buttons.

3.	. Providing a text entry box for user input.

To construct the Alert Dialog user interface, create a new AlertDialog.Builder object, as shown below:

AlertDialog.Builder ad = new AlertDialog.Builder(context);

You can then assign values for the title and message to display, and optionally assign values to be used for any buttons, selection items, and text input boxes you wish to display. That includes setting event listeners to handle user interaction.

The following code gives an example of a new Alert Dialog used to display a message and offer two button options to continue. Clicking on either button will automatically close the Dialog after executing the attached Click Listener.

Context context = MyActivity.this;

String title = ¡°It is Pitch Black¡±;

String message = ¡°You are likely to be eaten by a grue.¡±;

String button1String = ¡°Go Back¡±;

String button2String = ¡°Move Forward¡±;

AlertDialog.Builder ad = new AlertDialog.Builder(context);

ad.setTitle(title);

ad.setMessage(message);

ad.setPositiveButton(button1String,

new OnClickListener() {

public void onClick(DialogInterface dialog,

int arg1) {

eatenByGrue();

}

});

ad.setNegativeButton(button2String,

new OnClickListener(){

public void onClick(DialogInterface dialog,

int arg1) {

// do nothing

}

});

ad.setCancelable(true);

ad.setOnCancelListener(new OnCancelListener() {

public void onCancel(DialogInterface dialog) {

eatenByGrue();

}

});

Specialist Input Dialogs

One of the major uses of Dialog boxes is to provide an interface for user input. Android includes several specialist Dialog boxes that encapsulate controls designed to facilitate common user input requests. They include the following:

❑ DatePickerDialog Lets users select a date from a DatePicker View. The constructor includes a callback listener to alert your calling Activity when the date has been set.

❑ TimePickerDialog Similar to the DatePickerDialog, this Dialog lets users select a time from a TimePicker View.

❑ ProgressDialog A Dialog that displays a progress bar beneath a message textbox. Perfect for keeping the user informed of the ongoing progress of a time-consuming operation.

Using and Managing Dialogs

Rather than creating new instances of a Dialog each time it’s required, Android provides theOnCreateDialog and onPrepareDialog event handlers within the Activity class to persist and manage Dialog-box instances. By overriding the onCreateDialog class, you can specify Dialogs that will be created on demand when showDialog is used to display a specific Dialog. As shown in this code snippet, the overridden method includes a switch statement that lets you determine which Dialog is required:

static final private int TIME_DIALOG = 1;

@Override

public Dialog onCreateDialog(int id) {

switch(id) {

case (TIME_DIALOG) :

AlertDialog.Builder timeDialog = new AlertDialog.Builder(this);

timeDialog.setTitle(“The Current Time Is...”);

timeDialog.setMessage(“Now”);

return timeDialog.create();

}

return null;

}

After the initial creation, each time a showDialog is called, it will trigger the onPrepareDialog handler. By overriding this method, you can modify a Dialog immediately before it is displayed. This lets you contextualize any of the display values, as shown in the following snippet, which assigns the current time to the Dialog created above:

@Override

public void onPrepareDialog(int id, Dialog dialog) {

switch(id) {

case (TIME_DIALOG) :

SimpleDateFormat sdf = new SimpleDateFormat(“HH:mm:ss”);

Date currentTime;

currentTime = new Date(java.lang.System.currentTimeMillis());

String dateString = sdf.format(currentTime);

AlertDialog timeDialog = (AlertDialog)dialog;

timeDialog.setMessage(dateString);

break;

}

}

Once you’ve overridden these methods, you can display the Dialogs by calling showDialog, as shown below. Pass in the identifi er for the Dialog you wish to display, and Android will create (if necessary) and prepare the Dialog before displaying it:

showDialog(TIME_DIALOG);

As well as improving resource use, this technique lets your Activity handle the persistence of state information within Dialogs. Any selection or data input (such as item selection and text entry) will be persisted between displays of each Dialog instance.

Using Activities as Dialogs

Dialogs offer a simple and lightweight technique for displaying screens, but there will still be times when you need more control over the content and life cycle of your Dialog box. The solution is to implement it as a full Activity. By creating an Activity, you lose the lightweight nature of the Dialog class, but you gain the ability to implement any screen you want and full access to the Activity life-cycle event handlers.

So, when is an Activity a Dialog? The easiest way to make an Activity look like a Dialog is to apply the android:style/ Theme.Dialog theme when you add it to your manifest, as shown in the following XML snippet:

<activity android:name=”MyDialogActivity”

android:theme=”@android:style/Theme.Dialog”>

</activity>

This will cause your Activity to behave like a Dialog, floating on top of, and partially obscuring, the Activity beneath it.