- No licensing, distribution, or development fees
- Wi-Fi hardware access
- GSM, EDGE, and 3G networks for telephony or data transfer, allowing you to make or receive calls or SMS messages, or to send and retrieve data across mobile networks
- Comprehensive APIs for location-based services such as GPS
- Full multimedia hardware control including playback and recording using the camera and microphone
- APIs for accelerometer and compass hardware
- IPC message passing
- Shared data stores
- An integrated open source WebKit-based browser
- Full support for applications that integrate Map controls as part of their user interface
- Peer-to-peer (P2P) support using Google Talk
- Mobile-optimized hardware-accelerated graphics including a path-based 2D graphics library and support for 3D graphics using OpenGL ES
- Media libraries for playing and recording a variety of audio/video or still image formats
- An application framework that encourages reuse of application components and the replacement of native applications
Android supports applications and services designed to run invisibly in the background.
Rapid and efficient data storage and retrieval are essential for a device whose storage capacity is limited by its compact nature.
- A Java ME implementation Android applications are written using the Java language, but they are not run within a Java ME virtual machine, and Java-compiled classes and executables will not run natively in Android.
- Part of the Linux Phone Standards Forum (LiPS) or the Open Mobile Alliance (OMA) Android runs on an open source Linux kernel, but, while their goals are similar, Android’s complete software stack approach goes further than the focus of these standards defining organizations.
- Simply an application layer (like UIQ or S60) While it does include an application layer, “Android” also describes the entire software stack encompassing the underlying operating system, API libraries, and the applications themselves.
- A mobile phone handset Android includes a reference design for mobile handset manufacturers, but unlike the iPhone, there is no single “Android Phone.” Instead, Android has been designed to support many alternative hardware devices.
- Google’s answer to the iPhone The iPhone is a fully proprietary hardware and software platform released by a single company (Apple), while Android is an open source software stack produced and supported by the Open Handset Alliance and designed to operate on any handset that meets the requirements. There’s been a lot of speculation regarding a Google-branded Android phone, but even should Google produce one, it will be just one company’s hardware implementation of the Android platform.
http://googleblog.blogspot.com/2007/11/wheres-my-gphone.html
- A hardware reference design that describes the capabilities required of a mobile device in order to support the software stack
- A Linux operating system kernel that provides the low-level interface with the hardware, memory management, and process control, all optimized for mobile devices
- Open source libraries for application development including SQLite, WebKit, OpenGL, and a media manager A run time used to execute and host Android applications, including the Dalvik virtual machine and the core libraries that provide Android specific c functionality. The run time is designed to be small and effi cient for use on mobile devices.
- An application framework that agnostically exposes system services to the application layer, including the window manager, content providers, location manager, telephony, and peer-to-peer services
- A user interface framework used to host and launch applications
- Preinstalled applications shipped as part of the stack
- A software development kit used to create applications, including the tools, plug-ins, and documentation
Android phones will normally come with a suite of preinstalled applications including, but not limited to:
- An e-mail client compatible with Gmail but not limited to it
- An SMS management application
- A full PIM (personal information management) suite including a calendar and contacts list, both tightly integrated with Google’s online services
- A fully featured mobile Google Maps application including StreetView, business finder, driving directions, satellite view, and traffic conditions
- A WebKit-based web browser
- An Instant Messaging Client
- A music player and picture viewer
- The Android Marketplace client for downloading third-party Android applications.
- The Amazon MP3 store client for purchasing DRM free music.
- Active Processes Active (foreground) processes are those hosting applications with components currently interacting with the user. These are the processes Android is trying to keep responsive by reclaiming resources. There are generally very few of these processes, and they will be killed only as a last resort.Active processes include:
- Activities in an “active” state; that is, they are in the foreground and responding to user events. You will explore Activity states in greater detail later in this chapter.
- Activities, Services, or Broadcast Receivers that are currently executing an onReceive event handler.
- Services that are executing an onStart, onCreate, or onDestroy event handler.
-
- Visible Processes Visible, but inactive processes are those hosting “visible” Activities. As the name suggests, visible Activities are visible, but they aren’t in the foreground or responding to user events. This happens when an Activity is only partially obscured (by a non-full-screen or transparent Activity). There are generally very few visible processes, and they’ll only be killed in extreme circumstances to allow active processes to continue.
- Started Service Processes Processes hosting Services that have been started. Services support ongoing processing that should continue without a visible interface. Because Services don’t interact directly with the user, they receive a slightly lower priority than visible Activities. They are still considered to be foreground processes and won’t be killed unless resources are needed for active or visible processes.
- Background Processes Processes hosting Activities that aren’t visible and that don’t have any Services that have been started are considered background processes. There will generally be a large number of background processes that Android will kill using a last-seen-first-killed pattern to obtain resources for foreground processes.
- Empty Processes To improve overall system performance, Android often retains applications in memory after they have reached the end of their lifetimes. Android maintains this cache to improve the start-up time of applications when they’re re-launched. These processes are routinely killed as required.
<resources>
<string name=”app_name”>To Do List</string>
<color name=”app_background”>#FF0000FF</color>
<dimen name=”default_border”>5px</dimen>
<array name=”string_array”>
<item>Item 1</item>
<item>Item 2</item>
<item>Item 3</item>
</array>
<array name=”integer_array”>
<item>3</item>
<item>2</item>
<item>1</item>
</array>
</resources>
Strings
Externalizing your strings helps maintain consistency within your application and makes it much easier to create localized versions.
String resources are specified using the string tag as shown in the following XML snippet:
<string name=”stop_message”>Stop.</string>
Within your code, use the Html.fromHtml method to convert this back into a styled character sequence:
String rString = getString(R.string.stop_message);
String fString = String.format(rString, “Collaborate and listen.”);
CharSequence styledString = Html.fromHtml(fString);
Use the color tag to define a new color resource. Specify the color value using a # symbol followed by the (optional) alpha channel, then the red, green, and blue values using one or two hexadecimal numbers with any of the following notations:
-
#RGB
-
#RRGGBB
-
#ARGB
-
#ARRGGBB
<color name=”opaque_blue”>#00F</color>
<color name=”transparent_green”>#7700FF00</color>
Dimensions are most commonly referenced within style and layout resources. They’re useful for creating layout constants such as borders and font heights.
To specify a dimension resource, use the dimen tag, specifying the dimension value, followed by an identifier describing the scale of your dimension:
-
px Screen pixels
-
in Physical inches
-
pt Physical points
-
mm Physical millimeters
-
dp Density-independent pixels relative to a 160-dpi screen
-
sp Scale-independent pixels
These alternatives let you define a dimension not only in absolute terms, but also using relative scales that account for different screen resolutions and densities to simplify scaling on different hardware.
The following XML snippet shows how to specify dimension values for a large font size and a standard border:
<dimen name=”standard_border”>5px</dimen>
<dimen name=”large_font_size”>16sp</dimen>
Style resources let your applications maintain a consistent look and feel by specifying the attribute values used by Views. The most common use of themes and styles is to store the colors and fonts for an application.
To create a style, use a style tag that includes a name attribute, and contains one or more item tags. Each item tag should include a name attribute used to specify the attribute (such as font size or color) being defined. The tag itself should then contain the value, as shown in the skeleton code below:
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
<style name=”StyleName”>
<item name=”attributeName”>value</item>
</style>
</resources>
Styles support inheritance using the parent attribute on the style tag, making it easy to create simple variations.
The following example shows two styles that can also be used as a theme; a base style that sets several text properties and a second style that modifies the first to specify a smaller font.
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
<style name=”BaseText”>
<item name=”android:textSize”>14sp</item>
<item name=”android:textColor”>#111</item>
</style>
<style name=”SmallText” parent=”BaseText”>
<item name=”android:textSize”>8sp</item>
</style>
</resources>
Drawable resources include bitmaps and NinePatch (stretchable PNG) images. They are stored as individual files in the res/drawable folder.
The resource identifier for a bitmap resource is the lowercase filename without an extension.
The preferred format for a bitmap resource is PNG, although JPG and GIF fi les are also supported.
NinePatch (or stretchable) images are PNG fi les that mark the parts of an image that can be stretched. NinePatch images must be properly defi ned PNG files that end in .9.png. The resource identifier for NinePatches is the filename without the trailing .9.png.
A NinePatch is a variation of a PNG image that uses a 1-pixel border to defi ne the area of the image that can be stretched if the image is enlarged. To create a NinePatch, draw single-pixel black lines that represent stretchable areas along the left and top borders of your image. The unmarked sections won’t be resized, and the relative size of each of the marked sections will remain the same as the image size changes.
NinePatches are a powerful technique for creating images for the backgrounds of Views or Activities that may have a variable size; for example, Android uses NinePatches for creating button backgrounds.
Layout resources let you decouple your presentation layer by designing user-interface layouts in XML rather than constructing them in code.
The most common use of a layout is to define the user interface for an Activity. Once defined in XML, the layout is “inflated” within an Activity using setContentView, usually within the onCreate method.
You can also reference layouts from within other layout resources, such as layouts for each row in a List View.
Using layouts to create your screens is best-practice UI design in Android. The decoupling of the layout from the code lets you create optimized layouts for different hardware configurations, such as varying screen sizes, orientation, or the presence of keyboards and touch screens.
Each layout definition is stored in a separate fi le, each containing a single layout, in the res/layout folder. The filename then becomes the resource identifier.
A thorough explanation of layout containers and View elements is included in the next chapter, but as an example, the following code snippet shows the layout created by the New Project Wizard. It uses a LinearLayout as a layout container for a TextView that displays the “Hello World” greeting.
<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”Hello World!”
/>
</LinearLayout>
Android supports two types of animation. Tweened animations can be used to rotate, move, stretch, and fade a View; or you can create frame-by-frame animations to display a sequence of drawable images.
Defining animations as external resources allows you to reuse the same sequence in multiple places and provides you with the opportunity to present an alternative animation based on device hardware or orientation.
Each tweened animation is stored in a separate XML fi le in the project’s res/anim folder. As with layouts and drawable resources, the animation’s filename is used as its resource identifier.
An animation can be defined for changes in alpha (fading), scale (scaling), translate (moving), or rotate (rotating).
| Alpha | fromAlpha and toAlpha | Float from 0 to 1 |
| Scale | fromXScale/toXScale fromYScale/toYScale pivotX/pivotY | Float from 0 to 1 Float from 0 to 1 String of the percentage of graphic width/height from 0% to 100% |
| Translate | fromX/toX fromY/toY | Float from 0 to 1 Float from 0 to 1 |
| Rotate | fromDegrees/toDegrees pivotX/pivotY | Float from 0 to 360 String of the percentage of graphic width/height from 0% to 100% |
You can create a combination of animations using the set tag. An animation set contains one or more animation transformations and supports various additional tags and attributes to customize when and how each animation within the set is run.
The following list shows some of the set tags available:
-
duration Duration of the animation in milliseconds.
-
startOffset Millisecond delay before starting this animation.
-
fillBefore True to apply the animation transformation before it begins.
-
fillAfter True to apply the animation transformation after it begins.
-
interpolator Interpolator to set how the speed of this effect varies over time. To specify an interpolator, reference the system animation resources at android:anim/interpolatorName.
If you do not use the startOffset tag, all the animation effects within a set will execute simultaneously.
The following example shows an animation set that spins the target 360 degrees while it shrinks and fades out:
<?xml version=”1.0” encoding=”utf-8”?>
<set xmlns:android=”http://schemas.android.com/apk/res/android”
android:interpolator=”@android:anim/accelerate_interpolator”>
<rotate
android:fromDegrees=”0”
android:toDegrees=”360”
android:pivotX=”50%”
android:pivotY=”50%”
android:startOffset=”500”
android:duration=”1000” />
<scale
android:fromXScale=”1.0”
android:toXScale=”0.0”
android:fromYScale=”1.0”
android:toYScale=”0.0”
android:pivotX=”50%”
android:pivotY=”50%”
android:startOffset=”500”
android:duration=”500” />
<alpha
android:fromAlpha=”1.0”
android:toAlpha=”0.0”
android:startOffset=”500”
android:duration=”500” />
</set>
Frame-by-Frame Animations
Frame-by-frame animations let you create a sequence of drawables, each of which will be displayed for a specified duration, on the background of a View.
Because frame-by-frame animations represent animated drawables, they are stored in the res/drawble folder, rather than with the tweened animations, and use their filenames (without the xml extension) as their resource IDs.
The following XML snippet shows a simple animation that cycles through a series of bitmap resources, displaying each one for half a second. In order to use this snippet, you will need to create new image resources rocket1 through rocket3.
<animation-list
xmlns:android=”http://schemas.android.com/apk/res/android”
android:oneshot=”false”>
<item android:drawable=”@drawable/rocket1” android:duration=”500” />
<item android:drawable=”@drawable/rocket2” android:duration=”500” />
<item android:drawable=”@drawable/rocket3” android:duration=”500” />
</animation-list>
Using Resources
As well as the resources you create, Android supplies several system resources that you can use in your applications. The resources can be used directly from your application code and can also be referenced from within other resources (e.g., a dimension resource might be referenced in a layout definition).
It’s important to note that when using resources you cannot choose a particular specialized version. Android will automatically select the most appropriate value for a given resource identifier based on the current hardware and device settings.
You access resources in code using the static R class. R is a generated class based on your external resources and created by compiling your project. The R class contains static subclasses for each of the resource types for which you’ve defined at least one resource. For example, the default new project includes the R.string and R.drawable subclasses.
If you are using the ADT plug-in in Eclipse, the R class will be created automatically when you make any change to an external resource fi le or folder. If you are not using the plug-in, use the AAPT tool to compile your project and generate the R class. R is a compiler-generated class, so don’t make any manual modifications to it as they will be lost when the fi le is regenerated.
Each of the subclasses within R exposes its associated resources as variables, with the variable names matching the resource identifiers — for example, R.string.app_name or R.drawable.icon.
The value of these variables is a reference to the corresponding resource’s location in the resource table, not an instance of the resource itself.
Where a constructor or method, such as setContentView, accepts a resource identifier, you can pass in the resource variable, as shown in the code snippet below:
// Inflate a layout resource.
setContentView(R.layout.main);
// Display a transient dialog box that displays the
// error message string resource.
Toast.makeText(this, R.string.app_error, Toast.LENGTH_LONG).show();
When you need an instance of the resource itself, you’ll need to use helper methods to extract them from the resource table, represented by an instance of the Resources class.
Because these methods perform lookups on the application’s resource table, these helper methods can’t be static. Use the getResources method on your application context as shown in the snippet below to access your application’s Resource instance:
Resources myResources = getResources();
The Resources class includes getters for each of the available resource types and generally works by passing in the resource ID you’d like an instance of. The following code snippet shows an example of using the helper methods to return a selection of resource values:
Resources myResources = getResources();
CharSequence styledText = myResources.getText(R.string.stop_message);
Drawable icon = myResources.getDrawable(R.drawable.app_icon);
int opaqueBlue = myResources.getColor(R.color.opaque_blue);
float borderWidth = myResources.getDimension(R.dimen.standard_border);
Animation tranOut;
tranOut = AnimationUtils.loadAnimation(this, R.anim.spin_shrink_fade);
String[] stringArray;
stringArray = myResources.getStringArray(R.array.string_array);
int[] intArray = myResources.getIntArray(R.array.integer_array);
Frame-by-frame animated resources are infl ated into AnimationResources. You can return the value using getDrawable and casting the return value as shown below:
AnimationDrawable rocket;
rocket = (AnimationDrawable)myResources.getDrawable(R.drawable.frame_by_frame);
At the time of going to print, there is a bug in the AnimationDrawable class. Currently, AnimationDrawable resources are not properly loaded until some time after an Activity’s onCreate method has completed. Current work-arounds use timers to force a delay before loading a frame-by-frame resource.
to be continued . . . . . .
previous Android Development Tools
Before you start writing Android applications, it’s important to understand how they’re constructed and have an understanding of the Android application life cycle. In this chapter, you’ll be introduced to the loosely coupled components that make up Android applications (and how they’re bound together using the Android manifest). Next you’ll see how and why you should use external resources, before getting an introduction to the Activity component.
In recent years, there’s been a move toward development frameworks featuring managed code, such as the Java virtual machine and the .NET Common Language Runtime.
Mobile devices now come in many shapes and sizes and are used internationally. In this chapter, you’ll learn how to give your applications the flexibility to run seamlessly on different hardware, in different countries, and using multiple languages by externalizing resources.
Next you’ll examine the Activity component. Arguably the most important of the Android building blocks, the Activity class forms the basis for all your user interface screens. You’ll learn how to create new Activities and gain an understanding of their life cycles and how they affect the application lifetime.
Finally, you’ll be introduced to some of the Activity subclasses that wrap up resource management for some common user interface components such as maps and lists.
What Makes an Android Application?
Android applications consist of loosely coupled components, bound using a project manifest that describes each component and how they interact.
There are six components that provide the building blocks for your applications:
-
Activities Your application’s presentation layer. Every screen in your application will be an extension of the Activity class. Activities use Views to form graphical user interfaces that display information and respond to user actions. In terms of desktop development, an Activity is equivalent to a Form.
-
Services The invisible workers of your application. Service components run invisibly, updating your data sources and visible Activities and triggering Notifications. They’re used to perform regular processing that needs to continue even when your application’s Activities aren’t active or visible.
-
Content Providers A shareable data store. Content Providers are used to manage and share application databases. Content Providers are the preferred way of sharing data across application boundaries. This means that you can configure your own Content Providers to permit access from other applications and use Content Providers exposed by others to access their stored data. Android devices include several native Content Providers that expose useful databases like contact information.
-
Intents A simple message-passing framework. Using Intents, you can broadcast messages system- wide or to a target Activity or Service, stating your intention to have an action performed. The system will then determine the target(s) that will perform any actions as appropriate.
-
Broadcast Receivers Intent broadcast consumers. By creating and registering a Broadcast Receiver, your application can listen for broadcast Intents that match specific filter criteria. Broadcast Receivers will automatically start your application to respond to an incoming Intent, making them ideal for event-driven applications.
-
Notifications A user notification framework. Notifications let you signal users without stealing focus or interrupting their current Activities. They’re the preferred technique for getting a user’s attention from within a Service or Broadcast Receiver. For example, when a device receives a text message or an incoming call, it alerts you by flashing lights, making sounds, displaying icons, or showing dialog messages. You can trigger these same events from your own applications using Notifications.
By decoupling the dependencies between application components, you can share and interchange individual pieces, such as Content Providers or Services, with other applications — both your own and those of third parties.
Introducing the Application Manifest
Each Android project includes a manifest fi le, AndroidManifest.xml, stored in the root of the project hierarchy. The manifest lets you define the structure and metadata of your application and its components.
It includes nodes for each of the components (Activities, Services, Content Providers, and Broadcast Receivers) that make up your application and, using Intent Filters and Permissions, determines how they interact with each other and other applications.
It also offers attributes to specify application metadata (like its icon or theme), and additional top-level nodes can be used for security settings and unit tests as described below.
The manifest is made up of a root manifest tag with a package attribute set to the project’s package. It usually includes an xmlns:android attribute that supplies several system attributes used within the file. A typical manifest node is shown in the XML snippet below:
<manifest xmlns:android=http://schemas.android.com/apk/res/android
package=”com.my_domain.my_app”>
[ ... manifest nodes ... ]
</manifest>
The manifest tag includes nodes that define the application components, security settings, and test classes that make up your application. The following list gives a summary of the available manifest node tags, and an XML snippet demonstrating how each one is used:
- application A manifest can contain only one application node. It uses attributes to specify the metadata for your application (including its title, icon, and theme). It also acts as a container that includes the Activity, Service, Content Provider, and Broadcast Receiver tags used to specify the application components.
<application android:icon=”@drawable/icon”
android:theme=”@style/my_theme”>
[ ... application nodes ... ]
</application> -
activity An activity tag is required for every Activity displayed by your application, using the android:name attribute to specify the class name. This must include the main launch Activity and any other screen or dialogs that can be displayed. Trying to start an Activity that’s not defi ned in the manifest will throw a runtime exception. Each Activity node supports intent-filter child tags that specify which Intents launch the Activity.
<activity android:name=”.MyActivity” android:label=”@string/app_name”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity> -
service As with the activity tag, create a new service tag for each Service class used in your application. Service tags also support intent-filter child tags to allow late runtime binding.
<service android:enabled=”true” android:name=”.MyService”></service> -
provider Provider tags are used for each of your application’s Content Providers. Content Providers are used to manage database access and sharing within and between applications.
<provider android:permission=”com.paad.MY_PERMISSION”
android:name=”.MyContentProvider”
android:enabled=”true”
android:authorities=”com.paad.myapp.MyContentProvider”>
</provider> -
receiver By adding a receiver tag, you can register a Broadcast Receiver without having to launch your application first. As you’ll see in Chapter 5, Broadcast Receivers are like global event listeners that, once registered, will execute whenever a matching Intent is broadcast by an application. By registering a Broadcast Receiver in the manifest, you can make this process entirely autonomous. If a matching Intent is broadcast, your application will be started automatically and the registered Broadcast Receiver will be run.
<receiver android:enabled=”true”
android:label=”My Broadcast Receiver”
android:name=”.MyBroadcastReceiver”>
</receiver> -
uses-permission As part of the security model, uses-permission tags declare the permissions you’ve determined that your application needs for it to operate properly. The permissions you include will be presented to the user, to grant or deny, during installation. Permissions are required for many of the native Android services, particularly those with a cost or security implication (such as dialing, receiving SMS, or using the location-based services). As shown in the item below, third-party applications, including your own, can also specify permissions before providing access to shared application components.
<uses-permission android:name=”android.permission.ACCESS_LOCATION”>
</uses-permission> -
permission Before you can restrict access to an application component, you need to define a permission in the manifest. Use the permission tag to create these permission definitions. Application components can then require them by adding the android:permission attribute. Other applications will then need to include a uses-permission tag in their manifests (and have it granted) before they can use these protected components.
Within the permission tag, you can specify the level of access the permission will permit (normal, dangerous, signature, signature Or System), a label, and an external resource containing the description that explain the risks of granting this permission.
<permission android:name=”com.paad.DETONATE_DEVICE”
android:protectionLevel=”dangerous”
android:label=”Self Destruct”
android:description=”@string/detonate_description”>
</permission> - instrumentation Instrumentation classes provide a framework for running tests on your Activities and Services at run time. They provide hooks to monitor your application and its interaction with the system resources. Create a new node for each of the test classes you’ve created for your application.
<instrumentation android:label=”My Test”
android:name=”.MyTestClass”
android:targetPackage=”com.paad.aPackage”>
</instrumentation>
A more detailed description of the manifest and each of these nodes can be found at
http://code.google.com/android/devel/bblocks-manifest.html
The ADT New Project Wizard automatically creates a new manifest fi le when it creates a new project.
You’ll return to the manifest as each of the application components is introduced.
Using the Manifest Editor
The ADT plug-in includes a visual Manifest Editor to manage your manifest, rather than your having to manipulate the underlying XML directly.
To use the Manifest Editor in Eclipse, right-click the AndroidManifest.xml fi le in your project folder, and select Open With ➪ Android Manifest Editor. This presents the Android Manifest Overview screen, as shown in Figure 3-1. This gives you a high-level view of your application structure and provides shortcut links to the Application, Permissions, Instrumentation, and raw XML screens.
Each of the next three tabs contains a visual interface for managing the application, security, and instrumentation (testing) settings, while the last tag (using the manifest’s fi lename) gives access to the raw XML.
Of particular interest is the Application tab, shown in Figure 3-2. Use it to manage the application node and the application component hierarchy, where you specify the application components.
You can specify an application’s attributes — including its Icon, Label, and Theme — in the Application Attributes panel. The Application Nodes tree beneath it lets you manage the application components, including their attributes and any associated Intent Filter subnodes.
next The Android Application Life Cycle
- The Android Emulator An implementation of the Android virtual machine designed to run on your development computer. You can use the emulator to test and debug your android applications.
- Dalvik Debug Monitoring Service (DDMS) Use the DDMS perspective to monitor and control the Dalvik virtual machines on which you’re debugging your applications.
- Android Asset Packaging Tool (AAPT) Constructs the distributable Android package fi les (.apk).
- Android Debug Bridge (ADB) The ADB is a client-server application that provides a link to a running emulator. It lets you copy fi les, install compiled application packages (.apk), and run shell commands.
- SQLite3 A database tool that you can use to access the SQLite database fi les created and used by Android
- Traceview Graphical analysis tool for viewing the trace logs from your Android application
- MkSDCard Creates an SDCard disk image that can be used by the emulator to simulate an external storage card.
- dx Converts Java .class bytecode into Android .dex bytecode.
- activityCreator Script that builds Ant build fi les that you can then use to compile your Android applications without the ADT plug-in
- Fast
- Responsive
- Secure
- Seamless
- An application must respond to any user action, such as a key press or screen touch, within 5 seconds.
- A Broadcast Receiver must return from its onReceive handler within 10 seconds.
- Consider requiring permissions for any services you create or broadcasts you transmit.
- Take special care when accepting input to your application from external sources such as the Internet, SMS messages, or instant messaging (IM).
- Be cautious when your application may expose access to lower-level hardware.
In this example, you’ll be creating a new Android application from scratch. This simple example creates a new to-do list application using native Android View controls. It’s designed to illustrate the basic steps involved in starting a new project.
- Take this opportunity to set up debug and run configurations by selecting Run ➪ Open Debug Dialog … and then Run ➪ Open Run Dialog …, creating a new configuration for each, specifying the Todo_List project. You can leave the launch actions as Launch Default Activity or explicitly set them to launch the new ToDoList Activity, as shown in Figure 2-11.
- Now decide what you want to show the users and what actions they’ll need to perform. Design a user interface that will make this as intuitive as possible.In this example, we want to present users with a list of to-do items and a text entry box to add new ones. There’s both a list and a text entry control (View) available from the Android libraries. The preferred method for laying out your UI is using a layout resource fi le. Open the main.xml layout file in the res/layout project folder, as shown in Figure 2-12.
- Modify the main layout to include a ListView and an EditText within a LinearLayout. It’s important to give both the EditText and ListView controls IDs so you can get references to them in code.<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>
<EditText
android:id=”@+id/myEditText”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”New To Do Item”
/>
<ListView
android:id=”@+id/myListView”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content” /> - With your user interface defined, open the ToDoList.java Activity class from your project’s source folder. In this example, you’ll make all your changes by overriding the onCreate method. Start by inflating your UI using setContentView and then get references to the ListView and EditText using findViewById.public void onCreate(Bundle icicle) {
// Inflate your view
setContentView(R.layout.main);
// Get references to UI widgets
ListView myListView = (ListView)findViewById(R.id.myListView);
final EditText myEditText = (EditText)findViewById(R.id.myEditText);
} - Still within onCreate, defi ne an ArrayList of Strings to store each to-do list item. You can bind a ListView to an ArrayList using an ArrayAdapter, so create a new ArrayAdapter instance to bind the to-do item array to the ListView.public void onCreate(Bundle icicle) {
setContentView(R.layout.main);
ListView myListView = (ListView)findViewById(R.id.myListView);
final EditText myEditText = (EditText)findViewById(R.id.myEditText);
// Create the array list of to do items
final ArrayList<String> todoItems = new ArrayList<String>();
// Create the array adapter to bind the array to the listview
final ArrayAdapter<String> aa;
aa = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
todoItems);
// Bind the array adapter to the listview.
myListView.setAdapter(aa);
} - The final step to make this to-do list functional is to let users add new to-do items. Add an onKeyListener to the EditText that listens for a “D-pad center button” click before adding the contents of the EditText to the to-do list array and notifying the ArrayAdapter of the change. Then clear the EditText to prepare for another item.public void onCreate(Bundle icicle) {
setContentView(R.layout.main);
ListView myListView = (ListView)findViewById(R.id.myListView);
final EditText myEditText = (EditText)findViewById(R.id.myEditText);
final ArrayList<String> todoItems = new ArrayList<String>();
final ArrayAdapter<String> aa;
aa = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
todoItems);
myListView.setAdapter(aa);
myEditText.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN)
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
{
todoItems.add(0, myEditText.getText().toString());
aa.notifyDataSetChanged();
myEditText.setText(“”);
return true;
}
return false;
}
});
} - You’ve now finished your first “real” Android application. Try adding breakpoints to the code to test the debugger and experiment with the DDMS perspective.
previous Creating Your First Android Activity
With that confirmed, let’s take a step back and have a real look at your first Android application.
Activity is the base class for the visual, interactive components of your application; it is roughly equivalent to a Form in traditional desktop development. The following snippet shows the skeleton code for an Activity-based class; note that it extends Activity, overriding the onCreate method.
package com.paad.helloworld;
import android.app.Activity;
import android.os.Bundle;
public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
}
}
What’s missing from this template is the layout of the visual interface. In Android, visual components are called Views, which are similar to controls in traditional desktop development.
In the Hello World template created by the wizard, the onCreate method is overridden to call setContentView, which lays out the user interface by inflating a layout resource, as highlighted below:
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
}
The resources for an Android project are stored in the res folder of your project hierarchy, which includes drawable, layout, and values subfolders. The ADT plug-in interprets these XML resources to provide design time access to them through the R variable.
The following code snippet shows the UI layout defined in the main.xml fi le created by the Android project template:
<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”Hello World, HelloWorld”
/>
</LinearLayout>
Defining your UI in XML and inflating it is the preferred way of implementing your user interfaces, as it neatly decouples your application logic from your UI design.
To get access to your UI elements in code, you add identifier attributes to them in the XML definition. You can then use the findViewById method to return a reference to each named item. The following XML snippet shows an ID attribute added to the TextView widget in the Hello World template:
<TextView
android:id=”@+id/myTextView”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”Hello World, HelloWorld”
/>
And the following snippet shows how to get access to it in code:
TextView myTextView = (TextView)findViewById(R.id.myTextView);
Alternatively (although it’s not considered good practice), if you need to, you can create your layout directly in code as shown below:
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout.LayoutParams lp;
lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
LinearLayout.LayoutParams textViewLP;
textViewLP = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
TextView myTextView = new TextView(this);
myTextView.setText(“Hello World, HelloWorld”);
ll.addView(myTextView, textViewLP);
this.addContentView(ll, lp);
}
All the properties available in code can be set with attributes in the XML layout. As well as allowing easier substitution of layout designs and individual UI elements, keeping the visual design decoupled from the application code helps keep the code more concise.
The Android web site (http://code.google.com/android/documentation.html) includes several excellent step-by-step guides that demonstrate many of the features and good practices you will be using as an Android developer. They’re easy to follow and give a good idea of how Android applications fi t together.
Types of Android Applications
Most of the applications you create in Android will fall into one of the following categories:
-
Foreground Activity An application that’s only useful when it’s in the foreground and is effectively suspended when it’s not visible. Games and map mashups are common examples.
-
Background Service An application with limited interaction that, apart from when being configured, spends most of its lifetime hidden. Examples of this include call screening applications or SMS auto-responders.
-
Intermittent Activity Expects some interactivity but does most of its work in the background. Often these applications will be set up and then run silently, notifying users when appropriate. A common example would be a media player.
Complex applications are difficult to pigeonhole into a single category and include elements of all three. When creating your application, you need to consider how it’s likely to be used and then design it accordingly. Let’s look more closely at some of the design considerations for each application type described above.
Foreground Activities
When creating foreground applications, you need to consider the Activity life cycle carefully so that the Activity switches seamlessly between the foreground and the background.
Applications have no control over their life cycles, and a backgrounded application, with no Services, is a prime candidate for cleanup by Android’s resource management. This means that you need to save the state of the application when the Activity becomes invisible, and present the exact same state when it returns to the foreground.
It’s also particularly important for foreground Activities to present a slick and intuitive user experience.
Background Services
These applications run silently in the background with very little user input. They often listen for messages or actions caused by the hardware, system, or other applications, rather than rely on user interaction.
It’s possible to create completely invisible services, but in practice, it’s better form to provide at least some sort of user control. At a minimum, you should let users confirm that the service is running and let them configure, pause, or terminate it as needed.
Intermittent Activities
Often you’ll want to create an application that reacts to user input but is still useful when it’s not the active foreground Activity. These applications are generally a union of a visible controller Activity with an invisible background Service.
These applications need to be aware of their state when interacting with the user. This might mean updating the Activity UI when it’s visible and sending notifications to keep the user updated when it’s in the background.
Developing for Mobile Devices
Android does a lot to simplify mobile-device software development, but it’s still important to understand the reasons behind the conventions. There are several factors to account for when writing software for mobile and embedded devices, and when developing for Android, in particular.
Hardware-Imposed Design Considerations
Small and portable, mobile devices offer exciting opportunities for software development. Their limited screen size and reduced memory, storage, and processor power are far less exciting, and instead present some unique challenges.
Compared to desktop or notebook computers, mobile devices have relatively:
-
Low processing power
-
Limited RAM
-
Limited permanent storage capacity
-
Small screens with low resolution
-
Higher costs associated with data transfer
-
Slower data transfer rates with higher latency
-
Less reliable data connections
-
Limited battery life
It’s important to keep these restrictions in mind when creating new applications.
Be Efficient
Manufacturers of embedded devices, particularly mobile devices, value small size and long battery life over potential improvements in processor speed. For developers, that means losing the head start traditionally afforded thanks to Moore’s law. The yearly performance improvements you’ll see in desktop and server hardware usually translate into smaller, more power-efficient mobiles without much improvement in processor power.
In practice, this means that you always need to optimize your code so that it runs quickly and responsively, assuming that hardware improvements over the lifetime of your software are unlikely to do you any favors.
Since code efficiency is a big topic in software engineering, I’m not going to try and capture it here. This chapter covers some Android-specific efficiency tips below, but for now, just note that efficiency is particularly important for resource-constrained environments like mobile devices.
Expect Limited Capacity
Advances in flash memory and solid-state disks have led to a dramatic increase in mobile-device storage capacities (although people’s MP3 collections tend to expand to fill the available space). In practice, most devices still offer relatively limited storage space for your applications. While the compiled size of your application is a consideration, more important is ensuring that your application is polite in its use of system resources.
You should carefully consider how you store your application data. To make life easier, you can use the Android databases and Content Providers to persist, reuse, and share large quantities of data. For smaller data storage, such as preferences or state settings, Android provides an optimized framework.
Of course, these mechanisms won’t stop you from writing directly to the file system when you want or need to, but in those circumstances, always consider how you’re structuring these files, and ensure that yours is an efficient solution.
Part of being polite is cleaning up after yourself. Techniques like caching are useful for limiting repetitive network lookups, but don’t leave fi les on the file system or records in a database when they’re no longer needed.
Design for Small Screens
The small size and portability of mobiles are a challenge for creating good interfaces, particularly when users are demanding an increasingly striking and information-rich graphical user experience.
Write your applications knowing that users will often only glance at the (small) screen. Make your applications intuitive and easy to use by reducing the number of controls and putting the most important information front and center.
Graphical controls are an excellent way to convey dense information in an easy-to-understand way. Rather than a screen full of text with lots of buttons and text entry boxes, use colors, shapes, and graphics to display information.
If you’re planning to include touch-screen support (and if you’re not, you should be), you’ll need to consider how touch input is going to affect your interface design. The time of the stylus has passed; now it’s all about finger input, so make sure your Views are big enough to support interaction using a finger on the screen.
Of course, mobile-phone resolutions and screen sizes are increasing, so it’s smart to design for small screens, but also make sure your UIs scale.
Expect Low Speeds, High Latency
The mobile Web unfortunately isn’t as fast, reliable, or readily available as we’d often like, so when you’re developing your Internet-based applications, it’s best to assume that the network connection will be slow, intermittent, and expensive. With unlimited 3G data plans and city-wide Wi-Fi, this is changing, but designing for the worst case ensures that you always deliver a high-standard user experience.
This also means making sure that your applications can handle losing (or not finding) a data connection.
The Android Emulator lets you control the speed and latency of your network connection when setting up an Eclipse launch configuration. Figure 2-7 shows the emulator’s network connection speed and latency set up to simulate a distinctly suboptimal EDGE connection.
Experiment to ensure responsiveness no matter what the speed, latency, and availability of network access. You might find that in some circumstances, it’s better to limit the functionality of your application or reduce network lookups to cached bursts, based on the network connection(s) available.
At What Cost?
If you’re a mobile owner, you know all too well that some of the more powerful features on your mobile can literally come at a price. Services like SMS, GPS, and data transfer often incur an additional tariff from your service provider.
It’s obvious why it’s important that any costs associated with functionality in your applications are minimized, and that users are aware when an action they perform might result in them being charged.
It’s a good approach to assume that there’s a cost associated with any action involving an interaction with the outside world. Minimize interaction costs by the following:
-
Transferring as little data as possible
-
Caching data and GPS results to eliminate redundant or repetitive lookups
-
Stopping all data transfers and GPS updates when your activity is not visible in the foreground if they’re only being used to update the UI
-
Keeping the refresh/update rates for data transfers (and location lookups) as low as practicable
-
Scheduling big updates or transfers at “off peak” times using alarms
Often the best solution is to use a lower-quality option that comes at a lower cost.
When using the location-based services, you can select a location provider based on whether there is an associated cost. Within your location-based applications, consider giving users the choice of lower cost or greater accuracy.
In some circumstances, costs are hard to define, or they’re different for different users. Charges for services vary between service providers and user plans. While some people will have free unlimited data transfers, others will have free SMS.
Rather than enforcing a particular technique based on which seems cheaper, consider letting your users choose. For example, when downloading data from the Internet, you could ask users if they want to use any network available or limit their transfers to only when they’re connected via Wi-Fi.
Considering the Users’ Environment
You can’t assume that your users will think of your application as the most important feature of their phones.
Generally, a mobile is first and foremost a phone, secondly an SMS and e-mail communicator, thirdly a camera, and fourthly an MP3 player. The applications you write will most likely be in a fifth category of “useful mobile tools.”
That’s not a bad thing — it’s in good company with others including Google Maps and the web browser. That said, each user’s usage model will be different; some people will never use their mobiles to listen to music, and some phones don’t include a camera, but the multitasking principle inherent in a device as ubiquitous as it is indispensable is an important consideration for usability design.
It’s also important to consider when and how your users will use your applications. People use their mobiles all the time — on the train, walking down the street, or even while driving their cars. You can’t make people use their phones appropriately, but you can make sure that your applications don’t distract them any more than necessary.
What does this mean in terms of software design? Make sure that your application:
-
Is well behaved Start by ensuring that your Activities suspend when they’re not in the foreground. Android triggers event handlers when your Activity is suspended or resumed so you can pause UI updates and network lookups when your application isn’t visible — there’s no point updating your UI if no one can see it. If you need to continue updating or processing in the background, Android provides a Service class designed to run in the background without the UI overheads.
-
Switches seamlessly from the background to the foreground With the multitasking nature of mobile devices, it’s very likely that your applications will regularly switch into and out of the background. When this happens, it’s important that they “come to life” quickly and seamlessly. Android’s nondeterministic process management means that if your application is in the background, there’s every chance it will get killed to free up resources. This should be invisible to the user. You can ensure this by saving the application state and queuing updates so that your users don’t notice a difference between restarting and resuming your application. Switching back to it should be seamless with users being shown the exact UI and application state they last saw.
-
Is polite Your application should never steal focus or interrupt a user’s current activity. Use Notifications and Toasts (detailed in Chapter 8) instead to inform or remind users that their attention is requested if your application isn’t in the foreground. There are several ways for mobile devices to alert users. For example, when a call is coming in, your phone rings; when you have unread messages, the LED flashes; and when you have new voice mail, a small “mail” icon appears in your status bar. All these techniques and more are available through the notification mechanism.
-
Presents a consistent user interface Your application is likely to be one of several in use at any time, so it’s important that the UI you present is easy to use. Don’t force users to interpret and relearn your application every time they load it. Using it should be simple, easy, and obvious— particularly given the limited screen space and distracting user
-
Is responsive Responsiveness is one of the most important design considerations on a mobile device. You’ve no doubt experienced the frustration of a “frozen” piece of software; the multifunction nature of a mobile makes it even more annoying. With possible delays due to slow and unreliable data connections, it’s important that your application use worker threads and background services to keep your activities responsive and, more importantly, stop them from preventing other applications from responding in a timely manner.
next Developing for Android