SlideShare a Scribd company logo
1 of 58
Understanding Android Framework for Effective Testing
Introduction
To develop apps for Android devices, you use a set of tools that are included in the
Android SDK. Once you've downloaded and installed the SDK, you can access these
tools right from your Eclipse IDE, through the ADT plugin, or from the command line.
Developing with Eclipse is the preferred method because it can directly invoke the tools
that you need while developing applications.
However, you may choose to develop with another IDE or a simple text editor and invoke
the tools on the command line or with scripts. This is a less streamlined way to develop
because you will sometimes have to call command line tools manually, but you will have
access to the same number of features that you would have in Eclipse.
The basic steps for developing applications (with or without Eclipse) are shown in figure
1. The development steps encompass four development phases, which include:
Setup
During this phase you install and set up your development environment. You also create
Android Virtual Devices (AVDs) and connect hardware devices on which you can install
your applications.
See Managing Virtual Devices and Using Hardware Devices for more information.
Development
During this phase you set up and develop your Android project, which contains all of the
source code and resource files for your application. For more information, see Create an
Android project.
Debugging and Testing
During this phase you build your project into a debuggable .apk package that you can
install and run on the emulator or an Android-powered device. If you are using Eclipse,
builds are generated each time you project is saved. If you're using another IDE, you can
build your project using Ant and install it on a device using adb. For more information,
see Build and run your application.
Next, you debug your application using a JDWP-compliant debugger along with the
debugging and logging tools that are provided with the Android SDK. Eclipse already
comes packaged with a compatible debugger. For more information see, Debug your
application with the SDK debugging and logging tools.
Last, you test your application using various Android SDK testing tools. For more
information, see Test your application with the Testing and Instrumentation framework.
Publishing
During this phase you configure and build your application for release and distribute your
application to users. For more information, see Publishing Overview.
Figure 1. The
development process
for Android
applications.
Application
Fundamentals
Android
apps are
written in the
Java
programming
language. The
Android SDK
tools compile
your code—
along with
any data and
resource files
—into an
APK: an
Android
package, which is an archive file with an .apk suffix. One APK file contains all
the contents of an Android app and is the file that Android-powered devices use
to install the app.
Once installed on a device, each Android app lives in its own security sandbox:
• The Android operating system is a multi-user Linux system in which each app is a
different user.
• By default, the system assigns each app a unique Linux user ID (the ID is used
only by the system and is unknown to the app). The system sets permissions for all
the files in an app so that only the user ID assigned to that app can access them.
• Each process has its own virtual machine (VM), so an app's code runs in isolation
from other apps.
• By default, every app runs in its own Linux process. Android starts the process
when any of the app's components need to be executed, then shuts down the
process when it's no longer needed or when the system must recover memory for
other apps.
In this way, the Android system implements the principle of least privilege. That is, each
app, by default, has access only to the components that it requires to do its work and no
more. This creates a very secure environment in which an app cannot access parts of the
system for which it is not given permission.
However, there are ways for an app to share data with other apps and for an app to access
system services:
• It's possible to arrange for two apps to share the same Linux user ID, in which
case they are able to access each other's files. To conserve system resources, apps
with the same user ID can also arrange to run in the same Linux process and share
the same VM (the apps must also be signed with the same certificate).
• An app can request permission to access device data such as the user's contacts,
SMS messages, the mountable storage (SD card), camera, Bluetooth, and more.
All app permissions must be granted by the user at install time.
That covers the basics regarding how an Android app exists within the system. The rest of
this document introduces you to:
• The core framework components that define your app.
• The manifest file in which you declare components and required device features
for your app.
• Resources that are separate from the app code and allow your app to gracefully
optimize its behavior for a variety of device configurations.
App Components
App components are the essential building blocks of an Android app. Each component is
a different point through which the system can enter your app. Not all components are
actual entry points for the user and some depend on each other, but each one exists as its
own entity and plays a specific role—each one is a unique building block that helps
define your app's overall behavior.
There are four different types of app components. Each type serves a distinct purpose and
has a distinct lifecycle that defines how the component is created and destroyed.
Here are the four types of app components:
Activities
An activity represents a single screen with a user interface. For example, an email app
might have one activity that shows a list of new emails, another activity to compose
an email, and another activity for reading emails. Although the activities work
together to form a cohesive user experience in the email app, each one is independent
of the others. As such, a different app can start any one of these activities (if the email
app allows it). For example, a camera app can start the activity in the email app that
composes new mail, in order for the user to share a picture.
An activity is implemented as a subclass of Activity and you can learn more about it in
the Activities developer guide.
Services
A service is a component that runs in the background to perform long-running
operations or to perform work for remote processes. A service does not provide a user
interface. For example, a service might play music in the background while the user is
in a different app, or it might fetch data over the network without blocking user
interaction with an activity. Another component, such as an activity, can start the
service and let it run or bind to it in order to interact with it.
A service is implemented as a subclass of Service and you can learn more about it in the
Services developer guide.
Content providers
A content provider manages a shared set of app data. You can store the data in the file
system, an SQLite database, on the web, or any other persistent storage location your
app can access. Through the content provider, other apps can query or even modify
the data (if the content provider allows it). For example, the Android system provides
a content provider that manages the user's contact information. As such, any app with
the proper permissions can query part of the content provider (such as
ContactsContract.Data) to read and write information about a particular person.
Content providers are also useful for reading and writing data that is private to your app
and not shared. For example, the Note Pad sample app uses a content provider to save
notes.
A content provider is implemented as a subclass of ContentProvider and must implement
a standard set of APIs that enable other apps to perform transactions. For more
information, see the Content Providers developer guide.
Broadcast receivers
A broadcast receiver is a component that responds to system-wide broadcast
announcements. Many broadcasts originate from the system—for example, a
broadcast announcing that the screen has turned off, the battery is low, or a picture
was captured. Apps can also initiate broadcasts—for example, to let other apps know
that some data has been downloaded to the device and is available for them to use.
Although broadcast receivers don't display a user interface, they may create a status
bar notification to alert the user when a broadcast event occurs. More commonly,
though, a broadcast receiver is just a "gateway" to other components and is intended
to do a very minimal amount of work. For instance, it might initiate a service to
perform some work based on the event.
A broadcast receiver is implemented as a subclass of BroadcastReceiver and each
broadcast is delivered as an Intent object. For more information, see the
BroadcastReceiver class.
A unique aspect of the Android system design is that any app can start another app’s
component. For example, if you want the user to capture a photo with the device camera,
there's probably another app that does that and your app can use it, instead of developing
an activity to capture a photo yourself. You don't need to incorporate or even link to the
code from the camera app. Instead, you can simply start the activity in the camera app
that captures a photo. When complete, the photo is even returned to your app so you can
use it. To the user, it seems as if the camera is actually a part of your app.
When the system starts a component, it starts the process for that app (if it's not already
running) and instantiates the classes needed for the component. For example, if your app
starts the activity in the camera app that captures a photo, that activity runs in the process
that belongs to the camera app, not in your app's process. Therefore, unlike apps on most
other systems, Android apps don't have a single entry point (there's no main() function,
for example).
Because the system runs each app in a separate process with file permissions that restrict
access to other apps, your app cannot directly activate a component from another app.
The Android system, however, can. So, to activate a component in another app, you must
deliver a message to the system that specifies your intent to start a particular component.
The system then activates the component for you.
Activating Components
Three of the four component types—activities, services, and broadcast receivers—are
activated by an asynchronous message called an intent. Intents bind individual
components to each other at runtime (you can think of them as the messengers that
request an action from other components), whether the component belongs to your app or
another.
An intent is created with an Intent object, which defines a message to activate either a
specific component or a specific type of component—an intent can be either explicit or
implicit, respectively.
For activities and services, an intent defines the action to perform (for example, to "view"
or "send" something) and may specify the URI of the data to act on (among other things
that the component being started might need to know). For example, an intent might
convey a request for an activity to show an image or to open a web page. In some cases,
you can start an activity to receive a result, in which case, the activity also returns the
result in an Intent (for example, you can issue an intent to let the user pick a personal
contact and have it returned to you—the return intent includes a URI pointing to the
chosen contact).
For broadcast receivers, the intent simply defines the announcement being broadcast (for
example, a broadcast to indicate the device battery is low includes only a known action
string that indicates "battery is low").
The other component type, content provider, is not activated by intents. Rather, it is
activated when targeted by a request from a ContentResolver. The content resolver
handles all direct transactions with the content provider so that the component that's
performing transactions with the provider doesn't need to and instead calls methods on
the ContentResolver object. This leaves a layer of abstraction between the content
provider and the component requesting information (for security).
There are separate methods for activating each type of component:
• You can start an activity (or give it something new to do) by passing an Intent to
startActivity() or startActivityForResult() (when you want the activity to return a
result).
• You can start a service (or give new instructions to an ongoing service) by passing
an Intent to startService(). Or you can bind to the service by passing an Intent to
bindService().
• You can initiate a broadcast by passing an Intent to methods like sendBroadcast(),
sendOrderedBroadcast(), or sendStickyBroadcast().
• You can perform a query to a content provider by calling query() on a
ContentResolver.
For more information about using intents, see the Intents and Intent Filters document.
More information about activating specific components is also provided in the following
documents: Activities, Services, BroadcastReceiver and Content Providers.
The Manifest File
Before the Android system can start an app component, the system must know that the
component exists by reading the app's AndroidManifest.xml file (the "manifest" file).
Your app must declare all its components in this file, which must be at the root of the app
project directory.
The manifest does a number of things in addition to declaring the app's components, such
as:
• Identify any user permissions the app requires, such as Internet access or read-
access to the user's contacts.
• Declare the minimum API Level required by the app, based on which APIs the
app uses.
• Declare hardware and software features used or required by the app, such as a
camera, bluetooth services, or a multitouch screen.
• API libraries the app needs to be linked against (other than the Android
framework APIs), such as the Google Maps library.
• And more
Declaring components
The primary task of the manifest is to inform the system about the app's components. For
example, a manifest file can declare an activity as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:icon="@drawable/app_icon.png" ... >
<activity android:name="com.example.project.ExampleActivity"
android:label="@string/example_label" ... >
</activity>
...
</application>
</manifest>
In the <application> element, the android:icon attribute points to resources for an icon
that identifies the app.
In the <activity> element, the android:name attribute specifies the fully qualified class
name of the Activity subclass and the android:label attributes specifies a string to use as
the user-visible label for the activity.
You must declare all app components this way:
• <activity>elements for activities
• <service>elements for services
• <receiver>elements for broadcast receivers
• <provider>elements for content providers
Activities, services, and content providers that you include in your source but do not
declare in the manifest are not visible to the system and, consequently, can never run.
However, broadcast receivers can be either declared in the manifest or created
dynamically in code (as BroadcastReceiver objects) and registered with the system by
calling registerReceiver().
For more about how to structure the manifest file for your app, see The
AndroidManifest.xml File documentation.
Declaring component capabilities
As discussed above, in Activating Components, you can use an Intent to start activities,
services, and broadcast receivers. You can do so by explicitly naming the target
component (using the component class name) in the intent. However, the real power of
intents lies in the concept of implicit intents. An implicit intent simply describe the type
of action to perform (and optionally, the data upon which you’d like to perform the
action) and allow the system to find a component on the device that can perform the
action and start it. If there are multiple components that can perform the action described
by the intent, then the user selects which one to use.
The way the system identifies the components that can respond to an intent is by
comparing the intent received to the intent filters provided in the manifest file of other
apps on the device.
When you declare an activity in your app's manifest, you can optionally include intent
filters that declare the capabilities of the activity so it can respond to intents from other
apps. You can declare an intent filter for your component by adding an <intent-filter>
element as a child of the component's declaration element.
For example, if you've built an email app with an activity for composing a new email,
you can declare an intent filter to respond to "send" intents (in order to send a new email)
like this:
<manifest ... >
... <application ... > <activity
android:name="com.example.project.ComposeEmailActivity"> <intent-filter>
<action android:name="android.intent.action.SEND" /> <data
android:type="*/*" /> <category
android:name="android.intent.category.DEFAULT" /> </intent-filter>
</activity> </application></manifest>
Then, if another app creates an intent with the ACTION_SEND action and pass it to
startActivity(), the system may start your activity so the user can draft and send an email.
For more about creating intent filters, see the Intents and Intent Filters document.
Declaring app requirements
There are a variety of devices powered by Android and not all of them provide the same
features and capabilities. In order to prevent your app from being installed on devices that
lack features needed by your app, it's important that you clearly define a profile for the
types of devices your app supports by declaring device and software requirements in your
manifest file. Most of these declarations are informational only and the system does not
read them, but external services such as Google Play do read them in order to provide
filtering for users when they search for apps from their device.
For example, if your app requires a camera and uses APIs introduced in Android 2.1 (API
Level 7), you should declare these as requirements in your manifest file like this:
<manifest ... > <uses-feature android:name="android.hardware.camera.any"
android:required="true" /> <uses-sdk android:minSdkVersion="7"
android:targetSdkVersion="19" />
...</manifest>
Now, devices that do not have a camera and have an Android version lower than 2.1
cannot install your app from Google Play.
However, you can also declare that your app uses the camera, but does not require it. In
that case, your app must set the required attribute to "false" and check at runtime whether
the device has a camera and disable any camera features as appropriate.
More information about how you can manage your app's compatibility with different
devices is provided in the Device Compatibility document.
App Resources
An Android app is composed of more than just code—it requires resources that are
separate from the source code, such as images, audio files, and anything relating to the
visual presentation of the app. For example, you should define animations, menus, styles,
colors, and the layout of activity user interfaces with XML files. Using app resources
makes it easy to update various characteristics of your app without modifying code and—
by providing sets of alternative resources—enables you to optimize your app for a variety
of device configurations (such as different languages and screen sizes).
For every resource that you include in your Android project, the SDK build tools define a
unique integer ID, which you can use to reference the resource from your app code or
from other resources defined in XML. For example, if your app contains an image file
named logo.png (saved in the res/drawable/ directory), the SDK tools generate a resource
ID named R.drawable.logo, which you can use to reference the image and insert it in your
user interface.
One of the most important aspects of providing resources separate from your source code
is the ability for you to provide alternative resources for different device configurations.
For example, by defining UI strings in XML, you can translate the strings into other
languages and save those strings in separate files. Then, based on a language qualifier
that you append to the resource directory's name (such as res/values-fr/ for French string
values) and the user's language setting, the Android system applies the appropriate
language strings to your UI.
Android supports many different qualifiers for your alternative resources. The qualifier is
a short string that you include in the name of your resource directories in order to define
the device configuration for which those resources should be used. As another example,
you should often create different layouts for your activities, depending on the device's
screen orientation and size. For example, when the device screen is in portrait orientation
(tall), you might want a layout with buttons to be vertical, but when the screen is in
landscape orientation (wide), the buttons should be aligned horizontally. To change the
layout depending on the orientation, you can define two different layouts and apply the
appropriate qualifier to each layout's directory name. Then, the system automatically
applies the appropriate layout depending on the current device orientation.
App Components
Android's application framework lets you create rich and innovative apps using a set of reusable
components. This section explains how you can build the components that define the building
blocks of your app and how to connect them together using intents.
Activities
Quickview
• An activity provides a user interface for a single screen in your application
• Activities can move into the background and then be resumed with their state restored
An Activity is an application component that provides a screen with which users can
interact in order to do something, such as dial the phone, take a photo, send an email, or
view a map. Each activity is given a window in which to draw its user interface. The
window typically fills the screen, but may be smaller than the screen and float on top of
other windows.
An application usually consists of multiple activities that are loosely bound to each other.
Typically, one activity in an application is specified as the "main" activity, which is
presented to the user when launching the application for the first time. Each activity can
then start another activity in order to perform different actions. Each time a new activity
starts, the previous activity is stopped, but the system preserves the activity in a stack (the
"back stack"). When a new activity starts, it is pushed onto the back stack and takes user
focus. The back stack abides to the basic "last in, first out" stack mechanism, so, when the
user is done with the current activity and presses the Back button, it is popped from the
stack (and destroyed) and the previous activity resumes. (The back stack is discussed
more in the Tasks and Back Stack document.)
When an activity is stopped because a new activity starts, it is notified of this change in
state through the activity's lifecycle callback methods. There are several callback methods
that an activity might receive, due to a change in its state—whether the system is creating
it, stopping it, resuming it, or destroying it—and each callback provides you the
opportunity to perform specific work that's appropriate to that state change. For instance,
when stopped, your activity should release any large objects, such as network or database
connections. When the activity resumes, you can reacquire the necessary resources and
resume actions that were interrupted. These state transitions are all part of the activity
lifecycle.
The rest of this document discusses the basics of how to build and use an activity,
including a complete discussion of how the activity lifecycle works, so you can properly
manage the transition between various activity states.
Creating an Activity
To create an activity, you must create a subclass of Activity (or an existing subclass of it).
In your subclass, you need to implement callback methods that the system calls when the
activity transitions between various states of its lifecycle, such as when the activity is
being created, stopped, resumed, or destroyed. The two most important callback methods
are:
onCreate()
You must implement this method. The system calls this when creating your activity.
Within your implementation, you should initialize the essential components of your
activity. Most importantly, this is where you must call setContentView() to define the
layout for the activity's user interface.
onPause()
The system calls this method as the first indication that the user is leaving your
activity (though it does not always mean the activity is being destroyed). This is
usually where you should commit any changes that should be persisted beyond the
current user session (because the user might not come back).
There are several other lifecycle callback methods that you should use in order to provide
a fluid user experience between activities and handle unexpected interuptions that cause
your activity to be stopped and even destroyed. All of the lifecycle callback methods are
discussed later, in the section about Managing the Activity Lifecycle.
Implementing a user interface
The user interface for an activity is provided by a hierarchy of views—objects derived
from the View class. Each view controls a particular rectangular space within the
activity's window and can respond to user interaction. For example, a view might be a
button that initiates an action when the user touches it.
Android provides a number of ready-made views that you can use to design and organize
your layout. "Widgets" are views that provide a visual (and interactive) elements for the
screen, such as a button, text field, checkbox, or just an image. "Layouts" are views
derived from ViewGroup that provide a unique layout model for its child views, such as a
linear layout, a grid layout, or relative layout. You can also subclass the View and
ViewGroup classes (or existing subclasses) to create your own widgets and layouts and
apply them to your activity layout.
The most common way to define a layout using views is with an XML layout file saved
in your application resources. This way, you can maintain the design of your user
interface separately from the source code that defines the activity's behavior. You can set
the layout as the UI for your activity with setContentView(), passing the resource ID for
the layout. However, you can also create new Views in your activity code and build a
view hierarchy by inserting new Views into a ViewGroup, then use that layout by passing
the root ViewGroup to setContentView().
For information about creating a user interface, see the User Interface documentation.
Declaring the activity in the manifest
You must declare your activity in the manifest file in order for it to be accessible to the
system. To declare your activity, open your manifest file and add an <activity> element as
a child of the <application> element. For example:
<manifest ... > <application ... > <activity android:name=".ExampleActivity" />
... </application ... >
...</manifest >
There are several other attributes that you can include in this element, to define properties
such as the label for the activity, an icon for the activity, or a theme to style the activity's
UI. The android:name attribute is the only required attribute—it specifies the class name
of the activity. Once you publish your application, you should not change this name,
because if you do, you might break some functionality, such as application shortcuts (read
the blog post, Things That Cannot Change).
See the <activity> element reference for more information about declaring your activity
in the manifest.
Using intent filters
An <activity> element can also specify various intent filters—using the <intent-filter>
element—in order to declare how other application components may activate it.
When you create a new application using the Android SDK tools, the stub activity that's
created for you automatically includes an intent filter that declares the activity responds
to the "main" action and should be placed in the "launcher" category. The intent filter
looks like this:
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
<intent-filter> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-
filter></activity>
The <action> element specifies that this is the "main" entry point to the application. The
<category> element specifies that this activity should be listed in the system's application
launcher (to allow users to launch this activity).
If you intend for your application to be self-contained and not allow other applications to
activate its activities, then you don't need any other intent filters. Only one activity should
have the "main" action and "launcher" category, as in the previous example. Activities
that you don't want to make available to other applications should have no intent filters
and you can start them yourself using explicit intents (as discussed in the following
section).
However, if you want your activity to respond to implicit intents that are delivered from
other applications (and your own), then you must define additional intent filters for your
activity. For each type of intent to which you want to respond, you must include an
<intent-filter> that includes an <action> element and, optionally, a <category> element
and/or a <data> element. These elements specify the type of intent to which your activity
can respond.
For more information about how your activities can respond to intents, see the Intents and
Intent Filters document.
Starting an Activity
You can start another activity by calling startActivity(), passing it an Intent that describes
the activity you want to start. The intent specifies either the exact activity you want to
start or describes the type of action you want to perform (and the system selects the
appropriate activity for you, which can even be from a different application). An intent
can also carry small amounts of data to be used by the activity that is started.
When working within your own application, you'll often need to simply launch a known
activity. You can do so by creating an intent that explicitly defines the activity you want
to start, using the class name. For example, here's how one activity starts another activity
named SignInActivity:
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
However, your application might also want to perform some action, such as send an
email, text message, or status update, using data from your activity. In this case, your
application might not have its own activities to perform such actions, so you can instead
leverage the activities provided by other applications on the device, which can perform
the actions for you. This is where intents are really valuable—you can create an intent
that describes an action you want to perform and the system launches the appropriate
activity from another application. If there are multiple activities that can handle the intent,
then the user can select which one to use. For example, if you want to allow the user to
send an email message, you can create the following intent:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
The EXTRA_EMAIL extra added to the intent is a string array of email addresses to
which the email should be sent. When an email application responds to this intent, it
reads the string array provided in the extra and places them in the "to" field of the email
composition form. In this situation, the email application's activity starts and when the
user is done, your activity resumes.
Starting an activity for a result
Sometimes, you might want to receive a result from the activity that you start. In that
case, start the activity by calling startActivityForResult() (instead of startActivity()). To
then receive the result from the subsequent activity, implement the onActivityResult()
callback method. When the subsequent activity is done, it returns a result in an Intent to
your onActivityResult() method.
For example, perhaps you want the user to pick one of their contacts, so your activity can
do something with the information in that contact. Here's how you can create such an
intent and handle the result:
private void pickContact() { // Create an intent to "pick" a contact, as defined by the
content provider URI Intent intent = new Intent(Intent.ACTION_PICK,
Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);}@Overrideprotected
void onActivityResult(int requestCode, int resultCode, Intent data) { // If the request
went well (OK) and the request was PICK_CONTACT_REQUEST if (resultCode ==
Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { //
Perform a query to the contact's content provider for the contact's name Cursor cursor
= getContentResolver().query(data.getData(), new String[]
{Contacts.DISPLAY_NAME}, null, null, null); if (cursor.moveToFirst()) { // True if
the cursor is not empty int columnIndex =
cursor.getColumnIndex(Contacts.DISPLAY_NAME); String name =
cursor.getString(columnIndex); // Do something with the selected contact's name...
} }}
This example shows the basic logic you should use in your onActivityResult() method in
order to handle an activity result. The first condition checks whether the request was
successful—if it was, then the resultCode will be RESULT_OK—and whether the request
to which this result is responding is known—in this case, the requestCode matches the
second parameter sent with startActivityForResult(). From there, the code handles the
activity result by querying the data returned in an Intent (the data parameter).
What happens is, a ContentResolver performs a query against a content provider, which
returns a Cursor that allows the queried data to be read. For more information, see the
Content Providers document.
For more information about using intents, see the Intents and Intent Filters document.
Shutting Down an Activity
You can shut down an activity by calling its finish() method. You can also shut down a
separate activity that you previously started by calling finishActivity().
Note: In most cases, you should not explicitly finish an activity using these methods. As
discussed in the following section about the activity lifecycle, the Android system
manages the life of an activity for you, so you do not need to finish your own activities.
Calling these methods could adversely affect the expected user experience and should
only be used when you absolutely do not want the user to return to this instance of the
activity.
Managing the Activity Lifecycle
Managing the lifecycle of your activities by implementing callback methods is crucial to
developing a strong and flexible application. The lifecycle of an activity is directly
affected by its association with other activities, its task and back stack.
An activity can exist in essentially three states:
Resumed
The activity is in the foreground of the screen and has user focus. (This state is also
sometimes referred to as "running".)
Paused
Another activity is in the foreground and has focus, but this one is still visible. That
is, another activity is visible on top of this one and that activity is partially transparent
or doesn't cover the entire screen. A paused activity is completely alive (the Activity
object is retained in memory, it maintains all state and member information, and
remains attached to the window manager), but can be killed by the system in
extremely low memory situations.
Stopped
The activity is completely obscured by another activity (the activity is now in the
"background"). A stopped activity is also still alive (the Activity object is retained in
memory, it maintains all state and member information, but is not attached to the
window manager). However, it is no longer visible to the user and it can be killed by
the system when memory is needed elsewhere.
If an activity is paused or stopped, the system can drop it from memory either by asking it
to finish (calling its finish() method), or simply killing its process. When the activity is
opened again (after being finished or killed), it must be created all over.
Implementing the lifecycle callbacks
When an activity transitions into and out of the different states described above, it is
notified through various callback methods. All of the callback methods are hooks that you
can override to do appropriate work when the state of your activity changes. The
following skeleton activity includes each of the fundamental lifecycle methods:
public class ExampleActivity extends Activity { @Override public void
onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //
The activity is being created. } @Override protected void onStart()
{ super.onStart(); // The activity is about to become visible. } @Override
protected void onResume() { super.onResume(); // The activity has become
visible (it is now "resumed"). } @Override protected void onPause()
{ super.onPause(); // Another activity is taking focus (this activity is about to be
"paused"). } @Override protected void onStop() { super.onStop(); // The
activity is no longer visible (it is now "stopped") } @Override protected void
onDestroy() { super.onDestroy(); // The activity is about to be destroyed. }}
Note: Your implementation of these lifecycle methods must always call the superclass
implementation before doing any work, as shown in the examples above.
Taken together, these methods define the entire lifecycle of an activity. By implementing
these methods, you can monitor three nested loops in the activity lifecycle:
• The entire lifetime of an activity happens between the call to onCreate() and the
call to onDestroy(). Your activity should perform setup of "global" state (such as
defining layout) in onCreate(), and release all remaining resources in onDestroy(). For
example, if your activity has a thread running in the background to download data
from the network, it might create that thread in onCreate() and then stop the thread in
onDestroy().
The visible lifetime of an activity happens between the call to onStart() and the call to
onStop(). During this time, the user can see the activity on-screen and interact with it. For
example, onStop() is called when a new activity starts and this one is no longer visible.
Between these two methods, you can maintain resources that are needed to show the
activity to the user. For example, you can register a BroadcastReceiver in onStart() to
monitor changes that impact your UI, and unregister it in onStop() when the user can no
longer see what you are displaying. The system might call onStart() and onStop()
multiple times during the entire lifetime of the activity, as the activity alternates between
being visible and hidden to the user.
The foreground lifetime of an activity happens between the call to onResume() and the
call to onPause(). During this time, the activity is in front of all other activities on screen
and has user input focus. An activity can frequently transition in and out of the
foreground—for example, onPause() is called when the device goes to sleep or when a
dialog appears. Because this state can transition often, the code in these two methods
should be fairly lightweight in order to avoid slow transitions that make the user wait.
Figure 1 illustrates these loops and the paths an activity might take between states. The
rectangles represent the callback methods you can implement to perform operations when
the activity transitions between states.
Figure 1. The activity lifecycle.
The same lifecycle callback methods are listed in table 1, which describes each of the
callback methods in more detail and locates each one within the activity's overall
lifecycle, including whether the system can kill the activity after the callback method
completes.
Table 1. A summary of the activity lifecycle's callback methods.
Method Description
Killable
after?
Next
onCreate()
Called when the activity is first created. This is
where you should do all of your normal static
set up — create views, bind data to lists, and so
on. This method is passed a Bundle object
containing the activity's previous state, if that
state was captured (see Saving Activity State,
later).
Always followed by onStart().
No onStart()
onRestart()
Called after the activity has been stopped, just
prior to it being started again.
Always followed by onStart()
No onStart()
onStart()
Called just before the activity becomes visible
to the user.
Followed by onResume() if the activity comes
to the foreground, or onStop() if it becomes
hidden.
No
onResume(
)
or
onStop()
onResum
e()
Called just before the activity starts interacting
with the user. At this point the activity is at the
top of the activity stack, with user input going
to it.
Always followed by onPause().
No onPause()
onPause()
Called when the system is about to start
resuming another activity. This method is
typically used to commit unsaved changes to
persistent data, stop animations and other things
that may be consuming CPU, and so on. It
should do whatever it does very quickly,
because the next activity will not be resumed
until it returns.
Followed either by onResume() if the activity
returns back to the front, or by onStop() if it
Yes
onResume(
)
or
onStop()
becomes invisible to the user.
onStop()
Called when the activity is no longer visible to
the user. This may happen because it is being
destroyed, or because another activity (either an
existing one or a new one) has been resumed
and is covering it.
Followed either by onRestart() if the activity is
coming back to interact with the user, or by
onDestroy() if this activity is going away.
Yes
onRestart()
or
onDestroy(
)
onDestroy()
Called before the activity is destroyed. This is
the final call that the activity will receive. It
could be called either because the activity is
finishing (someone called finish() on it), or
because the system is temporarily destroying
this instance of the activity to save space. You
can distinguish between these two scenarios
with the isFinishing() method.
Yes nothing
The column labeled "Killable after?" indicates whether or not the system can kill the
process hosting the activity at any time after the method returns, without executing
another line of the activity's code. Three methods are marked "yes": (onPause(), onStop(),
and onDestroy()). Because onPause() is the first of the three, once the activity is created,
onPause() is the last method that's guaranteed to be called before the process can be
killed—if the system must recover memory in an emergency, then onStop() and
onDestroy() might not be called. Therefore, you should use onPause() to write crucial
persistent data (such as user edits) to storage. However, you should be selective about
what information must be retained during onPause(), because any blocking procedures in
this method block the transition to the next activity and slow the user experience.
Methods that are marked "No" in the Killable column protect the process hosting the
activity from being killed from the moment they are called. Thus, an activity is killable
from the time onPause() returns to the time onResume() is called. It will not again be
killable until onPause() is again called and returns.
Note: An activity that's not technically "killable" by this definition in table 1 might still
be killed by the system—but that would happen only in extreme circumstances when
there is no other recourse. When an activity might be killed is discussed more in the
Processes and Threading document.
Saving activity state
The introduction to Managing the Activity Lifecycle briefly mentions that when an
activity is paused or stopped, the state of the activity is retained. This is true because the
Activity object is still held in memory when it is paused or stopped—all information
about its members and current state is still alive. Thus, any changes the user made within
the activity are retained so that when the activity returns to the foreground (when it
"resumes"), those changes are still there.
However, when the system destroys an activity in order to recover memory, the Activity
object is destroyed, so the system cannot simply resume it with its state intact. Instead,
the system must recreate the Activity object if the user navigates back to it. Yet, the user
is unaware that the system destroyed the activity and recreated it and, thus, probably
expects the activity to be exactly as it was. In this situation, you can ensure that important
information about the activity state is preserved by implementing an additional callback
method that allows you to save information about the state of your activity:
onSaveInstanceState().
The system calls onSaveInstanceState() before making the activity vulnerable to
destruction. The system passes this method a Bundle in which you can save state
information about the activity as name-value pairs, using methods such as putString() and
putInt(). Then, if the system kills your application process and the user navigates back to
your activity, the system recreates the activity and passes the Bundle to both onCreate()
and onRestoreInstanceState(). Using either of these methods, you can extract your saved
state from the Bundle and restore the activity state. If there is no state information to
restore, then the Bundle passed to you is null (which is the case when the activity is
created for the first time).
Figure 2. The two ways in which an activity returns to user focus with its state intact:
either the activity is destroyed, then recreated and the activity must restore the previously
saved state, or the activity is stopped, then resumed and the activity state remains intact.
Note: There's no guarantee that onSaveInstanceState() will be called before your activity
is destroyed, because there are cases in which it won't be necessary to save the state (such
as when the user leaves your activity using the Back button, because the user is explicitly
closing the activity). If the system calls onSaveInstanceState(), it does so before onStop()
and possibly before onPause().
However, even if you do nothing and do not implement onSaveInstanceState(), some of
the activity state is restored by the Activity class's default implementation of
onSaveInstanceState(). Specifically, the default implementation calls the corresponding
onSaveInstanceState() method for every View in the layout, which allows each view to
provide information about itself that should be saved. Almost every widget in the Android
framework implements this method as appropriate, such that any visible changes to the
UI are automatically saved and restored when your activity is recreated. For example, the
EditText widget saves any text entered by the user and the CheckBox widget saves
whether it's checked or not. The only work required by you is to provide a unique ID
(with the android:id attribute) for each widget you want to save its state. If a widget does
not have an ID, then the system cannot save its state.
You can also explicitly stop a view in your layout from saving its state by setting the
android:saveEnabled attribute to "false" or by calling the setSaveEnabled() method.
Usually, you should not disable this, but you might if you want to restore the state of the
activity UI differently.
Although the default implementation of onSaveInstanceState() saves useful information
about your activity's UI, you still might need to override it to save additional information.
For example, you might need to save member values that changed during the activity's
life (which might correlate to values restored in the UI, but the members that hold those
UI values are not restored, by default).
Because the default implementation of onSaveInstanceState() helps save the state of the
UI, if you override the method in order to save additional state information, you should
always call the superclass implementation of onSaveInstanceState() before doing any
work. Likewise, you should also call the superclass implementation of
onRestoreInstanceState() if you override it, so the default implementation can restore
view states.
Note: Because onSaveInstanceState() is not guaranteed to be called, you should use it
only to record the transient state of the activity (the state of the UI)—you should never
use it to store persistent data. Instead, you should use onPause() to store persistent data
(such as data that should be saved to a database) when the user leaves the activity.
A good way to test your application's ability to restore its state is to simply rotate the
device so that the screen orientation changes. When the screen orientation changes, the
system destroys and recreates the activity in order to apply alternative resources that
might be available for the new screen configuration. For this reason alone, it's very
important that your activity completely restores its state when it is recreated, because
users regularly rotate the screen while using applications.
Handling configuration changes
Some device configurations can change during runtime (such as screen orientation,
keyboard availability, and language). When such a change occurs, Android recreates the
running activity (the system calls onDestroy(), then immediately calls onCreate()). This
behavior is designed to help your application adapt to new configurations by
automatically reloading your application with alternative resources that you've provided
(such as different layouts for different screen orientations and sizes).
If you properly design your activity to handle a restart due to a screen orientation change
and restore the activity state as described above, your application will be more resilient to
other unexpected events in the activity lifecycle.
The best way to handle such a restart is to save and restore the state of your activity using
onSaveInstanceState() and onRestoreInstanceState() (or onCreate()), as discussed in the
previous section.
For more information about configuration changes that happen at runtime and how you
can handle them, read the guide to Handling Runtime Changes.
Coordinating activities
When one activity starts another, they both experience lifecycle transitions. The first
activity pauses and stops (though, it won't stop if it's still visible in the background),
while the other activity is created. In case these activities share data saved to disc or
elsewhere, it's important to understand that the first activity is not completely stopped
before the second one is created. Rather, the process of starting the second one overlaps
with the process of stopping the first one.
The order of life cycle callbacks is well defined, particularly when the two activities are
in the same process and one is starting the other. Here's the order of operations that occur
when Activity A starts Acivity B:
• Activity A's onPause() method executes.
• Activity B's onCreate(), onStart(), and onResume() methods execute in sequence.
(Activity B now has user focus.)
• Then, if Activity A is no longer visible on screen, its onStop() method executes.
This predictable sequence of life cycle callbacks allows you to manage the transition of
information from one activity to another. For example, if you must write to a database
when the first activity stops so that the following activity can read it, then you should
write to the database during onPause() instead of during onStop().
There are three types of Activities :
 Fragments
A Fragment represents a behavior or a portion of user interface in an Activity.
You can combine multiple fragments in a single activity to build a multi-pane UI
and reuse a fragment in multiple activities. You can think of a fragment as a
modular section of an activity, which has its own lifecycle, receives its own input
events, and which you can add or remove while the activity is running (sort of
like a "sub activity" that you can reuse in different activities).
 Loaders
Introduced in Android 3.0, loaders make it easy to asynchronously load data in
an activity or fragment. Loaders have these characteristics:
• They are available to every Activity and Fragment.
• They provide asynchronous loading of data.
• They monitor the source of their data and deliver new results when the content
changes.
• They automatically reconnect to the last loader's cursor when being recreated
after a configuration change. Thus, they don't need to re-query their data.
 Task and Back State.
An application usually contains multiple activities. Each activity should be
designed around a specific kind of action the user can perform and can start
other activities. For example, an email application might have one activity to
show a list of new email. When the user selects an email, a new activity opens to
view that email.
Services
A Service is an application component that can perform long-running operations in the
background and does not provide a user interface. Another application component can
start a service and it will continue to run in the background even if the user switches to
another application. Additionally, a component can bind to a service to interact with it
and even perform interprocess communication (IPC). For example, a service might
handle network transactions, play music, perform file I/O, or interact with a content
provider, all from the background.
A service can essentially take two forms:
Started
A service is "started" when an application component (such as an activity) starts it by
calling startService(). Once started, a service can run in the background indefinitely,
even if the component that started it is destroyed. Usually, a started service performs a
single operation and does not return a result to the caller. For example, it might
download or upload a file over the network. When the operation is done, the service
should stop itself.
Bound
A service is "bound" when an application component binds to it by calling
bindService(). A bound service offers a client-server interface that allows components
to interact with the service, send requests, get results, and even do so across processes
with interprocess communication (IPC). A bound service runs only as long as another
application component is bound to it. Multiple components can bind to the service at
once, but when all of them unbind, the service is destroyed.
Although this documentation generally discusses these two types of services separately,
your service can work both ways—it can be started (to run indefinitely) and also allow
binding. It's simply a matter of whether you implement a couple callback methods:
onStartCommand() to allow components to start it and onBind() to allow binding.
Regardless of whether your application is started, bound, or both, any application
component can use the service (even from a separate application), in the same way that
any component can use an activity—by starting it with an Intent. However, you can
declare the service as private, in the manifest file, and block access from other
applications. This is discussed more in the section about Declaring the service in the
manifest.
Caution: A service runs in the main thread of its hosting process—the service does not
create its own thread and does not run in a separate process (unless you specify
otherwise). This means that, if your service is going to do any CPU intensive work or
blocking operations (such as MP3 playback or networking), you should create a new
thread within the service to do that work. By using a separate thread, you will reduce the
risk of Application Not Responding (ANR) errors and the application's main thread can
remain dedicated to user interaction with your activities.
Content Provider
Content providers manage access to a structured set of data. They encapsulate the data,
and provide mechanisms for defining data security. Content providers are the standard
interface that connects data in one process with code running in another process.
When you want to access data in a content provider, you use the ContentResolver object
in your application's Context to communicate with the provider as a client. The
ContentResolver object communicates with the provider object, an instance of a class that
implements ContentProvider. The provider object receives data requests from clients,
performs the requested action, and returns the results.
You don't need to develop your own provider if you don't intend to share your data with
other applications. However, you do need your own provider to provide custom search
suggestions in your own application. You also need your own provider if you want to
copy and paste complex data or files from your application to other applications.
Android itself includes content providers that manage data such as audio, video, images,
and personal contact information. You can see some of them listed in the reference
documentation for the android.provider package. With some restrictions, these providers
are accessible to any Android application.
The following topics describe content providers in more detail:
Content Provider Basics
How to access data in a content provider when the data is organized in tables.
Creating a Content Provider
How to create your own content provider.
Calendar Provider
How to access the Calendar Provider that is part of the Android platform.
Contacts Provider
How to access the Contacts Provider that is part of the Android platform.
Intents
An Intent is a messaging object you can use to request an action from another app
component. Although intents facilitate communication between components in several
ways, there are three fundamental use-cases:
To start an activity:
An Activity represents a single screen in an app. You can start a new instance of an
Activity by passing an Intent to startActivity(). The Intent describes the activity to start
and carries any necessary data.
If you want to receive a result from the activity when it finishes, call
startActivityForResult(). Your activity receives the result as a separate Intent object in
your activity's onActivityResult() callback. For more information, see the Activities
guide.
To start a service:
A Service is a component that performs operations in the background without a user
interface. You can start a service to perform a one-time operation (such as download a
file) by passing an Intent to startService(). The Intent describes the service to start and
carries any necessary data.
If the service is designed with a client-server interface, you can bind to the service from
another component by passing an Intent to bindService(). For more information, see the
Services guide.
To deliver a broadcast:
A broadcast is a message that any app can receive. The system delivers various
broadcasts for system events, such as when the system boots up or the device starts
charging. You can deliver a broadcast to other apps by passing an Intent to
sendBroadcast(), sendOrderedBroadcast(), or sendStickyBroadcast().
Intent Types
There are two types of intents:
• Explicit intentsspecify the component to start by name (the fully-qualified class
name). You'll typically use an explicit intent to start a component in your own app,
because you know the class name of the activity or service you want to start. For
example, start a new activity in response to a user action or start a service to
download a file in the background.
• Implicit intentsdo not name a specific component, but instead declare a general
action to perform, which allows a component from another app to handle it. For
example, if you want to show the user a location on a map, you can use an implicit
intent to request that another capable app show a specified location on a map.
When you create an explicit intent to start an activity or service, the system immediately
starts the app component specified in the Intent object.
Figure 1. Illustration of how an implicit intent is delivered through the system to start
another activity: [1] Activity A creates an Intent with an action description and passes it to
startActivity(). [2] The Android System searches all apps for an intent filter that matches
the intent. When a match is found, [3] the system starts the matching activity (Activity B)
by invoking its onCreate() method and passing it the Intent.
When you create an implicit intent, the Android system finds the appropriate component
to start by comparing the contents of the intent to the intent filters declared in the
manifest file of other apps on the device. If the intent matches an intent filter, the system
starts that component and delivers it the Intent object. If multiple intent filters are
compatible, the system displays a dialog so the user can pick which app to use.
An intent filter is an expression in an app's manifest file that specifies the type of intents
that the component would like to receive. For instance, by declaring an intent filter for an
activity, you make it possible for other apps to directly start your activity with a certain
kind of intent. Likewise, if you do not declare any intent filters for an activity, then it can
be started only with an explicit intent.
Caution: To ensure your app is secure, always use an explicit intent when starting a
Service and do not declare intent filters for your services. Using an implicit intent to start
a service is a security hazard because you cannot be certain what service will respond to
the intent, and the user cannot see which service starts.
Testing Android User Interface
User Interface
Your app's user interface is everything that the user can see and interact with. Android
provides a variety of pre-build UI components such as structured layout objects and UI
controls that allow you to build the graphical user interface for your app. Android also
provides other UI modules for special interfaces such as dialogs, notifications, and menus
UI Overview
All user interface elements in an Android app are built using View and ViewGroup
objects. A View is an object that draws something on the screen that the user can interact
with. A ViewGroup is an object that holds other View (and ViewGroup) objects in order
to define the layout of the interface.
Android provides a collection of both View and ViewGroup subclasses that offer you
common input controls (such as buttons and text fields) and various layout models (such
as a linear or relative layout).
User Interface Layout
The user interface for each component of your app is defined using a hierarchy of View
and ViewGroup objects, as shown in figure 1. Each view group is an invisible container
that organizes child views, while the child views may be input controls or other widgets
that draw some part of the UI. This hierarchy tree can be as simple or complex as you
need it to be (but simplicity is best for performance).
Figure 1. Illustration of a view hierarchy, which defines a UI layout.
To declare your layout, you can instantiate View objects in code and start building a tree,
but the easiest and most effective way to define your layout is with an XML file. XML
offers a human-readable structure for the layout, similar to HTML.
The name of an XML element for a view is respective to the Android class it represents.
So a <TextView> element creates a TextView widget in your UI, and a <LinearLayout>
element creates a LinearLayout view group.
For example, a simple vertical layout with a text view and a button looks like this:
<?xml version="1.0" encoding="utf-8"?><LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" > <TextView android:id="@+id/text"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="I am a TextView" /> <Button android:id="@+id/button"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="I am a Button" /></LinearLayout>
When you load a layout resource in your app, Android initializes each node of the layout
into a runtime object you can use to define additional behaviors, query the object state, or
modify the layout.
For a complete guide to creating a UI layout, see XML Layouts.
User Interface Components
You don't have to build all of your UI using View and ViewGroup objects. Android
provides several app components that offer a standard UI layout for which you simply
need to define the content. These UI components each have a unique set of APIs that are
described in their respective documents, such as Action Bar, Dialogs, and Status
Notifications.
Layouts
A layout defines the visual structure for a user interface, such as the UI for an activity or
app widget. You can declare a layout in two ways:
Declare UI elements in XML. Android provides a straightforward XML vocabulary
that corresponds to the View classes and subclasses, such as those for widgets and
layouts.
Instantiate layout elements at runtime. Your application can create View and
ViewGroup objects (and manipulate their properties) programmatically.
The Android framework gives you the flexibility to use either or both of these methods
for declaring and managing your application's UI. For example, you could declare your
application's default layouts in XML, including the screen elements that will appear in
them and their properties. You could then add code in your application that would modify
the state of the screen objects, including those declared in XML, at run time.
In general, the XML vocabulary for declaring UI elements closely follows the structure
and naming of the classes and methods, where element names correspond to class names
and attribute names correspond to methods. In fact, the correspondence is often so direct
that you can guess what XML attribute corresponds to a class method, or guess what class
corresponds to a given xml element. However, note that not all vocabulary is identical. In
some cases, there are slight naming differences. For example, the EditText element has a
text attribute that corresponds to EditText.setText().
Tip: Learn more about different layout types in Common Layout Objects. There are also
a collection of tutorials on building various layouts in the Hello Views tutorial guide.
Write the XML
Using Android's XML vocabulary, you can quickly design UI layouts and the screen
elements they contain, in the same way you create web pages in HTML — with a series
of nested elements.
Each layout file must contain exactly one root element, which must be a View or
ViewGroup object. Once you've defined the root element, you can add additional layout
objects or widgets as child elements to gradually build a View hierarchy that defines your
layout. For example, here's an XML layout that uses a vertical LinearLayout to hold a
TextView and a Button:
<?xml version="1.0" encoding="utf-8"?><LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" > <TextView android:id="@+id/text"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Hello, I am a TextView" /> <Button android:id="@+id/button"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Hello, I am a Button" /></LinearLayout>
After you've declared your layout in XML, save the file with the .xml extension, in your
Android project's res/layout/ directory, so it will properly compile.
More information about the syntax for a layout XML file is available in the Layout
Resources document.
Load the XML Resource
When you compile your application, each XML layout file is compiled into a View
resource. You should load the layout resource from your application code, in your
Activity.onCreate() callback implementation. Do so by calling setContentView(), passing
it the reference to your layout resource in the form of: R.layout.layout_file_name For
example, if your XML layout is saved as main_layout.xml, you would load it for your
Activity like so:
public void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);}
The onCreate() callback method in your Activity is called by the Android framework
when your Activity is launched (see the discussion about lifecycles, in the Activities
document).
Attributes
Every View and ViewGroup object supports their own variety of XML attributes. Some
attributes are specific to a View object (for example, TextView supports the textSize
attribute), but these attributes are also inherited by any View objects that may extend this
class. Some are common to all View objects, because they are inherited from the root
View class (like the id attribute). And, other attributes are considered "layout parameters,"
which are attributes that describe certain layout orientations of the View object, as
defined by that object's parent ViewGroup object.
ID
Any View object may have an integer ID associated with it, to uniquely identify the View
within the tree. When the application is compiled, this ID is referenced as an integer, but
the ID is typically assigned in the layout XML file as a string, in the id attribute. This is
an XML attribute common to all View objects (defined by the View class) and you will
use it very often. The syntax for an ID, inside an XML tag is:
android:id="@+id/my_button"
The at-symbol (@) at the beginning of the string indicates that the XML parser should
parse and expand the rest of the ID string and identify it as an ID resource. The plus-
symbol (+) means that this is a new resource name that must be created and added to our
resources (in the R.java file). There are a number of other ID resources that are offered by
the Android framework. When referencing an Android resource ID, you do not need the
plus-symbol, but must add the android package namespace, like so:
android:id="@android:id/empty"
With the android package namespace in place, we're now referencing an ID from the
android.R resources class, rather than the local resources class.
In order to create views and reference them from the application, a common pattern is to:
• Define a view/widget in the layout file and assign it a unique ID:
<Button android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/my_button_text"/>
• Then create an instance of the view object and capture it from the layout
(typically in the onCreate() method):
Button myButton = (Button) findViewById(R.id.my_button);
Defining IDs for view objects is important when creating a RelativeLayout. In a relative
layout, sibling views can define their layout relative to another sibling view, which is
referenced by the unique ID.
An ID need not be unique throughout the entire tree, but it should be unique within the
part of the tree you are searching (which may often be the entire tree, so it's best to be
completely unique when possible).
Layout Parameters
XML layout attributes named layout_something define layout parameters for the View
that are appropriate for the ViewGroup in which it resides.
Every ViewGroup class implements a nested class that extends
ViewGroup.LayoutParams. This subclass contains property types that define the size and
position for each child view, as appropriate for the view group. As you can see in figure
1, the parent view group defines layout parameters for each child view (including the
child view group).
Figure 1. Visualization of a view hierarchy with layout parameters associated with each
view.
Note that every LayoutParams subclass has its own syntax for setting values. Each child
element must define LayoutParams that are appropriate for its parent, though it may also
define different LayoutParams for its own children.
All view groups include a width and height (layout_width and layout_height), and each
view is required to define them. Many LayoutParams also include optional margins and
borders.
You can specify width and height with exact measurements, though you probably won't
want to do this often. More often, you will use one of these constants to set the width or
height:
• wrap_contenttells your view to size itself to the dimensions required by its
content
• fill_parent(renamed match_parent in API Level 8) tells your view to become as
big as its parent view group will allow.
In general, specifying a layout width and height using absolute units such as pixels is not
recommended. Instead, using relative measurements such as density-independent pixel
units (dp), wrap_content, or fill_parent, is a better approach, because it helps ensure that
your application will display properly across a variety of device screen sizes. The
accepted measurement types are defined in the Available Resources document.
Layout Position
The geometry of a view is that of a rectangle. A view has a location, expressed as a pair
of left and top coordinates, and two dimensions, expressed as a width and a height. The
unit for location and dimensions is the pixel.
It is possible to retrieve the location of a view by invoking the methods getLeft() and
getTop(). The former returns the left, or X, coordinate of the rectangle representing the
view. The latter returns the top, or Y, coordinate of the rectangle representing the view.
These methods both return the location of the view relative to its parent. For instance,
when getLeft() returns 20, that means the view is located 20 pixels to the right of the left
edge of its direct parent.
In addition, several convenience methods are offered to avoid unnecessary computations,
namely getRight() and getBottom(). These methods return the coordinates of the right and
bottom edges of the rectangle representing the view. For instance, calling getRight() is
similar to the following computation: getLeft() + getWidth().
Size, Padding and Margins
The size of a view is expressed with a width and a height. A view actually possess two
pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define
how big a view wants to be within its parent. The measured dimensions can be obtained
by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and
drawing height. These dimensions define the actual size of the view on screen, at drawing
time and after layout. These values may, but do not have to, be different from the
measured width and height. The width and height can be obtained by calling getWidth()
and getHeight().
To measure its dimensions, a view takes into account its padding. The padding is
expressed in pixels for the left, top, right and bottom parts of the view. Padding can be
used to offset the content of the view by a specific amount of pixels. For instance, a left
padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding
can be set using the setPadding(int, int, int, int) method and queried by calling
getPaddingLeft(), getPaddingTop(), getPaddingRight() and getPaddingBottom().
Even though a view can define a padding, it does not provide any support for margins.
However, view groups provide such a support. Refer to ViewGroup and
ViewGroup.MarginLayoutParams for further information.
For more information about dimensions, see Dimension Values.
Common Layouts
Each subclass of the ViewGroup class provides a unique way to display the views you
nest within it. Below are some of the more common layout types that are built into the
Android platform.
Note: Although you can nest one or more layouts within another layout to acheive your
UI design, you should strive to keep your layout hierarchy as shallow as possible. Your
layout draws faster if it has fewer nested layouts (a wide view hierarchy is better than a
deep view hierarchy).
Linear Layout
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.
Relative Layout
Enables you to specify
the location of child
objects relative to each
other (child A to the left
of child B) or to the
parent (aligned to the
top of the parent).
Web View
Displays web pages.
Building Layouts with
an Adapter
When the content for your layout is dynamic or not pre-determined, you can use a layout
that subclasses AdapterView to populate the layout with views at runtime. A subclass of
the AdapterView class uses an Adapter to bind data to its layout. The Adapter behaves as
a middle-man between the data source and the AdapterView layout—the Adapter
retrieves the data (from a source such as an array or a database query) and converts each
entry into a view that can be added into the AdapterView layout.
Common layouts backed by an adapter include:
List View
Displays a scrolling
single column list.
Grid View
Displays a scrolling
grid of columns and
rows.
Filling an adapter
view with data
You can populate an
AdapterView such as
ListView or GridView by binding the AdapterView instance to an Adapter, which
retrieves data from an external source and creates a View that represents each data entry.
Android provides several subclasses of Adapter that are useful for retrieving different
kinds of data and building views for an AdapterView. The two most common adapters
are:
ArrayAdapter
Use this adapter when your data source is an array. By default, ArrayAdapter creates
a view for each array item by calling toString() on each item and placing the contents
in a TextView.
For example, if you have an array of strings you want to display in a ListView, initialize a
new ArrayAdapter using a constructor to specify the layout for each string and the string
array:
ArrayAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, myStringArray);
The arguments for this constructor are:
o Your app Context
o The layout that contains a TextView for each string in the array
o The string array
Then simply call setAdapter() on your ListView:
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
To customize the appearance of each item you can override the toString() method for the
objects in your array. Or, to create a view for each item that's something other than a
TextView (for example, if you want an ImageView for each array item), extend the
ArrayAdapter class and override getView() to return the type of view you want for each
item.
SimpleCursorAdapter
Use this adapter when your data comes from a Cursor. When using
SimpleCursorAdapter, you must specify a layout to use for each row in the Cursor
and which columns in the Cursor should be inserted into which views of the layout.
For example, if you want to create a list of people's names and phone numbers, you
can perform a query that returns a Cursor containing a row for each person and
columns for the names and numbers. You then create a string array specifying which
columns from the Cursor you want in the layout for each result and an integer array
specifying the corresponding views that each column should be placed:
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};int[] toViews =
{R.id.display_name, R.id.phone_number};
When you instantiate the SimpleCursorAdapter, pass the layout to use for each result, the
Cursor containing the results, and these two arrays:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);ListView
listView = getListView();
listView.setAdapter(adapter);
The SimpleCursorAdapter then creates a view for each row in the Cursor using the
provided layout by inserting each fromColumns item into the corresponding toViews
view.
If, during the course of your application's life, you change the underlying data that is read
by your adapter, you should call notifyDataSetChanged(). This will notify the attached
view that the data has been changed and it should refresh itself.
Handling click events
You can respond to click events on each item in an AdapterView by implementing the
AdapterView.OnItemClickListener interface. For example:
// 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) { // Do something in
response to the click }};
listView.setOnItemClickListener(mMessageClickedHandler);
Linear Layout
LinearLayout is a view group that aligns all children in a single direction, vertically or
horizontally. You can specify the layout direction with the android:orientation attribute.
All children of a LinearLayout are stacked one after the other, so a vertical list will only
have one child per row, no matter how wide they are, and a horizontal list will only be
one row high (the height of the tallest child, plus padding). A LinearLayout respects
margins between children and the gravity (right, center, or left alignment) of each child.
Layout Weight
LinearLayout also supports assigning a weight to individual children with the
android:layout_weight attribute. This attribute assigns an "importance" value to a view in
terms of how much space is should occupy on the screen. A larger weight value allows it
to expand to fill any remaining space in the parent view. Child views can specify a weight
value, and then any remaining space in the view group is assigned to children in the
proportion of their declared weight. Default weight is zero.
For example, if there are three text fields and two of them declare a weight of 1, while the
other is given no weight, the third text field without weight will not grow and will only
occupy the area required by its content. The other two will expand equally to fill the
space remaining after all three fields are measured. If the third field is then given a weight
of 2 (instead of 0), then it is now declared more important than both the others, so it gets
half the total remaining space, while the first two share the rest equally.
Example
<?xml version="1.0" encoding="utf-8"?><LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:paddingLeft="16dp" android:paddingRight="16dp"
android:orientation="vertical" > <EditText android:layout_width="fill_parent"
android:layout_height="wrap_content" android:hint="@string/to" /> <EditText
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:hint="@string/subject" /> <EditText android:layout_width="fill_parent"
android:layout_height="0dp" android:layout_weight="1" android:gravity="top"
android:hint="@string/message" /> <Button android:layout_width="100dp"
android:layout_height="wrap_content" android:layout_gravity="right"
android:text="@string/send" /></LinearLayout>
Relative Layout
RelativeLayout is a
view group that
displays child views
in relative positions.
The position of each
view can be specified
as relative to sibling
elements (such as to
the left-of or below
another view) or in
positions relative to
the parent
RelativeLayout area
(such as aligned to
the bottom, left of
center).
A RelativeLayout is a very powerful utility for designing a user interface because it can
eliminate nested view groups and keep your layout hierarchy flat, which improves
performance. If you find yourself using several nested LinearLayout groups, you may be
able to replace them with a single RelativeLayout.
Positioning Views
RelativeLayout lets child views specify their position relative to the parent view or to
each other (specified by ID). So you can align two elements by right border, or make one
below another, centered in the screen, centered left, and so on. By default, all child views
are drawn at the top-left of the layout, so you must define the position of each view using
the various layout properties available from RelativeLayout.LayoutParams.
Some of the many layout properties available to views in a RelativeLayout include:
android:layout_alignParentTop
If "true", makes the top edge of this view match the top edge of the parent.
android:layout_centerVertical
If "true", centers this child vertically within its parent.
android:layout_below
Positions the top edge of this view below the view specified with a resource ID.
android:layout_toRightOf
Positions the left edge of this view to the right of the view specified with a resource
ID.
These are just a few examples. All layout attributes are documented at
RelativeLayout.LayoutParams.
The value for each layout property is either a boolean to enable a layout position relative
to the parent RelativeLayout or an ID that references another view in the layout against
which the view should be positioned.
In your XML layout, dependencies against other views in the layout can be declared in
any order. For example, you can declare that "view1" be positioned below "view2" even
if "view2" is the last view declared in the hierarchy. The example below demonstrates
such a scenario.
Example
Each of the attributes that control the relative position of each view are emphasized.
<?xml version="1.0" encoding="utf-8"?><RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:paddingLeft="16dp" android:paddingRight="16dp" > <EditText
android:id="@+id/name" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:hint="@string/reminder" />
<Spinner android:id="@+id/dates" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_below="@id/name"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/times" /> <Spinner android:id="@id/times"
android:layout_width="96dp" android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_alignParentRight="true" /> <Button
android:layout_width="96dp" android:layout_height="wrap_content"
android:layout_below="@id/times" android:layout_alignParentRight="true"
android:text="@string/done" /></RelativeLayout>
List View
ListView is a view
group that displays a
list of scrollable
items. The list items
are automatically
inserted to the list
using an Adapter that
pulls content from a
source such as an
array or database
query and converts
each item result into a
view that's placed
into the list.
For an introduction to
how you can
dynamically insert
views using an
adapter, read
Building Layouts
with an Adapter.
Grid View
GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid. The
grid items are automatically inserted to the layout using a ListAdapter.
For an introduction to how you can dynamically insert views using an adapter, read
Building Layouts with an Adapter.
Hierarchy Viewer
Hierarchy Viewer allows you to debug and optimize your user interface. It provides a visual
representation of the layout's View hierarchy (the Layout View) and a magnified inspector of the
display (the Pixel Perfect View).
To start Hierarchy Viewer, enter the following command from the SDK tools/ directory:
Widget
Widgets are an essential aspect of home screen customization. You can imagine them as
"at-a-glance" views of an app's most important data and functionality that is accessible
right from the user's home screen. Users can move widgets across their home screen
panels, and, if supported, resize them to tailor the amount of information within a widget
to their preference.
Widget types
As you begin planning your widget, think about what kind of widget you're trying to
build. Widgets typically fall into one of the following categories:
Information widgets
Information widgets typically display a few crucial information elements that are
important to a user and track how that information changes over time. Good examples for
information widgets are weather widgets, clock widgets or sports score trackers.
Touching information widgets typically launches the associated app and opens a detail
view of the widget information.
Collection widgets
As the name implies, collection widgets specialize in displaying multitude elements of
the same type, such as a collection of pictures from a gallery app, a collection of articles
from a news app or a collection of emails/messages from a communication app.
Collection widgets typically focus on two use cases: browsing the collection, and opening
an element of the collection to its detail view for consumption. Collection widgets can
scroll vertically.
ListView widget
GridView widget
Control widgets
The main purpose of a control widget is to display often used functions that the user can
trigger right from the home screen without having to open the app first. Think of them as
remote controls for an app. A typical example of control widgets are music app widgets
that allow the user to play, pause or skip music tracks from outside the actual music app.
Interacting with control widgets may or may not progress to an associated detail view
depending on if the control widget's function generated a data set, such as in the case of a
search widget.
Hybrid widgets
While all widgets tend to gravitate towards one of the three types described above, many
widgets in reality are hybrids that combine elements of different types.
For the purpose of your widget planning, center your widget around one of the base types
and add elements of other types if needed.
A music player widget is primarily a control widget, but also keeps the user informed
about what track is currently playing. It essentially combines a control widget with
elements of an information widget type.
Widget limitations
While widgets could be understood as "mini apps", there are certain limitations that are
important to understand before you start to embark on designing your widget:
Gestures
Because widgets live on the home screen, they have to co-exist with the navigation that is
established there. This limits the gesture support that is available in a widget compared to
a full-screen app. While apps for example may support a view pager that allows the user
to navigate between screens laterally, that gesture is already taken on the home screen for
the purpose of navigating between home panels.
The only gestures available for widgets are:
• Touch
• Vertical swipe
Elements
Given the above interaction limitations, some of the UI building blocks that rely on
restricted gestures are not available for widgets. For a complete list of supported building
blocks and more information on layout restrictions, please refer to the "Creating App
Widget Layouts" section in the App Widgets API Guide.
Design guidelines
Widget content
Widgets are a great mechanism to attract a user to your app by "advertising" new and
interesting content that is available for consumption in your app.
Just like the teasers on the front page of a newspaper, widgets should consolidate and
concentrate an app's information and then provide a connection to richer detail within the
app; or in other words: the widget is the information "snack" while the app is the "meal."
As a bottom line, always make sure that your app shows more detail about an information
item than what the widget already displays.
Widget navigation
Besides the pure information content, you should also consider to round out your widget's
offering by providing navigation links to frequently used areas of your app. This lets
users complete tasks quicker and extends the functional reach of the app to the home
screen.
Good candidates for navigation links to surface on widgets are:
• Generative functions: These are the functions that allow the user to create new
content for an app, such as creating a new document or a new message.
• Open application at top level: Tapping on an information element will usually
navigate the user to a lower level detail screen. Providing access to the top level of
your application provides more navigation flexibility and can replace a dedicated app
shortcut that users would otherwise use to navigate to the app from the home screen.
Using your application icon as an affordance can also provide your widget with a
clear identity in case the data you're displaying is ambiguous.
Widget resizing
With version 3.1, Android introduced resizable widgets to the platform. Resizing allows
users to adjust the height and/or the width of a widget within the constraints of the home
panel placement grid. You can decide if your widget is freely resizable or if it is
constrained to horizontal or vertical size changes. You do not have to support resizing if
your particular widget is inherently fixed-size.
Allowing users to resize widgets has important benefits:
• They can fine-tune how much information they want to see on each widget.
• They can better influence the layout of widgets and shortcuts on their home
panels.
A long press and subsequent release sets resizable widgets into resize mode. Users can
use the drag handles or the widget corners to set the desired size.
Planning a resize strategy for your widget depends on the type of widget you're creating.
List or grid-based collection widgets are usually straightforward because resizing the
widget will simply expand or contract the vertical scrolling area. Regardless of the of the
widget's size, the user can still scroll all information elements into view. Information
widgets on the other hand require a bit more hands-on planning, since they are not
scrollable and all content has to fit within a given size. You will have to dynamically
adjust your widget's content and layout to the size the user defined through the resize
operation.
In this simple example the user can horizontally resize a weather widget in 4 steps and
expose richer information about the weather at the current location as the widget grows.
For each widget size determine how much of your app's information should surface. For
smaller sizes concentrate on the essential and then add more contextual information as the
widget grows horizontally and vertically.
Layout considerations
It will be tempting to layout your widgets according to the dimensions of the placement
grid of a particular device that you own and develop with. This can be a useful initial
approximation as you layout your widget, but keep the following in mind:
• The number, size and spacing of cells can vary widely from device to device, and
hence it is very important that your widget is flexible and can accommodate more or
less space than anticipated.
• In fact, as the user resizes a widget, the system will respond with a dp size range
in which your widget can redraw itself. Planning your widget resizing strategy across
"size buckets" rather than variable grid dimensions will give you the most reliable
results.
Widget configuration
Sometimes widgets need to be setup before they can become useful. Think of an email
widget for example, where you need to provide an account before the inbox can be
displayed. Or a static photo widget where the user has to assign the picture that is to be
displayed from the gallery.
Android widgets display their configuration choices right after the widget is dropped onto
a home panel. Keep the widget configuration light and don't present more than 2-3
configuration elements. Use dialog-style instead of full-screen activities to present
configuration choices and retain the user's context of place, even if doing so requires use
of multiple dialogs.
Once setup, there typically is not a lot of reason to revisit the setup. Therefore Android
widgets do not show a "Setup" or "Configuration" button.
After adding a Play
widget to a home
panel, the widget asks
the user to specify the
type of media the
widget should display.
Checklist
• Focus on small
portions of
glanceable
information on your widget. Expand on the information in your app.
• Choose the right widget type for your purpose.
• For resizable widgets, plan how the content for your widget should adapt to
different sizes.
• Make your widget orientation and device independent by ensuring that the layout
is capable of stretching and contracting.
UI Event
On Android, there's more than one way to intercept the events from a user's interaction
with your application. When considering events within your user interface, the approach
is to capture the events from the specific View object that the user interacts with. The
View class provides the means to do so.
Within the various View classes that you'll use to compose your layout, you may notice
several public callback methods that look useful for UI events. These methods are called
by the Android framework when the respective action occurs on that object. For instance,
when a View (such as a Button) is touched, the onTouchEvent() method is called on that
object. However, in order to intercept this, you must extend the class and override the
method. However, extending every View object in order to handle such an event would
not be practical. This is why the View class also contains a collection of nested interfaces
with callbacks that you can much more easily define. These interfaces, called event
listeners, are your ticket to capturing the user interaction with your UI.
While you will more commonly use the event listeners to listen for user interaction, there
may come a time when you do want to extend a View class, in order to build a custom
component. Perhaps you want to extend the Button class to make something more fancy.
In this case, you'll be able to define the default event behaviors for your class using the
class event handlers.
Adapter
An Adapter object acts as a bridge between an AdapterView and the underlying data for
that view. The Adapter provides access to the data items. The Adapter is also responsible
for making a View for each item in the data set.
Mobile testing   android
Mobile testing   android
Mobile testing   android
Mobile testing   android
Mobile testing   android
Mobile testing   android
Mobile testing   android
Mobile testing   android
Mobile testing   android

More Related Content

What's hot

Sensors in Android (old)
Sensors in Android (old)Sensors in Android (old)
Sensors in Android (old)Ahsanul Karim
 
Day: 2 Environment Setup for Android Application Development
Day: 2 Environment Setup for Android Application DevelopmentDay: 2 Environment Setup for Android Application Development
Day: 2 Environment Setup for Android Application DevelopmentAhsanul Karim
 
Day 3: Getting Active Through Activities
Day 3: Getting Active Through ActivitiesDay 3: Getting Active Through Activities
Day 3: Getting Active Through ActivitiesAhsanul Karim
 
Introduction to Android for Quality Engineers
Introduction to Android for Quality EngineersIntroduction to Android for Quality Engineers
Introduction to Android for Quality EngineersAhmed Faidy
 
Day 2 android internals a quick overview
Day 2 android internals a quick overviewDay 2 android internals a quick overview
Day 2 android internals a quick overviewAhsanul Karim
 
PukaPuka Presentation
PukaPuka PresentationPukaPuka Presentation
PukaPuka PresentationDevanshMaurya
 
Day 6: Android BroadcastReceiver Component
Day 6: Android BroadcastReceiver ComponentDay 6: Android BroadcastReceiver Component
Day 6: Android BroadcastReceiver ComponentAhsanul Karim
 
Lecture 2(b) Android Internals A Quick Overview
Lecture 2(b) Android Internals A Quick OverviewLecture 2(b) Android Internals A Quick Overview
Lecture 2(b) Android Internals A Quick OverviewAhsanul Karim
 
Multiple Activity and Navigation Primer
Multiple Activity and Navigation PrimerMultiple Activity and Navigation Primer
Multiple Activity and Navigation PrimerAhsanul Karim
 
Introduction to android
Introduction to androidIntroduction to android
Introduction to androidjavalabsf
 
Android developer interview questions with answers pdf
Android developer interview questions with answers pdfAndroid developer interview questions with answers pdf
Android developer interview questions with answers pdfazlist247
 
How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?Paul Cook
 
Day 15: Working in Background
Day 15: Working in BackgroundDay 15: Working in Background
Day 15: Working in BackgroundAhsanul Karim
 

What's hot (20)

Sensors in Android (old)
Sensors in Android (old)Sensors in Android (old)
Sensors in Android (old)
 
Android components
Android componentsAndroid components
Android components
 
Android 1.8 sensor
Android 1.8 sensorAndroid 1.8 sensor
Android 1.8 sensor
 
Day: 2 Environment Setup for Android Application Development
Day: 2 Environment Setup for Android Application DevelopmentDay: 2 Environment Setup for Android Application Development
Day: 2 Environment Setup for Android Application Development
 
Android Services
Android ServicesAndroid Services
Android Services
 
Day 3: Getting Active Through Activities
Day 3: Getting Active Through ActivitiesDay 3: Getting Active Through Activities
Day 3: Getting Active Through Activities
 
Introduction to Android for Quality Engineers
Introduction to Android for Quality EngineersIntroduction to Android for Quality Engineers
Introduction to Android for Quality Engineers
 
Day 2 android internals a quick overview
Day 2 android internals a quick overviewDay 2 android internals a quick overview
Day 2 android internals a quick overview
 
Android Basics
Android BasicsAndroid Basics
Android Basics
 
PukaPuka Presentation
PukaPuka PresentationPukaPuka Presentation
PukaPuka Presentation
 
Day 6: Android BroadcastReceiver Component
Day 6: Android BroadcastReceiver ComponentDay 6: Android BroadcastReceiver Component
Day 6: Android BroadcastReceiver Component
 
Lecture 2(b) Android Internals A Quick Overview
Lecture 2(b) Android Internals A Quick OverviewLecture 2(b) Android Internals A Quick Overview
Lecture 2(b) Android Internals A Quick Overview
 
AndroidManifest
AndroidManifestAndroidManifest
AndroidManifest
 
Multiple Activity and Navigation Primer
Multiple Activity and Navigation PrimerMultiple Activity and Navigation Primer
Multiple Activity and Navigation Primer
 
Android Study Jams - Session 1
Android Study Jams - Session 1Android Study Jams - Session 1
Android Study Jams - Session 1
 
Training android
Training androidTraining android
Training android
 
Introduction to android
Introduction to androidIntroduction to android
Introduction to android
 
Android developer interview questions with answers pdf
Android developer interview questions with answers pdfAndroid developer interview questions with answers pdf
Android developer interview questions with answers pdf
 
How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?How Android Architecture Components can Help You Improve Your App’s Design?
How Android Architecture Components can Help You Improve Your App’s Design?
 
Day 15: Working in Background
Day 15: Working in BackgroundDay 15: Working in Background
Day 15: Working in Background
 

Similar to Mobile testing android

Android application fundamentals
Android application fundamentalsAndroid application fundamentals
Android application fundamentalsJohn Smith
 
Android app fundamentals
Android app fundamentalsAndroid app fundamentals
Android app fundamentalsAmr Salman
 
5 beginner android application development foundation
5 beginner android application development foundation5 beginner android application development foundation
5 beginner android application development foundationCbitss Technologies
 
Android Development Tutorial
Android Development TutorialAndroid Development Tutorial
Android Development TutorialGermán Bringas
 
architecture of android.pptx
architecture of android.pptxarchitecture of android.pptx
architecture of android.pptxallurestore
 
Kotlin for Android App Development Presentation
Kotlin for Android App Development PresentationKotlin for Android App Development Presentation
Kotlin for Android App Development PresentationKnoldus Inc.
 
Android 101 Session @thejunction32
Android 101 Session @thejunction32Android 101 Session @thejunction32
Android 101 Session @thejunction32Eden Shochat
 
Android In A Nutshell
Android In A NutshellAndroid In A Nutshell
Android In A NutshellTed Chien
 
Mobile Application Development Lecture 05 & 06.pdf
Mobile Application Development Lecture 05 & 06.pdfMobile Application Development Lecture 05 & 06.pdf
Mobile Application Development Lecture 05 & 06.pdfAbdullahMunir32
 
Getting started with android programming
Getting started with android programmingGetting started with android programming
Getting started with android programmingPERKYTORIALS
 
Android application structure
Android application structureAndroid application structure
Android application structureAlexey Ustenko
 
android development training in mumbai
android development training in mumbaiandroid development training in mumbai
android development training in mumbaifaizrashid1995
 
Os eclipse-androidwidget-pdf
Os eclipse-androidwidget-pdfOs eclipse-androidwidget-pdf
Os eclipse-androidwidget-pdfweerabahu
 
Android Application Components
Android Application ComponentsAndroid Application Components
Android Application ComponentsJAINAM KAPADIYA
 
Hello android world
Hello android worldHello android world
Hello android worldeleksdev
 

Similar to Mobile testing android (20)

Android application fundamentals
Android application fundamentalsAndroid application fundamentals
Android application fundamentals
 
Android beginners David
Android beginners DavidAndroid beginners David
Android beginners David
 
Android app fundamentals
Android app fundamentalsAndroid app fundamentals
Android app fundamentals
 
Basics 4
Basics   4Basics   4
Basics 4
 
5 beginner android application development foundation
5 beginner android application development foundation5 beginner android application development foundation
5 beginner android application development foundation
 
Android Development Tutorial
Android Development TutorialAndroid Development Tutorial
Android Development Tutorial
 
architecture of android.pptx
architecture of android.pptxarchitecture of android.pptx
architecture of android.pptx
 
Kotlin for Android App Development Presentation
Kotlin for Android App Development PresentationKotlin for Android App Development Presentation
Kotlin for Android App Development Presentation
 
Android 101 Session @thejunction32
Android 101 Session @thejunction32Android 101 Session @thejunction32
Android 101 Session @thejunction32
 
Aptech Apps
Aptech Apps Aptech Apps
Aptech Apps
 
Android In A Nutshell
Android In A NutshellAndroid In A Nutshell
Android In A Nutshell
 
Mobile Application Development Lecture 05 & 06.pdf
Mobile Application Development Lecture 05 & 06.pdfMobile Application Development Lecture 05 & 06.pdf
Mobile Application Development Lecture 05 & 06.pdf
 
Getting started with android programming
Getting started with android programmingGetting started with android programming
Getting started with android programming
 
Android basics
Android basicsAndroid basics
Android basics
 
Android application structure
Android application structureAndroid application structure
Android application structure
 
android development training in mumbai
android development training in mumbaiandroid development training in mumbai
android development training in mumbai
 
Os eclipse-androidwidget-pdf
Os eclipse-androidwidget-pdfOs eclipse-androidwidget-pdf
Os eclipse-androidwidget-pdf
 
Android Application Components
Android Application ComponentsAndroid Application Components
Android Application Components
 
Android Development Basics
Android Development BasicsAndroid Development Basics
Android Development Basics
 
Hello android world
Hello android worldHello android world
Hello android world
 

Recently uploaded

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 

Recently uploaded (20)

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 

Mobile testing android

  • 1. Understanding Android Framework for Effective Testing Introduction To develop apps for Android devices, you use a set of tools that are included in the Android SDK. Once you've downloaded and installed the SDK, you can access these tools right from your Eclipse IDE, through the ADT plugin, or from the command line. Developing with Eclipse is the preferred method because it can directly invoke the tools that you need while developing applications. However, you may choose to develop with another IDE or a simple text editor and invoke the tools on the command line or with scripts. This is a less streamlined way to develop because you will sometimes have to call command line tools manually, but you will have access to the same number of features that you would have in Eclipse. The basic steps for developing applications (with or without Eclipse) are shown in figure 1. The development steps encompass four development phases, which include: Setup During this phase you install and set up your development environment. You also create Android Virtual Devices (AVDs) and connect hardware devices on which you can install your applications. See Managing Virtual Devices and Using Hardware Devices for more information. Development During this phase you set up and develop your Android project, which contains all of the source code and resource files for your application. For more information, see Create an Android project. Debugging and Testing During this phase you build your project into a debuggable .apk package that you can install and run on the emulator or an Android-powered device. If you are using Eclipse, builds are generated each time you project is saved. If you're using another IDE, you can build your project using Ant and install it on a device using adb. For more information, see Build and run your application. Next, you debug your application using a JDWP-compliant debugger along with the debugging and logging tools that are provided with the Android SDK. Eclipse already comes packaged with a compatible debugger. For more information see, Debug your application with the SDK debugging and logging tools. Last, you test your application using various Android SDK testing tools. For more information, see Test your application with the Testing and Instrumentation framework.
  • 2. Publishing During this phase you configure and build your application for release and distribute your application to users. For more information, see Publishing Overview. Figure 1. The development process for Android applications. Application Fundamentals Android apps are written in the Java programming language. The Android SDK tools compile your code— along with any data and resource files —into an APK: an Android package, which is an archive file with an .apk suffix. One APK file contains all the contents of an Android app and is the file that Android-powered devices use to install the app. Once installed on a device, each Android app lives in its own security sandbox: • The Android operating system is a multi-user Linux system in which each app is a different user. • By default, the system assigns each app a unique Linux user ID (the ID is used only by the system and is unknown to the app). The system sets permissions for all the files in an app so that only the user ID assigned to that app can access them. • Each process has its own virtual machine (VM), so an app's code runs in isolation from other apps. • By default, every app runs in its own Linux process. Android starts the process
  • 3. when any of the app's components need to be executed, then shuts down the process when it's no longer needed or when the system must recover memory for other apps. In this way, the Android system implements the principle of least privilege. That is, each app, by default, has access only to the components that it requires to do its work and no more. This creates a very secure environment in which an app cannot access parts of the system for which it is not given permission. However, there are ways for an app to share data with other apps and for an app to access system services: • It's possible to arrange for two apps to share the same Linux user ID, in which case they are able to access each other's files. To conserve system resources, apps with the same user ID can also arrange to run in the same Linux process and share the same VM (the apps must also be signed with the same certificate). • An app can request permission to access device data such as the user's contacts, SMS messages, the mountable storage (SD card), camera, Bluetooth, and more. All app permissions must be granted by the user at install time. That covers the basics regarding how an Android app exists within the system. The rest of this document introduces you to: • The core framework components that define your app. • The manifest file in which you declare components and required device features for your app. • Resources that are separate from the app code and allow your app to gracefully optimize its behavior for a variety of device configurations. App Components App components are the essential building blocks of an Android app. Each component is a different point through which the system can enter your app. Not all components are actual entry points for the user and some depend on each other, but each one exists as its own entity and plays a specific role—each one is a unique building block that helps define your app's overall behavior. There are four different types of app components. Each type serves a distinct purpose and has a distinct lifecycle that defines how the component is created and destroyed. Here are the four types of app components: Activities An activity represents a single screen with a user interface. For example, an email app
  • 4. might have one activity that shows a list of new emails, another activity to compose an email, and another activity for reading emails. Although the activities work together to form a cohesive user experience in the email app, each one is independent of the others. As such, a different app can start any one of these activities (if the email app allows it). For example, a camera app can start the activity in the email app that composes new mail, in order for the user to share a picture. An activity is implemented as a subclass of Activity and you can learn more about it in the Activities developer guide. Services A service is a component that runs in the background to perform long-running operations or to perform work for remote processes. A service does not provide a user interface. For example, a service might play music in the background while the user is in a different app, or it might fetch data over the network without blocking user interaction with an activity. Another component, such as an activity, can start the service and let it run or bind to it in order to interact with it. A service is implemented as a subclass of Service and you can learn more about it in the Services developer guide. Content providers A content provider manages a shared set of app data. You can store the data in the file system, an SQLite database, on the web, or any other persistent storage location your app can access. Through the content provider, other apps can query or even modify the data (if the content provider allows it). For example, the Android system provides a content provider that manages the user's contact information. As such, any app with the proper permissions can query part of the content provider (such as ContactsContract.Data) to read and write information about a particular person. Content providers are also useful for reading and writing data that is private to your app and not shared. For example, the Note Pad sample app uses a content provider to save notes. A content provider is implemented as a subclass of ContentProvider and must implement a standard set of APIs that enable other apps to perform transactions. For more information, see the Content Providers developer guide. Broadcast receivers A broadcast receiver is a component that responds to system-wide broadcast announcements. Many broadcasts originate from the system—for example, a broadcast announcing that the screen has turned off, the battery is low, or a picture was captured. Apps can also initiate broadcasts—for example, to let other apps know that some data has been downloaded to the device and is available for them to use. Although broadcast receivers don't display a user interface, they may create a status bar notification to alert the user when a broadcast event occurs. More commonly, though, a broadcast receiver is just a "gateway" to other components and is intended to do a very minimal amount of work. For instance, it might initiate a service to perform some work based on the event.
  • 5. A broadcast receiver is implemented as a subclass of BroadcastReceiver and each broadcast is delivered as an Intent object. For more information, see the BroadcastReceiver class. A unique aspect of the Android system design is that any app can start another app’s component. For example, if you want the user to capture a photo with the device camera, there's probably another app that does that and your app can use it, instead of developing an activity to capture a photo yourself. You don't need to incorporate or even link to the code from the camera app. Instead, you can simply start the activity in the camera app that captures a photo. When complete, the photo is even returned to your app so you can use it. To the user, it seems as if the camera is actually a part of your app. When the system starts a component, it starts the process for that app (if it's not already running) and instantiates the classes needed for the component. For example, if your app starts the activity in the camera app that captures a photo, that activity runs in the process that belongs to the camera app, not in your app's process. Therefore, unlike apps on most other systems, Android apps don't have a single entry point (there's no main() function, for example). Because the system runs each app in a separate process with file permissions that restrict access to other apps, your app cannot directly activate a component from another app. The Android system, however, can. So, to activate a component in another app, you must deliver a message to the system that specifies your intent to start a particular component. The system then activates the component for you. Activating Components Three of the four component types—activities, services, and broadcast receivers—are activated by an asynchronous message called an intent. Intents bind individual components to each other at runtime (you can think of them as the messengers that request an action from other components), whether the component belongs to your app or another. An intent is created with an Intent object, which defines a message to activate either a specific component or a specific type of component—an intent can be either explicit or implicit, respectively. For activities and services, an intent defines the action to perform (for example, to "view" or "send" something) and may specify the URI of the data to act on (among other things that the component being started might need to know). For example, an intent might convey a request for an activity to show an image or to open a web page. In some cases, you can start an activity to receive a result, in which case, the activity also returns the result in an Intent (for example, you can issue an intent to let the user pick a personal contact and have it returned to you—the return intent includes a URI pointing to the chosen contact). For broadcast receivers, the intent simply defines the announcement being broadcast (for example, a broadcast to indicate the device battery is low includes only a known action string that indicates "battery is low").
  • 6. The other component type, content provider, is not activated by intents. Rather, it is activated when targeted by a request from a ContentResolver. The content resolver handles all direct transactions with the content provider so that the component that's performing transactions with the provider doesn't need to and instead calls methods on the ContentResolver object. This leaves a layer of abstraction between the content provider and the component requesting information (for security). There are separate methods for activating each type of component: • You can start an activity (or give it something new to do) by passing an Intent to startActivity() or startActivityForResult() (when you want the activity to return a result). • You can start a service (or give new instructions to an ongoing service) by passing an Intent to startService(). Or you can bind to the service by passing an Intent to bindService(). • You can initiate a broadcast by passing an Intent to methods like sendBroadcast(), sendOrderedBroadcast(), or sendStickyBroadcast(). • You can perform a query to a content provider by calling query() on a ContentResolver. For more information about using intents, see the Intents and Intent Filters document. More information about activating specific components is also provided in the following documents: Activities, Services, BroadcastReceiver and Content Providers. The Manifest File Before the Android system can start an app component, the system must know that the component exists by reading the app's AndroidManifest.xml file (the "manifest" file). Your app must declare all its components in this file, which must be at the root of the app project directory. The manifest does a number of things in addition to declaring the app's components, such as: • Identify any user permissions the app requires, such as Internet access or read- access to the user's contacts. • Declare the minimum API Level required by the app, based on which APIs the app uses. • Declare hardware and software features used or required by the app, such as a camera, bluetooth services, or a multitouch screen. • API libraries the app needs to be linked against (other than the Android framework APIs), such as the Google Maps library. • And more Declaring components
  • 7. The primary task of the manifest is to inform the system about the app's components. For example, a manifest file can declare an activity as follows: <?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:icon="@drawable/app_icon.png" ... > <activity android:name="com.example.project.ExampleActivity" android:label="@string/example_label" ... > </activity> ... </application> </manifest> In the <application> element, the android:icon attribute points to resources for an icon that identifies the app. In the <activity> element, the android:name attribute specifies the fully qualified class name of the Activity subclass and the android:label attributes specifies a string to use as the user-visible label for the activity. You must declare all app components this way: • <activity>elements for activities • <service>elements for services • <receiver>elements for broadcast receivers • <provider>elements for content providers Activities, services, and content providers that you include in your source but do not declare in the manifest are not visible to the system and, consequently, can never run. However, broadcast receivers can be either declared in the manifest or created dynamically in code (as BroadcastReceiver objects) and registered with the system by calling registerReceiver(). For more about how to structure the manifest file for your app, see The AndroidManifest.xml File documentation. Declaring component capabilities As discussed above, in Activating Components, you can use an Intent to start activities, services, and broadcast receivers. You can do so by explicitly naming the target component (using the component class name) in the intent. However, the real power of intents lies in the concept of implicit intents. An implicit intent simply describe the type of action to perform (and optionally, the data upon which you’d like to perform the
  • 8. action) and allow the system to find a component on the device that can perform the action and start it. If there are multiple components that can perform the action described by the intent, then the user selects which one to use. The way the system identifies the components that can respond to an intent is by comparing the intent received to the intent filters provided in the manifest file of other apps on the device. When you declare an activity in your app's manifest, you can optionally include intent filters that declare the capabilities of the activity so it can respond to intents from other apps. You can declare an intent filter for your component by adding an <intent-filter> element as a child of the component's declaration element. For example, if you've built an email app with an activity for composing a new email, you can declare an intent filter to respond to "send" intents (in order to send a new email) like this: <manifest ... > ... <application ... > <activity android:name="com.example.project.ComposeEmailActivity"> <intent-filter> <action android:name="android.intent.action.SEND" /> <data android:type="*/*" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application></manifest> Then, if another app creates an intent with the ACTION_SEND action and pass it to startActivity(), the system may start your activity so the user can draft and send an email. For more about creating intent filters, see the Intents and Intent Filters document. Declaring app requirements There are a variety of devices powered by Android and not all of them provide the same features and capabilities. In order to prevent your app from being installed on devices that lack features needed by your app, it's important that you clearly define a profile for the types of devices your app supports by declaring device and software requirements in your manifest file. Most of these declarations are informational only and the system does not read them, but external services such as Google Play do read them in order to provide filtering for users when they search for apps from their device. For example, if your app requires a camera and uses APIs introduced in Android 2.1 (API Level 7), you should declare these as requirements in your manifest file like this: <manifest ... > <uses-feature android:name="android.hardware.camera.any" android:required="true" /> <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" /> ...</manifest> Now, devices that do not have a camera and have an Android version lower than 2.1 cannot install your app from Google Play.
  • 9. However, you can also declare that your app uses the camera, but does not require it. In that case, your app must set the required attribute to "false" and check at runtime whether the device has a camera and disable any camera features as appropriate. More information about how you can manage your app's compatibility with different devices is provided in the Device Compatibility document. App Resources An Android app is composed of more than just code—it requires resources that are separate from the source code, such as images, audio files, and anything relating to the visual presentation of the app. For example, you should define animations, menus, styles, colors, and the layout of activity user interfaces with XML files. Using app resources makes it easy to update various characteristics of your app without modifying code and— by providing sets of alternative resources—enables you to optimize your app for a variety of device configurations (such as different languages and screen sizes). For every resource that you include in your Android project, the SDK build tools define a unique integer ID, which you can use to reference the resource from your app code or from other resources defined in XML. For example, if your app contains an image file named logo.png (saved in the res/drawable/ directory), the SDK tools generate a resource ID named R.drawable.logo, which you can use to reference the image and insert it in your user interface. One of the most important aspects of providing resources separate from your source code is the ability for you to provide alternative resources for different device configurations. For example, by defining UI strings in XML, you can translate the strings into other languages and save those strings in separate files. Then, based on a language qualifier that you append to the resource directory's name (such as res/values-fr/ for French string values) and the user's language setting, the Android system applies the appropriate language strings to your UI. Android supports many different qualifiers for your alternative resources. The qualifier is a short string that you include in the name of your resource directories in order to define the device configuration for which those resources should be used. As another example, you should often create different layouts for your activities, depending on the device's screen orientation and size. For example, when the device screen is in portrait orientation (tall), you might want a layout with buttons to be vertical, but when the screen is in landscape orientation (wide), the buttons should be aligned horizontally. To change the layout depending on the orientation, you can define two different layouts and apply the appropriate qualifier to each layout's directory name. Then, the system automatically applies the appropriate layout depending on the current device orientation.
  • 10. App Components Android's application framework lets you create rich and innovative apps using a set of reusable components. This section explains how you can build the components that define the building blocks of your app and how to connect them together using intents. Activities Quickview • An activity provides a user interface for a single screen in your application • Activities can move into the background and then be resumed with their state restored An Activity is an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map. Each activity is given a window in which to draw its user interface. The window typically fills the screen, but may be smaller than the screen and float on top of other windows. An application usually consists of multiple activities that are loosely bound to each other. Typically, one activity in an application is specified as the "main" activity, which is presented to the user when launching the application for the first time. Each activity can then start another activity in order to perform different actions. Each time a new activity starts, the previous activity is stopped, but the system preserves the activity in a stack (the "back stack"). When a new activity starts, it is pushed onto the back stack and takes user focus. The back stack abides to the basic "last in, first out" stack mechanism, so, when the user is done with the current activity and presses the Back button, it is popped from the stack (and destroyed) and the previous activity resumes. (The back stack is discussed more in the Tasks and Back Stack document.) When an activity is stopped because a new activity starts, it is notified of this change in state through the activity's lifecycle callback methods. There are several callback methods that an activity might receive, due to a change in its state—whether the system is creating it, stopping it, resuming it, or destroying it—and each callback provides you the opportunity to perform specific work that's appropriate to that state change. For instance, when stopped, your activity should release any large objects, such as network or database connections. When the activity resumes, you can reacquire the necessary resources and resume actions that were interrupted. These state transitions are all part of the activity lifecycle. The rest of this document discusses the basics of how to build and use an activity, including a complete discussion of how the activity lifecycle works, so you can properly manage the transition between various activity states. Creating an Activity
  • 11. To create an activity, you must create a subclass of Activity (or an existing subclass of it). In your subclass, you need to implement callback methods that the system calls when the activity transitions between various states of its lifecycle, such as when the activity is being created, stopped, resumed, or destroyed. The two most important callback methods are: onCreate() You must implement this method. The system calls this when creating your activity. Within your implementation, you should initialize the essential components of your activity. Most importantly, this is where you must call setContentView() to define the layout for the activity's user interface. onPause() The system calls this method as the first indication that the user is leaving your activity (though it does not always mean the activity is being destroyed). This is usually where you should commit any changes that should be persisted beyond the current user session (because the user might not come back). There are several other lifecycle callback methods that you should use in order to provide a fluid user experience between activities and handle unexpected interuptions that cause your activity to be stopped and even destroyed. All of the lifecycle callback methods are discussed later, in the section about Managing the Activity Lifecycle. Implementing a user interface The user interface for an activity is provided by a hierarchy of views—objects derived from the View class. Each view controls a particular rectangular space within the activity's window and can respond to user interaction. For example, a view might be a button that initiates an action when the user touches it. Android provides a number of ready-made views that you can use to design and organize your layout. "Widgets" are views that provide a visual (and interactive) elements for the screen, such as a button, text field, checkbox, or just an image. "Layouts" are views derived from ViewGroup that provide a unique layout model for its child views, such as a linear layout, a grid layout, or relative layout. You can also subclass the View and ViewGroup classes (or existing subclasses) to create your own widgets and layouts and apply them to your activity layout. The most common way to define a layout using views is with an XML layout file saved in your application resources. This way, you can maintain the design of your user interface separately from the source code that defines the activity's behavior. You can set the layout as the UI for your activity with setContentView(), passing the resource ID for the layout. However, you can also create new Views in your activity code and build a view hierarchy by inserting new Views into a ViewGroup, then use that layout by passing the root ViewGroup to setContentView(). For information about creating a user interface, see the User Interface documentation. Declaring the activity in the manifest
  • 12. You must declare your activity in the manifest file in order for it to be accessible to the system. To declare your activity, open your manifest file and add an <activity> element as a child of the <application> element. For example: <manifest ... > <application ... > <activity android:name=".ExampleActivity" /> ... </application ... > ...</manifest > There are several other attributes that you can include in this element, to define properties such as the label for the activity, an icon for the activity, or a theme to style the activity's UI. The android:name attribute is the only required attribute—it specifies the class name of the activity. Once you publish your application, you should not change this name, because if you do, you might break some functionality, such as application shortcuts (read the blog post, Things That Cannot Change). See the <activity> element reference for more information about declaring your activity in the manifest. Using intent filters An <activity> element can also specify various intent filters—using the <intent-filter> element—in order to declare how other application components may activate it. When you create a new application using the Android SDK tools, the stub activity that's created for you automatically includes an intent filter that declares the activity responds to the "main" action and should be placed in the "launcher" category. The intent filter looks like this: <activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent- filter></activity> The <action> element specifies that this is the "main" entry point to the application. The <category> element specifies that this activity should be listed in the system's application launcher (to allow users to launch this activity). If you intend for your application to be self-contained and not allow other applications to activate its activities, then you don't need any other intent filters. Only one activity should have the "main" action and "launcher" category, as in the previous example. Activities that you don't want to make available to other applications should have no intent filters and you can start them yourself using explicit intents (as discussed in the following section). However, if you want your activity to respond to implicit intents that are delivered from other applications (and your own), then you must define additional intent filters for your activity. For each type of intent to which you want to respond, you must include an <intent-filter> that includes an <action> element and, optionally, a <category> element and/or a <data> element. These elements specify the type of intent to which your activity can respond.
  • 13. For more information about how your activities can respond to intents, see the Intents and Intent Filters document. Starting an Activity You can start another activity by calling startActivity(), passing it an Intent that describes the activity you want to start. The intent specifies either the exact activity you want to start or describes the type of action you want to perform (and the system selects the appropriate activity for you, which can even be from a different application). An intent can also carry small amounts of data to be used by the activity that is started. When working within your own application, you'll often need to simply launch a known activity. You can do so by creating an intent that explicitly defines the activity you want to start, using the class name. For example, here's how one activity starts another activity named SignInActivity: Intent intent = new Intent(this, SignInActivity.class); startActivity(intent); However, your application might also want to perform some action, such as send an email, text message, or status update, using data from your activity. In this case, your application might not have its own activities to perform such actions, so you can instead leverage the activities provided by other applications on the device, which can perform the actions for you. This is where intents are really valuable—you can create an intent that describes an action you want to perform and the system launches the appropriate activity from another application. If there are multiple activities that can handle the intent, then the user can select which one to use. For example, if you want to allow the user to send an email message, you can create the following intent: Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent); The EXTRA_EMAIL extra added to the intent is a string array of email addresses to which the email should be sent. When an email application responds to this intent, it reads the string array provided in the extra and places them in the "to" field of the email composition form. In this situation, the email application's activity starts and when the user is done, your activity resumes. Starting an activity for a result Sometimes, you might want to receive a result from the activity that you start. In that case, start the activity by calling startActivityForResult() (instead of startActivity()). To then receive the result from the subsequent activity, implement the onActivityResult() callback method. When the subsequent activity is done, it returns a result in an Intent to your onActivityResult() method. For example, perhaps you want the user to pick one of their contacts, so your activity can do something with the information in that contact. Here's how you can create such an
  • 14. intent and handle the result: private void pickContact() { // Create an intent to "pick" a contact, as defined by the content provider URI Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(intent, PICK_CONTACT_REQUEST);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { // If the request went well (OK) and the request was PICK_CONTACT_REQUEST if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { // Perform a query to the contact's content provider for the contact's name Cursor cursor = getContentResolver().query(data.getData(), new String[] {Contacts.DISPLAY_NAME}, null, null, null); if (cursor.moveToFirst()) { // True if the cursor is not empty int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); String name = cursor.getString(columnIndex); // Do something with the selected contact's name... } }} This example shows the basic logic you should use in your onActivityResult() method in order to handle an activity result. The first condition checks whether the request was successful—if it was, then the resultCode will be RESULT_OK—and whether the request to which this result is responding is known—in this case, the requestCode matches the second parameter sent with startActivityForResult(). From there, the code handles the activity result by querying the data returned in an Intent (the data parameter). What happens is, a ContentResolver performs a query against a content provider, which returns a Cursor that allows the queried data to be read. For more information, see the Content Providers document. For more information about using intents, see the Intents and Intent Filters document. Shutting Down an Activity You can shut down an activity by calling its finish() method. You can also shut down a separate activity that you previously started by calling finishActivity(). Note: In most cases, you should not explicitly finish an activity using these methods. As discussed in the following section about the activity lifecycle, the Android system manages the life of an activity for you, so you do not need to finish your own activities. Calling these methods could adversely affect the expected user experience and should only be used when you absolutely do not want the user to return to this instance of the activity. Managing the Activity Lifecycle Managing the lifecycle of your activities by implementing callback methods is crucial to developing a strong and flexible application. The lifecycle of an activity is directly affected by its association with other activities, its task and back stack. An activity can exist in essentially three states:
  • 15. Resumed The activity is in the foreground of the screen and has user focus. (This state is also sometimes referred to as "running".) Paused Another activity is in the foreground and has focus, but this one is still visible. That is, another activity is visible on top of this one and that activity is partially transparent or doesn't cover the entire screen. A paused activity is completely alive (the Activity object is retained in memory, it maintains all state and member information, and remains attached to the window manager), but can be killed by the system in extremely low memory situations. Stopped The activity is completely obscured by another activity (the activity is now in the "background"). A stopped activity is also still alive (the Activity object is retained in memory, it maintains all state and member information, but is not attached to the window manager). However, it is no longer visible to the user and it can be killed by the system when memory is needed elsewhere. If an activity is paused or stopped, the system can drop it from memory either by asking it to finish (calling its finish() method), or simply killing its process. When the activity is opened again (after being finished or killed), it must be created all over. Implementing the lifecycle callbacks When an activity transitions into and out of the different states described above, it is notified through various callback methods. All of the callback methods are hooks that you can override to do appropriate work when the state of your activity changes. The following skeleton activity includes each of the fundamental lifecycle methods: public class ExampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // The activity is being created. } @Override protected void onStart() { super.onStart(); // The activity is about to become visible. } @Override protected void onResume() { super.onResume(); // The activity has become visible (it is now "resumed"). } @Override protected void onPause() { super.onPause(); // Another activity is taking focus (this activity is about to be "paused"). } @Override protected void onStop() { super.onStop(); // The activity is no longer visible (it is now "stopped") } @Override protected void onDestroy() { super.onDestroy(); // The activity is about to be destroyed. }} Note: Your implementation of these lifecycle methods must always call the superclass implementation before doing any work, as shown in the examples above. Taken together, these methods define the entire lifecycle of an activity. By implementing these methods, you can monitor three nested loops in the activity lifecycle: • The entire lifetime of an activity happens between the call to onCreate() and the call to onDestroy(). Your activity should perform setup of "global" state (such as defining layout) in onCreate(), and release all remaining resources in onDestroy(). For example, if your activity has a thread running in the background to download data from the network, it might create that thread in onCreate() and then stop the thread in
  • 16. onDestroy(). The visible lifetime of an activity happens between the call to onStart() and the call to onStop(). During this time, the user can see the activity on-screen and interact with it. For example, onStop() is called when a new activity starts and this one is no longer visible. Between these two methods, you can maintain resources that are needed to show the activity to the user. For example, you can register a BroadcastReceiver in onStart() to monitor changes that impact your UI, and unregister it in onStop() when the user can no longer see what you are displaying. The system might call onStart() and onStop() multiple times during the entire lifetime of the activity, as the activity alternates between being visible and hidden to the user. The foreground lifetime of an activity happens between the call to onResume() and the call to onPause(). During this time, the activity is in front of all other activities on screen and has user input focus. An activity can frequently transition in and out of the foreground—for example, onPause() is called when the device goes to sleep or when a dialog appears. Because this state can transition often, the code in these two methods should be fairly lightweight in order to avoid slow transitions that make the user wait. Figure 1 illustrates these loops and the paths an activity might take between states. The rectangles represent the callback methods you can implement to perform operations when the activity transitions between states.
  • 17.
  • 18. Figure 1. The activity lifecycle. The same lifecycle callback methods are listed in table 1, which describes each of the callback methods in more detail and locates each one within the activity's overall lifecycle, including whether the system can kill the activity after the callback method completes. Table 1. A summary of the activity lifecycle's callback methods. Method Description Killable after? Next onCreate() Called when the activity is first created. This is where you should do all of your normal static set up — create views, bind data to lists, and so on. This method is passed a Bundle object containing the activity's previous state, if that state was captured (see Saving Activity State, later). Always followed by onStart(). No onStart() onRestart() Called after the activity has been stopped, just prior to it being started again. Always followed by onStart() No onStart() onStart() Called just before the activity becomes visible to the user. Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden. No onResume( ) or onStop() onResum e() Called just before the activity starts interacting with the user. At this point the activity is at the top of the activity stack, with user input going to it. Always followed by onPause(). No onPause() onPause() Called when the system is about to start resuming another activity. This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because the next activity will not be resumed until it returns. Followed either by onResume() if the activity returns back to the front, or by onStop() if it Yes onResume( ) or onStop()
  • 19. becomes invisible to the user. onStop() Called when the activity is no longer visible to the user. This may happen because it is being destroyed, or because another activity (either an existing one or a new one) has been resumed and is covering it. Followed either by onRestart() if the activity is coming back to interact with the user, or by onDestroy() if this activity is going away. Yes onRestart() or onDestroy( ) onDestroy() Called before the activity is destroyed. This is the final call that the activity will receive. It could be called either because the activity is finishing (someone called finish() on it), or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method. Yes nothing The column labeled "Killable after?" indicates whether or not the system can kill the process hosting the activity at any time after the method returns, without executing another line of the activity's code. Three methods are marked "yes": (onPause(), onStop(), and onDestroy()). Because onPause() is the first of the three, once the activity is created, onPause() is the last method that's guaranteed to be called before the process can be killed—if the system must recover memory in an emergency, then onStop() and onDestroy() might not be called. Therefore, you should use onPause() to write crucial persistent data (such as user edits) to storage. However, you should be selective about what information must be retained during onPause(), because any blocking procedures in this method block the transition to the next activity and slow the user experience. Methods that are marked "No" in the Killable column protect the process hosting the activity from being killed from the moment they are called. Thus, an activity is killable from the time onPause() returns to the time onResume() is called. It will not again be killable until onPause() is again called and returns. Note: An activity that's not technically "killable" by this definition in table 1 might still be killed by the system—but that would happen only in extreme circumstances when there is no other recourse. When an activity might be killed is discussed more in the Processes and Threading document. Saving activity state The introduction to Managing the Activity Lifecycle briefly mentions that when an activity is paused or stopped, the state of the activity is retained. This is true because the Activity object is still held in memory when it is paused or stopped—all information about its members and current state is still alive. Thus, any changes the user made within the activity are retained so that when the activity returns to the foreground (when it "resumes"), those changes are still there.
  • 20. However, when the system destroys an activity in order to recover memory, the Activity object is destroyed, so the system cannot simply resume it with its state intact. Instead, the system must recreate the Activity object if the user navigates back to it. Yet, the user is unaware that the system destroyed the activity and recreated it and, thus, probably expects the activity to be exactly as it was. In this situation, you can ensure that important information about the activity state is preserved by implementing an additional callback method that allows you to save information about the state of your activity: onSaveInstanceState(). The system calls onSaveInstanceState() before making the activity vulnerable to destruction. The system passes this method a Bundle in which you can save state information about the activity as name-value pairs, using methods such as putString() and putInt(). Then, if the system kills your application process and the user navigates back to your activity, the system recreates the activity and passes the Bundle to both onCreate() and onRestoreInstanceState(). Using either of these methods, you can extract your saved state from the Bundle and restore the activity state. If there is no state information to restore, then the Bundle passed to you is null (which is the case when the activity is created for the first time). Figure 2. The two ways in which an activity returns to user focus with its state intact: either the activity is destroyed, then recreated and the activity must restore the previously saved state, or the activity is stopped, then resumed and the activity state remains intact. Note: There's no guarantee that onSaveInstanceState() will be called before your activity is destroyed, because there are cases in which it won't be necessary to save the state (such
  • 21. as when the user leaves your activity using the Back button, because the user is explicitly closing the activity). If the system calls onSaveInstanceState(), it does so before onStop() and possibly before onPause(). However, even if you do nothing and do not implement onSaveInstanceState(), some of the activity state is restored by the Activity class's default implementation of onSaveInstanceState(). Specifically, the default implementation calls the corresponding onSaveInstanceState() method for every View in the layout, which allows each view to provide information about itself that should be saved. Almost every widget in the Android framework implements this method as appropriate, such that any visible changes to the UI are automatically saved and restored when your activity is recreated. For example, the EditText widget saves any text entered by the user and the CheckBox widget saves whether it's checked or not. The only work required by you is to provide a unique ID (with the android:id attribute) for each widget you want to save its state. If a widget does not have an ID, then the system cannot save its state. You can also explicitly stop a view in your layout from saving its state by setting the android:saveEnabled attribute to "false" or by calling the setSaveEnabled() method. Usually, you should not disable this, but you might if you want to restore the state of the activity UI differently. Although the default implementation of onSaveInstanceState() saves useful information about your activity's UI, you still might need to override it to save additional information. For example, you might need to save member values that changed during the activity's life (which might correlate to values restored in the UI, but the members that hold those UI values are not restored, by default). Because the default implementation of onSaveInstanceState() helps save the state of the UI, if you override the method in order to save additional state information, you should always call the superclass implementation of onSaveInstanceState() before doing any work. Likewise, you should also call the superclass implementation of onRestoreInstanceState() if you override it, so the default implementation can restore view states. Note: Because onSaveInstanceState() is not guaranteed to be called, you should use it only to record the transient state of the activity (the state of the UI)—you should never use it to store persistent data. Instead, you should use onPause() to store persistent data (such as data that should be saved to a database) when the user leaves the activity. A good way to test your application's ability to restore its state is to simply rotate the device so that the screen orientation changes. When the screen orientation changes, the system destroys and recreates the activity in order to apply alternative resources that might be available for the new screen configuration. For this reason alone, it's very important that your activity completely restores its state when it is recreated, because users regularly rotate the screen while using applications. Handling configuration changes Some device configurations can change during runtime (such as screen orientation, keyboard availability, and language). When such a change occurs, Android recreates the
  • 22. running activity (the system calls onDestroy(), then immediately calls onCreate()). This behavior is designed to help your application adapt to new configurations by automatically reloading your application with alternative resources that you've provided (such as different layouts for different screen orientations and sizes). If you properly design your activity to handle a restart due to a screen orientation change and restore the activity state as described above, your application will be more resilient to other unexpected events in the activity lifecycle. The best way to handle such a restart is to save and restore the state of your activity using onSaveInstanceState() and onRestoreInstanceState() (or onCreate()), as discussed in the previous section. For more information about configuration changes that happen at runtime and how you can handle them, read the guide to Handling Runtime Changes. Coordinating activities When one activity starts another, they both experience lifecycle transitions. The first activity pauses and stops (though, it won't stop if it's still visible in the background), while the other activity is created. In case these activities share data saved to disc or elsewhere, it's important to understand that the first activity is not completely stopped before the second one is created. Rather, the process of starting the second one overlaps with the process of stopping the first one. The order of life cycle callbacks is well defined, particularly when the two activities are in the same process and one is starting the other. Here's the order of operations that occur when Activity A starts Acivity B: • Activity A's onPause() method executes. • Activity B's onCreate(), onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.) • Then, if Activity A is no longer visible on screen, its onStop() method executes. This predictable sequence of life cycle callbacks allows you to manage the transition of information from one activity to another. For example, if you must write to a database when the first activity stops so that the following activity can read it, then you should write to the database during onPause() instead of during onStop(). There are three types of Activities :  Fragments A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities).
  • 23.  Loaders Introduced in Android 3.0, loaders make it easy to asynchronously load data in an activity or fragment. Loaders have these characteristics: • They are available to every Activity and Fragment. • They provide asynchronous loading of data. • They monitor the source of their data and deliver new results when the content changes. • They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data.  Task and Back State. An application usually contains multiple activities. Each activity should be designed around a specific kind of action the user can perform and can start other activities. For example, an email application might have one activity to show a list of new email. When the user selects an email, a new activity opens to view that email. Services A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background. A service can essentially take two forms: Started A service is "started" when an application component (such as an activity) starts it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it might download or upload a file over the network. When the operation is done, the service
  • 24. should stop itself. Bound A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed. Although this documentation generally discusses these two types of services separately, your service can work both ways—it can be started (to run indefinitely) and also allow binding. It's simply a matter of whether you implement a couple callback methods: onStartCommand() to allow components to start it and onBind() to allow binding. Regardless of whether your application is started, bound, or both, any application component can use the service (even from a separate application), in the same way that any component can use an activity—by starting it with an Intent. However, you can declare the service as private, in the manifest file, and block access from other applications. This is discussed more in the section about Declaring the service in the manifest. Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities. Content Provider Content providers manage access to a structured set of data. They encapsulate the data, and provide mechanisms for defining data security. Content providers are the standard interface that connects data in one process with code running in another process. When you want to access data in a content provider, you use the ContentResolver object in your application's Context to communicate with the provider as a client. The ContentResolver object communicates with the provider object, an instance of a class that implements ContentProvider. The provider object receives data requests from clients, performs the requested action, and returns the results. You don't need to develop your own provider if you don't intend to share your data with other applications. However, you do need your own provider to provide custom search
  • 25. suggestions in your own application. You also need your own provider if you want to copy and paste complex data or files from your application to other applications. Android itself includes content providers that manage data such as audio, video, images, and personal contact information. You can see some of them listed in the reference documentation for the android.provider package. With some restrictions, these providers are accessible to any Android application. The following topics describe content providers in more detail: Content Provider Basics How to access data in a content provider when the data is organized in tables. Creating a Content Provider How to create your own content provider. Calendar Provider How to access the Calendar Provider that is part of the Android platform. Contacts Provider How to access the Contacts Provider that is part of the Android platform. Intents An Intent is a messaging object you can use to request an action from another app component. Although intents facilitate communication between components in several ways, there are three fundamental use-cases: To start an activity: An Activity represents a single screen in an app. You can start a new instance of an Activity by passing an Intent to startActivity(). The Intent describes the activity to start and carries any necessary data. If you want to receive a result from the activity when it finishes, call
  • 26. startActivityForResult(). Your activity receives the result as a separate Intent object in your activity's onActivityResult() callback. For more information, see the Activities guide. To start a service: A Service is a component that performs operations in the background without a user interface. You can start a service to perform a one-time operation (such as download a file) by passing an Intent to startService(). The Intent describes the service to start and carries any necessary data. If the service is designed with a client-server interface, you can bind to the service from another component by passing an Intent to bindService(). For more information, see the Services guide. To deliver a broadcast: A broadcast is a message that any app can receive. The system delivers various broadcasts for system events, such as when the system boots up or the device starts charging. You can deliver a broadcast to other apps by passing an Intent to sendBroadcast(), sendOrderedBroadcast(), or sendStickyBroadcast(). Intent Types There are two types of intents: • Explicit intentsspecify the component to start by name (the fully-qualified class name). You'll typically use an explicit intent to start a component in your own app, because you know the class name of the activity or service you want to start. For example, start a new activity in response to a user action or start a service to download a file in the background. • Implicit intentsdo not name a specific component, but instead declare a general action to perform, which allows a component from another app to handle it. For example, if you want to show the user a location on a map, you can use an implicit intent to request that another capable app show a specified location on a map. When you create an explicit intent to start an activity or service, the system immediately starts the app component specified in the Intent object.
  • 27. Figure 1. Illustration of how an implicit intent is delivered through the system to start another activity: [1] Activity A creates an Intent with an action description and passes it to startActivity(). [2] The Android System searches all apps for an intent filter that matches the intent. When a match is found, [3] the system starts the matching activity (Activity B) by invoking its onCreate() method and passing it the Intent. When you create an implicit intent, the Android system finds the appropriate component to start by comparing the contents of the intent to the intent filters declared in the manifest file of other apps on the device. If the intent matches an intent filter, the system starts that component and delivers it the Intent object. If multiple intent filters are compatible, the system displays a dialog so the user can pick which app to use. An intent filter is an expression in an app's manifest file that specifies the type of intents that the component would like to receive. For instance, by declaring an intent filter for an activity, you make it possible for other apps to directly start your activity with a certain kind of intent. Likewise, if you do not declare any intent filters for an activity, then it can be started only with an explicit intent. Caution: To ensure your app is secure, always use an explicit intent when starting a Service and do not declare intent filters for your services. Using an implicit intent to start a service is a security hazard because you cannot be certain what service will respond to the intent, and the user cannot see which service starts.
  • 28. Testing Android User Interface User Interface Your app's user interface is everything that the user can see and interact with. Android provides a variety of pre-build UI components such as structured layout objects and UI controls that allow you to build the graphical user interface for your app. Android also provides other UI modules for special interfaces such as dialogs, notifications, and menus UI Overview All user interface elements in an Android app are built using View and ViewGroup objects. A View is an object that draws something on the screen that the user can interact with. A ViewGroup is an object that holds other View (and ViewGroup) objects in order to define the layout of the interface. Android provides a collection of both View and ViewGroup subclasses that offer you common input controls (such as buttons and text fields) and various layout models (such as a linear or relative layout). User Interface Layout The user interface for each component of your app is defined using a hierarchy of View and ViewGroup objects, as shown in figure 1. Each view group is an invisible container that organizes child views, while the child views may be input controls or other widgets that draw some part of the UI. This hierarchy tree can be as simple or complex as you need it to be (but simplicity is best for performance).
  • 29. Figure 1. Illustration of a view hierarchy, which defines a UI layout. To declare your layout, you can instantiate View objects in code and start building a tree, but the easiest and most effective way to define your layout is with an XML file. XML offers a human-readable structure for the layout, similar to HTML. The name of an XML element for a view is respective to the Android class it represents. So a <TextView> element creates a TextView widget in your UI, and a <LinearLayout> element creates a LinearLayout view group. For example, a simple vertical layout with a text view and a button looks like this: <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="I am a Button" /></LinearLayout> When you load a layout resource in your app, Android initializes each node of the layout into a runtime object you can use to define additional behaviors, query the object state, or modify the layout. For a complete guide to creating a UI layout, see XML Layouts. User Interface Components
  • 30. You don't have to build all of your UI using View and ViewGroup objects. Android provides several app components that offer a standard UI layout for which you simply need to define the content. These UI components each have a unique set of APIs that are described in their respective documents, such as Action Bar, Dialogs, and Status Notifications. Layouts A layout defines the visual structure for a user interface, such as the UI for an activity or app widget. You can declare a layout in two ways: Declare UI elements in XML. Android provides a straightforward XML vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts. Instantiate layout elements at runtime. Your application can create View and ViewGroup objects (and manipulate their properties) programmatically. The Android framework gives you the flexibility to use either or both of these methods for declaring and managing your application's UI. For example, you could declare your application's default layouts in XML, including the screen elements that will appear in them and their properties. You could then add code in your application that would modify the state of the screen objects, including those declared in XML, at run time. In general, the XML vocabulary for declaring UI elements closely follows the structure and naming of the classes and methods, where element names correspond to class names and attribute names correspond to methods. In fact, the correspondence is often so direct that you can guess what XML attribute corresponds to a class method, or guess what class corresponds to a given xml element. However, note that not all vocabulary is identical. In some cases, there are slight naming differences. For example, the EditText element has a text attribute that corresponds to EditText.setText(). Tip: Learn more about different layout types in Common Layout Objects. There are also a collection of tutorials on building various layouts in the Hello Views tutorial guide. Write the XML Using Android's XML vocabulary, you can quickly design UI layouts and the screen elements they contain, in the same way you create web pages in HTML — with a series of nested elements. Each layout file must contain exactly one root element, which must be a View or ViewGroup object. Once you've defined the root element, you can add additional layout objects or widgets as child elements to gradually build a View hierarchy that defines your layout. For example, here's an XML layout that uses a vertical LinearLayout to hold a TextView and a Button: <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"
  • 31. android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /></LinearLayout> After you've declared your layout in XML, save the file with the .xml extension, in your Android project's res/layout/ directory, so it will properly compile. More information about the syntax for a layout XML file is available in the Layout Resources document. Load the XML Resource When you compile your application, each XML layout file is compiled into a View resource. You should load the layout resource from your application code, in your Activity.onCreate() callback implementation. Do so by calling setContentView(), passing it the reference to your layout resource in the form of: R.layout.layout_file_name For example, if your XML layout is saved as main_layout.xml, you would load it for your Activity like so: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout);} The onCreate() callback method in your Activity is called by the Android framework when your Activity is launched (see the discussion about lifecycles, in the Activities document). Attributes Every View and ViewGroup object supports their own variety of XML attributes. Some attributes are specific to a View object (for example, TextView supports the textSize attribute), but these attributes are also inherited by any View objects that may extend this class. Some are common to all View objects, because they are inherited from the root View class (like the id attribute). And, other attributes are considered "layout parameters," which are attributes that describe certain layout orientations of the View object, as defined by that object's parent ViewGroup object. ID Any View object may have an integer ID associated with it, to uniquely identify the View within the tree. When the application is compiled, this ID is referenced as an integer, but the ID is typically assigned in the layout XML file as a string, in the id attribute. This is an XML attribute common to all View objects (defined by the View class) and you will use it very often. The syntax for an ID, inside an XML tag is: android:id="@+id/my_button"
  • 32. The at-symbol (@) at the beginning of the string indicates that the XML parser should parse and expand the rest of the ID string and identify it as an ID resource. The plus- symbol (+) means that this is a new resource name that must be created and added to our resources (in the R.java file). There are a number of other ID resources that are offered by the Android framework. When referencing an Android resource ID, you do not need the plus-symbol, but must add the android package namespace, like so: android:id="@android:id/empty" With the android package namespace in place, we're now referencing an ID from the android.R resources class, rather than the local resources class. In order to create views and reference them from the application, a common pattern is to: • Define a view/widget in the layout file and assign it a unique ID: <Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/> • Then create an instance of the view object and capture it from the layout (typically in the onCreate() method): Button myButton = (Button) findViewById(R.id.my_button); Defining IDs for view objects is important when creating a RelativeLayout. In a relative layout, sibling views can define their layout relative to another sibling view, which is referenced by the unique ID. An ID need not be unique throughout the entire tree, but it should be unique within the part of the tree you are searching (which may often be the entire tree, so it's best to be completely unique when possible). Layout Parameters XML layout attributes named layout_something define layout parameters for the View that are appropriate for the ViewGroup in which it resides. Every ViewGroup class implements a nested class that extends ViewGroup.LayoutParams. This subclass contains property types that define the size and position for each child view, as appropriate for the view group. As you can see in figure 1, the parent view group defines layout parameters for each child view (including the child view group).
  • 33. Figure 1. Visualization of a view hierarchy with layout parameters associated with each view. Note that every LayoutParams subclass has its own syntax for setting values. Each child element must define LayoutParams that are appropriate for its parent, though it may also define different LayoutParams for its own children. All view groups include a width and height (layout_width and layout_height), and each view is required to define them. Many LayoutParams also include optional margins and borders. You can specify width and height with exact measurements, though you probably won't want to do this often. More often, you will use one of these constants to set the width or height: • wrap_contenttells your view to size itself to the dimensions required by its content • fill_parent(renamed match_parent in API Level 8) tells your view to become as big as its parent view group will allow. In general, specifying a layout width and height using absolute units such as pixels is not recommended. Instead, using relative measurements such as density-independent pixel units (dp), wrap_content, or fill_parent, is a better approach, because it helps ensure that your application will display properly across a variety of device screen sizes. The accepted measurement types are defined in the Available Resources document.
  • 34. Layout Position The geometry of a view is that of a rectangle. A view has a location, expressed as a pair of left and top coordinates, and two dimensions, expressed as a width and a height. The unit for location and dimensions is the pixel. It is possible to retrieve the location of a view by invoking the methods getLeft() and getTop(). The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. For instance, when getLeft() returns 20, that means the view is located 20 pixels to the right of the left edge of its direct parent. In addition, several convenience methods are offered to avoid unnecessary computations, namely getRight() and getBottom(). These methods return the coordinates of the right and bottom edges of the rectangle representing the view. For instance, calling getRight() is similar to the following computation: getLeft() + getWidth(). Size, Padding and Margins The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values. The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent. The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight(). The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight(). To measure its dimensions, a view takes into account its padding. The padding is expressed in pixels for the left, top, right and bottom parts of the view. Padding can be used to offset the content of the view by a specific amount of pixels. For instance, a left padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding can be set using the setPadding(int, int, int, int) method and queried by calling getPaddingLeft(), getPaddingTop(), getPaddingRight() and getPaddingBottom(). Even though a view can define a padding, it does not provide any support for margins. However, view groups provide such a support. Refer to ViewGroup and ViewGroup.MarginLayoutParams for further information. For more information about dimensions, see Dimension Values. Common Layouts Each subclass of the ViewGroup class provides a unique way to display the views you nest within it. Below are some of the more common layout types that are built into the
  • 35. Android platform. Note: Although you can nest one or more layouts within another layout to acheive your UI design, you should strive to keep your layout hierarchy as shallow as possible. Your layout draws faster if it has fewer nested layouts (a wide view hierarchy is better than a deep view hierarchy). Linear Layout 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. Relative Layout Enables you to specify the location of child objects relative to each other (child A to the left of child B) or to the parent (aligned to the top of the parent). Web View Displays web pages. Building Layouts with an Adapter When the content for your layout is dynamic or not pre-determined, you can use a layout that subclasses AdapterView to populate the layout with views at runtime. A subclass of the AdapterView class uses an Adapter to bind data to its layout. The Adapter behaves as
  • 36. a middle-man between the data source and the AdapterView layout—the Adapter retrieves the data (from a source such as an array or a database query) and converts each entry into a view that can be added into the AdapterView layout. Common layouts backed by an adapter include: List View Displays a scrolling single column list. Grid View Displays a scrolling grid of columns and rows. Filling an adapter view with data You can populate an AdapterView such as ListView or GridView by binding the AdapterView instance to an Adapter, which retrieves data from an external source and creates a View that represents each data entry. Android provides several subclasses of Adapter that are useful for retrieving different kinds of data and building views for an AdapterView. The two most common adapters are: ArrayAdapter Use this adapter when your data source is an array. By default, ArrayAdapter creates a view for each array item by calling toString() on each item and placing the contents in a TextView. For example, if you have an array of strings you want to display in a ListView, initialize a new ArrayAdapter using a constructor to specify the layout for each string and the string array: ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray); The arguments for this constructor are:
  • 37. o Your app Context o The layout that contains a TextView for each string in the array o The string array Then simply call setAdapter() on your ListView: ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter); To customize the appearance of each item you can override the toString() method for the objects in your array. Or, to create a view for each item that's something other than a TextView (for example, if you want an ImageView for each array item), extend the ArrayAdapter class and override getView() to return the type of view you want for each item. SimpleCursorAdapter Use this adapter when your data comes from a Cursor. When using SimpleCursorAdapter, you must specify a layout to use for each row in the Cursor and which columns in the Cursor should be inserted into which views of the layout. For example, if you want to create a list of people's names and phone numbers, you can perform a query that returns a Cursor containing a row for each person and columns for the names and numbers. You then create a string array specifying which columns from the Cursor you want in the layout for each result and an integer array specifying the corresponding views that each column should be placed: String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};int[] toViews = {R.id.display_name, R.id.phone_number}; When you instantiate the SimpleCursorAdapter, pass the layout to use for each result, the Cursor containing the results, and these two arrays: SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);ListView listView = getListView(); listView.setAdapter(adapter); The SimpleCursorAdapter then creates a view for each row in the Cursor using the provided layout by inserting each fromColumns item into the corresponding toViews view. If, during the course of your application's life, you change the underlying data that is read by your adapter, you should call notifyDataSetChanged(). This will notify the attached view that the data has been changed and it should refresh itself. Handling click events
  • 38. You can respond to click events on each item in an AdapterView by implementing the AdapterView.OnItemClickListener interface. For example: // 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) { // Do something in response to the click }}; listView.setOnItemClickListener(mMessageClickedHandler); Linear Layout LinearLayout is a view group that aligns all children in a single direction, vertically or horizontally. You can specify the layout direction with the android:orientation attribute. All children of a LinearLayout are stacked one after the other, so a vertical list will only have one child per row, no matter how wide they are, and a horizontal list will only be one row high (the height of the tallest child, plus padding). A LinearLayout respects margins between children and the gravity (right, center, or left alignment) of each child. Layout Weight
  • 39. LinearLayout also supports assigning a weight to individual children with the android:layout_weight attribute. This attribute assigns an "importance" value to a view in terms of how much space is should occupy on the screen. A larger weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero. For example, if there are three text fields and two of them declare a weight of 1, while the other is given no weight, the third text field without weight will not grow and will only occupy the area required by its content. The other two will expand equally to fill the space remaining after all three fields are measured. If the third field is then given a weight of 2 (instead of 0), then it is now declared more important than both the others, so it gets half the total remaining space, while the first two share the rest equally. Example <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="16dp" android:paddingRight="16dp" android:orientation="vertical" > <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/to" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/subject" /> <EditText android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="top" android:hint="@string/message" /> <Button android:layout_width="100dp" android:layout_height="wrap_content" android:layout_gravity="right" android:text="@string/send" /></LinearLayout>
  • 40. Relative Layout RelativeLayout is a view group that displays child views in relative positions. The position of each view can be specified as relative to sibling elements (such as to the left-of or below another view) or in positions relative to the parent RelativeLayout area (such as aligned to the bottom, left of center). A RelativeLayout is a very powerful utility for designing a user interface because it can eliminate nested view groups and keep your layout hierarchy flat, which improves performance. If you find yourself using several nested LinearLayout groups, you may be able to replace them with a single RelativeLayout. Positioning Views
  • 41. RelativeLayout lets child views specify their position relative to the parent view or to each other (specified by ID). So you can align two elements by right border, or make one below another, centered in the screen, centered left, and so on. By default, all child views are drawn at the top-left of the layout, so you must define the position of each view using the various layout properties available from RelativeLayout.LayoutParams. Some of the many layout properties available to views in a RelativeLayout include: android:layout_alignParentTop If "true", makes the top edge of this view match the top edge of the parent. android:layout_centerVertical If "true", centers this child vertically within its parent. android:layout_below Positions the top edge of this view below the view specified with a resource ID. android:layout_toRightOf Positions the left edge of this view to the right of the view specified with a resource ID. These are just a few examples. All layout attributes are documented at RelativeLayout.LayoutParams. The value for each layout property is either a boolean to enable a layout position relative to the parent RelativeLayout or an ID that references another view in the layout against which the view should be positioned. In your XML layout, dependencies against other views in the layout can be declared in any order. For example, you can declare that "view1" be positioned below "view2" even if "view2" is the last view declared in the hierarchy. The example below demonstrates such a scenario. Example Each of the attributes that control the relative position of each view are emphasized. <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="16dp" android:paddingRight="16dp" > <EditText android:id="@+id/name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/reminder" /> <Spinner android:id="@+id/dates" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_below="@id/name" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/times" /> <Spinner android:id="@id/times" android:layout_width="96dp" android:layout_height="wrap_content" android:layout_below="@id/name" android:layout_alignParentRight="true" /> <Button android:layout_width="96dp" android:layout_height="wrap_content" android:layout_below="@id/times" android:layout_alignParentRight="true"
  • 42. android:text="@string/done" /></RelativeLayout> List View ListView is a view group that displays a list of scrollable items. The list items are automatically inserted to the list using an Adapter that pulls content from a source such as an array or database query and converts each item result into a view that's placed into the list. For an introduction to how you can dynamically insert views using an adapter, read Building Layouts with an Adapter. Grid View GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid. The grid items are automatically inserted to the layout using a ListAdapter. For an introduction to how you can dynamically insert views using an adapter, read Building Layouts with an Adapter. Hierarchy Viewer Hierarchy Viewer allows you to debug and optimize your user interface. It provides a visual representation of the layout's View hierarchy (the Layout View) and a magnified inspector of the display (the Pixel Perfect View). To start Hierarchy Viewer, enter the following command from the SDK tools/ directory: Widget Widgets are an essential aspect of home screen customization. You can imagine them as "at-a-glance" views of an app's most important data and functionality that is accessible right from the user's home screen. Users can move widgets across their home screen
  • 43. panels, and, if supported, resize them to tailor the amount of information within a widget to their preference. Widget types As you begin planning your widget, think about what kind of widget you're trying to build. Widgets typically fall into one of the following categories: Information widgets Information widgets typically display a few crucial information elements that are important to a user and track how that information changes over time. Good examples for information widgets are weather widgets, clock widgets or sports score trackers. Touching information widgets typically launches the associated app and opens a detail view of the widget information. Collection widgets As the name implies, collection widgets specialize in displaying multitude elements of the same type, such as a collection of pictures from a gallery app, a collection of articles from a news app or a collection of emails/messages from a communication app. Collection widgets typically focus on two use cases: browsing the collection, and opening an element of the collection to its detail view for consumption. Collection widgets can scroll vertically. ListView widget GridView widget Control widgets
  • 44. The main purpose of a control widget is to display often used functions that the user can trigger right from the home screen without having to open the app first. Think of them as remote controls for an app. A typical example of control widgets are music app widgets that allow the user to play, pause or skip music tracks from outside the actual music app. Interacting with control widgets may or may not progress to an associated detail view depending on if the control widget's function generated a data set, such as in the case of a search widget. Hybrid widgets While all widgets tend to gravitate towards one of the three types described above, many widgets in reality are hybrids that combine elements of different types. For the purpose of your widget planning, center your widget around one of the base types and add elements of other types if needed. A music player widget is primarily a control widget, but also keeps the user informed about what track is currently playing. It essentially combines a control widget with elements of an information widget type. Widget limitations While widgets could be understood as "mini apps", there are certain limitations that are important to understand before you start to embark on designing your widget: Gestures Because widgets live on the home screen, they have to co-exist with the navigation that is established there. This limits the gesture support that is available in a widget compared to a full-screen app. While apps for example may support a view pager that allows the user to navigate between screens laterally, that gesture is already taken on the home screen for the purpose of navigating between home panels. The only gestures available for widgets are:
  • 45. • Touch • Vertical swipe Elements Given the above interaction limitations, some of the UI building blocks that rely on restricted gestures are not available for widgets. For a complete list of supported building blocks and more information on layout restrictions, please refer to the "Creating App Widget Layouts" section in the App Widgets API Guide. Design guidelines Widget content Widgets are a great mechanism to attract a user to your app by "advertising" new and interesting content that is available for consumption in your app. Just like the teasers on the front page of a newspaper, widgets should consolidate and concentrate an app's information and then provide a connection to richer detail within the
  • 46. app; or in other words: the widget is the information "snack" while the app is the "meal." As a bottom line, always make sure that your app shows more detail about an information item than what the widget already displays. Widget navigation Besides the pure information content, you should also consider to round out your widget's offering by providing navigation links to frequently used areas of your app. This lets users complete tasks quicker and extends the functional reach of the app to the home screen. Good candidates for navigation links to surface on widgets are: • Generative functions: These are the functions that allow the user to create new content for an app, such as creating a new document or a new message. • Open application at top level: Tapping on an information element will usually navigate the user to a lower level detail screen. Providing access to the top level of your application provides more navigation flexibility and can replace a dedicated app shortcut that users would otherwise use to navigate to the app from the home screen. Using your application icon as an affordance can also provide your widget with a clear identity in case the data you're displaying is ambiguous. Widget resizing With version 3.1, Android introduced resizable widgets to the platform. Resizing allows users to adjust the height and/or the width of a widget within the constraints of the home panel placement grid. You can decide if your widget is freely resizable or if it is constrained to horizontal or vertical size changes. You do not have to support resizing if your particular widget is inherently fixed-size. Allowing users to resize widgets has important benefits: • They can fine-tune how much information they want to see on each widget. • They can better influence the layout of widgets and shortcuts on their home panels.
  • 47. A long press and subsequent release sets resizable widgets into resize mode. Users can use the drag handles or the widget corners to set the desired size. Planning a resize strategy for your widget depends on the type of widget you're creating. List or grid-based collection widgets are usually straightforward because resizing the widget will simply expand or contract the vertical scrolling area. Regardless of the of the widget's size, the user can still scroll all information elements into view. Information widgets on the other hand require a bit more hands-on planning, since they are not scrollable and all content has to fit within a given size. You will have to dynamically adjust your widget's content and layout to the size the user defined through the resize operation. In this simple example the user can horizontally resize a weather widget in 4 steps and expose richer information about the weather at the current location as the widget grows. For each widget size determine how much of your app's information should surface. For smaller sizes concentrate on the essential and then add more contextual information as the widget grows horizontally and vertically. Layout considerations
  • 48. It will be tempting to layout your widgets according to the dimensions of the placement grid of a particular device that you own and develop with. This can be a useful initial approximation as you layout your widget, but keep the following in mind: • The number, size and spacing of cells can vary widely from device to device, and hence it is very important that your widget is flexible and can accommodate more or less space than anticipated. • In fact, as the user resizes a widget, the system will respond with a dp size range in which your widget can redraw itself. Planning your widget resizing strategy across "size buckets" rather than variable grid dimensions will give you the most reliable results. Widget configuration Sometimes widgets need to be setup before they can become useful. Think of an email widget for example, where you need to provide an account before the inbox can be displayed. Or a static photo widget where the user has to assign the picture that is to be displayed from the gallery. Android widgets display their configuration choices right after the widget is dropped onto a home panel. Keep the widget configuration light and don't present more than 2-3 configuration elements. Use dialog-style instead of full-screen activities to present configuration choices and retain the user's context of place, even if doing so requires use of multiple dialogs. Once setup, there typically is not a lot of reason to revisit the setup. Therefore Android widgets do not show a "Setup" or "Configuration" button. After adding a Play widget to a home panel, the widget asks the user to specify the type of media the widget should display. Checklist • Focus on small portions of glanceable information on your widget. Expand on the information in your app. • Choose the right widget type for your purpose. • For resizable widgets, plan how the content for your widget should adapt to different sizes. • Make your widget orientation and device independent by ensuring that the layout is capable of stretching and contracting. UI Event
  • 49. On Android, there's more than one way to intercept the events from a user's interaction with your application. When considering events within your user interface, the approach is to capture the events from the specific View object that the user interacts with. The View class provides the means to do so. Within the various View classes that you'll use to compose your layout, you may notice several public callback methods that look useful for UI events. These methods are called by the Android framework when the respective action occurs on that object. For instance, when a View (such as a Button) is touched, the onTouchEvent() method is called on that object. However, in order to intercept this, you must extend the class and override the method. However, extending every View object in order to handle such an event would not be practical. This is why the View class also contains a collection of nested interfaces with callbacks that you can much more easily define. These interfaces, called event listeners, are your ticket to capturing the user interaction with your UI. While you will more commonly use the event listeners to listen for user interaction, there may come a time when you do want to extend a View class, in order to build a custom component. Perhaps you want to extend the Button class to make something more fancy. In this case, you'll be able to define the default event behaviors for your class using the class event handlers. Adapter An Adapter object acts as a bridge between an AdapterView and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View for each item in the data set.