android documentation
TRANSCRIPT
ANDROID DOCUMENTATIONCOMPILED BY FASTOP
http://fastoponandroid.googlepages.com/ http://fastoponandroid.googlepages.com/ http://fastoponandroid.googlepages.com/
Android - An Open Handset Alliance Project
The Android platform is a software stack for mobile devices including an operating system, middleware and key applications.
Developers can create applications for the platform using the Android SDK. Applications are written using the Java
programming language and run on Dalvik, a custom virtual machine designed for embedded use which runs on top of a
Linux kernel.
If you want to know how to develop applications for Android , you're in the right place. This site provides a variety of
documentation that will help you learn about Android and develop mobile applications for the platform.
An early look at the the Android SDK is also available. It includes sample projects with source code, development tools, an
emulator, and of course all the libraries you'll need to bui ld an Android application.
Download the SDK
To start learning about the Android platform, please read the documentation in the following order:
What is Android?
An overview of the Android platform
Getting Started
All the basics, including Hello World
Developing Applications
The nuts and bolts of Android applications
Developer Toolbox
In-depth information on specific topics
Reference Information
A myriad of reference material
Sample Code
Several sample Android applications for your viewing pleasure
Frequently Asked Questions
Common issues and questions
Welcome to Android!
1Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Android will ship with a set of core applications including an email client, SMS program, calendar, maps, browser,
contacts, and others. All applications are written using the Java programming language.
Developers have full access to the same framework APIs used by the core applications. The application
architecture is designed to simplify the reuse of components; any application can publish its capabilities and any
other application may then make use of those capabilities (subject to security constraints enforced by the
framework). This same mechanism allows components to be replaced by the user.
Underlying all applications is a set of services and systems, includ ing:
A rich and extensible set of Views that can be used to build an application, including li sts, grids, text boxes,
buttons, and even an embeddable web browser
Content Providers that enable applications to access data from other applications (such as Contacts), or to
share their own data
A Resource Manager, providing access to non-code resources such as localized strings, graph ics, and
layout files
A Notification Manager that enables all applications to display custom alerts in the status bar
An Activity Manager that manages the lifecycle of applications and provides a common navigation
backstack
Applications
Application Framework
For more details and a walkthrough of an application, see Writing an Android Application .
Android includes a set of C/C++ libraries used by various components of the Android system. These capabilities
are exposed to developers through the Android application frame work. Some of the core libraries are listed
below:
System C library - a BSD-derived implementation of the standard C system library (libc), tuned for
embedded Linux-based devices
Media Libraries - based on PacketVideo's OpenCORE; the libraries support playback and recording of
many popular audio and video formats, as well as static image f iles, including MPEG4, H.264, MP3, AAC,
AMR, JPG, and PNG
Surface Manager - manages access to the display subsystem and seamlessly composites 2D and 3D
graphic layers from multiple applications
LibWebCore - a modern web browser engine which powers both the Android b rowser and an embeddable
web view
SGL - the underlying 2D graphics engine
3D libraries - an implementation based on OpenGL ES 1.0 APIs; the libraries use either hardware 3D
acceleration (where available) or the included, highly optimize d 3D software rasterizer
FreeType - bitmap and vector font rendering
SQLite - a powerful and lightweight relational database engin e available to all applications
Libraries
3Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
android.graphics
is the core rendering package.
android.text, android.text.method, android.text.style, and android.text.util
supply a rich set of text processing tools, supporting rich text, input methods, etc.
android.database
contains low-level APIs for working with databases.
android.content
provides various services for accessing data on the device: applications installed on the device and their associated
resources, and content providers for persistent dynamic data.
android.view
is the core user-interface framework.
android.widget
supplies standard user interface elements (lists, buttons, layout managers, etc) built from the view package.
android.app
provides the high-level application model, implemented using Activities.
These packages provide additional domain-specific features of the Android platform. They are not necessary for basic
application development.
android.provider
contains definitions for various standard content providers included with the platform.
android.telephony
provides APIs for interacting with the device's phone stack.
android.webkit
includes various APIs for working with web-based content.
Other Notable Packages
5Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Fill out the project details
The next screen allows you to enter the relevant details for your project. Here's an example:
2.
Here's what each field on this screen means:
Project
Name
This is the name of the directory or folder on your computer that you want to
contain the project.
Package
Name
This is the package namespace — similar to the Java programming language —
that you want all your source code to reside under. This also sets the package
name under which the stub Activity will be generated.
The package name you use in your application must be unique across all
packages installed on the system; for this reason, it's very important to use a
standard domain-style package for your applications. In the example above, we
used the package domain "com.google.android"; you should use a different one
appropriate to your organization.
Activity
Name
This is the name for the class stub that will be generated by the plugin. This will
be a subclass of Android's Activity class. An Activity is simply a class that can run
and do work. It can create a UI if it chooses, but it doesn't need to.
Application
Name
This is the human-readable title for your application.
The checkbox for toggling "Use default location" allows you to change the location on disk where the
project's files will be generated and stored.
7Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Nothing too surprising there.
At this point, we've constructed a TextView and told it what text to display. The final step is to connect this
TextView with the on-screen display, like so:
setContentView(tv);
The setContentView() method on Activity indicates to the system which View should be associated with the
Activity's UI. If an Activity doesn't call this method, no UI is present at all and the system will display a blank
screen. For our purposes, all we want is to display some text, so we pass it the TextView we just created.
There it is — "Hello, World" in Android! The next step, of course, is to see it running.
The Eclipse plugin makes it very easy to run your applications. Begin by selecting the Run > Open Run
Dialog menu entry; you should see a dialog like this:
Run the Code: Hello, Android
Once we've constructed the TextView, we need to tell it what to display:
tv.setText("Hello, Android");
Next, highlight the "Android Application" entry, and then press the icon in the top left corner (the one
depicting a sheet of paper with a plus sign in the corner) or simply double-click the "Android Application"
entry. You should have a new launcher entry named "New_configura tion".
9Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
That's "Hello, World" in Android. Pretty straightforward, eh? The next sections of the tutorial offer more
detailed information that you may find valuable as you learn more about Android.
Upgrading the UI to an XML Layout
The "Hello, World" example you just completed uses what we call "programmatic" UI layout. This means
that you construct and build your application's UI directly in source code. If you've done much UI
programming, you're probably familiar with how brittle that approach can sometimes be: small changes in
layout can result in big source-code headaches. It's also very easy to forget to properly connect Views
together, which can result in errors in your layout and wasted time debugging your code.
That's why Android provides an alternate UI construction model: XML-based layout files. The easiest way to
explain this concept is to show an example. Here's an XML layout file that is identical in behavior to the
programmatically-constructed example you just completed:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com /apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Hello, Android"/>
The general structure of an Android XML layout file is simple. It's a tree of tags, where each tag is the name
of a View class. In this example, it's a very simple tree of one element, a TextView. You can use the name
of any class that extends View as a tag name in your XML layouts, including custom View classes you
define in your own code. This structure makes it very easy to quickly build up UIs, using a much simpler
structure and syntax than you would in source code. This model is inspired by the web development model,
where you can separate the presentation of your application (i ts UI) from the application logic used to fetch
and fill in data.
11Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The last thing you need to do is modify your HelloAndroid source code to use the new XML version of your
UI, instead of the hard-coded version. Here's what your new class will look like. As you can see, the source
code becomes much simpler:
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
}
}
When you make this change, don't just copy-and-paste it in. Try out the code-completion feature on that R
class. You'll probably find that it helps a lot.
Now that you've made this change, go ahead and re-run your application — all you need to do is press the
green Run arrow icon, or select Run > Run Last Launched from the menu. You should see.... well, exactly
the same thing you saw before! After all, the point was to show that the two different layout approaches
produce identical results.
There's a lot more to creating these XML layouts, but that's as far as we'll go here. Read the Implementing a
User Interface documentation for more information on the power of this approach.
The Android Plugin for Eclipse also has excellent integration w ith the Eclipse debugger. To demonstrate
this, let's introduce a bug into our code. Change your HelloAndroid source code to look like this:
Debugging Your Project
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Object o = null;
o.toString();
setContentView(R.layout.main);
}
}
This change simply introduces a NullPointerException into your code . If you run your application again,
you'll eventually see this:
13Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
There are four building blocks to an Android application:
Activity
Intent Receiver
Service
Content Provider
Not every application needs to have all four, but your application will be written with some combination of these.
Once you have decided what components you need for your applica tion, you should list them in a file called
AndroidManifest.xml. This is an XML file where you declare the components of your application and what their capabilities
and requirements are. See the Android manifest file documentation for complete details.
Activities are the most common of the four Android building blocks. An activity is usually a single screen in your application.
Each activity is implemented as a single class that extends the Activity base class. Your class will display a user interface
composed of Views and respond to events. Most applications consist of multiple screens. For example, a text messaging
application might have one screen that shows a list of contacts to send messages to, a second screen to write the message
to the chosen contact, and other screens to review old messages or change settings. Each of these screens would be
implemented as an activity. Moving to another screen is accomplished by a starting a new activity. In some cases an activity
may return a value to the previous activity -- for example an activity that lets the user pick a photo would return the chosen
photo to the caller.
When a new screen opens, the previous screen is paused and put onto a history stack. The user can navigate backward
through previously opened screens in the history. Screens can also choose to be removed from the history stack when it
would be inappropriate for them to remain. Android retains history stacks for each application launched from the home
screen.
Android uses a special class called an Intent to move from screen to screen. An intent describes what an application wants
done. The two most important parts of the intent data structure are the action and the data to act upon. Typical values for
action are MAIN (the front door of the activity), VIEW, PICK, EDIT, etc. The data is expressed as a URI. For example, to
view contact information for a person, you would create an intent with the VIEW action and the data set to a URI
representing that person.
There is a related class called an IntentFilter. While an intent is effectively a request to do something, an intent filter is a
description of what intents an activity (or intent receiver, see below) is capable of handling. An activity that is able to display
contact information for a person would publish an IntentFil ter that said that it knows how to handle the action VIEW when
applied to data representing a person. Activities publish the ir IntentFilters in the AndroidManifest.xml file.
Navigating from screen to screen is accomplished by resolving intents. To navigate forward, an activity calls
startActivity(myIntent). The system then looks at the intent filters for all installed applications and picks the activity
whose intent filters best matches myIntent. The new activity is informed of the intent, which causes it to be launched. The
process of resolving intents happens at run time when startActivity is called, which offers two key benefits:
Activities can reuse functionality from other components simply by making a request in the form of an Intent
Activities can be replaced at any time by a new Activity with an equivalent IntentFilter
Anatomy of an Android Application
Activity
Intent and Intent Filters
15Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The tutorial in this section gives you a "hands-on" introduction to the Android framework and the tools you use to build
applications on it. Starting from a preconfigured project file, it guides you through the process of developing a simple
notepad application and provides concrete examples of how to set up the project, develop the application logic and user
interface, and then compile and run the application.
The tutorial presents the notepad application development as a set of exercises (see below), each consisting of several
steps. You can follow along with the steps in each exercise and gradually build up and refine your application. The exerci ses
explain each step in detail and provide all the sample code you need to complete the application.
When you are finished with the tutorial, you will have created a functioning Android application and learned in dep th about
many of the most important concepts in Android development. If you want to add more complex features to your application,
you can look at and use the code in the notepad application that is supplied in the sample code area of the Android SDK.
Who Should Use this Tutorial
Preparing for the Exercises
Exercises
Other Resources and Further Learning
This tutorial is designed for experienced developers, especially those with knowledge of the Java programming language. If
you haven't written Java applications before, you can still use the tutorial, but you might need to work at a slower pace.
Also, the tutorial builds on the information provided in the Installing the SDK and Hello Android documents, which explain in
detail how to set up your development environment for building Android applications. Before you start the tutorial, make sure
that you have already downloaded the SDK and installed it according to the instructions.
Finally, this tutorial describes how to develop the notepad application in the Eclipse development environment, with the
Android plugin installed. If you are not using Eclipse, you can follow the exercises and build the application, but you will need
to determine how to accomplish the Eclipse-specific steps in your environment. If you want to add more complex features to
your application, you can look at and use the code in the notepad application that is supplied in the sample code area of the
Android SDK.
The tutorial assumes that you have some familiarity with the basic Android application concepts and terminology. If you
aren't yet familiar with those, you should read Overview of an Android Application and Application Lifecycle before
continuing.
Before you begin, it's important that you install the SDK and set up your Eclipse development. Once your environment is set
up, locate and unpack the exercises archive, which is included in the SDK package. The archive includes a series of Eclipse
project files that are used in the exercises. You can use these project files instead of creating and configuring your own
project files.
To get the tutorial project files:
Download the project exercises archive (.zip)1.
Tutorial: A Notepad Application
Contents
Who Should Use this Tutorial
Preparing for the Exercises
Unpack the archive file to a suitable location on your machine2.
Open the NotepadCodeLab folder3.
Inside the NotepadCodeLab folder, you should see six project files: Notepadv1, Notepadv2, Notepadv3,
Notepadv1Solution, Notepadv2Solution and Notepadv3Solution. The Notepadv* projects are the starting points
for each of the exercises, while the Notepadv*Solution projects are the exercise solutions. If you are having trouble with
a particular exercise, you can compare your current work against the exercise solution to try and track down the problem.
17Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Take a look at the DBHelper class — this class is provided to encapsulate data
access to a SQLite database that will hold our notes data and allow us to update it.
Typically you would implement this using a ContentProvider, and in fact the full
Notepad application included with the SDK does implement such a
ContentProvider. However, there is no reason you can't just use your own SQLite
database directly as we do here. The main thing to notice about this class is that it
takes care of the details of storing, retrieving and updating data in the SQLite
database for us. There are methods for retrieving all the rows, retrieving a row
based on rowIds, creating a new row, deleting an existing row and updating a row.
If you want a quick primer in how to use the SQLite Database for your own
applications, either take a look at this class or better yet, look at the full Notepad
application included with the SDK in the samples/ folder as the sample uses a ContentProvider.
Open the notepad_list.xml file in res/layout and take a look at it:
This is a layout definition file with a default starting point in it, we have provided
this as a convenience to get you going quickly.
All Android layout files must start with the XML header line: <?xml a.
Step 2
For this exercise, we are just going to use
a SQLite database directly to store our
data, but in a real application it would be
much better to write a proper
ContentProvider to encapsulate this
behavior instead.
If you are interested, you can find out
more about content providers or the
whole subject of Storing, Retrieving, and
Exposing Data.
Accessing and modifying data
Step 3
Most Activities will have a layout
associated with them. The layout will be
the "face" of the activity to the user. In
this case our layout will take over the
Layouts and activities
version="1.0" encoding="utf-8"?>.
Also, the next definition will often (but not always) be a layout definition of
some kind, in this case a LinearLayout.
b.
Note also that the xml namespace of Android should always be defined in
the top level component or layout in the XML so that android: tags can be
used through the rest of the file:
xmlns:android="http://schemas.android.com/apk/res/android"
c.
whole screen and provide a list of notes.
Full screen layouts are not the only option
for an Activity however. You might also
want to use a floating layout (for example,
a dialog or alert), or perhaps you don't
need a layout at all (the activity will be
invisible to the user unless you specify
some kind of layout for it to use).
We need to create the layout to hold our list. Add code inside of the LinearLayout tag so the whole file looks like this: (you
may have to hit the Source tab in order to edit the XML file)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView id="@id/android:list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView id="@id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_notes"/>
</LinearLayout>
Step 4
The ListView and TextView can be thought as two alternative views, only one of which will be displayed at once.
ListView will be used when there are notes to be shown, while the TextView (which has a default value of "No Notes
Yet!" defined as a string resource, will be displayed if there aren't any notes to display).
a.
The @ in the id strings of the ListView and TextView means that the XML parser should parse and expand the rest of
the id string and use an ID resource.
b.
19Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Fill out the body of the onCreate() method.
Here we will set the title for the activity (shown at the top of the screen), use the notepad_list layout we have created for
the activity display contents, set up the DBHelper instance we will use to access notes data, then populate the list with the
available note titles:
call super() with the icicle parameter passed into our methoda.
setContentView to R.layout.notepad_listb.
Create a new private class field called dbHelper of class DBHelper (before the onCreate method)c.
Back in the onCreate method, construct a DBHelper instance — assign to the dbHelper field (note, you must pass
this into the constructor for DBHelper)
d.
Finally, call a new method -fillData()- gets the data and populates it using the helper, we haven't defined it yete.
onCreate() should now look like this:
@Override
public void onCreate(Bundle icicle)
f.
Step 9
{
super.onCreate(icicle);
setContentView(R.layout.notepad_list);
dbHelper = new DBHelper(this);
fillData();
}
And remember to add the DBHelper field definition (right under the noteNumber definition):
private DBHelper dbHelper;
Fill out the body of the onCreateOptionsMenu() method.
We are going to add just one menu item for now, "Add Item", using a string we will
create in strings.xml, and defined with a constant we will create at the top of the
class to identify the Add Item operation.
In strings.xml resource (under res/values), add a new string for
menu_insert with text "Add Item"
<string name="menu_insert">Add Item</string>, then save the
file
a.
Also, you need a menu position constant at the top of the Notepadv1 class (right under the KEY_BODY definition):
public static final int INSERT_ID = Menu.FIRST;
b.
In the onCreateOptionsMenu() method, add the menu item. Also take care of the result of the super call being
returned. The whole method should now look like this:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean result = super.onCreateOptionsMenu(menu);
menu.add(0, INSERT_ID, R.string.menu_insert);
return result;
}
c.
Step 10
The notepad application we are
constructing only scratches the surface
with menus.
You can also add shortcut keys for menu
items, create submenus and even add
menu items to other applications!.
More on menus
21Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Define the fillData() method. This is fairly long:
This method uses ArrayAdapter, which is the simplest way of putting data into
a ListView. ArrayAdapter takes either a List or an array of Strings, and binds
them into a text view provided in the layout defined for the list row (this is the
text1 field in our notes_row.xml layout). The method simply obtains a list of
notes from the database helper, constructs a List of Strings using the title strings
from each row, and then creates an ArrayAdapter out of those items and
bound to use the notes_row we defined.
private void fillData() {
// We need a list of strings for the list items
List<String> items = new ArrayList<String>();
// Get all of the rows from the database and create the item list
List<Row> rows = dbHelper.fetchAllRows();
for (Row row : rows) {
items.add(row.title);
}
// Now create an array adapter and set it to display using our row
ArrayAdapter<String> notes =
new ArrayAdapter<String>(this, R.layout.notes_row, items);
Step 13
Our example uses a very simple array
adapter which binds an array or list of
items into a ListView. More commonly in
Android, List Adapters go hand in hand
with ContentProviders, and this is also a
very easy way to use lists.
To bind a ContentProvider to a ListView
you can use a
android.widget.SimpleCursorAdapter to
bind data from a ContentProvider into a
ListView
List adapters
setListAdapter(notes);
}
ArrayAdapter needs a List of Strings (List<String>) containing the items to displaya.
The data is read out of the database as rows, and the title field from each row is used to populate the list of stringsb.
We specify the notes_row view we created as the receptacle for the datac.
If you get compiler errors about classes not being found, ctrl-shift-O or (cmd-shift-O on the mac) to organize imports.d.
Note: that for this exercise we use an ArrayAdapter, this is not a very scalable solution and more typically a
SimpleCursorAdapter would be used with a ContentProvider or at least a Cursor returned from a query. See the
sidebar on List Adapters for more information.
Run it!
Right click on the Notepadv1 projecta.
From the popup menu, select Run As -> Android Applicationb.
If you see a dialog come up, select Android Launcher as the way of running the application (you can also use the link
near the top of the dialog to set this as your default for the workspace, this is recommended as it will stop the plugin
from asking you this every time)
c.
Add new notes by hitting the menu button and selecting Add Item from the menud.
You can see the solution to this class in Notepadv1Solution from the zip file to compare with your own.
Once you are ready, move on to Tutorial Exercise 2 to add the ability to create, edit and delete notes.
Step 14
Solution and Next Steps
23Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
In the onMenuItemSelected() method, add a new case for DELETE_ID:
dbHelper.deleteRow(rows.get(getSelection()).rowId);
fillData();
break;
This uses the getSelection() method from the ListActivity to see
what note is currently selected from the list
a.
It then looks that row up from the rows field we have been holding on to,
and gets the rowId, and uses it to delete the row using the DBHelper
b.
We fill data afterwards to keep everything up to datec.
The whole method should now look like this:
@Override
public boolean onMenuItemSelected(int featureId, Item item) {
super.onMenuItemSelected(featureId, item);
switch(item.getId()) {
case INSERT_ID:
createNote();
fillData();
break;
case DELETE_ID:
dbHelper.deleteRow(rows.get(getSelection()).rowId);
fillData();
break;
}
return true;
}
d.
Fill in the body of the createNote() method:
We will create a new Intent to create a note (ACTIVITY_CREATE) using the NoteEdit class. We then fire the Intent
using the startSubActivity() method call.
Intent i = new Intent(this, NoteEdit.class);
startSubActivity(i, ACTIVITY_CREATE);
Don't worry about the fact that NoteEdit doesn't exist yet, we will fix that soon.
Note: in this example our Intent uses a class name specifically. While this makes sense sometimes, it is more common
to call an Intent using an action and contentURI. See android.content.Intent for more information.
Fill in the body of the onListItemClick() override.
onListItemClick() is the overridden method that is called when the user selects an item from the list. It is passed four
parameters: the ListView object it was invoked from, the View inside the ListView that was clicked on, the position in
the list that was clicked, and the rowId of the item that was clicked. In this instance we can ignore the first two parameters
(we only have one ListView it could be), and we ignore the rowId as well. All we are interested in is the position that
the user selected. We use this to get the data from the correct row, and bundle it up to send in to the NoteEdit activity.
Step 4
As well as starting intents in classes we
already know about, be they in our own
application or another application, we can
also create intents without knowing
exactly which application will handle it.
For example, we might want to open a
page in a browser, and for this we still
use an intent. But instead of specifying a
class to handle it, we use a predefined
Intent constant, and a content URI that
describes what we want to do.
Starting Other Activities
Step 5
Step 6
25Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Open the file note_edit.xml that has been provided and take a look at it. This
is the UI code for the Note Editor.
This is the most sophisticated UI we have dealt with yet. The file is given to you to
avoid problems that may sneak in when typing the code in (the XML is very strict
about case sensitivity and structure, mistakes in these are the usual cause of
problems with layout XML files).
There is a new parameter used here that we haven't seen before:
android:layout_weight (in this case set to use the value 1).
layout_weight is used in LinearLayouts to assign "importance" to views within
the layout. All views have a default layout_weight of zero, meaning they take
up only as much room on the screen as they need to be displayed. Assigning a
value higher than zero will split up the rest of the available space in the parent
according to the value of the view's layout_weight and its ratio to the overall
layout_weight specified in the current layout for this and other views.
To give an example: let's say we have a text label and two text edit views in a horizontal row. The label has no
layout_weight specified, so it takes up the minimum space required to render. If the layout_weight of each of the two
text edit views is set to 1, the remaining width in the parent layout will be split equally between them. If one has a
layout_weight of 1 and the other has a layout_weight of 2, then one third of the remaining space will be given to the
first, and two thirds to the second.
This layout also demonstrates how to nest multiple layouts inside each other to achieve a more complex and pleasant
layout. In this example, a horizontal linear layout is nested inside the vertical one to allow the title label and text field to be
alongside each other horizontally.
Create a NoteEdit class that extends android.app.Activity.
This is the first time we will have created an activity without the Android Eclipse plugin doing it for us. When you do so, the
onCreate() method is not automatically overridden for you. It is hard to imagine an activity that doesn't override the
onCreate() method, so this should be the first thing you do (there is an override/implement methods option available from
the right click popup menu in the eclipse editor that we will use)
Right click on the com.google.android.demo.notepad2 package in the Package Explorer, and select
New->Class from the popup menu
a.
Fill in NoteEdit for the Name: field in the dialogb.
In the Superclass: field, enter android.app.Activity (you can also just type Activity and hit Ctrl-Space on
Windows and Linux or Cmd-Space on the Mac, to invoke code assist and find the right package and class)
c.
Hit the Finish buttond.
In the resulting NoteEdit class, right click in the editor window and select Source->Override/Implement
Methods...
e.
Scroll down through the checklist in the dialog until you see onCreate(Bundle) — and check the box next to itf.
Hit the OK button.g.
Fill in the body of the onCreate() method.
This will set the title of our new activity to say "Edit Note" (one of the strings defined in strings.xml). It will also set the
content view to use our note_edit.xml layout file. We can then grab handles to the title and body text edit views, and the
confirm button, so that our class can use them to set and get the note title and body, and attach an event to the confirm
Step 8
The provided note_edit.xml layout file is
the most sophisticated one in the
application we will be building, but that
doesn't mean it is even close to the kind
of sophistication you will be likely to want
in real Android applications.
Creating a good UI is part art and part
science, and the rest is work. Mastering
Android layout is an essential part of
creating a good looking Android
application.
Take a look at the View Gallery for some
example layouts and how to use them.
The ApiDemos sample project is also a
great resource from which to learn how to
create different layouts.
The Art of Layout
Step 9
Step 10
button for when it is pressed by the user.
27Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Fill in the body of the onClick() method.
This is the code that will be run when the user clicks on the confirm button. We want this to grab the title and body text from
the edit text fields, and put them into the return bundle so that they can be passed back to the activity that invoked this Intent
in the first place. If the operation is an edit rather than a create, we also want to put the rowId into the bundle as well so that
the Notepadv2 class can save the changes back to the correct note.
Create a bundle and put the title and body text into it using the constants defined in Notepadv2 as keys
Bundle bundle = new Bundle();
bundle.putString(Notepadv2.KEY_TITLE, titleText.getText().toString());
bundle.putString(Notepadv2.KEY_BODY, bodyText.getText().toString());
if (rowId != null) {
bundle.putLong(Notepadv2.KEY_ROW_ID, rowId);
}
a.
Set the result information, including the bundle, and finish the activity:
The setResult() method is used to set the result code, return data string, and extras bundle to be passed back to
the Intent caller. In this case everything worked, so we return RESULT_OK for the result code. We are not using the
string data field in this case, so we pass a null back for that and pass the bundle we have just created with the title,
body and rowId information in it.
The finish() call is used to signal that the activity is done (like a return call). Anything set in the Result will then be
returned to the caller, along with execution control.
setResult(RESULT_OK, null, bundle);
finish();
b.
The full onCreate() method (plus supporting class fields) should now look like this:
private EditText titleText;
private EditText bodyText;
private Long rowId;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.note_edit);
titleText = (EditText) findViewById(R.id.title);
bodyText = (EditText) findViewById(R.id.body);
Button confirmButton = (Button) findViewById(R.id.confirm);
rowId = null;
Bundle extras = getIntent().getExtras();
if (extras != null) {
String title = extras.getString(Notepadv2.KEY_TITLE);
String body = extras.getString(Notepadv2.KEY_BODY);
rowId = extras.getLong(Notepadv2.KEY_ROW_ID);
if (title != null) {
titleText.setText(title);
}
if (body != null) {
bodyText.setText(body);
}
}
c.
Step 11
29Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
In this exercise, you will use life-cycle event callbacks to store and retrieve application state data. This exercise
demonstrates:
Life-cycle events and how your application can use them
Techniques for maintaining application state
The current example has some problems — hitting the back button when editing causes a crash, and anything else that
happens during editing will cause the edits to be lost.
To fix this, we will move most of the functionality for creating and editing the note into the NoteEdit class, and introduce a full
lifecycle for editing notes.
Import Notepadv3 into Eclipse. If you see an error about AndroidManifest.xml, or some problems related to an
Android zip file, right click on the project and select Android Tools->Fix Project Properties from the popup menu. The starting
point for this exercise is exactly the same as the solution for Notepadv2.
Remove the NoteEdit code to parse out the title and body from the extras bundle.
We are going to use the DBHelper class to access the notes from the database directly. All we need passed into the
activity is a rowId (if we are editing, if creating we don't need anything). We will get rid of the properties that were
being passed in through the extras bundle that we were using to set the title and body text edit values in the UI.
a.
Remove the lines that read:
String title = extras.getString(Notepadv3.KEY_TITLE);
String body = extras.getString(Notepadv3.KEY_BODY);
and
if (title != null) {
titleText.setText(title);
}
if (body != null) {
bodyText.setText(body);
}
(Extra credit, you could replace the remaining if (extras != null) block with a ternary operator as well:
rowId = extras != null ? extras.getLong(Notepadv3.KEY_ROW_ID) : null;
b.
Create a class field for a DBHelper at the top of the class:
private DBHelper dbHelper;
and an instance of DBHelper in the onCreate() method (right below the super.onCreate() call):
Tutorial: Notepad Exercise 3
Step 1
Step 2
dbHelper = new DBHelper(this);
31Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
populateFields();
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
setResult(RESULT_OK);
finish();
}
});
Define the populateFields() method.
private void populateFields() {
if (rowId != null) {
DBHelper.Row row = dbHelper.fetchRow(rowId);
if (row.rowId > -1) {
titleText.setText(row.title);
bodyText.setText(row.body);
}
}
}
Override methods onFreeze(), onPause() and onResume()
These are our lifecycle methods (along with onCreate() which we already have).
onFreeze() is called by Android if the Activity is being stopped and may be
killed before it is resumed! This means it should store any state necessary to
re-initialize to the same condition when the activity is restarted. It is the
counterpart to the onCreate() method, and in fact the icicle bundle passed
in to onCreate() is the same bundle that you construct as outState in the
onFreeze() method.
onPause() and onResume() are also complimentary methods. onPause() is
always called when the Activity ends, even if we instigated that (with a finish call
for example). We will use this to save the current note back to the database.
Good practice is to release any resources that can be released during an
onPause() as well, to take up less resources when in the passive state. For this
reason we will close the DBHelper class and set the field to null so that it can be
garbage collected if necessary. onResume() on the other hand, will re-create
the dbHelper instance so we can use it, and then read the note out of the
database again and populate the fields.
Step 6
Step 7
If you are used to always having control
in your applications, you might not
understand why all this lifecycle work is
necessary. The reason is that in Android,
you are not in control of your activity, the
operating system is!
As we have already seen, the Android
model is based around Activities calling
each other. When one Activity calls
another, the current activity is paused at
the very least, and may be killed
altogether if the system starts to run low
on resources. If this happens, your
Activity will have to store enough state to
come back up later, preferably in the
same state it was in when it was killed.
Android has a well-defined lifecycle.
Lifecycle events can happen even if you
are not handing off control to another
Why handling lifecycle events is
important
rowId = icicle != null ? icicle.getLong(Notepadv3.KEY_ROW_ID) : null;
if (rowId == null) {
Bundle extras = getIntent().getExtras();
if (extras != null) {
rowId = extras.getLong(Notepadv3.KEY_ROW_ID);
}
}
activity explicitly. For example, perhaps a
call comes in to the handset. If this
happens, and your activity is running, it
will be swapped out while the call activity
takes over.
33Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Also remove the lines which set the title and body from the onListItemClick() method (again they are no longer
needed, only the rowId is):
i.putExtra(KEY_TITLE, rows.get(position).title);
i.putExtra(KEY_BODY, rows.get(position).body);
Run it! (use Run As -> Android Application on the project right click menu again)
You can see the solution to this exercise in Notepadv3Solution from the zip file to compare with your own.
When you are ready, move on to the Tutorial Extra Credit exercise, where you can use the Eclipse debugger to examine the
lifecycle events as they happen.
Step 10
Solution and Next Steps
In this exercise, you will use the debugger to look at the work you did in Exercise 3. This exercise demonstrates:
How to set breakpoints to observe execution
How to run your application in debug mode
Using the working Notepadv3, put breakpoints in the code at the beginning of the onCreate(), onPause(), onFreeze()
and onResume() methods in the NoteEdit class (if you are not familiar with Eclipse, just right click in the narrow grey
border on the left of the edit window at the line you want a breakpoint, and select Toggle Breakpoint, you should see a blue
dot appear).
Now start the notepad demo in debug mode:
Right click on the Notepadv3 project and from the Debug menu select Debug As -> Android Application.a.
The Android emulator should say "waiting for debugger to connect" briefly and then run the application.b.
If it gets stuck on the waiting... screen, quit the emulator and Eclipse, from the command line do an adb
kill-server, and then restart Eclipse and try again.
c.
When you edit or create a new note you should see the breakpoints getting hit and the execution stopping.
Hit the Resume button to let execution continue (yellow rectangle with a green triangle to its right in the Eclipse toolbars near
the top).
Experiment a bit with the confirm and back buttons, and try hitting home and making other mode changes. Watch what
lifecycle events are generated and when.
The Android Eclipse plugin not only offers excellent debugging support for your application development, but also superb
profiling support. If your application is running too slow, this can help you find the bottlenecks and fix them.
Tutorial: Extra Credit
Step 1
Step 2
Step 3
Step 4
Step 5
35Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Here is a list of the basic steps in building an application.
Create your required resource files This includes the AndroidManifest.xml global description file, string files that
your application needs, and layout files describing your user in terface. A full list of optional and required files and
syntax details for each is given in File List for an Android Application.
1.
Design your user interface See Implementing a UI for details on elements of the Android screen. 2.
Implement your Activity (this page) You will create one class/file for each screen in your application. Screens will
inherit from an android.app class, typically android.app.Activity for basic screens, android.app.ListActivity for list
screens, or android.app.Dialog for dialog boxes. You will implement the required callbacks that let you draw your
screen, query data, and commit changes, and also perform any required tasks such as opening additional screens or
reading data from the device. Common tasks, such as opening a new screen or reading data from the device, are
described below. The list of files you'll need for your application are described in List of Files for an Android
Application.
3.
Build and install your package. The Android SDK has some nice tools for generating projects and debugging code.4.
Android calls a number of callbacks to let you draw your screen, store data before pausing, and refresh data after closing.
You must implement at least some of these methods. See Lifetime of a Screen to learn when and in what order these
methods are called. Here are some of the standard types of screen classes that Android provides:
android.app.Activity - This is a standard screen, with no specialization.
android.app.ListActivity - This is a screen that is used to display a list of something. It hosts a ListView object, and
exposes methods to let you identify the selected item, receive callbacks when the selected item changes, and perform
other list-related actions.
android.app.Dialog - This is a small, popup dialog-style window that isn't intended to remain in the history stack. (It is
not resizeable or moveable by the user.)
Your Activity will often need to open another Activity screen as it progresses. This new screen can be part of the same
application or part of another application, the new screen can be floating or full screen, it can return a result, and you can
decide whether to close this screen and remove it from the history stack when you are done with it, or to keep the screen
open in history. These next sections describe all these options.
When you open a new screen you can decide whether to make it transparent or floating, or full-screen. The choice of new
screen affects the event sequence of events in the old screen (if the new screen obscures the old screen, a different series
of events is called in the old screen). See Lifetime of an Activity for details.
Transparent or floating windows are implemented in three standard ways:
Create an app.Dialog class
Create an app.AlertDialog class
Set the Theme_Dialog theme attribute to @android:style/Theme.Dialog in your AndroidManifest.xml file. For
example:
<activity class="AddRssItem" android:label="Add an item"
android:theme="@android:style/Theme.Dialog"/>
Calling startActivity() or startSubActivity() will open a new screen in whatever way it defines itself (if it uses a floating theme it
will be floating, otherwise it will be full screen).
When you want to open a new screen, you can either explicitly specify the activity class to open, or you can let the operating
system decide which screen to open, based upon the data and various parameters you pass in. A screen is opened by
calling startActivity and passing in an Intent object, which specifies the criteria for the handling screen. To specify a specific
screen, call Intent.setClass or setClassName with the exact activity class to open. Otherwise, set a variety of values and
Implementing Activity Callbacks
Opening a New Screen
Floating or full?
Opening a Screen
37Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
}
else {
myFightFunction(data, extras);
}
default:
break;
}
}
// Class SentResult
// Temporary screen to let the user choose something.
private OnClickListener mLincolnListener = new OnClickListener(){
public void onClick(View v) {
Bundle stats = new Bundle();
stats.putString("height","6\'4\"");
stats.putString("weight", "190 lbs");
stats.putString("reach", "74\"");
setResult(RESULT_OK, "Lincoln", stats);
finish();
}
};
private OnClickListener mWashingtonListener = new OnClickListener() {
public void onClick(View v){
Bundle stats = new Bundle();
stats.putString("height","6\'2\"");
stats.putString("weight", "190 lbs");
stats.putString("reach", "73\"");
setResult(RESULT_OK, "Washington", Bundle);
finish();
}
};
An activity can remove itself from the history stack by calling Activity.finish() on itself, or the activity that opened the screen
can call Activity.finishSubActivity() on any screens that it opens to close them.
Button click and other UI event capturing are covered in Listening for UI Notifications on the UI Design page.
You can set a number of general window properties, such as whether to display a title, whether the window is floating, and
whether it displays an icon, by calling methods on the Window member of the underlying View object for the window.
Examples include calling getWindow().requestFeature() (or the convenience method
requestWindowFeature( some_feature)) to hide the title. Here is an example of hiding the ti tle bar:
//Hide the title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
If your application is dumped from memory because of space concerns, it will lose all user interface state information such
as checkbox state and text box values as well as class member values. Android calls Activity.onFreeze before it pauses the
application. This method hands in a Bundle that can be used to store name/value pairs that will persist and be handed back
to the application even if it is dropped from memory. Android will pass this Bundle back to you when it calls onCreate() . This
Lifetime of the new screen
Listening for Button Clicks
Configuring General Window Properties
Storing and Retrieving State
39Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Receiver Java code:
public class AlarmReceiver extends IntentReceiver{
// Display an alert that we've received a message.
@Override
public void onReceiveIntent(Context context, Intent intent){
// Send a text notification to the screen.
NotificationManager nm = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notifyWithText(R.id.alarm,
"Alarm!!!",
NotificationManager.LENGTH_SHORT,
null);
}
}
You can listen for other system messages sent by Android as well, such as USB connection/removal messages, SMS arrival
messages, and timezone changes. See Intent for a list of broadcast messages to listen for. Messages are marked
"Broadcast Action" in the documentation.
The telephony package overview page describes how to register to listen for phone events.
Android provides an AlarmManager service that will let you specify an Intent to send at a designated time. This intent is
typically used to start an application at a preset time. (Note: If you want to send a notification to a sleeping or running
application, use Handler instead.)
There are two major kinds of alerts that you may display to the user: (1) Normal alerts are displayed in response to a user
action, such as trying to perform an action that is not allowed. (2) Out-of-band alerts, called notifications, are displayed as a
result of something happening in the background, such as the user receiving new e-mail.
Android provides a number of ways for you to show popup notifications to your user as they interact with your application.
Class Description
app.Dialog A generic floating dialog box with a layout that you design.
app.AlertDialog
or
Context.showAlert()
A popup alert dialog with two buttons (typically OK and Cancel) that take callback handlers. It
can be created separately, or launched using the Application helper method
Context.showAlert(). See the section after this table for more details.
ProgressDialog A dialog box used to indicate progress of an operation with a known progress value or an
indeterminate length (setProgress(bool)). See Views > Progress Bar in ApiDemos for
examples.
Activity By setting the theme of an activity to android:theme="android:style/Theme.Dialog" , your activity
will take on the appearance of a normal dialog, floating on top of whatever was underneath it.
You usually set the theme through the android:theme attribute in your AndroidManifest.xml. The
advantage of this over Dialog and AlertDialog is that Application has a much better managed
Other system messages
Listening for phone events
Setting Alarms
Displaying Alerts
Normal Alerts
41Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
if (messageCount > 0) {
nm.notifyWithText(myApp.NOTIFICATION_GUID, // ID for this notification.
messageCount + " new message" + messageCount > 1 ? "s":"", // Text to
display.
NotificationManager.LENGTH_SHORT); // Show it for a short time only.
}
}
To display a notification in the status bar and have it launch an intent when the user selects it (such as the new text message
notification does), call NotificationManager.notify() , and pass in vibration patterns, status bar icons, or Intents to associate
with the notification.
An activity can display a progress bar to notify the user that something is happening. To display a progress bar in a screen,
call Activity.requestWindowFeature(Window.FEATURE_PROGRESS) . To set the value of the progress bar, call
Activity.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, level). Progress bar values are from 0 to 9,999, or set
the value to 10,000 to make the progress bar invisible.
You can also use the ProgressDialog class, which enables a dialog box with an embedded progress bar to send a "I'm
working on it" notification to the user.
You can't. Only a user can add an application to the Favorites list.
Every Android screen has a default menu with default options, such as adding the activity to the favorites menu. You can
add your own menu entries to the default menu options by implementing Activity.onCreateOptionsMenu or
Activity.onPrepareOptionsMenu() , and adding Item objects to the Menu passed in. To handle clicks implement
Activity.onOptionsItemSelected() to handle the click in your Activity class. You may also pass the Item object a handler class
that implements the Runnable class (a handler) but this is less efficient and discouraged.
An application receives a callback at startup time to enable it to populate its menu. Additionally, it receives callbacks each
time the user displays the options menu to let you perform some contextual modifications on the menu. To populate the
menu on startup, override Activity.onCreateOptionsMenu; to populate it when the menu is called (somewhat less efficient),
you can override Activity.onPrepareOptionsMenu() . Each Activity has its own menu list.
Menu items are displayed in the order added, though you can group them as described in the Menu.add documentation. The
following code snippet adds three items to the default menu options and handles them through the overridden
Activity.onOptionsItemSelected() method. You can show or hide menu items by calling setItemShown() or setGroupShown() .
// Called only the first time the options menu is displayed.
// Create the menu entries.
// Menu adds items in the order shown.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// Parameters for menu.add are:
// group -- Not used here.
// id -- Used only when you want to handle and identify the click yourself.
// title
menu.add(0, 0, "Zoom");
menu.add(0, 1, "Settings");
menu.add(0, 2, "Other");
Displaying a Progress Bar
Adding Your Application to the Favorites List
Adding Items to the Screen Menu
43Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
example, suppose you implement a new image handling tool that shrinks an image to a smaller size and you would like to
offer this as a menu option to any other Activity that handles pictures. To do this, you would exposes your capabilities inside
an intent filter in your manifest. If another application that handles photos asks Android for any Activities that can perform
actions on pictures, Android will perform intent resolution, find your Activity, and add it to the other Activity's options menu.
The application offering the service must include an <intent-filter> element in the manifest, inside the <activity>
tag of the offering Activity. The intent filter includes all the details describing what it can do, such as a <type> element that
describes the MIME type of data that it can handle, a custom <action> value that describes what your handling application
can do (this is so that when it receives the Intent on opening it knows what it is expected to do), and most important, include
a <category> filter with the value android.intent.category.ALTERNATIVE and/or
android.intent.category.SELECTED_ALTERNATIVE (SELECTED_ALTERNATIVE is used to handle only the
currently selected element on the screen, rather than the whole Activity intent.
Here's an example of a snip of a manifest that advertises picture shrinking technology for both selected items and the whole
screen.
<activity class="PictureShrink"> <!-- Handling class -->
<intent-filter label="Shrink picture"> <!-- Menu label to display -->
<action value="com.example.sampleapp.SHRINK_IT" />
<type value="image/*" /> <!-- MIME type for generic images -->
<category value="android.intent.category.ALTERNATIVE " />
<category value="android.intent.category.SELECTED_ALTERNATIVE" />
</intent-filter>
</activity>
An application that wants to display a menu that includes any additional external services must, first of all, handle its menu
creation callback. As part of that callback it creates an intent with the category Intent.ALTERNATIVE_CATEGORY and/or
Intent.SELECTED_ALTERNATIVE, the MIME type currently selected, and any other requirements, the same way as it would
satisfy an intent filter to open a new Activity. It then calls menu.addIntentOptions() to have Android search for and add any
services meeting those requirements. It can optionally add addit ional custom menu items of its own.
You should implement SELECTED_ALTERNATIVE in onPrepareOptionsMenu() rath er than onCreateOptionsMenu(),
because the user's selection can change after the application is launched.
Here's a code snippet demonstrating how a picture application would search for additional services to display on its menu.
@Override public boolean
onCreateOptionsMenu(Menu menu){
super.onCreateOptionsMenu(menu);
// Create an Intent that describes the requirements to fulfill to be included
// in our menu. The offering app must include a category value of
Intent.ALTERNATIVE_CATEGORY.
Intent intent = new Intent(null, getIntent().getData());
intent.addCategory(Intent.ALTERNATIVE_CATEGORY);
// Search for, and populate the menu with, acceptable offering applications.
menu.addIntentOptions(
0, // Group
0, // Any unique IDs we might care to add.
MySampleClass.class.getName(), // Name of the class displaying the menu--here,
its this class.
null, // No specifics.
intent, // Previously created intent that describes our requirements.
0, // No flags.
null); // No specifics.
return true;
The offering application
The menu-displaying application
}
45Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The following outline illustrates a typical implementation:
public class MyActivity extends Activity {
[ . . . ]
// Need handler for callbacks to the UI thread
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResultsInUi();
}
};
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
[ . . . ]
}
protected void startLongRunningOperation() {
// Fire off a thread to do some work that we shouldn't do directly in the UI
thread
Thread t = new Thread() {
public void run() {
mResults = doSomethingExpensive();
mHandler.post(mUpdateResults);
}
};
t.start();
}
private void updateResultsInUi() {
// Back in the UI thread -- update our UI elements based on the data in mResults
[ . . . ]
}
}
For further discussions on this topic, see Developing Responsive Applications and the Handler documentation.
You can highlight or style the formatting of strings or substrings of text in a TextView object. There are two ways to do this:
If you use a string resource, you can add some simple styling, such as bold or italic using HTML notation. So, for
example, in res/values/strings.xml you could declare this:<resource>
<string>id="@+id/styled_welcome_message">We are <b><i>so</i></b> glad to see
you.</string>
</resources>
To style text on the fly, or to add highlighting or more complex styling, you must use the Spannable object as described
next.
To style text on the fly, you must make sure the TextView is using Spannable storage for the text (this will always be true if
the TextView is an EditText), retrieve its text with getText(), and call setSpan(Object, int, int, int), passing in a new style class
Selecting, Highlighting, or Styling Portions of Text
47Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
In most cases, every Android application runs in its own Linux process. This process is created for the application when
some of its code needs to be run, and will remain running until it is no longer needed and the system needs to reclaim its
memory for use by other applications.
An important and unusual feature of Android is that an application process's lifetime is not directly controlled by the
application itself. Instead, it is determined by the system through a combination of the parts of the application that the system
knows are running, how important these things are to the user, and how much overall memory is available in the system.
It is important that application developers understand how different application components (in particular Activity, Service,
and IntentReceiver) impact the lifetime of the application's process. Not using these components correctly can result in
the system killing the application's process while it is doing important work.
A common example of a process lifecycle bug is an IntentReceiver that starts a thread when it receives an Intent in its
onReceiveIntent() method, and then returns from the function. Once it returns, the system considers that IntentReceiver to
be no longer active, and thus its hosting process no longer needed (unless other application components are active in it).
Thus, it may kill the process at any time to reclaim memory, terminating the spawned thread that is running in it. The solution
to this problem is to start a Service from the IntentReceiver, so the system knows that there is still active work being done in
the process.
To determine which processes should be killed when low on memory, Android places them into an "importance hierarchy"
based on the components running in them and the state of those components. These are, in order of importance:
A foreground process is one holding an Activity at the top of the screen that the user is interacting with (its
onResume() method has been called) or an IntentReceiver that is currently running (its onReceiveIntent() method is
executing). There will only ever be a few such processes in the system, and these will only be killed as a last resort if
memory is so low that not even these processes can continue to run. Generally at this point the device has reached a
memory paging state, so this action is required in order to keep the user interface responsive.
1.
A visible process is one holding an Activity that is visible to the user on-screen but not in the foreground (its
onPause() method has been called). This may occur, for example, if the foreground activity has been displayed with a
dialog appearance that allows the previous activity to be seen behind it. Such a process is considered extremely
important and will not be killed unless doing so is required to keep all foreground processes running.
2.
A service process is one holding a Service that has been started with the startService() method. Though these
processes are not directly visible to the user, they are generally doing things that the user cares about (such as
background mp3 playback or background network data upload or down load), so the system will always keep such
processes running unless there is not enough memory to retain all foreground and visible process.
3.
A background process is one holding an Activity that is not currently visible to the user (its onStop() method has been
called). These processes have no direct impact on the user experience. Provided they implement their activity lifecycle
correctly (see Activity for more details), the system can kill such processes at any time to reclaim memory for one of
the three previous processes types. Usually there are many of these processes running, so they are kept in an LRU list
to ensure the process that was most recently seen by the user is the last to be killed when running low on memory.
4.
An empty process is one that doesn't hold any active application components. The only reason to keep such a
process around is as a cache to improve startup time the next time a component of its application needs to run. As
such, the system will often kill these processes in order to balance overall system resources between these empty
cached processes and the underlying kernel caches.
5.
When deciding how to classify a process, the system picks the most important level of all the components currently active in
the process. See the Activity, Service, and IntentReceiver documentation for more detail on how each of these components
contribute to the overall lifecycle of a process. The documentation for each of these classes describes in more detail how
they impact the overall lifecycle of their application.
Lifecycle of an Android Application
49Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The Android SDK includes a mobile device emulator — a virtual device that
runs on your computer. The emulator lets you prototype, develop, and test
Android applications without using a physical device.
The Android emulator mimics all of the typical functions and behaviors of a
mobile device, except that it can not receive or place phone calls. As shown at
right, the emulator provides a variety of navigation and control keys, which you can "press" using your mouse or keyboard to generate events for your
application. It also provides a screen in which your application is displayed,
together with any other Android applications running.
To help you model and test your application, the emulator lets your application
use the services of the Android platform to invoke other applications, access
the network, play audio and video, store and retrieve data, notify the user, and
render graphical transitions and themes.
The emulator also includes a variety of debug capabilities, such as a console
from which you can log kernel output, simulate application interrupts (such as
arriving SMS messages or phone calls), and simulate latency effects and
dropouts on the data channel.
The sections below provide more information about the emulator and how to
use it when developing your applications.
Starting and Stopping the Emulator
Controlling the Emulator
Emulator Startup Options
Using the Emulator Console
Port Redirections
Network Status
Network Delay Emulation
Network Speed Emulation
Telephony Emulation
Using Emulator Skins
Running Multiple Instances of the Emulator
Installing Applications on the Emulator
SD Card Emulation
Creating a Disk Image
Copying Files to a Disk Image
Loading the Disk Image at Emulator Startup
Troubleshooting Emulator Problems
Android Emulator
Contents
Emulator Limitations
To start the emulator, change to the tools/ folder of the SDK and enter emulator or ./emulator. This initializes the
Android system and you will see the emulator window appear on your screen.
To stop the emulator, close the emulator window.
Starting and Stopping the Emulator
51Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Category Option Description Comments
Help -help Print a list of all emulator
commands.
Data -data [file] Use <file> as the working
user-data disk image.
If -data is not used, the emulator looks for
a file named "userdata.img" in ~/.android
(Linux/Mac) or C:\Documents and
Settings\<user>\Local Settings\Android
(Windows).
If you use -data <file> but <file> does
not exist, the emulator creates a file at that
location.
-ramdisk <file> Use <file> as the ramdisk
image.
Default value is <system>/ramdisk.img
-sdcard <file> Use <file> as the SD card
image.
Default value is <system>/sdcard.img
-wipe-data Wipe all data on the user disk
image (see -data) before
starting.
Debug -console Enable console shell on the
current terminal.
-debug-kernel Send kernel output to the
console.
-logcat
<logtags>
Enable logcat output with given
tags.
If the environment variable
ANDROID_LOG_TAGS is defined and not
empty, its value will be used to enable logcat
output by default
-trace <name> Enable code profiling (press F9
to start).
-verbose Enable verbose output.
-verbosekeys Enable verbose key presses.
Media -mic <device or
file>
Use device or WAV file for audio
input.
-noaudio Disable Android audio support. Set by default.
-radio <device> Redirect radio modem interface
to a host character device.
-useaudio Enable Android audio support. Disabled by default.
Network -netdelay
<delay>
Set network latency emulation to
<delay>.
Default value is none. See the table in
Network Delay Emulation for supported
53Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
console and use the netstatus command. Here's an example of the command and its output.
network status
The emulator lets you simulate various network latency levels, so that you can test your applicaton in an environment more
typical of the actual conditions in which it will run. You can set a latency level or range at emulator startup or you can use the
console to change the latency dynamically, while the applicat ion is running in the emulator.
To set latency at emulator startup, use the -netdelay emulator option with a supported <delay> value, as listed in the
table below. Here are some examples:
emulator -netdelay gprs
emulator -netdelay 40 100
To make dynamic changes to network delay while the emulator is running, connect to the console and use the netdelay
command with a supported <delay> value from the table below.
network delay gprs
The format of network is one of the following (numbers are milliseconds):
Value Description Comments
gprs GPRS (min 150, max 550)
edge EDGE/EGPRS (min 80, max 400)
umts UMTS/3G (min 35, max 200)
none No latency (min 0, max 0)
<num> Emulate an exact latency
(milliseconds).
<min>:<max> Emulate an specified latency range
(min, max milliseconds).
The emulator also lets you simulate various network transfer rates. You can set a transfer rate or range at emulator startup
or you can use the console to change the rate dynamically, while the application is running in the emulator.
To set the network speed at emulator startup, use the -netspeed emulator option with a supported <speed> value, as
listed in the table below. Here are some examples:
emulator -netspeed gsm
emulator -netspeed 14.4 80
To make dynamic changes to network speed while the emulator is running, connect to the console and use the netspeed
command with a supported <speed> value from the table below.
network speed 14.4 80
The format of network <speed> is one of the following (numbers are kilobits/sec):
Network Delay Emulation
Network Speed Emulation
55Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
You can run the emulator with any of four default skins, as described in the table below. To specify a skin, use -skin
<skinID> when starting the emulator.
For example:
emulator -skin HVGA-L
Note that you must enter the in uppercase letters (if your development computer is case-sensitive).
skinID Description Skin
QVGA-L 320x240, landscape (default)
QVGA-P 240x320, portrait
HVGA-L 480x320, landscape
HVGA-P 320x480, portrait
Using Emulator Skins
57Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The adb utility sees the emulator as an actual physical device. For this reason, you might have to use the -d flag with some
common adb commands, such as install. The -d flag lets you specify which of several connected devices to use as the
target of a command. If you don't specify -d, the emulator will target the first device in its list. For more information about
adb, see Android Debug Bridge.
For emulators running on Mac OS X, if you see an error "Warning: No DNS servers found" when starting the emulator,
check to see whether you have an /etc/resolv.conf file. If not, please run the following line in a command window:
ln -s /private/var/run/resolv.conf /etc/resolv.conf
See Frequently Asked Questions for more troubleshooting information.
In this release, the limitations of the emulator include:
No support for placing or receiving actual phone calls. You can simulate phone calls (placed and received) through the
emulator console, however.
No support for USB connections
No support for camera/video capture (input).
No support for audio input (capture). Output (playback) is supported.
No support for device-attached headphones
No support for determining connected state
No support for determining battery charge level and AC charging state
No support for determining SD card insert/eject
No support for Bluetooth
Troubleshooting Emulator Problems
Emulator Limitations
59Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The basic functional unit of an Android application is the activity--an object of the class android.app.Activity. An activity can
do many things, but by itself it does not have a presence on the screen. To give your activity a screen presence and design
its UI, you work with views and viewgroups -- basic units of user interface expression on the Android platform.
A view is an object of base class android.view.View. It's a data structure whose properties store the layout and content for a
specific rectangular area of the screen. A View object handles measuring and layout, drawing, focus change, scrolling, and
key/gestures for the screen area it represents.
The View class serves as a base class for widgets -- a set of fully implemented subclasses that draw interactive screen
elements. Widgets handle their own measuring and drawing, so you can use them to build your UI more quickly. The list of
widgets available includes Text, EditText, InputMethod, MovementMethod, Button, RadioButton, Checkbox, and ScrollView.
A viewgroup is an object of class android.view.Viewgroup. As its name indicates, a viewgroup is a special type of view object
whose function is to contain and manage a subordinate set of views and other viewgroups, Viewgroups let you add structure
to your UI and build up complex screen elements that can be addressed as a single entity.
The Viewgroup class serves as a base class for layouts -- a set of fully implemented subclasses that provide common types
of screen layout. The layouts give you a way to build a structure for a set of views.
On the Android platform, you define an Activity's UI using a tree of view and viewgroup nodes, as shown in the diagram
below. The tree can be as simple or complex as you need to make it, and you can build it up using Android's set of
predefined widgets and layouts or custom view types that you create yourself.
To attach the tree to the screen for rendering, your Activity calls its setContentView() method and passes a reference to the
root node object. Once the Android system has the reference to the root node object, it can work directly with the node to
invalidate, measure, and draw the tree. When your Activity becomes active and receives focus, the system notifies your
activity and requests the root node to measure and draw the tree. The root node then requests that its child nodes draw
themselves -- in turn, each viewgroup node in the tree is responsible for drawing its direct children.
As mentioned previously, each view group has the responsibility of measuring its available space, laying out its children, and
calling Draw() on each child to let it render itself. The children may request a size and location in the parent, but the parent
object has the final decision on where how big each child can be.
Hierarchy of Screen Elements
Views
Viewgroups
A Tree-Structured UI
61Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The following two forms represent a LinearLayout with
a set of elements: a button, some labels, some text
boxes. Both have padding values to adjust the
padding nicely. The text boxes have their width set to
FILL_PARENT; other elements are set to
WRAP_CONTENT. The gravity, by default, is left. The
form on the left has weight values unset (0 by
default); the form on the right has the comments text
box weight set to 1. If the Name textbox had also been set to 1, the Name and Comments text boxes would
be the same height.
Tip: To create a proportionate size layout on the
screen, create a container object that is
fill_parent, assign the children heights or widths of
zero, and then assign relative weight values to
each child, depending on what proportion of the
screen each should take.
Within a horizontal LinearLayout, items are aligned by the position of their text base line (the first line of the
first list element — topmost or leftmost — is considered the reference line). This is so that people scanning
elements in a form shouldn't have to jump up and down to read element text in neighboring elements. This
can be turned off by setting android:baselineAligned="false" in the layout XML.
TableLayout positions its children into rows and columns. A TableLayout consists of a number of TableRow
objects, each defining a row (actually, you can have other children, which will be explained below).
TableLayout containers do not display border lines for their rows, columns, or cells. Each row has zero or
more cells; each cell can hold one View object. The table has as many columns as the row with the most
cells. A table can leave cells empty. Cells cannot span columns, as they can in HTML. The following image
shows a table layout, with the invisible cell borders displayed as dotted lines.
TableLayout
Columns can be hidden, can be marked to stretch to fill available screen space, or can be marked as
shrinkable to force the column to shrink until the table fits the screen. See the reference documentation for
this class for more details. 63Compiled by fastop 2007-2
http://fastoponandroid.googlepages.com
These objects all hold child UI elements. Some provide visible UI, and others only handle child layout.
Class Description
AbsoluteLayout Enables you to specify the location of child objects relative to the parent in exact
measurements (for example, pixels).
FrameLayout Layout that acts as a view frame to display a single object.
Gallery A horizontal scrolling display of images, from a bound list.
GridView Displays a scrolling grid of m columns and n rows.
LinearLayout A layout that organizes its children into a single horizontal or vertical row. It creates a
scrollbar if the length of the window exceeds the length of the screen.
ListView Displays a scrolling single column list.
Summary of Important View Groups
As we mentioned, some view groups have UI. These objects typically subclass AdapterView. Examples include such as
Gallery (an image selection widget) and ListView (a list of views). These objects have two jobs in common:
Filling the layout with data
Handling user selections
This is typically done by binding the class to an Adapter that gets its data from somewhere — either a list that the code
supplies, or query results from the device's database.
// Get a Spinner and bind it to an ArrayAdapter that
// references a String array.
private String[] fruit = {"apples", "oranges", "lemons"}
Spinner s1 = (Spinner)findViewById(R.id.fruitlist);
s1.setAdapter(new ArrayAdapter<String>(this, R.layout.spinner_1, mStrings));
// Load a Spinner and bind it to a data query.
private String[] cols={android.provider.Contacts.PeopleColumns.NAME};
private Cursor cur = managedQuery(android.provider.Contacts.People.CONTENT_URI, cols,
null, null);
s2.setAdapter(new CursorAdapter(cur, this));
Working with AdapterViews (Binding to Data)
Filling the layout with data
This is done by setting the class's AdapterView.OnItemClickListener member to a listener and catching the selection changes.
Handling user selections
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id)
{
// Display a messagebox.
showAlert("You've got an event", "Clicked me!", "ok", false);
}
};
// Now hook into our object and set its onItemClickListener member
// to our class handler object.
mHistoryView = (ListView)findViewById(R.id.history);
mHistoryView.setOnItemClickListener(mMessageClickedHandler);
65Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Loading the compiled layout resource is very easy, and done with a single call in the application's onCreate() method, as shown here:
protected void onCreate(Bundle savedValues)
{
// Be sure to call the super class.
super.onCreate(savedValues);
// Load the compiled layout resource into the window's
// default ViewGroup.
// The source file is res/layout/hello_activity.xml
setContentView(R.layout.hello_activity);
// Retrieve any important stored values.
restoreValues(savedValues);
}
Loading the XML Resource
You can get a handle to a screen element by calling Activity.findViewById. You can use this handle to set or retrieve any
values exposed by the object.
TextView msgTextView = (TextView)findViewById(R.id.msg);
msgTextView.setText(R.string.push_me);
Hooking into a Screen Element
Some UI notifications are automatically exposed and called by Android. For instance, Activity exposes overrideable methods
onKeyDown and onKeyUp, and Widget exposes onFocusChanged(boolean, int) . However, some important callbacks, such
as button clicks, are not exposed natively, and must be registered for manually, as shown here.
public class SendResult extends Activity
{
/**
* Initialization of the Screen after it is first created. Must at least
* call setContentView() to
* describe what is to be displayed in the screen.
*/
protected void onCreate(Bundle savedValues)
{
...
// Listen for button clicks.
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(mCorkyListener);
}
// Create an anonymous class to act as a button click listener.
private OnClickListener mCorkyListener = new OnClickListener()
{
public void onClick(View v)
{
// To send a result, simply call setResult() before your
// activity is finished.
setResult(RESULT_OK, "Corky!");
finish();
}
};
Listening for UI Notifications
67Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Panel
A panel is a concept not backed by a specific class. It is a View of some sort that is tied in closely to a parent window,
but can handle clicks and perform simple functions related to its parent. A panel floats in front of its parent, and is
positioned relative to it. A common example of a panel (implemented by Android) is the options menu available to every
screen. At present, there are no specific classes or methods for creating a panel — it's more of a general idea.
Dialog
A dialog is a floating window that can have buttons, and acts as a lightweight form that is intended to, at most, perform a
simple action (such as click a button) and perhaps return a value. It is not intended to persist in the history stack,
contain complex layout, or perform complex actions. Android provides a default simple dialog for you with optional
buttons, though you can define a dialog layout yourself. The base class is Dialog, and the helper methods to open a
dialog box are the various Activity.showAlert() methods.
Window
An abstract class that specifies the elements of a generic window, such as the look and feel (title bar text, location and
content of menus, and so on). Dialog and Activity use an implementation of this class to render a window. You should
not need to implement this class.
Surface
A block of memory that gets composited to the screen. A Surface holds a Canvas object for drawing, and provides
various helper methods to draw layers and resize the surface. You should not use this class directly; use SurfaceView
instead.
SurfaceView
A View object that wraps a Surface for drawing, and exposes methods to specify its size and format dynamically. The
camera app uses SurfaceView for its preview screen. A SurfaceView provides a way to draw independently of the UI
thread for resource-intense operations (such as games or camera previews), but it uses extra memory as a result.
SurfaceView supports both Canvas and OpenGL ES graphics.
Canvas
A drawing surface where the actual bits are composited. It has methods for standard computer drawing of bitmaps,
lines, circles, rectangles, text, and so on. It is bound to a Bitmap or Surface. Canvas is the simplest, easiest way to draw
2D objects on the screen. However, it does not support hardware acceleration, as OpenGL ES does.
OpenGL ES
Android provides OpenGL ES libraries that you can use for fast, complex 3D images. It is much harder to use than a
Canvas object, but better for 3D objects. The graphics.glutils package exposes OpenGL ES functionality.
69Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
AndroidManifest.xml is a required file for every application. It sits in the root folder for an application, and describes global
values for your package, including the application components (activities, services, etc) that the package exposes and the
implementation classes for each component, what kind of data each can handle, and where they can be launched.
An important aspect of this file are the intent filters that it includes. These filters describe where and when that activity can be
started. When an activity (or the operating system) wants to perform an action such as open a Web page or open a contact
picker screen, it creates an Intent object. This object can hold several descriptors describing what you want to do, what data
you want to do it to, the type of data, and other bits of information. Android compares the information in an Intent object with
the intent filter exposed by every application and finds the activity most appropriate to handle the data or action specified by
the caller. More details on intents is given in the Intent reference page.
Besides declaring your application's Activities, Content Providers, Services, and Intent Receivers, you can also specify
permissions and instrumentation (security control and testing) in AndroidManifest.xml. For a reference of the tags and their
attributes, please see AndroidManifest.
A simple AndroidManifest.xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my_domain.app.helloactivity">
<application android:label="@string/app_name">
<activity class=".HelloActivity">
<intent-filter>
<action android:value="android.intent.action.MAIN"/>
<category android:value="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
Some general items to note:
Almost every AndroidManifest.xml (as well as many other Android XML files) will include the namespace declaration
xmlns:android="http://schemas.android.com/apk/res/android" in its first element. This makes a variety
of standard Android attributes available in the file, which will be used to supply most of the data for elements in that file.
Most manifests include a single <application> element, which defines all of the application-level components and
properties that are available in the package.
Any package that will be presented to the user as a top-level application available from the program launcher will need
to include at least one Activity component that supports the MAIN action and LAUNCHER category as shown here.
Here is a detailed outline of the structure of an AndroidManifest.xml file, describing all tags that are available.
<manifest>
The root node of the file, describing the complete contents of the package. Under it you can place:
<uses-permission>
The AndroidManifest.xml File
Requests a security permission that your package must be granted in order for it to operate correctly. See the
Security Model document for more information on permissions. A manifest can contain zero or more of these
elements.
71Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
A typical desktop operating system provides a common file system that any application can use to store and read files that
can be read by other applications (perhaps with some access control settings). Android uses a different system: on Android,
all application data (including files) are private to that application. However, Android also provides a standard way for an
application to expose its private data to other applications. This section describes the many ways that an application can
store and retrieve data, expose its data to other applications, and also how you can request data from other applications that
expose their data.
Android provides the following mechanisms for storing and retrieving data:
Preferences
A lightweight mechanism to store and retrieve key/value pairs of primitive data types. This is typically used to store
application preferences.
Files
You can store your files on the device or on a removable storage medium. By default, other applications cannot access
these files.
Databases
The Android APIs contain support for SQLite. Your application can create and use a private SQLite database. Each
database is private to the package that creates it.
Content Providers
A content provider is a optional component of an application that exposes read/write access to an application's private
data, subject to whatever restrictions it wants to impose. Content providers implement a standard request syntax for
data, and a standard access mechanism for the returned data. Android supplies a number of content providers for
standard data types, such as personal contacts.
Network
Don't forget that you can also use the network to store and retrieve data.
Storing, Retrieving and Exposing Data
You can store application preferences such as a default greeting or text font to be loaded whenever this application is
started. Call Context.getSharedPreferences() to read and write values. Assign a name to your set of preferences if
you want to share them with other components in the same package, or use Activity.getPreferences() with no name
to keep them private to the calling activity. You cannot share preferences across packages. Here is an example of setting
user preferences for silent keypress mode for a calculator.
public class Calc extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
...
@Override
protected void onCreate(Bundle state){
super.onCreate(state);
...
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent); }
@Override
protected void onStop(){
super.onStop();
// Save user preferences. We need an Editor object to
// make changes. All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
// Don't forget to commit your edits!!!
editor.commit(); }}
Using Application Preferences
73Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Modifying Data
Adding a Record
Deleting a Record
Each contact provider exposes a unique public URI (wrapped by ContentURI) that is used by a client to
query/add/update/delete data on that content provider. This URI has two forms: one to indicate all values of that type (e.g.,
all personal contacts), and one form to indicate a specific record of that type (e.g., Joe Smith's contact information).
content://contacts/people/ is the URI that would return a list of all contact names on the device.
content://contacts/people/23 is the URI string that would return a single result row, the contact with ID = 23. .
An application sends a query to the device that specifies a general type of item (all phone numbers), or a specific item
(Bob's phone number), to retrieve. Android then returns a Cursor over a recordset of results, with a specific set of columns.
Let's look at a hypothetical query string and a result set (the results have been trimmed a bit for clarity):
query = content://contacts/people/
Results:
Querying for Data
_ID _COUNT NUMBER NUMBER_KEY LABEL NAME TYPE
13 4 (425) 555 6677 425 555 6677 California office Bully Pulpit Work
44 4 (212) 555-1234 212 555 1234 NY apartment Alan Vain Home
45 4 (212) 555-6657 212 555 6657 Downtown office Alan Vain Work
53 4 201.555.4433 201 555 4433 Love Nest Rex Cars Home
Note that the query string isn't a standard SQL query string, but instead a URI string that describes the type of data to return.
This URI consists of three parts: the string "content://"; a segment that describes what kind of data to retrieve; and finally an
optional ID of a specific item of the specified content type. Here are a few more example query strings:
content://media/images is the URI string that would return a list of all images on the device.
content://contacts/people/ is the URI that would return a list of all contact names on the device.
content://contacts/people/23 is the URI string that would return a single result row, the contact with ID = 23.
Although there is a general form, query URIs are somewhat arbitrary and confusing. Therefore, Android provides a list of
helper classes in the android.provider package that define these query strings so you should not need to know the actual
URI value for different data types. These helper classes define a string (actually, a wrapper class called ContentURI) called
CONTENT_URI for a specific data type. For instance, android.provider.contacts.People.CONTENT_URI defines the query
string used to search for people in Android's built-in people content provider.
Typically you will use the defined CONTENT_URI object to make a query. The only time you should need to examine or
modify this string is to add an ID value to the end of the URI to retrieve a specific record. So, for example, if you were looking
for record 23 in the people contacts, you might run a query as shown here:
// Get the base URI for contacts.
ContentURI myPerson = new
ContentURI(android.provider.Contacts.People.CONTENT_URI.toURI());
// Add the ID of the record I'm looking for (I'd have to know this somehow).
myPerson.addId(23);
// Query for this record.
Cursor cur = managedQuery(myPerson, null, null, null);
This query returns a cursor over a database query result set. What columns are returned, what they're called, and what they
are named are discussed next. For now, though, know that you can specify that only certain columns be returned, the sort
order, and a SQL WHERE clause.
75Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Reading Retrieved Data
The Cursor object retrieved by the query provides access to a recordset of results. If you have queried for a specific record
by ID, this set will contain only one value; otherwise, it can contain multiple values. You can read data from specific fields in
the record, but you must know the data type of the field, because reading data requires a specialized method for each type
of data. (If you call the string reading method on most types of columns, Android will give you the String representation of the
data.) The Cursor lets you request the column name from the index, or the index number from the column name.
If you are reading binary data, such as an image file, you should call ContentResolver.openOutputStream() on the string
content:// URI stored in a column name.
The following snippet demonstrates reading the name and phone number from our phone number query:
private void getColumnData(Cursor cur){
if(!cur.first())
return;
String name;
String phoneNumber;
int nameColumn = cur.getColumnIndex(android.provider.Contacts.PeopleColumns.NAME);
int phoneColumn =
cur.getColumnIndex(android.provider.Contacts.PhonesColumns.NUMBER);
int pathColumn = cur.getColumnIndex(android.provider.Contacts.PeopleColumns.PHOTO);
String imagePath;
while (cur.next()) {
// Get the field values
name = cur.getString(nameColumn);
phoneNumber = cur.getString(phoneColumn);
imagePath = cur.getString(stringColumn);
InputStream is = getContentResolver().openInputStream(imagePath);
... read the file stream into something...
is.close()
// Do something with the values.
...
}
}
Note that the image field is actually a string path value. Some content provider convenience classes provide helper methods
to get specific field values such as files more easily.
Remember, whenever calling updating methods on the Cursor class, you must call commitUpdates() to send the changes to
the database.
To update an individual record, set the Cursor to the appropriate object, call the appropriate update... method, and then call
commitUpdates().
To batch update a group of records (for example, to change "NY" to "New York" in all contact fields), call the
ContentResolver.update() method with the columns and values to change.
Remember, whenever calling updating methods on the Cursor class, you must call commitUpdates() to send the changes to
the database.
Modifying Data
To add a new record, call ContentResolver.insert() with the URI of the type of item to add, and a Map of any values you want
to set immediately on the new record. This will return the full URI of the new record, including record number, which you can
then use to query and get a Cursor over the new record.
Remember, whenever calling updating methods on the Cursor class, you must call commitUpdates() to send the changes to
the database.
Adding a New Record
77Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
If you are exposing byte data, such as a bitmap file, the field that stores this data should actually be a string field with a
content:// URI for that specific file. This is the field that clients will call to retrieve this data. The content provider for that
content type (it can be the same content provider or another content provider — for example, if you're storing a photo
you would use the media content provider) should implement a field named _data for that record. The _data field lists
the exact file path on the device for that file. This field is not intended to be read by the client, but by the
ContentResolver. The client will call ContentResolver.openOutputStream() on the user-facing field holding the URI for
the item (for example, the column named photo might have a value content://media/images/4453). The
ContentResolver will request the _data field for that record, and because it has higher permissions than a client, it
should be able to access that file directly and return a read wrapper for that file to the client.
5.
Declare public static Strings that clients can use to specify which columns to return, or to specify field values from the
cursor. Carefully document the data type of each field. Remember that file fields, such as audio or bitmap fields, are
typically returned as string path values
6.
Return a Cursor object over a recordset in reply to a query. This means implementing the query(), update(), insert(),
and delete() methods. As a courtesy, you might want to call ContentResolver.notifyChange() to notify listeners about
updated information.
7.
Add a <provider> tag to AndroidManifest.xml, and use its authorities attribute to define the authority part of the 8.
content type it should handle. For example, if your content type is content://com.example.autos/auto to request a list of
all autos, then authorities would be com.example.autos. Set the multiprocess attribute to true if data does not need
to be synchronized between multiple running versions of the content provider.
If you are handling a new data type, you must define a new MIME type to return for your implementation of
android.ContentProvider.getType(url) . This type corresponds to the content:// URI submitted to getType(), which
will be one of the content types handled by the provider. The MIME type for each content type has two forms: one for a
specific record, and one for multiple records. Use the ContentURI methods to help determine what is being requested.
Here is the general format for each:
vnd.<yourcompanyname>.cursor.item/<contenttype> for a single row. For example: a request for train
record 122, using content://com.example.transportationprovider/trains/122, might return the
MIME type vnd.example.cursor.item/rail
vnd.<yourcompanyname>.cursor.dir/<contenttype> for multiple rows. So, for example, a request for all
train records, using content://com.example.transportationprovider/trains might return the MIME
type vnd.example.cursor.dir/rail.
9.
For an example of a private content provider implementation, see the NodePadProvider class in the notepad sample
application that ships with the SDK.
Here is a recap of the important parts of a content URI:
Standard required prefix. Never modified. A.
Authority part. For third-party applications, this should be a fully-qualified class to ensure uniqueness. This
corresponds to the value in the <provider> element's authorities attribute: <provider
class="TransportationProvider" authorities="com.example.transportationprovider" />
B.
The path that the content provider uses to determine what kind of data is being requested. This can be zero or more
segments: if the content provider exposes only one type of data (only trains, for example), this can be absent. If it
provides several types, including subtypes, this can be several elements long: e.g., "land/bus, land/train,
sea/ship, and sea/submarine" to give four possibilities.
C.
A specific record being requested, if any. This is the _id value of a specific record being requested. If all records of a
specific type are being requested, omit this and the trailing slash:
content://com.example.transportationprovider/trains
D.
In addition to all the on-device storage options, you can also store and retrieve data from the network (when available). To
do network operations, you'll want to use the following packages:
java.net.*
android.net.*
Network Accesses with Android
79Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
At application install time, permissions requested by the application are granted to it by the package installer, based on
checks with trusted authorities and interaction with the user. No checks with the user are done while an application is
running: it either was granted a particular permission when installed, and can use that feature as desired, or the permission
was not granted and any attempt to use the feature will fail without prompting the user.
Often times a permission failure will result in a SecurityException being thrown back to the application. However, this is not
guaranteed to occur everywhere. For example, the broadcastIntent(Intent) method checks permissions as data is being
delivered to each receiver, after the method call has returned, so you will not receive an exception if there are permission
failures. In almost all cases, however, a permission failure will be printed to the system log.
The permissions provided by the Android system can be found at Manifest.permission. Any application may also define and
enforce its own permissions, so this is not a comprehensive list of all possible permissions.
A particular permission may be enforced at a number of places during your program's operation:
At the time of a call into the system, to prevent an application from executing certain functions.
When starting an activity, to prevent applications from launching activities of other applications.
Both sending and receiving Intent broadcasts, to control who can receive your broadcast or who can send a broadcast
to you.
When accessing and operating on a content provider.
Binding or starting a service.
To enforce your own permissions, you must first declare them in your AndroidManifest.xml using one or more
<permission> tags.
For example, an application that wants to control who can start one of its activities could declare a permission for this
operation as follows:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.app.myapp" >
<permission id="com.google.android.app.myapp.permission.DEADLY_ACTIVITY"
android:label="@string/permlab_deadlyActivity"
android:description="@string/permdesc_deadlyActivity" />
</manifest>
Note that both a label and description should be supplied for the permission. These are string resources that can be
displayed to the user when they are viewing a list of permissions (android:label) or details on a single permission (
android:description). The label should be short, a few words describing the key piece of functionality the permission is
protecting. The description should be a couple sentences describing what the permission allows a holder to do. Our
convention for the description is two sentences, the first describing the permission, the second warning the user of what bad
things can happen if an application is granted the permission.
Here is an example of a label and description for the CALL_PHONE permission:
<string name="permlab_callPhone">Call Phone Numbers</string>
<string name="permdesc_callPhone">Allows application to call
phone numbers without your intervention. Bad applications may
cause unexpected calls on your phone bill.</string>
High-level permissions restricting access to entire components of the system or application can be applied through your
AndroidManifest.xml All that this requires is including an android:permission attribute on the desired component,
Declaring and Enforcing Permissions
Enforcing Permissions in AndroidManifest.xml
naming the permission that will be used to control access to it.
Activity permissions (applied to the <activity> tag) restrict who can start the associated activity. The permission is checked
during Context.startActivity() and Activity.startSubActivity(); if the caller does not have the required permission then
SecurityException is thrown from the call.
81Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Resources are external files (that is, non-code files) that are used by your code and compiled into your
application at build time. Android supports a number of different kinds of resource files, including XML, PNG,
and JPEG files. The XML files have very different formats depending on what they describe. This document
describes what kinds of files are supported, and the syntax or format of each.
Resources are externalized from source code, and XML files are compiled into a binary, fast loading format
for efficiency reasons. Strings, likewise are compressed into a more efficient storage form. It is for these
reasons that we have these different resource types in the Android platform.
This document contains the following sections:
Resources
Creating Resources
Using Resources
Using Resources in Code
References to Resources
References to Theme Attributes
Using System Resources
Alternate Resources
Resource Reference
Terminology
Internationalization (I18N)
This is a fairly technically dense document, and together with the Resource Reference document, they cover a
lot of information about resources. It is not necessary to know this document by heart to use Android, but
rather to know that the information is here when you need it.
This topic includes a terminology list associated with resources, and a series of examples of using resources
in code. For a complete guide to the supported Android resource types, see Resources.
The Android resource system keeps track of all non-code assets associated with an application. You use the
Resources class to access your application's resources; the Resources instance associated with your
application can generally be found through Context.getResources().
An application's resources are compiled into the application binary at build time for you by the build system. To
use a resource, you must install it correctly in the source tree and build your application. As part of the build
process, symbols for each of the resources are generated that you can use in your source code -- this allows
the compiler to verify that your application code matches up with the resources you defined.
The rest of this section is organized as a tutorial on how to use resources in an application.
Resources and Internationalization
Resources
Android supports string, bitmap, and many other types of resource. The syntax and format of each, and where
they're stored, depends upon the type of object. In general, though, you create resources from three types of
files: XML files (everything but bitmaps and raw), bitmap files(for images) and Raw files (anything else, for
example sound files, etc.). In fact, there are two different types of XML file as well, those that get compiled
as-is into the package, and those that are used to generate resources by aapt. Here is a list of each resource
Creating Resources
83Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
This section describes how to use the resources you've created. It includes the following topics:
Using resources in code - How to call resources in your code to instantiate them.
Referring to resources from other resources - You can reference resources from other resources. This
lets you reuse common resource values inside resources.
Supporting Alternate Resources for Alternate Configurations - You can specify different resources to
load, depending on the language or display configuration of the host hardware.
At compile time, Android generates a class named R that contains resource identifiers to all the resources in
your program. This class contains several subclasses, one for each type of resource supported by Android,
and for which you provided a resource file. Each class contains one or more identifiers for the compiled
resources, that you use in your code to load the resource. Here is a small resource file that contains string,
layout (screens or parts of screens), and image resources.
Note: the R class is an auto-generated file and is not designed to be edited by hand. It will be automatically
re-created as needed when the resources are updated.
package com.google.android.samples;
public final class R {
public static final class string {
public static final int greeting=0x0204000e;
public static final int start_button_text=0x02040001;
public static final int submit_button_text=0x02040008;
public static final int main_screen_title=0x0204000a;
};
public static final class layout {
public static final int start_screen=0x02070000;
public static final int new_user_pane=0x02070001;
public static final int select_user_list=0x02070002;
};
public static final class drawable {
public static final int company_logo=0x02020005;
public static final int smiling_cat=0x02020006;
public static final int yellow_fade_background=0x02020007;
public static final int stretch_button_1=0x02020008;
};
};
Using Resources
Using resources in code is just a matter of knowing the full resource ID and what type of object your resource
has been compiled into. Here is the syntax for referring to a resource:
R.resource_type.resource_name
or
android.R.resource_type.resource_name
Using Resources in Code
Where resource_type is the R subclass that holds a specific type of resource. resource_name is the name
attribute for resources defined in XML files, or the file name (without the extension) for resources defined by
other file types. Each type of resource will be added to a specific R subclass, depending on the type of resource
it is; to learn which R subclass hosts your compiled resource type, consult the resource reference document.
Resources compiled by your own application can be referred to without a package name (simply as
R.resource_type.resource_name). Android contains a number of standard resources, such as screen
styles and button backgrounds. To refer to these in code, you must qualify them with android, as in
android.R.drawable.button_background .85Compiled by fastop 2007-2
http://fastoponandroid.googlepages.com
<?xml version="1.0" encoding="utf-8"?>
<EditText id="text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:textColor="@android:color/opaque_red"
android:text="Hello, World!" />
As another example, you should always use resource references when supplying strings in a layout file so that
they can be localized:
<?xml version="1.0" encoding="utf-8"?>
<EditText id="text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:textColor="@android:color/opaque_red"
android:text="@string/hello_world" />
This facility can also be used to create references between resources. For example, we can create new
drawable resources that are aliases for existing images:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable
id="my_background">@android:drawable/theme2_background</drawable>
</resources>
Another kind of resource value allows you to reference the value of an attribute in the current theme. This
attribute reference can only be used in style resources and XML attributes; it allows you to customize the look
of UI elements by changing them to standard variations supplied by the current theme, instead of supplying
more concrete values.
As an example, we can use this in our layout to set the text color to one of the standard colors defined in the
base system theme:
<?xml version="1.0" encoding="utf-8"?>
<EditText id="text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:textColor="?android:textDisabledColor"
android:text="@string/hello_world" />
References to Theme Attributes
Note that this is very similar to a resource reference, except we are using an '?' prefix instead of '@'. When
you use this markup, you are supplying the name of an attribute resource that will be looked up in the theme --
because the resource tool knows that an attribute resource is expected, you do not need to explicitly state the
type (which would be ?android:attr/android:textDisabledColor ).
Other than using this resource identifier to find the value in the theme instead of raw resources, the name
syntax is identical to the '@' format: ?[namespace:]type/name with the type here being optional.
87Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Android supports several types of qualifiers, with various values for each. Append these to the end of the
resource folder name, separated by dashes. You can add multiple qualifiers to each folder name, but they
must appear in the order they are listed here. For example, a folder containing drawable resources for a fully
specified configuration would look like:
MyApp/
res/
drawable-en-rUS-port-160dpi-finger-qwerty-dpad-480x320/
More typically, you will only specify a few specific configuration options that a resource is defined for. You may
drop any of the values from the complete list, as long as the remaining values are still in the same order:
MyApp/
res/
drawable-en-rUS-finger/
drawable-port/
drawable-port-160dpi/
drawable-qwerty/
Qualifier Values
Language The two letter ISO 639-1 language code in lowercase. For example: en, fr, es
Region The two letter ISO 3166-1-alpha-2 language code in uppercase preceded by a
lowercase "r". For example: rUS, rFR, rES
Screen orientation port, land, square
Screen pixel density 92dpi, 108dpi, etc.
Touchscreen type notouch, stylus, finger
Primary text input
method
qwerty, 12key
Primary
non-touchscreen
navigation method
dpad, trackball, wheel
Screen dimensions 320x240, 640x480, etc. The larger dimension must be specified first.
This list does not include device-specific parameters such as carrier, branding, device/hardware, or
manufacturer. Everything that an application needs to know about the device that it is running on is encoded
via the resource qualifiers in the table above.
Here are some general guidelines on qualified resource directory names:
Values are separated by a dash (as well as a dash after the base directory name)
Values are case-sensitive (even though they must be unique across all folder names in a
case-insensitive way)
For example,
A portrait-specific drawable directory must be named drawable-port , not drawable-PORT .
You may not have two directories named drawable-port and drawable-PORT , even if you had
intended "port" and "PORT" to refer to different parameter values.
89Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
The resource system brings a number of different pieces together to form the final complete resource
functionality. To help understand the overall system, here are some brief definitions of the core concepts and
components you will encounter in using it:
Asset: A single blob of data associated with an application. This includes object files compiled from the Java
source code, graphics (such as PNG images), XML files, etc. These files are organized in a directory
hierarchy that, during final packaging of the application, is bundled together into a single ZIP file.
aapt: Android Asset Packaging Tool. The tool that generates the final ZIP file of application assets. In addition
to collecting raw assets together, it also parses resource definitions into binary asset data.
Resource Table: A special asset that aapt generates for you, describing all of the resources contained in an
application/package. This file is accessed for you by the Resources class; it is not touched directly by
applications.
Resource: An entry in the Resource Table describing a single named value. Broadly, there are two types of
resources: primitives and bags.
Resource Identifier: In the Resource Table all resources are identified by a unique integer number. In source
code (resource descriptions, XML files, Java source code) you can use symbolic names that stand as
constants for the actual resource identifier integer.
Primitive Resource: All primitive resources can be written as a simple string, using formatting to describe a
variety of primitive types included in the resource system: integers, colors, strings, references to other
resources, etc. Complex resources, such as bitmaps and XML describes, are stored as a primitive string
resource whose value is the path of the underlying Asset holding its actual data.
Bag Resource: A special kind of resource entry that, instead of a simple string, holds an arbitrary list of
name/value pairs. Each name is itself a resource identifier, and each value can hold the same kinds of string
formatted data as a normal resource. Bags also support inheritance: a bag can inherit the values from another
bag, selectively replacing or extending them to generate its own contents.
Kind: The resource kind is a way to organize resource identifiers for various purposes. For example, drawable
resources are used to instantiate Drawable objects, so their data is a primitive resource containing either a
color constant or string path to a bitmap or XML asset. Other common resource kinds are string (localized
string primitives), color (color primitives), layout (a string path to an XML asset describing a view layout), and
style (a bag resource describing user interface attributes). There is also a standard "attr" resource kind, which
defines the resource identifiers to be used for naming bag items and XML attributes
Style: The name of the resource kind containing bags that are used to supply a set of user interface attributes.
For example, a TextView class may be given a style resource that defines its text size, color, and alignment. In
a layout XML file, you associate a style with a bag using the "style" attribute, whose value is the name of the
style resource.
Style Class: Specifies a related set of attribute resources. This data is not placed in the resource table itself,
but used to generate constants in the source code that make it easier for you to retrieve values out of a style
resource and/or XML tag's attributes. For example, the Android platform defines a "View" style class that
Terminology
contains all of the standard view attributes: padding, visibility, background, etc.; when View is inflated it uses
this style class to retrieve those values from the XML file (at which point style and theme information is applied
as approriate) and load them into its instance.
Configuration: For any particular resource identifier, there may be multiple different available values
depending on the current configuration. The configuration includes the locale (language and country), screen
orientation, screen density, etc. The current configuration is used to select which resource values are in effect
when the resource table is loaded.
91Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
If you've read Getting Started and Developing Apps, then you know how to build an Android application. (If you haven't read
those sections you should now.)
Android is a large system though, and there's a lot to learn. The best apps always make the most of the system's features.
The links below tell you how to write code that bends the system to your will, allowing you to create cool custom components
and do amazing things with the many available APIs.
Design Philosophy
A manifesto explaining a technical philosophy and perspective that Android developers will find useful. By reading this
page, you'll learn how to write applications that perform well on embedded devices (such as phone handsets), and that
play nicely with other parts of the system.
Building Custom Components
Explains how to create custom Android components, such as Views, Services, and Content Providers. Read this, and
you'll soon be knocking out great-looking, efficient, and useful components. You can use these to make your own
application great, or you can share them with other applications.
Optional APIs
Describes the APIs that provide access to optional Android components, such as GPS and BlueTooth. Android aims to
be more than just another OS, and so the system supports all the features you could hope for in a phone. This section
will show you how to use the Location-Based Services (such as GPS, compass, etc.), OpenGL 3D graphics, Bluetooth,
and accelerometer.
Note that the APIs described in this section are all optional; if your application truly requires one of these APIs, you
should be sure that it fails gracefully if the features are not present on a given phone.
Google APIs and Services
Describes how to use the APIs for accessing Google services that are installed on many Android devices.
Android Developer Toolbox
The process of learning how to build applications for a new API is pretty similar, even if the platforms themselves are wildly
different. Generally, there are two phases: first, you learn how to use the APIs to do what you want to do; later, you learn the
nuances of the platform. Put another way, first you learn how you can build applications; later, you learn how you should
build them.
That second phase — learning the right way to build applications — can often take a long time, and frequently means
"paying your dues", making mistakes, and learning from them. Well, that's not a very efficient process, so this page and the
links below aim to give you a helping hand.
Before we dive into it, a quick word. Successful applications will offer an outstanding end-user experience. While the Android
team has built a robust core system, the vast majority of the user experience will come from users interacting with your
applications. As a result, we encourage you to take the time to build an outstanding user experience.
An outstanding user experience has three key characteristics: it is fast; it is responsive; and it is seamless. Of course every
platform since the dawn of computing has probably cited those same three qualities at one time or another. However, each
platform achieves them in different ways; the information below explains how your apps can achieve them on Android.
Android Application Design Philosophy
An Android application should be fast. Well, it's probably more accurate to say that it should be efficient. There is a tendency
in the computing world these days to assume that Moore's Law will solve all our problems — eventually. When it comes to
embedded applications, though, Moore's Law is a bit more complicated.
Moore's Law doesn't really apply to mobile devices in the same way as to desktop and server applications. Moore's Law is
actually a law about transistor density — that is, it says that you can pack more circuitry into a given chip size, over time. For
desktop and server applications, this means you can pack more "speed" into a chip of roughly the same size, resulting in the
well-known performance increases. For embedded applications like cell phones, however, Moore's Law is usually exploited
to make chips smaller. That is, the tendency is to use the increased density to make the same chip smaller and consume
less power, to make phones smaller and make batteries last longer. As a result, embedded devices like phones are
increasing in actual, raw speed much more slowly than desktop systems. For embedded devices, Moore's Law means more
features and better battery life; increased speed is only an afterthought.
Fast
93Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
In Android, application responsiveness is monitored by the Activity Manager and Window Manager system services. Android
will display the ANR dialog for a particular application when it detects one of the following conditions:
no response to an input event (e.g. key press, screen touch) within 5 seconds
an IntentReceiver hasn't finished executing within 10 seconds
Given the above definition for ANR, let's examine why this can occur in Android applications and how best to structure your
application to avoid ANR.
Android applications normally run entirely on a single (i.e. main) thread. This means that anything your application is doing in
the main thread that takes a long time to complete can trigger the ANR dialog because your application is not giving itself a
chance to handle the input event or Intent broadcast.
Therefore any method that runs in the main thread should do as little work as possible. In particular, Activities should do as
little as possible to set up in key lifecycle methods such as onCreate() and onResume(). Potentially long running
operations such as network or database operations, or computationally expensive calculations such as resizing bitmaps
should be done in a child thread (or in the case of databases operations, via an asynchronous request). However, this does
not mean that your main thread should block while waiting for the child thread to complete — nor should you call
Thread.wait() or Thread.sleep(). Instead of blocking while waiting for a child thread to complete, your main thread
should provide a Handler for child threads to post back to upon completion. Designing your application in this way will allow
your main thread to remain responsive to input and thus avoid ANR dialogs caused by the 5 second input event timeout.
These same practices should be followed for any other threads that display UI, as they are also subject to the same
timeouts.
The specific constraint on IntentReciever execution time emphasizes what they were meant to do: small, discrete amounts
of work in the background such as saving a setting or registering a Notification. So as with other methods called in the main
When Good Applications Go Bad
Avoiding ANR
thread, applications should avoid potentially long-running operations or calculations in IntentReceivers. But instead of doing
intensive tasks via child threads (as the life of an IntentReceiver is short), your application should start a Service if a
potentially long running action needs to be taken in response to an Intent broadcast. As a side note, you should also avoid
starting an Activity from an Intent Receiver, as it will spawn a new screen that will steal focus from whatever application the
user is currently has running. If your application has something to show the user in response to an Intent broadcast, it should
do so using the Notification Manager.
Generally, 100 to 200ms is the threshold beyond which users will perceive lag (or lack of "snappiness," if you will) in an
application. As such, here are some additional tips beyond what you should do to avoid ANR that will help make your
application seem responsive to users.
If your application is doing work in the background in response to user input, show that progress is being made
(ProgressBar and ProgressDialog are useful for this).
For games specifically, do calculations for moves in a child thread.
If your application has a time-consuming initial setup phase, consider showing a splash screen or rendering the main
view as quickly as possible and filling in the information asynchronously. In either case, you should indicate somehow
that progress is being made, lest the user perceive that the application is frozen.
Reinforcing Responsiveness
There's no way around it: Android devices are embedded devices. Modern handsets may be more like small handheldcomputers than mere phones these days, but even the fastest, highest-end handset doesn't even come close to thecapabilities of even a modest desktop system.
That's why it's very important to consider performance when you write Android applications. These systems are not that fastto begin with and they are also constrained by their battery life. This means that there's not a lot of horsepower to spare, sowhen you write Android code it's important to write it as efficiently as possible.
This page describes a number of things that developers can do to make their Android code run more efficiently. By followingthe tips on this page, you can help make sure your code runs as efficiently as possible.
Writing Efficient Android Code
95Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Suppose you have a HashMap object. You can declare it as a HashMap or as a generic Map:
Map myMap1 = new HashMap();
HashMap myMap2 = new HashMap();
Which is better?
Conventional wisdom says that you should prefer Map, because it allows you to change the underlying implementation toanything that implements the Map interface. Conventional wisdom is correct for conventional programming, but isn't so greatfor embedded systems. Calling through an interface reference can take 2x longer than a virtual method call through aconcrete reference.
If you have chosen a HashMap because it fits what you're doing, there is little value in calling it a Map. Given the availabilityof IDEs that refactor your code for you, there's not much value in calling it a Map even if you're not sure where the code isheaded. (Again, though, public APIs are an exception: a good API usually trumps small performance concerns.)
Prefer Virtual Over Interface
If you don't need to access an object's fields, make your method static. It can be called faster, because it doesn't require avirtual method table indirection. It's also good practice, because you can tell from the method signature that calling themethod can't alter the object's state.
In native languages like C++ it's common practice to use getters (e.g. i = getCount()) instead of accessing the field
directly (i = mCount). This is an excellent habit for C++, because the compiler can usually inline the access, and if you
need to restrict or debug field access you can add the code at any time.
On Android, this is a bad idea. Virtual method calls are expensive, much more so than instance field lookups. It's reasonableto follow common object-oriented programming practices and have getters and setters in the public interface, but within aclass you should always access fields directly.
Prefer Static Over Virtual
Avoid Internal Getters/Setters
Accessing object fields is much slower than accessing local variables. Instead of writing:
for (int i = 0; i < this.mCount; i++)
dumpItem(this.mItems[i]);
You should write:
int count = this.mCount;
Item[] items = this.mItems;
for (int i = 0; i < count; i++)
dumpItems(items[i]);
(We're using an explicit "this" to make it clear that these are member variables.)
Cache Field Lookups
A similar guideline is never call a method in the second clause of a "for" statement. For example, the following code willexecute the getCount() method once per iteration, which is a huge waste when you could have simply cached the value asan int:
for (int i = 0; i < this.getCount(); i++)
dumpItems(this.getItem(i));
97Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
However, the following code shows an acceptable use of foreach:
public class Foo {
int mSplat;
static Foo mArray[] = new Foo[27];
public static void zero() {
int sum = 0;
for (int i = 0; i < mArray.length; i++) {
sum += mArray[i].mSplat;
}
}
public static void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; i++) {
sum += localArray[i].mSplat;
}
}
public static void two() {
int sum = 0;
for (Foo a: mArray) {
sum += a.mSplat;
}
}
}
zero() retrieves the static field twice and gets the array length once for every iteration through the loop.
one() pulls everything out into local variables, avoiding the lookups.
two() uses the foreach syntax introduced in version 1.5 of the Java programming language. The code generated by thecompiler takes care of copying the array reference and the array length to local variables, making it a good choice forwalking through all elements of an array. It does generate an extra local load/store in the main loop (apparently preserving"a"), making it a teensy bit slower and 4 bytes longer than one().
To summarize all that a bit more clearly: "foreach" syntax performs well with arrays, but be cautious when using it withIterable objects since there is additional object creation.
Enums are very convenient, but unfortunately can be painful when size and speed matter. For example, this:
public class Foo {
public enum Shrubbery { GROUND, CRAWLING, HANGING }
}
turns into a 900 byte .class file (Foo$Shubbery.class). On first use, the class initializer invokes the <init> method on objectsrepresenting each of the enumerated values. Each object gets its own static field, and the full set is stored in an array (astatic field called "$VALUES"). That's a lot of code and data, just for three integers.
Avoid Enums
This:
Shrubbery shrub = Shrubbery.GROUND;
causes a static field lookup. If "GROUND" were a static final int, the compiler would treat it as a known constant and inline it.
99Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
/*package*/ static int Foo.access$100(Foo foo) {
return foo.mValue;
}
/*package*/ static void Foo.access$200(Foo foo, int value) {
foo.doStuff(value);
}
The inner-class code calls these static methods whenever it needs to access the "mValue" field or invoke the "doStuff"method in the outer class. What this means is that the code above really boils down to a case where you're accessingmember fields through accessor methods instead of directly. Earlier we talked about how accessors are slower than directfield accesses, so this is an example of a certain language idiom resulting in an "invisible" performance hit.
We can avoid this problem by declaring fields and methods accessed by inner classes to have package scope, rather thanprivate scope. This runs faster and removes the overhead of the generated methods. (Unfortunately it also means the fieldscould be accessed directly by other classes in the same package, which runs counter to the standard OO practice of makingall fields private. Once again, if you're designing a public API you might want to carefully consider using this optimization.)
Before the release of the Pentium CPU, it was common for game authors to do as much as possible with integer math. Withthe Pentium, the floating point math co-processor became a built-in feature, and by interleaving integer and floating-pointoperations your game would actually go faster than it would with purely integer math. The common practice on desktopsystems is to use floating point freely.
Unfortunately, embedded processors frequently do not have hardware floating point support, so all operations on "float" and"double" are performed in software. Some basic floating point operations can take on the order of a millisecond to complete.
Also, even for integers, some chips have hardware multiply but lack hardware divide. In such cases, integer division andmodulus operations are performed in software — something to think about if you're designing a hash table or doing lots ofmath.
Avoid Float
To illustrate some of our ideas, here is a table listing the approximate run times for a few basic actions. Note that thesevalues should NOT be taken as absolute numbers: they are a combination of CPU and wall clock time, and will change asimprovements are made to the system. However, it is worth noting how these values apply relative to each other — forexample, adding a member variable currently takes about four times as long as adding a local variable.
Action Time
Add a local variable 1
Add a member variable 4
Call String.length() 5
Call empty static native method 5
Call empty static method 12
Call empty virtual method 12.5
Call empty interface method 15
Call Iterator:next() on a HashMap 165
Call put() on a HashMap 600
Inflate 1 View from XML 22,000
Inflate 1 LinearLayout containing 1 TextView 25,000
Inflate 1 LinearLayout containing 6 View objects 100,000
Inflate 1 LinearLayout containing 6 TextView objects 135,000
Launch an empty activity 3,000,000
Some Sample Performance Numbers
101Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
UI events. For example, when the user presses a key, a key-down event is added to the Activity's main thread's queue. Theevent handler system needs to dequeue and handle that event quickly; if it doesn't, the system concludes after a few
seconds that the application is hung and offers to kill it for the user.
If you have long-running code, running it inline in your Activity will run it on the event handler thread, effectively blocking the
event handler. This will delay input processing, and result in the ANR dialogs. To avoid this, move your computations to a
thread; click here to learn how.
Any application worth using will probably have several different screens. When partitioning your UI, be sure to make
effective use of Activities.
Depending on your development background, you may interpret an Activity as similar to something like a Java Applet, in that
it is the entry point for your application. However, that's not quite accurate: where an Applet subclass is the single entry point
for a Java Applet, an Activity should be thought of as one of potentially several entry points to your application. The only
difference between your "main" Activity and any others you might have is that the "main" one just happens to be the only one
that expressed an interest in the "android.intent.action.MAIN" action in your AndroidManifest..xml file.
So, when designing your application, think of your application as a federation of Activities. This will make your code a lot
more maintainable in the long run, and as a nice side effect also plays nicely with Android's application history and
"backstack" model.
When it comes to the look-and-feel of the user interface, it's important to blend in nicely. Users are jarred by applications
which contrast with the user interface they've come to expect. When designing your UIs, you should try and avoid rolling
your own as much as possible. Instead, use a Theme. You can override or extend those parts of the theme that you need to,
but at least you're starting from the same UI base as all the other applications. For all the details, click here.
Different Android devices will sport different resolutions. Some will even be able to change resolutions on the fly, such as by
switching to landscape mode. It's important to make sure your layouts and drawables are flexible.
Fortunately, this is very easy to do. Check out Implementing a User Interface for the full details, but in brief what you must do
is provide different versions of your artwork (if you use any) for the key resolutions, and then design your layout to
accommodate various dimensions. (For example, avoid using hard-coded positions and instead use relative layouts.) If you
do that much, the system handles the rest, and your application looks great on any device.
Android devices will come with a variety of network-connectivity options. All will have some data-access provision, though
some will be faster than others. The lowest common denominator, however, is GPRS, the non-3G data service for GSM
networks. Even 3G-capable devices will spend lots of time on non-3G networks, so slow networks will remain a reality for
quite a long time to come.
That's why you should always code your applications to minimize network accesses and bandwidth. You can't assume the
network is fast, so you should always plan for it to be slow. If your users happen to be on faster networks, then that's great
— their experience will only improve. You want to avoid the inverse case though: applications that are usable some of the
time, but frustratingly slow the rest based on where the user is at any given moment are likely to be unpopular.
One potential gotcha here is that it's very easy to fall into this trap if you're using the emulator, since the emulator uses your
desktop computer's network connection. That's almost guaranteed to be much faster than a cell network, so you'll want to
change the settings on the emulator that simulate slower network speeds. You can do this in Eclipse, in the "Emulator
Settings" tab of your launch configuration or via a command line option when starting the emulator.
Avoid Huge Activities
Extend Themes
Make Being Flexible part of your Resolutions
Assume the Network is Slow
Different Keystrokes for Different Folks
Android will support a variety of handset form-factors. That's a fancy way of saying that some Android devices will have full
"QWERTY" keyboards, while others will have 40-key, 12-key, or even other key configurations. Similarly, some devices will
have touch-screens, but many won't.
When building your applications, keep that in mind. Don't make assumptions about specific keyboard layouts -- unless, of
course, you're really interested in restricting your application so that it can only be used on those devices.
103Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Fully customized components can be used to create graphical components that appear however you wish. Perhaps a
graphical VU meter that looks like an old analog gauge, or a sing-a-long text view where a bouncing ball moves along the
words so you can sing along with a karaoke machine. Either way, you want something that the built-in components just won't
do, no matter how you combine them.
Fortunately, you can easily create components that look and behave in any way you like, limited perhaps only by your
imagination, the size of the screen, and the available processing power (remember that ultimately your application might
have to run on something with significantly less power than your desktop workstation).
To create a fully customized component:
The most generic view you can extend is, unsurprisingly, View, so you will usually start by extending this to create your
new super component.
1.
You can supply a constructor which can take attributes and parameters from the XML, and you can also consume your
own such attributes and parameters (perhaps the color and range of the VU meter, or the width and damping of the
needle, etc.)
2.
You will probably want to create your own event listeners, property accessors and modifiers, and possibly more
sophisticated behavior in your component class as well.
3.
You will almost certainly want to override onMeasure() and are also likely to need to override onDraw() if you want
the component to show something. While both have default behavior, the default onDraw() will do nothing, and the
default onMeasure() will always set a size of 100x100 — which is probably not what you want.
4.
Other on... methods may also be overridden as required.5.
onDraw() delivers you a Canvas upon which you can implement anything you want: 2D graphics, other standard or custom
components, styled text, or anything else you can think of. If you want to use 3D graphics, you should extend GLView
instead of View, but otherwise the same concepts apply.
onMeasure() is a little more involved. onMeasure() is a critical piece of the rendering contract between your component
and its container. onMeasure() should be overridden to efficiently and accurately report the measurements of its contained
parts. This is made slightly more complex by the requirements of limits from the parent (which are passed in to the
onMeasure() method) and by the requirement to call the setMeasuredDimension() method with the measured width
and height once they have been calculated. If you fail to call this method from an overridden onMeasure() method, the
result will be an exception at measurement time.
At a high level, implementing onMeasure() looks something like this:
The overridden onMeasure() method is called with width and height measure specifications (widthMeasureSpec
and heighMeasureSpec parameters, both are integer codes representing dimensions) which should be treated as
requirements for the restrictions on the width and height measurements you should produce. A full reference to the
kind of restrictions these specifications can require can be found in the reference documentation under
View.onMeasure(int, int) (this reference documentation does a pretty good job of explaining the whole measurement
operation as well).
1.
Your component's onMeasure() method should calculate a measurement width and height which will be required to
render the component. It should try to stay within the specifications passed in, although it can choose to exceed them
(in this case, the parent can choose what to do, including clipping, scrolling, throwing an exception, or asking the
onMeasure() to try again, perhaps with different measurement specifications).
2.
Once the width and height are calculated, the setMeasuredDimension(int width, int height) method must
be called with the calculated measurements. Failure to do this will result in an exception being thrown.
3.
The CustomView sample in the API Demos provides an example of a customized component. The custom component is
defined in the LabelView class.
The LabelView sample demonstrates a number of different aspects of custom components:
Extending the View class for a completely custom component.
Fully Customized Components
A Customized Component Example
onDraw() and onMeasure()
Parameterized constructor that takes the view inflation parameters (parameters defined in the XML). Some of these
are passed through to the View superclass, but more importantly, there are some custom attributes defined and used
for LabelView.
105Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
There is an even easier option for creating a custom component which is useful in certain circumstances. If there is a
component that is already very similar to what you want, you can simply extend that component and just override the
behavior that you want to change. You can do all of the things you would do with a fully customized component, but by
starting with a more specialized class in the View heirarchy, you can also get a lot of behavior for free that probably does
exactly what you want.
For example, the SDK includes a NotePad application in the samples. This demonstrates many aspects of using the Android
platform, among them is extending an EditText View to make a lined notepad. This is not a perfect example, and the APIs for
doing this might change from this early preview, but it does demonstrate the principles.
If you haven't done so already, import the NotePad sample into Eclipse (or just look at the source using the link provided). In
particular look at the definition of MyEditText in the NoteEditor.java file.
Some points to note here
The Definition
The class is defined with the following line:
public static class MyEditText extends EditText
It is defined as an inner class within the NoteEditor activity, but it is public so that it could be accessed as
NoteEditor.MyEditText from outside of the NoteEditor class if desired.
It is static, meaning it does not generate the so-called "synthetic methods" that allow it to access data from the
parent class, which in turn means that it really behaves as a separate class rather than something strongly related
to NoteEditor. This is a cleaner way to create inner classes if they do not need access to state from the outer
class, keeps the generated class small, and allows it to be used easily from other classes.
It extends EditText, which is the View we have chosen to customize in this case. When we are finished, the
new class will be able to substitute for a normal EditText view.
1.
Class Initialization
As always, the super is called first. Furthermore, this is not a default constructor, but a parameterized one. The
EditText is created with these parameters when it is inflated from an XML layout file, thus, our constructor needs to
both take them and pass them to the superclass constructor as well.
2.
Overridden Methods
In this example, there is only one method to be overridden: onDraw() — but there could easily be others needed
when you create your own custom components.
For the NotePad sample, overriding the onDraw() method allows us to paint the blue lines on the EditText view
canvas (the canvas is passed into the overridden onDraw() method). The super.onDraw() method is called before the
method ends. The superclass method should be invoked, but in this case, we do it at the end after we have painted the
lines we want to include.
3.
Use the Custom Component
We now have our custom component, but how can we use it? In the NotePad example, the custom component is used
directly from the declarative layout, so take a look at note_editor.xml in the res/layout folder.
<view xmlns:android="http://schemas.android.com/apk/res/android"
class="com.google.android.notepad.NoteEditor$MyEditText"
id="@+id/note"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:drawable/empty"
android:padding="10dip"
android:scrollbars="vertical"
android:fadingEdge="vertical" />
The custom component is created as a generic view in the XML, and the class is specified using the full package.
Note also that the inner class we defined is referenced using the NoteEditor$MyEditText notation which is a
standard way to refer to inner classes in the Java programming language.
4.
Tweaking an Existing Component
107Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com
Since Android is an open cell phone platform, anyone will be able to build their own devices that run the core Android OS.
There is no requirement that any given phone include any Google software, or even be associated with Google at all.
However, some groups may choose to license a set of optional user applications from Google that provide convenient
developer access to Google services. This will generally be a collection of software included in the base system image and
shipped with the phone.
Because many devices will include these libraries, for the convenience of developers we're including information about
those APIs here. However, please be aware that any APIs you use from the list below may not be available on all Android
devices. If the Google software is not present, these libraries and classes will not be present. As a result, if your application
uses these APIs, it may not install or run properly on devices that lack the APIs.
The MapView is an Android View that allows third-party code to display and control a Google Map. This is a complementary
offering to the MapActivity provided in the Google Maps application that other Activities can use to display maps of a specific
location. The table below summarizes the differences between the two approaches.
Feature MapActivity MapView
Embeddable directly into your own Layout? No (can only set map display) Yes
User-controlled navigation? Yes Yes
Navigation via code? (i.e. scroll, zoom, etc. from your application code) No Yes
Can fire events into your own code? No Yes
The advantage of using the MapView over the Activity is that it gives you tight integration with your own layout; for instance,
you can wrap custom controls around it, or implement fancy input mechanisms (such as using a tilt-sensor to scroll the Map
based on how the user tilts the device). The disadvantage of using the MapView is that it requires more code to set up and
use; if you simply wish to display a Google Map with the standard UI, it will be much easier to use the Activity.
Applications will frequently need to communicate between devices. For instance, you might wish to send messages back
and forth between two devices, to implement an interactive game of checkers. Or, you might develop a social application
where you want to send a message to a buddy.
One way to do this is to simply send an SMS message to the other phone. It's possible to receive notifications via an
IntentReceiver of incoming SMS messages, inspect them to see if they contain data intended for your application, and then
consume the message, preventing other applications (and the user) from ever seeing it directly. This works well, but it has
two major down-sides: SMS messages can take several minutes to deliver, and they typically cost users money to send and
receive. If you built an online game using SMS message-passing, it might very well be both slow and frustrating, and very
expensive to your users.
As an alternative, Google provides an API that uses the XMPP protocol to pass messages. XMPP includes presence
notification, meaning that it provides a convenient way for phones to notify each other when they are online and available for
message-passing. It also provides a programmatic model similar to SMS-based message-passing, in that the sender calls a
method on a Service to send a message, and the receiver is notified via a broadcast Intent (which it can fetch via an
IntentReceiver). However, because XMPP is a persistent socket connection, the response time is much faster than SMS,
Google APIs and Services in Android
MapView
P2P Services Using XMPP
©2007 Google - Code Home - Site Terms of Service - Privacy Policy - Site Directory
allowing for a more fluid user experience.
The system currently maintains a single XMPP connection to the server, and all XMPP traffic — including both standard
XMPP instant messages, and this P2P message-passing system — is carried on the same connection.
109Compiled by fastop 2007-2 http://fastoponandroid.googlepages.com