1
Application Components and Lifecycle
Application Components
An Android application consists of
components that are coupled together;
each component can
be the entry point in your application, rather than having
one single entry point for everything in
th
e application (like the
main()
function for C/C++/Java)
.
The building blocks for your
application are provided by the following components:
Activities
.
An Activity is usually
one
screen of your application
, hence there could be
one or more Activities
per
application
. I
t represents the user interface, the application’s
presentation layer.
To display information and
respond to user
actions, Activities use
Views
to form the
graphical user interface.
The transition between Activities is done by
having one Acti
vity starting the next one.
Services
.
A Service is a compon
ent that runs in the background, thus not having a visual
user interface.
Because of this, it will not interact with the user, but rather it will
do some
work silently, invisibly
,
for you.
They ar
e used to
perform regular
processing
that needs
to continue
even when your application
’s Activities are
not active or visible.
As an
e
xample, a Service might
fetch data over the network
,
in
the background, while the user
normally interacts with the applica
tion.
Content Providers
.
When you want
specific data to b
e
available to other applications,
y
ou will use a Content Provider.
The data can be stored in a SQLite database, or in a File
,
and you can configure your own Content Provider to permit access to tha
t data.
For
example, on an Android phone, there is a specific Content Provider to access the contact
information.
Broadcast Receivers
.
A Broadcast Receiver
receives and reacts to
broadcast messages.
When you
have an event
-
driven environment, and you have
to
be able to listen for events
and
act in response, then you will register
a Broadcast Receiver
to listen for events that
match a
specific filter criteria
, and execute the desired action afterwards.
Intents
.
Intents
, or
asynchronous
messages
,
are used to
s
pecify what intentions you have
in terms of a specific action being performed
; mainly,
you use them to activate
other
components of your application.
The content of the message,
for activities and services,
names the action being requested, and specifies
the URI of the data to act on, among
other things.
Android Manifest File
(taken from
Professional Android Application
Development
)
All these components are bound together
using a project manifest
that describes each component
and how they interact.
The
re is one manifest file per application, called
AndroidManifest.xml
.
It includes nodes for each of the components (Activities, Services,
Content Providers, and Broadcast
Receivers) that make up your application and, using Intent
Filters and Permissions, de
termines how
they interact with each other and other applications.
It
also offers attributes to specify application metadata (like its icon or theme), and additional top
-
level
nodes can be used for security settings and unit tests as described below.
2
The
manifest is made up of a root manifest tag with a package attribute set to the project’s
package.
It usually includes an
xmlns:android
attribute that supplies several system attributes
used within the
fi
le. A typical manifest node is shown in the XML snipp
et below:
<manifest
x
mlns:android=http://schemas.android.com/apk/res/android
package=”com.my_domain.my_app”>
[ ... manifest nodes ... ]
</manifest>
The
manife
st
tag includes nodes that defi
ne the application components, security settings, and
test
cla
sses that make up your application. The following list gives a summary of the available
manifest
node tags, and an XML snippet demonstrating how each one is used:
application
A manifest can contain only one application node. It uses
attributes
to
specif
y
the metadata for your application (including its title, icon, and theme). It also acts
as a container
that includes the Activity, Service, Content Provider, and Broadcast
Receiver tags used to specify
the application components.
<application android
:icon=”@drawable/icon”
android:theme=”@style/my_theme”>
[ ... application nodes ... ]
</application>
activity
An
activity
tag is required for every Activity displayed by your
application,
using the
android:name
attribute to spe
cify the class name. This must
include the
main launch Activity and any other screen or dialogs that can be displayed.
Trying to
st
art an Activity that’s not defi
ned in the manifest will throw a runtime
exception. Each
Activity node supports
intent
-
filter
child tags that specify which
Intents launch the
Activity.
<activity
android:name=”.MyActivity”
android:label=”@string/app_name”>
<intent
-
filter>
<action android:name=”android.intent.action.MAIN” />
<category
android:name=”android.intent.categor
y.LAUNCHER” />
</intent
-
filter>
</activity>
service
As with the
activity
tag, create a new
service
tag for each Service class
used in your application. Service tags also
support
intent
-
filter
child tags to allow
late runtime binding.
<service andro
id:enabled=”true” android:name=”.MyService”></service>
provider
Provider tags are used for each of your application’s Content Providers.
Content Providers are used to manage database access and sharing within and between
applications.
3
<provider
android
:permission=”
package
.MY_PERMISSION”
android:name=”.MyContentProvider”
android:enabled=”true”
android:authorities=”
package
.myapp.MyContentProvider”>
</provider>
receiver
By adding a
receiver
tag, you can
register a Broadcast Receiver without
havin
g to launch your application fi
rst. Broadcast Receivers
are like global event listeners
that, once registered, will execute whenever a matching
Intent is broadcast by an
application. By registering a Broadcast Re
ceiver in the manifest,
you can make this
process entirely autonomous. If a matching Intent is broadcast,
your application will be
started automatically and the registered Broadcast Receiver
will be
run.
<receiver android:enabled=”true”
android:
label=”My Broadcast Receiver”
android:name=”.MyBroadcastReceiver”>
</receiver>
uses
-
permission
As part of the security model,
uses
-
permission
tags declare the
p
ermissions
you’ve determined that your application needs for it to operate properl
y. The
permissions
you include will be presented to the user, to grant or deny, during
installation. Permissions
are required for many of the native Android services,
particularly those with a cost or security
implication (such as dialing, receiving SMS, o
r
using the location
-
based services). As shown
in the item below, third
-
party applications,
including your own, can also specify permissions
before providing access to shared
application components.
<uses
-
permission android:name=”android.permission.ACCESS
_LOCATION”>
</uses
-
permission>
permission
Before you can restrict access to an applicat
ion component, you need to
defi
ne
a permission in the manifest. Use the
permission
tag
to create these permission
defi
nitions.
Application components can then require
them by adding the
android:permission
attribute.
Other applications will then need to include a
uses
-
permission
tag in their manifests (and
have it granted) before they can use these
protected components.
Within the
permission
tag, you can specify the
level of access the permission will
permit
(
normal
,
dangerous
,
signature
,
signatureOrSystem
), a label, and an
external
resource
containing the description that explain the risks of granting this
permission.
<permission android:name=”
package
.DETONATE_
DEVICE”
android:protectionLevel=”dangerous”
android:label=”Self Destruct”
android:description=”@string/detonate_description”>
</permission>
4
instrumentation
Instrumentation classes provide a framework for
running tests on
your
Activities and Services at run time. They provide hooks to monitor your application
and its
interaction with the system resources. Create a new node for each of the test
classes you’ve created
for your application.
<instrumentation a
ndroid:label=”My Test”
android:name=”.MyTestClass”
android:targetPackage=”
package
.aPackage”>
</instrumentation>
A more detailed description of the manifest and each of these nodes can be found at
http://code.google.com/android/devel/bblocks
-
manifest.html
The ADT New Project Wizard automati
cally creates a new manifest fi
le when it creates a new
project.
Activities
An activity is a single, focused thing that the user ca
n do. Almost all activities interact with the
user, so the Activity class takes care of creating a window for you in which you can place your
UI with
setContentView(View)
. While activities are often presented to the user as full
-
screen
windows, they can also be used in other ways: as floating windows (via a theme with
windowIsFloating
set) or embedded inside of another activity (using
ActivityGroup
). There are
two methods almost all subclasses of Activity w
ill implement:
onCreate(Bundle)
is where you initialize your activity. Most importantly, here you will
usually call
setContentView(int)
with a layout resource defining your UI, and using
findViewById(int)
to retrieve the widgets in that UI that you need to interact with
programmatically.
onPause()
is where you deal with the use
r leaving your activity. Most importantly, any
changes made by the user should at this point be committed (usually to the
ContentProvider
holding the data).
To be
of use with
Context.startActivity()
, all activity classes must have a corresponding
<activity>
declaration in their package's
AndroidManifest.xml
.
(Taken from
http://developer.android.com/re
ference/android/app/Activity.html
)
For our Sudoku application, lets us look at how the main activity looks like:
package
org.example.sudoku;
import
android.app.Activity;
public
class
Sudoku
extends
Activity
{
/**
Called
when
the
activity
is
first
created.
*/
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
5
//
Set the content view
…
}
@Override
protected
void
onResume() {
super
.onResume();
//
S
tart the music
}
@Override
protected
void
onPause() {
super
.onPause();
//
Stop the music
}
}
At this stage of the course, you do not need to understand all the elements in the code.
We will
cover them as we go through
other modul
es.
Let us examine
, at a high level,
our main a
ctivity,
Sudoku, piece by piece:
package
org.example.sudoku;
import
android.app.Activity;
The package declaration is the same as the one used when creating the project in Eclipse.
Any
classes that w
e refer
ence need to be imported, hence all the import statements
general to any
other Java project, but specific in terms of the actual classes imported.
Most of the Android
-
specific classes are
in the
android
package.
public
class
Sudoku
extends
Activity {
Ac
tivities are classes inheriting from the
android.app.Activity
base class.
These implies
that all the (public and protected) method
s
from the base c
l
a
ss are vis
ible in our own activity
class
.
/**
Called
when
the
activity
is
first
created.
*/
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
//
Set the content view
…
}
The method that is being called when our activity is first created is
onCreate
.
The first thing we
do is
chain up
to the sup
erclass so as to make sure that
the Android
activity
initialization
is done.
@Override
protected
void
onResume() {
6
super
.onResume();
//
Start the music
}
@Override
protected
void
onPause() {
super
.onPause();
//
Stop the music
}
Since our end application will also involve music, in the two methods above (which are
explained in more details in the next sections), we
start and stop the music.
The main methods of our Sudoku
Activity are
onCreate
,
onPause
,
o
nResume
(other will also
be mentioned later).
To understand when each method is b
eing called, it is important to
understand
the Activity lifecycle shown
in Figure
4.1
.
7
Figure 4.
1
Activity Lifecycle State Diagram
Activities are managed
as an activity
stack (a LIFO collection).
An Activity has four possible
states
:
Running
: activity is in the foreground
Paused
: activity has lost focus but it is still visible
Stopped
: activity is not visible (completely obscured by another activity)
Inactive
: activity h
as not been launched yet or has been killed.
There are three key loops you may be interested in monitoring within your activity:
The
entire lifetime
of an activity happens between the first call to
onCreate(Bundle)
through to a single final call to
onDestroy()
. An activity will do all setup
of "global" state
in onCreate(), and release all remaining resources in onDestroy(). For example, if it has a
thread running in the background to download data from the network, it may create that
thread in onCreate() and then stop the thread in onDestroy
().
8
The
visible lifetime
of an activity happens between a call to
onStart()
until a
corresponding call to
onStop()
. During this time the user can see the activity on
-
screen,
though it may not be in the foreground and interacting with the user. 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 for changes that
impact your UI, and unregister it in
onStop() when the user an no longer see what you are
displaying. The onStart() and onStop() methods can be called multiple times, as the
activity becomes visible and hidden to the user.
The
foreground lifetime
of an activity happens between a call to
onResume()
until a
corresponding call to
onPause()
. During
this time the activity is in front of all other
activities and interacting with the user. An activity can frequently go between the
resumed and paused states
--
for example when the device goes to sleep, when an activity
result is delivered, when a new in
tent is delivered
--
so the code in these methods should
be fairly lightweight.
In general the movement through an activity's lifecycle looks like this:
Method
Description
Killable?
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, etc.
This method also provides you with
a Bundle contai
ning the activity's
previously frozen state, if there was
one.
Always followed by
onStart()
.
No
onStart()
onRestart()
Called after your activity ha
s been
stopped, prior to it being started
again.
Always followed by
onStart()
No
onStart()
onStart()
Called when the activity is
becoming visible to the
user.
Followed by
onResume()
if the
activity comes to the foreground, or
onStop()
if it becomes hidden.
No
onResume()
or
onStop()
onResume()
Called
when the activity will start
interacting with the user. At this
point your activity is at the top of
the activity stack, with user input
going to it.
No
onPause()
9
Method
Description
Killable?
Next
Always followed by
onPause()
.
onPause()
Called when the system is about to
start resuming a previous activity.
This is typically used to commit
unsaved changes to persistent data,
stop animations and other things
that may be consuming CPU, etc.
Implementations of this method
must be very quick because the next
activity will not be resumed until
this method returns.
Followed by either
onResume()
if
the activity returns back to the
front, or
onStop()
if it becomes
invisible to the user.
Yes
onRes
ume()
or
onStop()
onStop()
Called when the activity is no
longer visible to the user, because
another activity has been resumed
and is covering this one. T
his may
happen either because a new
activity is being started, an existing
one is being brought in front of this
one, or this one is being destroyed.
Followed by either
onRestart()
if
this activity is coming back to
interact with the user, or
onDestroy()
if this activity is
going away.
Yes
onRestart()
or
onDestroy()
onDestroy()
The final call you receive before
your activity is destroyed. This can
happen
either because the activity is
finishing (someone called
finish()
on it, or because the system is
temporarily destroying this instance
of the activity to sav
e space. You
can distinguish between these two
scenarios with the
isFinishing()
method.
Yes
nothing
Note the "Killable" column in the above table
--
f
or those methods that are marked as being
killable, after that method returns the process hosting the activity may killed by the system
at any
10
time
without another line of its code being executed. Because of this, you should use the
onPause()
method to write any persistent data (such as user edits) to storage. In addition, the
method
onSaveInstanceState(Bundle)
is called before placing the activity in such a background
state, allowing you to save away any dynamic instance state in your activity into the given
Bundle, to be later rece
ived in
onCreate(Bundle)
if the activity needs to be re
-
created. See the
Process Lifecycle
section for more information on how the lifecycle of a process is tied to the
activities it is hosting. Note that it is important to save persistent data in
onPause()
instead of
onSaveInstanceState(Bundle)
because the later is
not part of the lifecycle callbacks, so will not
be called in every situation as described in its documentation.
For those methods that are not marked as being killable, the activity's process will not be killed
by the system starting from the time the met
hod is called and continuing after it returns. Thus an
activity is in the killable state, for example, between after
onPause()
to the start of
onResume()
.
(Taken from
http://d
eveloper.android.com/reference/android/app/Activity.html
)
Looking at our Sudoku example, we will go through
some
screens where t
he menu is being
displayed,
the user chooses the option to
find out more about the game
, goes back to the main
menu, and choos
es to start a new game
.
When the application is being started, the first screen is
the one shown
in Figure 4.
2
below:
Figure 4.
2
Main Screen for our Sudoku application
11
This actually represents the Sudoku Activity which code was presented previously. Wh
en this
Activity is first started, the
onCreate
,
onStart
, and
onResume
methods are called in this
order.
When the user choose the “
About
” option (by pressing the respective button),
the About
Activity is being started from inside the Sudoku Ac
tivity:
F
igure
1
.3
Provides more in
formation about the Sudoku game
At this point, the
onPause
method of our
Sudoku Activity
is being called because another
activity
(the About Activity) came in front of it.
If we press the back
button of t
he phone, the
screen in
Figure 4.2
reappears and the
onResume
method o
f the Sudoku Activity is called since
our activity
is still visible but has lost focus. If we were to actually start a new game
(by pressing
the “New Game” button)
, our Sudoku Activity w
ould no longer be visible to the user (as shown
in Figure 4
.4
), thus the
onStop
method would get called.
12
Figure 4.
4
The Game screen for our Sudoku application
Since each activity is hosted separately by a process, it is worth mentioning the process
li
fecycle
.
To free up resources, processes are being killed based on their priority:
Critical Priority
: foreground (active) processes
–
Foreground activities; components that execute an
onReceive
event handler;
services that are executing an
onStart
,
onCreate
,
or
onDestroy
event handler.
High Priority
: visible (inactive) processes and started service processes
–
Partially obscured activity (lost focus); services started.
Low Priority
: background processes
–
Activities that are not visible; activities with no start
ed service
You can find
out more about Activities by visiting the web address below:
http://developer.android.com/reference/android/app/Activity.html
Intents
Three of the
core components of an application
—
activities, services, and broadcast receivers
—
are activated through messages, called
intents
. Intent messaging is a facility for late run
-
time
binding between components in the same or different applications. The inte
nt itself, an
Intent
object, is a passive data structure holding an abstract description of an operation to be performed
13
—
or, in the case of broadcasts, a description of so
mething that has happened and is being
announced. There are separate mechanisms for delivering intents to each type of component:
An Intent object is passed to
Context.startActivity()
or
Activity.startActivityForResult()
to launch an ac
tivity or get an existing activity
to do something new.
An Intent object is passed to
Context.startService()
to initiate a ser
vice or deliver
new instructions to an ongoing service. Similarly, an intent can be passed to
Context.bindService()
to establish a connection between the calling component and a
target service. It can optionally initiate the service if it's not already running.
Intent objects passed to any of the broadcast methods (such as
Context.sendBroadcast()
,
Context.sendOrderedBroadcast()
, or
Context.sendStickyBroadcast()
) are deliv
ered to all interested broadcast receivers.
Many kinds of broadcasts originate in system code.
In each case, the Android system finds the appropriate activity, service, or set of broadcast
receivers to respond to the intent, instantiating them if necessary
. There is no overlap within
these messaging systems: Broadcast intents are delivered only to broadcast receivers, never to
activities or services. An intent passed to
startActivity()
is delivered only to an activity,
never to a service or broadcast receiv
er, and so on.
(Taken from
http://developer.android.com/guide/topics/intents/intents
-
filters.html
)
If we take a look at our Sudoku Activity, there is a call to the
st
artActivity method being made
when we want to find out more about the game:
case
R.id.
about_button
:
Intent i =
new
Intent(
this
, About.
class
);
startActivity(i);
break
;
An Intent object can explicitly name a target component. If it does, Android finds t
hat
component (based on the declarations in the manifest file) and activates it. But if a target is not
explicitly named, Android must locate the best component to respond to the intent. It does so by
comparing the Intent object to the
intent filters
of po
tential targets. A component's intent filters
inform Android of the kinds of intents the component is able to handle. Like other essential
information about the component, they're declared in the manifest file. Below is an excerpt from
our Sudoku game, the
AndroidManifest.xml
file:
<?
xml
version
=
"1.0"
encoding
=
"utf
-
8"
?>
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"org.example.sudoku"
android:versionCode
=
"1"
android:versionName
=
"1.0.0"
>
<
application
an
droid:icon
=
"@drawable/icon"
android:label
=
"@string/app_name"
>
<
activity
android:name
=
".Sudoku"
android:label
=
"@string/app_name"
>
<
intent
-
filter
>
<
action
android:name
=
"android.intent.action.MAIN"
/
>
<
category
android:name
=
"android.intent.category.LAUNCHER"
/>
</
intent
-
filter
>
14
</
activity
>
…
</
application
>
</
manifest
>
The filter in our Sudoku example
—
the combination of the action
"
android.inte
nt.action.MAIN
" and the category "
android.intent.category.LAUNCHER
"
—
is a common one. It marks the
Sudoku A
ctivity as one that should be represented in the
application launcher, the screen listing applications users can launch on the device. In other
word
s, the activity is the entry point for the application, the initial one users would see when they
choose the application in the launcher.
A component can have any number of intent filters, each one declaring a different set of
capabilities. If it doesn't
have any filters, it can be activated only by intents that explicitly name
the component as the target.
You can find out more about Intent and Intent Filters by visiting the
web
address below:
http://developer.android.com/guide/topics/intents/intents
-
filters.html
Enter the password to open this PDF file:
File name:
-
File size:
-
Title:
-
Author:
-
Subject:
-
Keywords:
-
Creation Date:
-
Modification Date:
-
Creator:
-
PDF Producer:
-
PDF Version:
-
Page Count:
-
Preparing document for printing…
0%
Comments 0
Log in to post a comment