You are on page 1of 268

Learning Android

D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Learning Android
Marko Gargcnta
Beijing Cambridge Farnham Kln Sebastopol Tokyo
Learning Android
Ly Maiko Gaigenta
Copyiight 2011 Maiko Gaigenta. All iights ieseiveu.
Piinteu in the Uniteu States ol Ameiica.
PuLlisheu Ly O`Reilly Meuia, Inc., 1005 Giavenstein Highway Noith, SeLastopol, CA 95+72.
O`Reilly Looks may Le puichaseu loi euucational, Lusiness, oi sales piomotional use. Online euitions
aie also availaLle loi most titles (http://ny.sajariboo|son|inc.con). Foi moie inloimation, contact oui
coipoiate/institutional sales uepaitment: (S00) 99S-993S oi corporatcorci||y.con.
Editors: Anuy Oiam anu Biian ]epson
Production Editor: Holly Bauei
Copyeditor: Genevieve u`Entiemont
Proofreader: ]ennilei Knight
Indexer: ]ay Maichanu
Cover Designer: Kaien Montgomeiy
Interior Designer: Daviu Futato
Illustrator: RoLeit Romano
Printing History:
Maich 2011: Fiist Euition.
Nutshell HanuLook, the Nutshell HanuLook logo, anu the O`Reilly logo aie iegisteieu tiauemaiks ol
O`Reilly Meuia, Inc. Lcarning Android, the image ol a Little Owl, anu ielateu tiaue uiess aie tiauemaiks
ol O`Reilly Meuia, Inc.
Many ol the uesignations useu Ly manulactuieis anu selleis to uistinguish theii piouucts aie claimeu as
tiauemaiks. Vheie those uesignations appeai in this Look, anu O`Reilly Meuia, Inc., was awaie ol a
tiauemaik claim, the uesignations have Leen piinteu in caps oi initial caps.
Vhile eveiy piecaution has Leen taken in the piepaiation ol this Look, the puLlishei anu authoi assume
no iesponsiLility loi eiiois oi omissions, oi loi uamages iesulting liom the use ol the inloimation con-
taineu heiein.
ISBN: 97S-1-++9-39050-1
LSI
1299702297
Table of Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
1. Android Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Anuioiu Oveiview 1
Compiehensive 1
Open Souice Platloim 2
Designeu loi MoLile Devices 2
Histoiy 3
Google`s Motivation 3
Open Hanuset Alliance +
Anuioiu Veisions +
Summaiy 5
2. The Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Stack Oveiview 7
Linux 7
PoitaLility 7
Secuiity S
Featuies S
Native LiLiaiies 9
Dalvik 9
Anuioiu anu ]ava 10
Application Fiamewoik 11
Applications 12
The APK 12
Application Signing 12
Application DistiiLution 12
Summaiy 13
3. Quick Start . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Installing the Anuioiu SDK 15
v
Setting Up a PATH to Tools 16
Installing Eclipse 16
Eclipse Voikspace 17
Setting Up Anuioiu Development Tools 17
Hello, Voilu 1S
Cieating a New Pioject 1S
Manilest File 20
Layout XML Coue 21
Stiings 21
The R File 22
]ava Souice Coue 22
The Emulatoi 23
An Emulatoi Veisus a Physical Phone 25
Summaiy 25
4. Main Building Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Vhat Aie Main Builuing Blocks? 27
A Real-Voilu Example 27
Activities 2S
Activity Lile Cycle 2S
Intents 31
Seivices 31
Content Pioviueis 32
Bioaucast Receiveis 3+
Application Context 3+
Summaiy 35
5. Yamba Project Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
The YamLa Application 37
Design Philosophy 39
Pioject Design 39
Pait 1: Anuioiu Usei Inteilace 39
Builuing an Activity +0
Netwoiking anu Multithieauing +1
DeLugging Anuioiu Apps +1
Pait 2: Pieleiences, Filesystem, Options Menu, anu Intents +1
The Activity +1
Menu System anu Intents +2
Filesystem +2
Pait 3: Anuioiu Seivices +2
Seivices +2
Application OLject +2
Pait +: Voiking with DataLases +2
vi | Table of Contents
SQLite anu Anuioiu`s Suppoit loi It +2
Relactoiing the Coue Again +3
Pait 5: Lists anu Auapteis +3
Timeline Activity +3
Moie Relactoiing? +3
Pait 6: Bioaucast Receiveis +3
Boot anu Netwoik Receiveis ++
Timeline Receivei ++
Peimissions ++
Pait 7: Content Pioviueis ++
Status Data ++
Anuioiu Viugets ++
Pait S: System Seivices +5
Compass anu Location +5
Intent Seivice, Alaims, anu Notilications +5
Summaiy +5
6. Android User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Two Vays to Cieate a Usei Inteilace +7
Declaiative Usei Inteilace +7
Piogiammatic Usei Inteilace +S
The Best ol Both Voilus +S
Views anu Layouts +S
LineaiLayout +9
TaLleLayout 50
FiameLayout 50
RelativeLayout 50
ALsoluteLayout 50
Staiting the YamLa Pioject 51
The StatusActivity Layout 52
Impoitant Viuget Piopeities 5+
Stiings Resouice 55
The StatusActivity ]ava Class 56
Cieating Youi Application-Specilic OLject anu Initialization Coue 56
Compiling Coue anu Builuing Youi Piojects: Saving Files 59
Auuing the jtwittei.jai LiLiaiy 59
Upuating the Manilest File loi Inteinet Peimission 61
Logging in Anuioiu 62
LogCat 62
Thieauing in Anuioiu 65
Single Thieau 65
Multithieaueu Execution 66
AsyncTask 67
Table of Contents | vii
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Othei UI Events 70
Auuing Coloi anu Giaphics 7+
Auuing Images 7+
Auuing Coloi 76
Alteinative Resouices 79
Optimizing the Usei Inteilace S0
Hieiaichy Viewei S1
Summaiy S2
7. Preferences, the Filesystem, the Options Menu, and Intents . . . . . . . . . . . . . . . . . . 83
Pieleiences S3
Piels Resouice S+
PielsActivity S7
Upuate the Manilest File SS
The Options Menu S9
The Menu Resouice S9
Anuioiu System Resouices 90
Upuate StatusActivity to Loau the Menu 91
Upuate StatusActivity to Hanule Menu Events 92
Stiings Resouice 92
Shaieu Pieleiences 93
The Filesystem Explaineu 95
Exploiing the Filesystem 95
Filesystem Paititions 96
System Paitition 96
SDCaiu Paitition 96
The Usei Data Paitition 97
Filesystem Secuiity 9S
Summaiy 99
8. Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
The YamLa Application OLject 102
The YamLaApplication Class 102
Upuate the Manilest File 10+
Simplilying StatusActivity 105
UpuateiSeivice 105
Cieating the UpuateiSeivice ]ava Class 106
Upuate the Manilest File 107
Auu Menu Items 10S
Upuate the Options Menu Hanuling 109
Testing the Seivice 109
Looping in the Seivice 110
Testing the Seivice 113
viii | Table of Contents
Pulling Data liom Twittei 113
Testing the Seivice 117
Summaiy 117
9. The Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
ALout SQLite 119
DLHelpei 120
The DataLase Schema anu Its Cieation 120
Foui Majoi Opeiations 121
Cuisois 122
Fiist Example 122
Upuate UpuateiSeivice 12+
Testing the Seivice 127
DataLase Constiaints 129
Relactoiing Status Data 130
Summaiy 135
10. Lists and Adapters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
TimelineActivity 137
Basic TimelineActivity Layout 13S
Intiouucing SciollView 13S
Cieating the TimelineActivity Class 139
ALout Auapteis 1+2
Auuing a ListView to TimelineActivity 1+2
Cieating a Row Layout 1+3
Cieating an Auaptei in TimelineActivity.java 1++
TimelineAuaptei 1+6
ViewBinuei: A Bettei Alteinative to TimelineAuaptei 1+9
Upuating the Manilest File 150
Initial App Setup 152
Base Activity 153
Toggle Seivice 15+
Summaiy 159
11. Broadcast Receivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
ALout Bioaucast Receiveis 161
BootReceivei 162
Registeiing the BootReceivei with the AnuioiuManilest File 162
Testing the Boot Receivei 163
The TimelineReceivei 163
Bioaucasting Intents 165
The Netwoik Receivei 167
Auuing Custom Peimissions to Senu anu Receive Bioaucasts 169
Table of Contents | ix
Declaiing Peimissions in the Manilest File 170
Upuating the Seivices to Enloice Peimissions 171
Upuating TimelineReceivei to Enloice Peimissions 172
Summaiy 173
12. Content Providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Cieating a Content Pioviuei 175
Delining the URI 176
Inseiting Data 177
Upuating Data 17S
Deleting Data 179
Queiying Data 179
Getting the Data Type 1S0
Upuating the Anuioiu Manilest File 1S1
Using Content Pioviueis Thiough Viugets 1S1
Implementing the YamLaViuget class 1S2
Cieating the XML Layout 1S5
Cieating the AppViugetPioviueiInlo File 1S5
Upuating the Manilest File 1S6
Testing the Viuget 1S6
Summaiy 1S6
13. System Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Compass Demo 1S9
Common Steps in Using System Seivices 190
Getting Upuates liom the Compass 190
Compass Main Activity 191
Custom Rose Viuget 19+
Location Seivice 195
Vheie Am I? Demo 196
Upuating YamLa to Use the Location Seivice 200
Upuating Oui Pieleiences 200
Upuating the YamLa Application 201
Upuating the Status Activity 202
Intent Seivice 206
Alaims 20S
Auuing an Inteival to Pieleiences 209
Upuating BootReceivei 210
Senuing Notilications 212
Summaiy 21+
14. The Android Interface Definition Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Implementing the Remote Seivice 215
x | Table of Contents
Viiting the AIDL 216
Implementing the Seivice 217
Implementing a Paicel 21S
Registeiing with the Manilest File 220
Implementing the Remote Client 221
Binuing to the Remote Seivice 221
Testing That It All Voiks 22+
Summaiy 225
15. The Native Development Kit (NDK) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
Vhat Is anu Isn`t the NDK Foi? 227
PioLlems Solveu Ly the NDK 227
The Toolchain 22S
Packaging Youi LiLs 22S
Documentation anu Stanuaiuizeu Heaueis 22S
An NDK Example: FiLonacci 229
FiLLiL 229
The ]NI Heauei File 231
C Implementation 232
The Makelile 23+
Builuing the Shaieu LiLiaiy 23+
The FiLonacci Activity 235
Testing That It All Voiks 236
Summaiy 237
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Table of Contents | xi
Preface
This Look spiang liom yeais ol ueliveiing the Maiakana Anuioiu Bootcamp tiaining
class to thousanus ol soltwaie uevelopeis at some ol the laigest moLile companies
locateu on loui continents aiounu the woilu. Teaching this class, ovei time I saw what
woiks anu what uoesn`t. This Look is a uistilleu veision ol the Anuioiu Bootcamp
tiaining couise that I uevelopeu at Maiakana anu line-tuneu ovei numeious
engagements.
My Lackgiounu is in ]ava liom Lack Leloie it was even calleu that. Fiom the Leginning,
I was veiy inteiesteu in emLeuueu uevelopment as a way to piogiam vaiious uevices
that suiiounu us in eveiyuay lile. Because ]ava piimaiily took oll in weL application
uevelopment, most ol my expeiience in the pievious uecaue has Leen in Luiluing laige
enteipiise systems. Then Anuioiu aiiiveu, anu once again I Lecame veiy exciteu aLout
Luiluing soltwaie loi nontiauitional computeis. My cuiient inteiests lie in using An-
uioiu on uevices that may not even iesemLle a typical phone.
This Look teaches anyone who knows ]ava (oi a similai language) how to uevelop a
ieasonaLly complex Anuioiu application. I hope you linu this Look laiily compiehen-
sive anu that you linu the example-Laseu leaining ieasonaLly motivating. The goal ol
Lcarning Android is to get you to thin| in Anuioiu teims.
Whats Inside
Chaptcr 1, Android Ovcrvicw
Is an intiouuction to Anuioiu anu its histoiy
Chaptcr 2, Thc Stac|
Is an oveiview ol the Anuioiu opeiating system anu all its paits liom a veiy high
level
Chaptcr 3, Quic| Start
Helps you set up youi enviionment loi Anuioiu application uevelopment
Chaptcr 1, Main Bui|ding B|oc|s
Explains the Anuioiu components application uevelopeis use to put togethei an
app
xiii
Chaptcr 5, Yanba Projcct Ovcrvicw
Explains the YamLa application that we`ll Luilu togethei thiough this Look anu
use as an example to leain Anuioiu`s vaiious leatuies
Chaptcr , Android Uscr |ntcrjacc
Explains how to Luilu the usei inteilace loi youi application
Chaptcr 7, Prcjcrcnccs, thc Ii|csystcn, thc Options Mcnu, and |ntcnts
Coveis some ol the opeiating system leatuies that make an application uevelopei`s
lile easiei
Chaptcr 8, Scrviccs
Coveis Luiluing an Anuioiu seivice to piocess Lackgiounu tasks
Chaptcr 9, Thc Databasc
Explains the Anuioiu liamewoik`s suppoit loi the Luilt-in SQLite uataLase anu
how to use it to peisist the uata in youi own application
Chaptcr 10, Lists and Adaptcrs
Coveis an impoitant leatuie ol Anuioiu that allows laige uata sets to Le linkeu
elliciently to ielatively small scieens
Chaptcr 11, Broadcast Rcccivcrs
Explains how to use the puLlish-suLsciiLe mechanism in Anuioiu to iesponu to
vaiious system anu usei-uelineu messages
Chaptcr 12, Contcnt Providcrs
Shows how to uesign a content pioviuei to shaie uata Letween applications, in this
case using it to enaLle oui app wiuget to uisplay uata on the home scieen
Chaptcr 13, Systcn Scrviccs
Intiouuces vaiious system seivices that an app uevelopei can tap into
Chaptcr 11, Thc Android |ntcrjacc Dcjinition Languagc
Coveis Luiluing an intei-piocess communication mechanism to allow loi iemote
access to a seivice liom anothei application
Chaptcr 15, Thc Nativc Dcvc|opncnt Kit (NDK)
Intiouuces how to wiite native C coue as pait ol youi Anuioiu application
Conventions Used in This Book
The lollowing typogiaphical conventions aie useu in this Look:
|ta|ic
Inuicates new teims, URLs, email auuiesses, lilenames, anu lile extensions.
Constant width
Useu loi piogiam listings, as well as within paiagiaphs to ielei to piogiam elements
such as vaiiaLle oi lunction names, uata types, anu XML entities.
Constant width bold
Shows commanus oi othei text that shoulu Le typeu liteially Ly the usei.
xiv | Preface
Constant width italic
Shows text that shoulu Le ieplaceu with usei-supplieu values oi Ly values uetei-
mineu Ly context.
This icon signilies a tip, suggestion, oi geneial note.
This icon inuicates a waining oi caution.
Using Code Examples
This Look is heie to help you get youi joL uone. In geneial, you may use the coue in
this Look in youi piogiams anu uocumentation. You uo not neeu to contact us loi
peimission unless you`ie iepiouucing a signilicant poition ol the coue. Foi example,
wiiting a piogiam that uses seveial chunks ol coue liom this Look uoes not ieguiie
peimission. Selling oi uistiiLuting a CD-ROM ol examples liom O`Reilly Looks uoes
ieguiie peimission. Answeiing a guestion Ly citing this Look anu guoting example
coue uoes not ieguiie peimission. Incoipoiating a signilicant amount ol example coue
liom this Look into youi piouuct`s uocumentation uoes ieguiie peimission.
Ve appieciate, Lut uo not ieguiie, attiiLution. An attiiLution usually incluues the title,
authoi, puLlishei, anu ISBN. Foi example: Lcarning Android Ly Maiko Gaigenta
(O`Reilly). Copyiight 2011 Maiko Gaigenta, 97S-1-++9-39050-1.
Il you leel youi use ol coue examples lalls outsiue laii use oi the peimission given heie,
leel liee to contact us at pcrnissionsorci||y.con.
Safari Books Online
Salaii Books Online is an on-uemanu uigital liLiaiy that lets you easily
seaich ovei 7,500 technology anu cieative ieleience Looks anu viueos to
linu the answeis you neeu guickly.
Vith a suLsciiption, you can ieau any page anu watch any viueo liom oui liLiaiy online.
Reau Looks on youi cell phone anu moLile uevices. Access new titles Leloie they aie
availaLle loi piint, get exclusive access to manusciipts in uevelopment, anu post leeu-
Lack loi the authois. Copy anu paste coue samples, oiganize youi lavoiites, uownloau
chapteis, Lookmaik key sections, cieate notes, piint out pages, anu Lenelit liom tons
ol othei time-saving leatuies.
Preface | xv
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
O`Reilly Meuia has uploaueu this Look to the Salaii Books Online seivice. To have lull
uigital access to this Look anu otheis on similai topics liom O`Reilly anu othei puL-
lisheis, sign up loi liee at http://ny.sajariboo|son|inc.con.
How to Contact Us
Please auuiess comments anu guestions conceining this Look to the puLlishei:
O`Reilly Meuia, Inc.
1005 Giavenstein Highway Noith
SeLastopol, CA 95+72
S00-99S-993S (in the Uniteu States oi Canaua)
707-S29-0515 (inteinational oi local)
707 S29-010+ (lax)
Ve have a weL page loi this Look, wheie we list eiiata, examples, anu any auuitional
inloimation. You can access this page at:
http://orci||y.con/cata|og/9781119390501/
To comment oi ask technical guestions aLout this Look, senu email to:
boo|qucstionsorci||y.con
Foi moie inloimation aLout oui Looks, couises, conleiences, anu news, see oui weLsite
at http://orci||y.con.
Finu us on FaceLook: http://jaccboo|.con/orci||y
Follow us on Twittei: http://twittcr.con/orci||yncdia
Vatch us on YouTuLe: http://www.youtubc.con/orci||yncdia
Acknowledgments
This Look is tiuly a iesult ol outstanuing teamwoik. Fiist, I`u like to thank my euitois
at O`Reilly, Anuy Oiam anu Biian ]epson. Anuy, youi comments weie spot-on anu
constiuctive. Biian, thank you loi peisuauing me to take on wiiting this Look in the
liist place.
I woulu like to thank all my technical euitois: Dan Boinstein, Heiv Guihot, Fiank
Makei III, anu Bill Schiickel. Thank you loi uiligently ieauing my hall-Lakeu uialts anu
pioviuing valuaLle comments.
This Look woulun`t Le what it is without lielu testing it on oui numeious clients. You
weie the tiue pioneeis on the cutting euge ol Anuioiu, anu youi piojects aie all veiy
inspiiing. Thank you loi youi tiust.
xvi | Preface
I`u like to thank my team at MaiakanaAleksanuai (Sasa) Gaigenta, Ken ]ones, anu
Lauient Tononloi Liinging Lack liisthanu leeuLack liom teaching Anuioiu Boot-
camp couises using the uialt ol this Look. Sasa, special thanks to you loi senuing me
Lack to the uiawing Loaiu moie times than I`u like to aumit. This Look is pioLaLly
months past uue Lecause ol youi in-uepth technical comments.
Anu linally, a huge thanks to my wile, Lisa, anu uaughtei, Kylie. I know what a saciilice
it was loi you while I was ciissciossing the woilu woiking on this mateiial. Thank you
loi suppoiting me along the way.
Preface | xvii
CHAPTER 1
Android Overview
In this chaptei, you will leain how Anuioiu came aLout. Ve`ll take a look at its histoiy
to help us unueistanu its lutuie. As this moLile enviionment enteis a make-oi-Lieak
yeai, we look at the key playeis in this ecosystem, what motivates them, anu what
stiengths anu weaknesses they Liing to the taLle.
By the enu ol this chaptei, you will Lettei unueistanu the ecosystem liom a Lusiness
point ol view, which shoulu help claiily the technology choices anu how they ielate to
long-teim auvantages loi vaiious platloims.
Android Overview
Anuioiu is a compiehensive open souice platloim uesigneu loi moLile uevices. It is
championeu Ly Google anu owneu Ly Open Hanuset Alliance. The goal ol the alliance
is to acceleiate innovation in moLile anu ollei consumeis a iichei, less expensive, anu
Lettei moLile expeiience. Anuioiu is the vehicle to uo so.
As such, Anuioiu is ievolutionizing the moLile space. Foi the liist time, it is a tiuly
open platloim that sepaiates the haiuwaie liom the soltwaie that iuns on it. This allows
loi a much laigei numLei ol uevices to iun the same applications anu cieates a much
iichei ecosystem loi uevelopeis anu consumeis.
Let`s Lieak uown some ol these Luzz woius anu see what`s Lehinu them.
Comprehensive
Anuioiu is a compiehensive platloim, which means it is a complete soltwaie stack loi
a moLile uevice.
Foi uevelopeis, Anuioiu pioviues all the tools anu liamewoiks loi ueveloping moLile
apps guickly anu easily. The Anuioiu SDK is all you neeu to stait ueveloping loi An-
uioiu; you uon`t even neeu a physical phone.
1
Foi useis, Anuioiu just woiks iight out ol the Lox. Auuitionally, useis can customize
theii phone expeiience suLstantially.
Foi manulactuieis, it is the complete solution loi iunning theii uevices. Othei than
some haiuwaie-specilic uiiveis, Anuioiu pioviues eveiything else to make theii uevices
woik.
Open Source Platform
Anuioiu is an open souice platloim. The entiie stack, liom low-level Linux mouules
all the way to native liLiaiies, anu liom the application liamewoik to complete appli-
cations, is totally open.
Moie so, Anuioiu is licenseu unuei Lusiness-liienuly licenses (Apache/MIT) so that
otheis can lieely extenu it anu use it loi vaiiety ol puiposes. Even some thiiu-paity
open souice liLiaiies that weie Liought into the Anuioiu stack weie iewiitten unuei
new license teims.
So, as a uevelopei, you have access to the entiie platloim souice coue. This allows you
to see how the guts ol the Anuioiu opeiating system woik. As manulactuiei, you can
easily poit Anuioiu OS to youi specilic haiuwaie. You can also auu youi own piopii-
etaiy seciet sauce, anu you uo not have to push it Lack to the uevelopment community
il you uon`t want to.
Theie`s no neeu to license Anuioiu. You can stait using it anu mouilying it touay, anu
theie aie no stiings attacheu. Moie so, Anuioiu has many hooks at vaiious levels ol the
platloim, allowing anyone to extenu it in unloieseen ways.
Theie aie couple ol minoi low-level pieces ol coue that aie piopiietaiy
to each venuoi, such as the soltwaie stack loi the cellulai, ViFi, anu
Bluetooth iauios. Anuioiu tiies haiu to aLstiact those components with
inteilaces so that venuoi-specilic coue can Le manageu easily.
Designed for Mobile Devices
Anuioiu is a puipose-Luilt platloim loi moLile uevices. Vhen uesigning Anuioiu, the
team lookeu at which moLile uevice constiaints likely weie not going to change loi the
loieseeaLle lutuie. Foi one, moLile uevices aie Latteiy poweieu, anu Latteiy peiloim-
ance likely is not going to get much Lettei any time soon. Seconu, the small size ol
moLile uevices means that they will always Le limiteu in teims ol memoiy anu speeu.
These constiaints weie taken into consiueiation liom the get-go anu weie auuiesseu
thioughout the platloim. The iesult is an oveiall Lettei usei expeiience.
Anuioiu was uesigneu to iun on all soits ol physical uevices. Anuioiu uoesn`t make
any assumptions aLout a uevice`s scieen size, iesolution, chipset, anu so on. Its coie is
uesigneu to Le poitaLle.
2 | Chapter 1:Android Overview
History
The histoiy ol Anuioiu is inteiesting anu olleis some peispective on what the lutuie
might holu.
These aie the key events ol the past lew yeais:
In 2005, Google Luys Anuioiu, Inc. The woilu thinks a gPhone is aLout to come
out.
Eveiything goes guiet loi a while.
In 2007, the Open Hanuset Alliance is announceu. Anuioiu is ollicially open
souiceu.
In 200S, the Anuioiu SDK 1.0 is ieleaseu. The G1 phone, manulactuieu Ly HTC
anu solu Ly the wiieless caiiiei T-MoLile USA, lollows shoitly alteiwaiu.
2009 sees a piolileiation ol Anuioiu-Laseu uevices. New veisions ol the opeiating
system aie ieleaseu: Cupcake (1.5), Donut (1.6), anu Eclaii (2.0 anu 2.1). Moie
than 20 uevices iun Anuioiu.
In 2010, Anuioiu is seconu only to BlackLeiiy as the Lest-selling smait phone
platloim. Fioyo (Anuioiu 2.2) is ieleaseu anu so aie moie than 60 uevices that
iun it.
In 2005, when Google puichaseu Anuioiu, Inc., the woilu thought Google was aLout
to entei the smait phone maiket, anu theie weie wiuespieau speculations aLout a ue-
vice calleu the gPhone.
Google`s CEO, Eiic Schmiut, maue it cleai iight away that Anuioiu`s amLitions weie
much laigei than a single phone. Insteau, they envisioneu a platloim that woulu enaLle
many phones anu othei uevices.
Googles Motivation
Google`s motivation loi suppoiting the Anuioiu pioject seems to Le having Anuioiu
eveiywheie anu Ly uoing that, cieating a level playing lielu loi moLile uevices. Ulti-
mately, Google is a meuia company, anu its Lusiness mouel is Laseu on selling auvei-
tising. Il eveiyone is using Anuioiu, then Google can pioviue auuitional seivices on top
ol it anu compete laiily. This is unlike the Lusiness mouels ol othei soltwaie venuois
who uepenu on licensing lees.
Although Google uoes license some piopiietaiy apps, such as Gmail anu Maps, anu
makes some money oll the Anuioiu maiket, its piimaiy motivation is still the auvei-
tising ievenue that those apps Liing in.
History | 3
Open Handset Alliance
Foi this to Le Liggei than just Google, Anuioiu is owneu Ly the Open Hanuset Alliance,
a nonpiolit gioup loimeu Ly key moLile opeiatois, manulactuieis, caiiieis, anu otheis.
The alliance is committeu to openness anu innovation loi the moLile usei expeiience.
In piactice, the alliance is still veiy young anu many memLeis aie still leaining to woik
with each othei. Google happens to Le putting the most muscle Lehinu the Anuioiu
pioject at the moment.
The liist veision ol the Anuioiu SDK was ieleaseu without an actual
phone on the maiket. The point ol this is that you uon`t ieally neeu a
phone loi Anuioiu uevelopment. Theie aie some exceptions (haiuwaie
sensois, telephony, etc.), Lut loi the most pait the Anuioiu SDK con-
tains eveiything you`ll neeu loi ueveloping on this platloim.
Android Versions
Like any soltwaie, Anuioiu is impioveu ovei time, which is iellecteu in its veision
numLeis. Howevei, the ielationship Letween uilleient veision numLeis can Le con-
lusing. TaLle 1-1 helps explain that.
Tab|c 1-1. Android vcrsions through Android 2.3
Android version API level Nickname
Android 1.0 1
Android 1.1 2
Android 1.5 3 Cupcake
Android 1.6 4 Donut
Android 2.0 5 Eclair
Android 2.01 6 Eclair
Android 2.1 7 Eclair
Android 2.2 8 Froyo (frozen yogurt)
Android 2.3 9 Gingerbread
Android 2.3.3 10 Gingerbread
Android 3.0 11 Honeycomb
The Anuioiu veision numLei itsell paitly tells the stoiy ol the soltwaie platloim`s majoi
anu minoi ieleases. Vhat is most impoitant is the API level. Veision numLeis change
all the time, sometimes Lecause the APIs have changeu, anu othei times Lecause ol
minoi Lug lixes oi peiloimance impiovements.
4 | Chapter 1:Android Overview
As application uevelopeis, you will want to make suie you know which API level youi
application is taigeting in oiuei to iun. That API level will ueteimine which uevices can
anu cannot iun youi application.
Typically youi oLjective is to have youi application iun on as many uevices as possiLle.
So, with that in minu, tiy to shoot loi an API level that is as low as possiLle. Keep in
minu the uistiiLution ol Anuioiu veisions on ieal uevices out theie. Figuie 1-1 shows
a snapshot ol the Anuioiu Device DashLoaiu liom miu-2010.
Iigurc 1-1. Historica| Android vcrsion distribution through january 2011
You may notice that theie aie not a lot ol useis ol Anuioiu 1.5 anu 1.6. You may also
notice that not a lot ol useis have the latest anu gieatest Anuioiu 2.3, Lut the numLei
ol 2.x useis is giowing. This is Lecause eveiyone with 1.0 anu 1.1 got upgiaueu ovei
the aii (OTA) automatically to 1.5. On the othei hanu, useis who still have uevices
with Anuioiu 1.5 anu 1.6 likely will nevei Le aLle to upgiaue to 2.x veisions. Theii
oluei uevices uo not have the ielevant liimwaie, anu most manulactuieis aie not plan-
ning on ieleasing liimwaie upgiaues as they aie Lusy woiking on new mouels.
Vith that in minu, you will pioLaLly choose 1.6 oi 2.0 as youi minimum uevelopment
taiget, unless you tiuly neeu the leatuies ol the latest veision.
Summary
The Anuioiu opeiating system was uesigneu liom the giounu up to Le a compiehensive
open souice platloim loi moLile uevices. It is a game-changei in the inuustiy anu has
enjoyeu gieat success.
In the next chaptei, we`ll take a look at the entiie Anuioiu opeiating system at a high
level to gain a technical unueistanuing ol how all the pieces lit togethei.
Summary | 5
CHAPTER 2
The Stack
This is the 9,000-loot oveiview ol the Anuioiu platloim. Although you`ie conceineu
piimaiily with wiiting Anuioiu applications, unueistanuing the layout ol the system
will help shape youi unueistanuing aLout what you can oi cannot uo easily with
Anuioiu.
By the enu ol this chaptei, you`ll unueistanu how the whole system woiks, at least liom
the high level.
Stack Overview
The Anuioiu opeiating system is like a cake consisting ol vaiious layeis. Each layei has
its own chaiacteiistics anu puipose. The layeis aie not cleanly sepaiateu Lut olten seep
into each othei.
Vhen you ieau thiough this chaptei, keep in minu that I am conceineu only with the
Lig pictuie ol the entiie system anu will get into the nitty-giitty uetails latei on. Fig-
uie 2-1 shows the paits ol the Anuioiu stack.
Linux
Anuioiu is Luilt on top ol Linux. Linux is a gieat opeiating system anu the postei chilu
ol open souice. Theie aie many goou ieasons loi choosing Linux as the Lase ol the
Anuioiu stack. Some ol the main ones aie its poitaLility, secuiity, anu leatuies.
Portability
Linux is a poitaLle platloim that is ielatively easy to compile on vaiious haiuwaie
aichitectuies. Vhat Linux Liings to Anuioiu is a level ol haiuwaie aLstiactions. By
Lasing Anuioiu on Linux, we uon`t have to woiiy too much aLout unueilying haiuwaie
leatuies. Most low-level paits ol Linux have Leen wiitten in laiily poitaLle C coue,
which allows loi thiiu paities to poit Anuioiu to a vaiiety ol uevices.
7
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Iigurc 2-1. Android stac|
Security
Linux is a highly secuie system, having Leen tiieu anu testeu thiough some veiy haish
enviionments ovei the uecaues. Anuioiu heavily ielies on Linux loi secuiity. All An-
uioiu applications iun as sepaiate Linux piocesses with peimissions set Ly the Linux
system. As such, Anuioiu passes many secuiity conceins to the unueilying Linux
system.
Features
Linux comes with a lot ol veiy uselul leatuies. Anuioiu leveiages many ol them, such
as suppoit loi memoiy management, powei management, anu netwoiking.
8 | Chapter 2:The Stack
Native Libraries
The native liLiaiies aie C/C-- liLiaiies, olten taken liom the open souice community
in oiuei to pioviue necessaiy seivices to the Anuioiu application layei. Among otheis,
they incluue:
Wcb|it
A last weL-ienueiing engine useu Ly Salaii, Chiome, anu othei Liowseis
SQLitc
A lull-leatuieu SQL uataLase
Apachc Harnony
An open souice implementation ol ]ava
OpcnGL
3D giaphics liLiaiies
OpcnSSL
The secuie locket layei
Although many ol these liLiaiies aie useu as-is, one notaLle exception is Bionic, which
is Lasically a iewiitten veision ol the stanuaiu C liLiaiy. Bionic is useu loi two ieasons:
Tcchno|ogy
To make it puipose-Luilt loi tiny, Latteiy-poweieu uevices
Liccnsc
To make it license-liienuly loi otheis who might want to auopt it anu change it
GNU liLc, the uelault C liLiaiy loi Linux, is licenseu unuei a GPL li-
cense, which ieguiies any changes that you ielease puLlicly to Le pusheu
Lack to the open souice community. As such, it might not Le the most
Lusiness-liienuly open souice license when a company wants to keep
theii ueiivative woik piopiietaiy. Bionic, on the othei hanu, is licenseu
unuei an Apache/MIT license, which uoesn`t ieguiie ueiivative woiks
to Le open souiceu.
Dalvik
Dalvik is a puipose-Luilt viitual machine uesigneu specilically loi Anuioiu, uevelopeu
Ly Dan Boinstein anu his team at Google.
The ]ava viitual machine (VM) was uesigneu to Le a one-size-lits-all solution, anu the
Dalvik team lelt they coulu uo a Lettei joL Ly locusing stiictly on moLile uevices. They
lookeu at which constiaints specilic to a moLile enviionment aie least likely to change
in the neai lutuie. One ol these is Latteiy lile, anu the othei is piocessing powei. Dalvik
was Luilt liom the giounu up to auuiess those constiaints.
Dalvik | 9
Anothei siue ellect ol ieplacing the ]ava VM with the Dalvik VM is the licensing.
Vheieas the ]ava language, ]ava tools, anu ]ava liLiaiies aie liee, the ]ava viitual ma-
chine is not. This was moie ol an issue Lack in 2005 when the woik on Dalvik staiteu.
Nowauays, theie aie open souice alteinatives to Sun`s ]ava VM, namely the
Open]DK anu Apache Haimony piojects.
By ueveloping a tiuly open souice anu license-liienuly viitual machine, Anuioiu yet
again pioviues a lull-leatuieu platloim that otheis aie encouiageu to auopt loi a vaiiety
ol uevices without having to woiiy aLout the license.
Android and Java
In ]ava, you wiite youi ]ava souice lile, compile it into a ]ava Lyte coue using the ]ava
compilei, anu then iun this Lyte coue on the ]ava VM. In Anuioiu, things aie uilleient.
You still wiite the ]ava souice lile, anu you still compile it to ]ava Lyte coue using the
same ]ava compilei. But at that point, you iecompile it once again using the Dalvik
compilei to Dalvik Lyte coue. It is this Dalvik Lyte coue that is then executeu on the
Dalvik VM. Figuie 2-2 illustiates this compaiison Letween stanuaiu ]ava (on the lelt)
in Anuioiu using Dalvik (on the iight).
Iigurc 2-2. java vcrsus Da|vi|
10 | Chapter 2:The Stack
It might sounu like you have to uo a lot moie woik with Anuioiu when
it comes to ]ava. Howevei, all these compilation steps aie automateu
Ly tools such as Eclipse oi Ant, anu you nevei notice the auuitional
steps.
You may wonuei, why not compile stiaight liom ]ava into the Dalvik Lyte coue? Theie
aie a couple ol goou ieasons loi the extia steps. Back in 2005, when woik on Dalvik
staiteu, the ]ava language was going thiough lieguent changes, Lut the ]ava Lyte coue
was moie oi less set in stone. So, the Anuioiu team chose to Lase Dalvik on ]ava Lyte
coue insteau ol ]ava souice coue.
A siue ellect ol this is that in theoiy you coulu wiite Anuioiu applications in any othei
language that compiles uown to ]ava Lyte coue. Foi example, you coulu use Python oi
RuLy. I say in theoiy Lecause in piactice the appiopiiate liLiaiies that aie pait ol the
SDK woulu neeu to Le availaLle. But it is likely that the open souice community will
come up with a solution to that in the lutuie.
Anothei thing to keep in minu is that Anuioiu ]ava is a nonstanuaiu collection ol ]ava
classes. ]ava typically ships in:
java Standard Edition
Useu loi uevelopment on Lasic uesktop-type applications
java Entcrprisc Edition (a|a j2EE or javaEE)
Useu loi uevelopment ol enteipiise applications
java Micro Edition (a|a j2ME or javaME)
]ava loi moLile applications
Anuioiu`s ]ava set ol liLiaiies is closest to ]ava Stanuaiu Euition. The majoi uilleience
is that ]ava usei inteilace liLiaiies (AVT anu Swing) have Leen taken out anu ieplaceu
with Anuioiu-specilic usei inteilace liLiaiies. Anuioiu also auus guite a lew new lea-
tuies to stanuaiu ]ava while suppoiting most ol ]ava`s stanuaiu leatuies. So, you have
most ol youi lavoiite ]ava liLiaiies at youi uisposal, plus many new ones.
Application Framework
The application liamewoik is a iich enviionment that pioviues numeious seivices to
help you, the app uevelopei, get youi joL uone. This is the Lest-uocumenteu anu most
extensively coveieu pait ol the platloim Lecause it is this layei that empoweis uevel-
opeis to get cieative anu Liing lantastic applications to the maiket.
In the application liamewoik layei, you will linu numeious ]ava liLiaiies specilically
Luilt loi Anuioiu. You will also linu many seivices (oi nanagcrs) that pioviue the eco-
system ol capaLilities youi application can tap into, such as location, sensois, ViFi,
telephony, anu so on.
Application Framework | 11
As you exploie Anuioiu application uevelopment, most ol youi locus will Le on this
pait ol the stack, anu you will get to use many ol the application liamewoik
components.
Applications
Anu linally, theie aie the applications that you anu othei uevelopeis cieate. These
applications aie what enu useis linu valuaLle aLout Anuioiu. They can come piein-
stalleu on the uevice oi can Le uownloaueu liom one ol the many Anuioiu maikets.
The APK
An application is a single application package (APK) lile. An APK lile ioughly has thiee
main components. An API consists ol the lollowing majoi components:
Da|vi| cxccutab|c
This is all youi ]ava souice coue compileu uown to a Dalvik executaLle. This is the
coue that iuns youi application.
Rcsourccs
Resouices aie eveiything that is not coue. Youi application may contain a numLei
ol images anu auuio/viueo clips, as well as numeious XML liles uesciiLing layouts,
language packs, anu so on. Collectively, these items aie the iesouices.
Nativc |ibrarics
Optionally, youi application may incluue some native coue, such as C/C-- li-
Liaiies. These liLiaiies coulu Le packageu togethei with youi APK lile.
Application Signing
Anuioiu applications must Le signeu Leloie they can Le installeu on a uevice. Foi ue-
velopment puiposes, we`ll Le signing oui example applications with a ueLug keya
key that you alieauy have on youi uevelopment platloim. Howevei, when you uistiiL-
ute youi application commeicially, you`ll want to sign it with youi own key. The
Anuioiu uevelopei uocument titleu Signing Youi Application has the uetails.
Application Distribution
One way in which Anuioiu is guite uilleient liom othei platloims is the uistiiLution
ol its apps. On most othei platloims, such as iPhone, a single venuoi holus a monopoly
ovei the uistiiLution ol applications. On Anuioiu, theie aie many uilleient stoies, oi
maikets. Each maiket has its own set ol policies with iespect to what is alloweu, how
the ievenue is split, anu so on. As such, Anuioiu is much moie ol a liee maiket space
in which venuois compete loi Lusiness.
12 | Chapter 2:The Stack
In piactice, the Liggest maiket cuiiently is Anuioiu Maiket, iun Ly Google. It is uncleai
whethei Google means to just seeu the maiket space while othei stoies uevelop oi plans
to make it a piolitaLle ventuie.
Applications can also Le uistiiLuteu via the VeL. Vhen you uownloau an APK lile
liom a weLsite thiough the Liowsei, the application iepiesenteu Ly the APK lile is
installeu automatically on youi phone.
What about viruses, malware, spyware, and other bad things?
Vith its uecentializeu application uistiiLution system, it is ceitainly possiLle loi an
unsuspecting usei to uownloau a malicious app that conseguently uoes Lau things. Foi
example, theie have Leen iepoits ol phishing attacks via lake Lanking apps.
So, Anuioiu leaves it to the maiketplace to soit it out. Eventually, theie will Le stoies
that aie moie ieputaLle anu those that aie less so, at least in theoiy. Google ielies on
usei iepoits loi policing its Anuioiu Maiket, Lut othei stoies may choose to uo moie
pioactive testing anu iaise the Lai on what gets into the stoie in the liist place.
Summary
In this chaptei, you got a Lig-pictuie oveiview ol what compiises the Anuioiu opeiating
system anu how its vaiious pieces lit togethei. You now unueistanu what makes An-
uioiu so complete, open, anu attiactive to uevelopeis.
In the next chaptei, we`ll look at how to set up youi uevelopment enviionment so you
can get up to speeu guickly. Ve`ll also look at a simple Hello Voilu application anu
uissect it to help you unueistanu the vaiious pieces ol an Anuioiu application.
Summary | 13
CHAPTER 3
Quick Start
In this chaptei, you will leain how to set up youi enviionment loi Anuioiu uevelop-
ment. I`ll go Leyonu just listing wheie you can uownloau the soltwaie, anu will covei
some ol the Lest piactices in getting set up. I`ll look at uevelopment opeiating system
choices as well as the Anuioiu tools availaLle. You will see the goou, the Lau, anu the
ugly ol the vaiious tool anu platloim choices that you`ie aLout to make (oi that some-
one else has alieauy maue loi you).
By the enu ol this chaptei, you will have youi entiie uevelopment enviionment set up.
You`ll Le aLle to wiite a Hello Voilu application, Luilu it, anu iun it on the emulatoi
(oi a physical uevice, il you want).
I`m going to use - to ielei to youi home uiiectoiy. On Mac OS X, that`s
typically something like /Uscrs/nar|o. On Linux, it woulu Le /honc/
nar|o, anu on Vinuows Vista anu 7, C:\Uscrs\nar|o (in Vinuows XP,
it woulu Le C:\Docuncnts and Scttings\nar|o). Also, I`m going to use
Unix-style loiwaiu slashes anu not Vinuows Lackslashes to uenote lile
path sepaiatois.
So, il you`ie on Vinuows, just change - to C:\Uscrs\YourUserName
anu / to \. Othei than that, eveiything shoulu Le pietty much loi uilleient
opeiating systems, iegaiuless ol whethei you use OS X, Linux, oi
Vinuows.
Installing the Android SDK
The Anuioiu Soltwaie Development Kit (SDK) is all you neeu to uevelop applications
loi Anuioiu. The SDK comes with a set ol tools as well as a platloim to iun it anu see
it all woik. You can uownloau the Anuioiu SDK loi youi paiticulai platloim liom the
Anuioiu SDK Downloau page.
15
Once you uownloau it, unzip (oi on Linux, untar) it into a loluei that is easy to get to.
Fuithei examples in the Look will assume youi SDK is in the loluei -/android-sd|. Il
it`s in a uilleient location, use that location insteau ol -/android-sd|. Foi example:
Windows
C:\apps\android-sd|-windows
Linux
/honc/YourUserName/android-sd|-|inux_8
Mac OS X
/Uscrs/YourUserName/android-sd|-nac_8
Foi Vinuows useis, I stiongly iecommenu choosing uiiectoiies without
spaces in them. This is Lecause we`ll Le uoing woik on the commanu
line anu spaces just complicate things. Because the Vinuows XP home
uiiectoiy is in C:\Docuncnts and Scttings, I woulu iecommenu putting
android-sd| in a top-level uiiectoiy that you cieate, such as C:\apps.
Howevei, on Vinuows Vista oi 7, you can simply extiact android-sd|
into C:\Uscrs\YourUserName.
Setting Up a PATH to Tools
The Anuioiu SDK has a loluei that contains all its majoi tools. Since we`ie going to use
these tools liom the commanu line, it is vcry helplul to auu youi -/android-sd|/too|s/
anu youi -/android-s|d/p|atjorn-too|s/ uiiectoiies to youi system PATH vaiiaLle. This
will make it easiei to access youi tools without having to navigate to theii specilic
location eveiy single time.
Details loi setting up the PATH vaiiaLle uepenu on the platloim; see step 2 ol the uocu-
ment Installing Anuioiu SDK.
Installing Eclipse
Eclipse is an open souice collection ol piogiamming tools oiiginally cieateu Ly IBM
loi ]ava. Nowauays, most uevelopeis in the ]ava community lavoi Eclipse as theii
Integiateu Development Enviionment (IDE) ol choice. Eclipse lives at http://cc|ipsc.org.
Eclipse has a lot ol time-saving leatuies, which I`ll Le pointing out as we continue. Keep
in minu that, although poweilul, Eclipse tenus to Le veiy iesouice-hungiy, anu so you
might want to iestait it once a uay il it staits iunning sluggishly.
Although you can uo Anuioiu uevelopment with any lavoiite text euitoi oi integiateu
uevelopment enviionment (IDE), most uevelopeis seem to Le using Eclipse, anu thus
that`s what I use in this Look.
16 | Chapter 3:Quick Start
Il you choose not to use Eclipse, please ielei to Developing in Othei
IDEs.
Downloau Eclipse at http://www.cc|ipsc.org/down|oads/. I iecommenu Eclipse IDE loi
]ava Developeis (not the twice-as-laige Eclipse loi ]ava EE Developeis). You can install
it in any uiiectoiy you`u like.
Eclipse Workspace
Eclipse oiganizes all youi woik Ly piojects. Piojects aie placeu in a woikspace, which
is a location you choose. So, wheie you put youi woikspace is signilicant. I iecommenu
-/wor|spacc as a simple place loi youi coue. On Vinuows, howevei, I iecommenu
stoiing youi woikspace in a uiiectoiy that uoesn`t have spaces in it (they complicate
anything you might uo at the commanu line). C:\wor|spacc is a goou choice loi Vin-
uows useis.
Setting Up Android Development Tools
You also neeu to set up Anuioiu Tools loi Eclipse. The instiuctions aie:
1. Stait Eclipse, then select HelpInstall New Soltwaie (see Figuie 3-1).
2. In the AvailaLle Soltwaie uialog, click Auu.
3. In the Auu Site uialog that appeais, entei a name loi the iemote site (loi example,
Anuioiu Plugin) in the Name lielu.
+. In the Location lielu, entei this URL: https://dl-ssl.google.com/android/
eclipse/.
5. Click OK.
6. Back in the AvailaLle Soltwaie view, you shoulu now see Developei Tools auueu
to the list. Select the checkLox next to Developei Tools, which will automatically
select the nesteu tools Anuioiu DDMS anu Anuioiu Development Tools. Click
Next.
7. In the iesulting Install Details uialog, the Anuioiu DDMS anu Anuioiu Develop-
ment Tools leatuies aie listeu. Click Next to ieau anu accept the license agieement
anu install any uepenuencies, then click Finish.
S. Restait Eclipse.
Il you have tiouLle uownloauing the plug-in, you can tiy using http
in the URL insteau ol https (https is pieleiieu loi secuiity ieasons).
Installing the Android SDK | 17
Hello, World
To make suie eveiything is set up piopeily, we`ie going to wiite a simple Hello Voilu
piogiam. As a mattei ol lact, theie`s not much loi us to wiite, Lut a lot to unueistanu.
This is Lecause Eclipse will cieate the pioject shell loi us liom some pieuelineu
templates.
Creating a New Project
In Eclipse, choose FileNewAnuioiu Pioject. Sometimes (especially the liist time you
iun Eclipse) the Anuioiu tools may not Le appeai theie iight away. They shoulu show
up in the lutuie altei you`ve useu them loi the liist time. Il Anuioiu Pioject is not an
option unuei FileNew, choose Othei anu look loi Anuioiu Pioject in theie.
Iigurc 3-1. |nsta|| ncw sojtwarc
18 | Chapter 3:Quick Start
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
In the new pioject uialog winuow, lill out the lollowing:
1. Pioject name is an Eclipse constiuct. Eclipse oiganizes eveiything into piojects.
A pioject name shoulu Le one woiu. I like to use the CamelCase naming convention
heie. Go aheau anu type HelloWorld.
2. Next, you neeu to choose the bui|d targct. The Luilu taiget tells the Luilu tools
which veision ol the Anuioiu platloim you aie Luiluing loi. In heie you shoulu see
a list ol availaLle platloims anu auu-ons you have installeu as pait ol youi SDK.
Go aheau anu pick one ol the newei ones, such as Anuioiu 2.2 (Lut uon`t choose
the taigets nameu Google APIsthose aie Google`s piopiietaiy extensions to the
Anuioiu platloim). Foi oui puiposes, we`ll stick to Anuioiu Open Souice veisions
ol the Anuioiu platloim.
3. You neeu to lill out youi pioject piopeities next. The application name is the plain
English name ol youi application. Go aheau anu entei something like Hello,
World!!!.
+. The package name is a ]ava constiuct. In ]ava, all souice coue is oiganizeu into
packages. Packages aie impoitant Lecause, among othei things, they specily the
visiLility ol oLjects Letween the vaiious ]ava classes in youi pioject. In Anuioiu,
packages aie also impoitant loi application signing puiposes. Youi package name
shoulu Le the ieveise ol youi uomain name with optional suLuomains. I might use
com.example.calculator il I weie Luiluing a calculatoi app anu my uomain name
was cxanp|c.con. I`m going to Le using com.marakana loi my package name heie.
5. You can optionally specily an activity. I haven`t coveieu activities yet (you`ll leain
aLout them in Chaptei 6), Lut think ol them as coiiesponuing to the vaiious scieens
in youi application. An activity is going to Le iepiesenteu Ly a ]ava class, anu
theieloie its name shoulu auheie to ]ava class naming conventions: stait with an
uppei-case lettei anu use CamelCase to sepaiate woius. So, type HelloWorld loi
youi activity name.
6. The minimum SDK veision is the minimum veision ol Anuioiuas iepiesenteu
Ly API levelthat is ieguiieu loi the uevice to iun this application. You want this
numLei to Le as low as possiLle so that youi app can iun on as many uevices as
possiLle. I`m going to put S heie to iepiesent Anuioiu 2.2, which I know I have
installeu.
Finally, click on the Finish Lutton, anu Eclipse will cieate youi pioject. Let`s look at
the vaiious liles that this piocess cieateu in Figuie 3-2.
Hello, World | 19
Iigurc 3-2. Hc||oWor|d ncw projcct window
Manifest File
The manilest lile glues eveiything togethei. It is this lile that explains what the appli-
cation consists ol, what all its main Luiluing Llocks aie, what peimissions it ieguiies,
anu so on (see Example 3-1).
20 | Chapter 3:Quick Start
Exanp|c 3-1. AndroidManijcst.xn|
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.marakana" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".HelloWorld" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>
Layout XML Code
The layout lile specilies the layout ol youi scieen. In this case, shown in Example 3-2,
we have only one scieen, anu it`s loaueu Ly the Hc||oWor|d.java coue seen in Exam-
ple 3-5.
Exanp|c 3-2. rcs/|ayout/nain.xn|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/hello" />
</LinearLayout>
Strings
This is anothei XML lile that contains all the text that youi application uses. Foi ex-
ample, the names ol Luttons, laLels, uelault text, anu similai types ol stiings go into
this lile. This is the Lest piactice loi sepaiating the conceins ol vaiious liles, even il they
aie XML liles. In othei woius, layout XML is iesponsiLle loi the layout ol wiugets, Lut
stiings XML is iesponsiLle loi theii textual content (see Example 3-3).
Exanp|c 3-3. rcs/va|ucs/strings.xn|
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, HelloWorld!</string>
<string name="app_name">Hello, World!!!</string>
</resources>
Hello, World | 21
The R File
The R lile is the glue Letween the woilu ol ]ava anu the woilu ol iesouices (see Exam-
ple 3-+). It is an automatically geneiateu lile, anu as such, you nevei mouily it. It is
iecieateu eveiy time you change anything in the rcs uiiectoiy, loi example, when you
auu an image oi XML lile.
You uon`t neeu to look at this lile much. Ve will use the uata in it guite a Lit, Lut we`ll
use Eclipse to help us ielei to values stoieu in this lile.
Exanp|c 3-1. gcn/con/nara|ana/R.java
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.marakana;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040001;
public static final int hello=0x7f040000;
}
}
Java Source Code
The ]ava coue is what uiives eveiything. This is the coue that ultimately gets conveiteu
to a Dalvik executaLle anu iuns youi application (see Example 3-5).
Exanp|c 3-5. Hc||oWor|d.java
package com.marakana;
import android.app.Activity;
import android.os.Bundle;
public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
22 | Chapter 3:Quick Start
setContentView(R.layout.main);
}
}
The Emulator
Running youi application on a physical uevice veisus an emulateu uevice is pietty much
the same thing. That is Lecause the emulatoi is an actual coue emulatoi, meaning it
iuns the same coue Lase as the actual uevice, all the way uown to the machine layei.
A simulatoi anu an emulatoi sounu veiy similai, Lut aie lunuamentally
uilleient. To emulate means to imitate the machine executing the Linaiy
coue. So, an emulatoi is soit ol like a viitual machine. A simulatoi meiely
simulates the Lehavioi ol the coue at a highei level. Anuioiu SDK ships
with a tiue emulatoi, Laseu on QEMU.
To use the emulatoi, we`ll have to cieate an Anuioiu Viitual Device (AVD). The easiest
way to uo that is to stait the android tool via Eclipse.
To cieate a new AVD, stait the tool calleu Anuioiu SDK anu AVD Managei (see Fig-
uie 3-3). You can stait this tool liom Eclipse Ly clicking on the icon oi via the
commanu line Ly staiting the tool calleu android, which is locateu in youi SDK/too|s
uiiectoiy.
Iigurc 3-3. Android SDK and A\D Managcr
Fiom within the Anuioiu SDK anu AVD Managei winuow, choosing New. pops
up a Cieate New AVD uialog winuow (see Figuie 3-+). In this uialog, you specily the
The Emulator | 23
paiameteis loi youi new AVD. The name can Le any name you choose. The taiget
uesignates which veision ol Anuioiu you want installeu on this paiticulai AVD. The
list ol possiLle taigets is Laseu on platloims anu auu-ons that you have installeu into
youi SDK. Il you uon`t have any taigets, go Lack to the Anuioiu SDK anu AVD Managei
winuow anu choose the AvailaLle packages taL to install at least one platloim, loi
example, Anuioiu 2.3 - API level 9.
Each AVD can have an SD caiu. You can just specily a numLei heie loi youi Luilt-in
caiu, in megaLytes. The skin is the look anu leel ol youi uevice as well as its loim lactoi.
The Haiuwaie option lets you line-tune what this AVD uoes anu uoesn`t suppoit.
Iigurc 3-1. Ncw A\D dia|og
Once you aie uone with this uialog, you will have an AVD in youi list. Go aheau anu
stait it, anu an emulatoi will pop up (see Figuie 3-5).
24 | Chapter 3:Quick Start
Iigurc 3-5. Enu|ator
An Emulator Versus a Physical Phone
Foi the most pait, iunning youi application on the emulatoi is iuentical to iunning it
on a physical phone. Theie aie some notaLle exceptions, mostly things that aie just
haiu to viitualize, such as sensois. Othei haiuwaie-ielateu leatuies such as telephony
anu location seivices, can Le simulateu in the emulatoi.
Summary
Setting up the Anuioiu uevelopment enviionment Lasically involves setting up Anuioiu
SDK anu Eclipse. Once you have set up youi uevelopment enviionment, a goou way
to test that eveiything is woiking is to use Eclipse to cieate a simple Hello Voilu pioject
anu iun it in the emulatoi. Il that iuns line, you aie almost ceitain that youi system is
set up anu ieauy loi luithei uevelopment.
Summary | 25
CHAPTER 4
Main Building Blocks
In this chaptei, you will leain aLout the Lig Llocks in Anuioiu. Ve`ll give you a high-
level oveiview ol what activities aie, how intents woik, why seivices aie cool, how to
use Lioaucast ieceiveis anu content pioviueis to make youi app scale, anu much moie.
By the enu ol this chaptei, you will unueistanu the main Anuioiu components loi
Luiluing applications. You shoulu conceptually know when you`u use what compo-
nent. You will also see how these components ielate to a ieal-woilu application.
What Are Main Building Blocks?
The main Luiluing Llocks aie components that you use as an application uevelopei to
Luilu Anuioiu apps. They aie the conceptual items that you put togethei to cieate a
Liggei whole. Vhen you stait thinking aLout youi application, it is goou to take a top-
uown appioach. You uesign youi application in teims ol scieens, leatuies, anu the
inteiactions Letween them. You stait with conceptual uiawing, something that you can
iepiesent in teims ol lines anu ciicles. This appioach to application uevelopment
helps you see the Lig pictuiehow the components lit togethei anu how it all makes
sense.
A Real-World Example
Let`s say that we want to Luilu a Twittei app. Ve know that the usei shoulu Le aLle
to post status upuates. Ve also know the usei shoulu Le aLle to see what hei liienus
aie up to. Those aie Lasic leatuies. Beyonu that, the usei shoulu also Le aLle to set hei
useiname anu passwoiu in oiuei to log into hei Twittei account. So, now we know we
shoulu have these thiee scieens.
Next, we woulu like this app to woik guickly iegaiuless ol the netwoik connection oi
lack theieol. To achieve that, the app has to pull the uata liom Twittei when it`s online
anu cache the uata locally. That will ieguiie a seivice that iuns in the Lackgiounu as
well as a uataLase.
27
Ve also know that we`u like this Lackgiounu seivice to Le staiteu when the uevice is
initially tuineu on, so Ly the time the usei liist uses the app, theie`s alieauy up-to-uate
inloimation on hei liienus.
So, these aie some stiaightloiwaiu ieguiiements. Anuioiu Luiluing Llocks make it easy
to Lieak them uown into conceptual units so that you can woik on them inuepenuently,
anu then easily put them togethei into a complete package.
Activities
An activity is usually a single scieen that the usei sees on the uevice at one time. An
application typically has multiple activities, anu the usei llips Lack anu loith among
them. As such, activities aie the most visiLle pait ol youi application.
I usually use a weLsite as an analogy loi activities. ]ust like a weLsite consists ol multiple
pages, so uoes an Anuioiu application consist ol multiple activities. ]ust like a weLsite
has a home page, an Anuioiu app has a main activity, usually the one that is shown
liist when you launch the application. Anu just like a weLsite has to pioviue some soit
ol navigation among vaiious pages, an Anuioiu app shoulu uo the same.
On the VeL, you can jump liom a page on one weLsite to a page on anothei. Similaily,
in Anuioiu, you coulu Le looking at an activity ol one application, Lut shoitly altei you
coulu stait anothei activity in a completely sepaiate application. Foi example, il you
aie in youi Contacts app anu you choose to text a liienu, you`u Le launching the activity
to compose a text message in the Messaging application.
Activity Life Cycle
Launching an activity can Le guite expensive. It may involve cieating a new Linux
piocess, allocating memoiy loi all the UI oLjects, inllating all the oLjects liom XML
layouts, anu setting up the whole scieen. Since we`ie uoing a lot ol woik to launch an
activity, it woulu Le a waste to just toss it out once the usei leaves that scieen. To avoiu
this waste, the activity lile cycle is manageu via Activity Managei.
Activity Managei is iesponsiLle loi cieating, uestioying, anu managing activities. Foi
example, when the usei staits an application loi the liist time, the Activity Managei
will cieate its activity anu put it onto the scieen. Latei, when the usei switches scieens,
the Activity Managei will move that pievious activity to a holuing place. This way, il
the usei wants to go Lack to an oluei activity, it can Le staiteu moie guickly. Oluei
activities that the usei hasn`t useu in a while will Le uestioyeu in oiuei to liee moie
space loi the cuiiently active one. This mechanism is uesigneu to help impiove the
speeu ol the usei inteilace anu thus impiove the oveiall usei expeiience.
Piogiamming loi Anuioiu is conceptually uilleient than piogiamming loi some othei
enviionments. In Anuioiu, you linu youisell iesponuing moie to ceitain changes in the
state ol youi application iathei than uiiving that change youisell. It is a manageu,
28 | Chapter 4:Main Building Blocks
containei-Laseu enviionment similai to piogiamming loi ]ava applets oi seivlets. So,
when it comes to an activity lile cycle, you uon`t get to say what state the activity is in,
Lut you have plenty ol oppoitunity to say what happens uuiing the tiansitions liom
state to state. Figuie +-1 shows the states that an activity can go thiough.
Iigurc 1-1. Activity |ijc cyc|c
Starting state
Vhen an activity uoesn`t exist in memoiy, it is in a starting statc. Vhile it`s staiting up,
the activity will go thiough a whole set ol callLack methous that you as a uevelopei
have an oppoitunity to lill out. Eventually, the activity will Le in a running statc.
Keep in minu that this tiansition liom staiting state to iunning state is one ol the
most expensive opeiations in teims ol computing time, anu this also uiiectly allects
the Latteiy lile ol the uevice. This is the exact ieason why we uon`t automatically uestioy
activities that aie no longei shown. The usei might want to come Lack to them, so we
keep them aiounu loi a while.
Running state
The activity in a iunning state is the one that is cuiiently on the scieen anu inteiacting
with the usei. Ve also say this activity is in locus, meaning that all usei inteiactions
such as typing, touching the scieen, anu clicking Luttonsaie hanuleu Ly this one
activity. As such, theie is only one iunning activity at any given time.
Activities | 29
The iunning activity is the one that has piioiity in teims ol getting the memoiy anu
iesouices it neeus to iun as guickly as possiLle. This is Lecause Anuioiu wants to make
suie the iunning activity is zippy anu iesponsive to the usei.
Paused state
Vhen an activity is not in locus (i.e., not inteiacting with the usei) Lut still visiLle on
the scieen, we say it`s in a pauscd statc. This is not a typical scenaiio, Lecause the
uevice`s scieen is usually small, anu an activity is eithei taking up the whole scieen oi
none at all. Ve olten see this case with uialog Loxes that come up in liont ol an activity,
causing it to Lecome Pauseu. All activities go thiough a pauseu state en ioute to Leing
stoppeu.
Pauseu activities still have high piioiity in teims ol getting memoiy anu othei iesouices.
This is Lecause they aie visiLle anu cannot Le iemoveu liom the scieen without making
it look veiy stiange to the usei.
Stopped state
Vhen an activity is not visiLle, Lut still in memoiy, we say it`s in a stoppcd statc. Stoppeu
activity coulu Le Liought Lack to the liont to Lecome a Running activity again. Oi, it
coulu Le uestioyeu anu iemoveu liom memoiy.
The system keeps activities aiounu in a stoppeu state Lecause it is likely that the usei
will still want to get Lack to those activities some time soon, anu iestaiting a stoppeu
activity is lai cheapei than staiting an activity liom sciatch. That is Lecause we alieauy
have all the oLjects loaueu in memoiy anu simply have to Liing it all up to the
loiegiounu.
Stoppeu activities can Le iemoveu liom memoiy at any point.
Destroyed state
A uestioyeu activity is no longei in memoiy. The Activity Managei ueciueu that this
activity is no longei neeueu anu has iemoveu it. Beloie the activity is uestioyeu, it can
peiloim ceitain actions, such as save any unsaveu inloimation. Howevei, theie`s no
guaiantee that youi activity will Le stoppeu piioi to Leing uestioyeu. It is possiLle loi
a pauseu activity to Le uestioyeu as well. Foi that ieason, it is Lettei to uo impoitant
woik, such as saving unsaveu uata, en ioute to a pauseu state iathei than a uestioyeu
state.
The lact that an activity is in a iunning state uoesn`t mean it`s uoing
much. It coulu Le just sitting theie anu waiting loi usei input. Similaily,
an activity in a stoppeu state is not necessaiily uoing nothing. The state
names mostly ielei to how active the activity is with iespect to usei
input, in othei woius, whethei an activity is visiLle, in locus, oi not
visiLle at all.
30 | Chapter 4:Main Building Blocks
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Intents
Intents aie messages that aie sent among the majoi Luiluing Llocks. They tiiggei an
activity to stait up, tell a seivice to stait oi stop, oi aie simply Lioaucasts. Intents aie
asynchionous, meaning the coue that senus them uoesn`t have to wait loi them to Le
completeu.
An intent coulu Le explicit oi implicit. In an explicit intent, the senuei cleaily spells
out which specilic component shoulu Le on the ieceiving enu. In an implicit intent, the
senuei specilies the type ol ieceivei. Foi example, youi activity coulu senu an intent
saying it simply wants someone to open up a weL page. In that case, any application
that is capaLle ol opening a weL page coulu compete to complete this action.
Vhen you have competing applications, the system will ask you which one you`u like
to use to complete a given action. You can also set an app as the uelault. This mechanism
woiks veiy similaily to youi uesktop enviionment, loi example, when you uownloaueu
Fiielox oi Chiome to ieplace youi uelault Inteinet Exploiei oi Salaii weL Liowseis.
This type ol messaging allows the usei to ieplace any app on the system with a custom
one. Foi example, you might want to uownloau a uilleient SMS application oi anothei
Liowsei to ieplace youi existing ones. Figuie +-2 shows how intents may Le useu to
jump Letween vaiious activities, in the same application oi in anothei app altogethei.
Iigurc 1-2. |ntcnts
Services
Seivices iun in the Lackgiounu anu uon`t have any usei inteilace components. They
can peiloim the same actions as activities, Lut without any usei inteilace. Seivices aie
uselul loi actions that we want to peiloim loi a while, iegaiuless ol what is on the
Services | 31
scieen. Foi example, you might want youi music playei to play music even as you aie
llipping Letween othei applications.
Don`t conluse the Anuioiu seivices that aie pait ol an Anuioiu app with
native Linux seivices, seiveis, oi uaemons, which aie a much lowei-level
component ol the opeiating system.
Seivices have a much simplei lile cycle than activities (see Figuie +-3). You eithei stait
a seivice oi stop it. Also, the seivice lile cycle is moie oi less contiolleu Ly the uevelopei,
anu not so much Ly the system. Conseguently, we as uevelopeis have to Le minulul to
iun oui seivices so that they uon`t consume shaieu iesouices unnecessaiily, such as
the CPU anu Latteiy.
Iigurc 1-3. Scrvicc |ijc cyc|c
The lact that a seivice iuns in the Lackgiounu uoesn`t mean it iuns on
a sepaiate thieau. Il a seivice is uoing some piocessing that takes a while
to complete (such as peiloiming netwoik calls), you woulu typically iun
it on a sepaiate thieau. Otheiwise, youi usei inteilace will iun notice-
aLly slowei. In othei woius, seivices anu activities iun on the same main
application thieau, olten calleu the UI thieau.
Content Providers
Content pioviueis aie inteilaces loi shaiing uata Letween applications. By uelault, An-
uioiu iuns each application in its own sanuLox so that all uata that Lelongs to an
application is totally isolateu liom othei applications on the system. Although small
amounts ol uata can Le passeu Letween applications via intents, content pioviueis aie
much Lettei suiteu loi shaiing peisistent uata Letween possiLly laige uatasets. As such,
the content pioviuei API nicely auheies to the CRUD piinciple. Figuie +-+ illustiates
how the content pioviuei`s CRUD inteilace pieices the application Lounuaiies anu
allows othei apps to connect to it to shaie uata.
32 | Chapter 4:Main Building Blocks
The Anuioiu system uses this mechanism all the time. Foi example, Contacts Pioviuei
is a content pioviuei that exposes all usei contact uata to vaiious applications. Settings
Pioviuei exposes system settings to vaiious applications, incluuing the Luilt-in Settings
application. Meuia Stoie is iesponsiLle loi stoiing anu shaiing vaiious meuia, such as
photos anu music, acioss vaiious applications. Figuie +-5 illustiates how the Contacts
app uses Contacts Pioviuei, a totally sepaiate application, to ietiieve uata aLout useis`
contacts. The Contacts app itsell uoesn`t have any contacts uata, anu Contacts Pioviuei
uoesn`t have any usei inteilace.
Iigurc 1-5. Contacts app|ication using Contacts Providcr to gct thc data
Iigurc 1-1. Contcnt providcr
Content Providers | 33
This sepaiation ol uata stoiage anu the actual usei inteilace application olleis gieatei
llexiLility to mash up vaiious paits ol the system. Foi example, a usei coulu install an
alteinative auuiess Look application that uses the same uata as the uelault Contacts
app. Oi, he coulu install wiugets on the Home scieen that allow loi easy changes in the
System Settings, such as tuining on oi oll the ViFi, Bluetooth, oi GPS leatuies. Many
phone manulactuies take auvantage ol content pioviueis to auu theii own applications
on top ol stanuaiu Anuioiu to impiove oveiall usei expeiience, such as HTC Sense.
Content pioviueis aie ielatively simple inteilaces, with the stanuaiu insert(),
update(), delete(), anu query() methous. These methous look a lot like stanuaiu ua-
taLase methous, so it is ielatively easy to implement a content pioviuei as a pioxy to
the uataLase. Having saiu that, you aie much moie likely to use content pioviueis than
wiite youi own.
Broadcast Receivers
Bioaucast ieceiveis aie Anuioiu`s implementation ol a system-wiue puLlish/suLsciiLe
mechanism, oi moie piecisely, an OLseivei pattein. The ieceivei is simply uoimant
coue that gets activateu once an event to which it is suLsciiLeu happens.
The system itsell Lioaucasts events all the time. Foi example, when an SMS aiiives, a
call comes in, the Latteiy iuns low, oi the system gets Looteu, all those events aie
Lioaucasteu, anu any numLei ol ieceiveis coulu Le tiiggeieu Ly them.
In oui Twittei app example, we want to stait the upuate seivice once the system staits
up. To uo that, we can suLsciiLe to the Lioaucast that tells us the system has completeu
Looting up.
You can also senu youi own Lioaucasts liom one pait ol youi application to anothei,
oi to a totally uilleient application.
Bioaucast ieceiveis themselves uo not have any visual iepiesentation, noi aie they ac-
tively iunning in memoiy. But when tiiggeieu, they get to execute some coue, such as
staiting an activity, a seivice, oi something else.
Application Context
So lai you have seen activities, seivices, content pioviueis, anu Lioaucast ieceiveis.
Togethei, they make up an application. Anothei way ol saying this is that they live
insiue the same application context.
Application context ieleis to the application enviionment anu the piocess within which
all its components aie iunning. It allows applications to shaie the uata anu iesouices
Letween vaiious Luiluing Llocks.
An application context gets cieateu whenevei the liist component ol this application
is staiteu up, iegaiuless ol whethei that component is an activity, seivice, oi something
34 | Chapter 4:Main Building Blocks
else. Application context lives as long as youi application is alive. As such, it is inue-
penuent ol the activities lile cycle. You can easily oLtain a ieleience to the context Ly
calling Context.getApplicationContext() oi Activity.getApplication(). Keep in minu
that activities anu seivices aie alieauy suLclasses ol context, anu as such they inheiit
all its methous.
Summary
In this chaptei, you leaineu aLout some ol the most impoitant Anuioiu application
components. Ve put togethei these components to cieate vaiious applications, liom
a simple Hello Voilu to much moie complex cieations.
In the next chaptei, we`ll outline a YamLa application as an example ol how all these
Lits anu pieces come togethei to loim a woiking Anuioiu app.
Summary | 35
CHAPTER 5
Yamba Project Overview
The Lest way to leain is Ly an example, anu that example has to meet ceitain ciiteiia.
Altei woiking with thousanus ol new Anuioiu uevelopeis anu using vaiious example
applications to explain some ol the unigue concepts that this platloim has to ollei, I
concluueu that the Lest example has to Le:
Conprchcnsivc
A goou example app shoulu uemonstiate most ol the aspects ol the application
liamewoik that aie unigue to Anuioiu. Auuitionally, theie shoulu Le a goou ieason
to use a specilic leatuie in oiuei to get the joL uone. This is impoitant in oiuei to
cieate the iight motivation loi those new to Anuioiu.
Iani|iar
The example application shoulu Le simple to unueistanu. Ve want to locus on
uesign anu implementation, anu not on leatuies anu Lenelits.
The Yamba Application
The application I pickeu loi this Look is a Twittei-like application. Ve call it YamLa,
which stanus loi Yct Anothcr Micro B|ogging App. YamLa lets a usei connect to a seivice
such as Twittei, pull uown liienus` statuses, anu upuate that usei`s own status.
YamLa coveis most ol the main Anuioiu Luiluing Llocks in a natuial way. As such, it`s
a gieat sample application to illustiate Loth how vaiious components woik inuiviuually
anu how they lit togethei. Seivices such as Twittei aie moie oi less lamiliai to most
people, so the leatuies ol the application uo not ieguiie much explanation.
Figuies 5-1 thiough 5-3 show what a linisheu piouuct coulu look like.
37
Iigurc 5-1. List oj status ncssagcs jron othcr pcop|c, ca||cd a tinc|inc
Iigurc 5-2. Scrccn whcrc thc uscr can cntcr a status ncssagc
Iigurc 5-3. Uscr prcjcrcnccs
38 | Chapter 5:Yamba Project Overview
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Figuie 5-1 shows how YamLa uisplays a list ol status messages liom youi liienus.
Figuie 5-2 shows the initial YamLa scieen, anu Figuie 5-3 shows the usei pieleiences.
Design Philosophy
Ve`ie going to auopt a ceitain uesign philosophy in tackling this pioject. This philos-
ophy will help guiue us in oui uevelopment anu seive as a noith stai when in uouLt
aLout what to uo next. Spelling out the uesign philosophy heie shoulu also help elim-
inate some conlusion in the piocess we`ie lollowing:
Sna|| incrcncnts
The YamLa application will stait out small anu will constantly giow in lunctionality
anu complexity. Initially, the app will not uo much, Lut it will giow oiganically
one step at a time. Along the way, we`ll explain each step so that you`ie expanuing
youi skills as you go.
A|ways who|c and conp|ctc
The application must always woik. In othei woius, we`ll auu new leatuies in small,
sell-containeu chunks anu pull them Lack into the main pioject so that you can
see how it lits togethei as a whole. The application must always woik at each
stopping point.
Rcjactoring codc
Once in a while, we`ll have to take a step Lack anu ielactoi the application to
iemove uuplicate coue anu optimize the uesign. The goal is to ieuse the coue anu
not ieinvent the wheel. But we aie going to cioss those Liiuges as we get to them,
pioviuing the motivation loi ielactoiing along the way. This piocess will teach you
aLout some geneial soltwaie uevelopment Lest piactices as well.
Project Design
Il you iememLei liom Chaptei +, an Anuioiu application is a loose collection ol activ-
ities, seivices, content pioviueis, anu Lioaucast ieceiveis. These aie the components
liom which we put togethei an application. Figuie 5-+ shows the uesign ol the entiie
YamLa application, which incoipoiates most ol the main Anuioiu Luiluing Llocks.
Part 1: Android User Interface
This pait, coveieu in Chaptei 6, will locus on ueveloping the liist component ol the
YamLa application: the Status Upuate scieen. Oui tasks aie Luiluing an activity, net-
woiking anu multithieauing, anu ueLugging.
Part 1: Android User Interface | 39
Building an Activity
Ve aie going to stait Ly intiouucing the Anuioiu usei inteilace (UI) mouel. In its UI,
Anuioiu is guite uilleient liom some othei paiauigms that you might Le lamiliai with.
The unigue leatuie is its uual appioach to UI via Loth ]ava anu XML.
Iigurc 5-1. Yanba dcsign diagran
40 | Chapter 5:Yamba Project Overview
In this chaptei, you will leain how to uevelop the usei inteilace loi Figuie 5-2, wheie
the usei upuates hei status. Thiough this piocess, you will use XML anu ]ava to put
togethei a woiking UI. You will leain aLout Layouts anu Views, units in Anuioiu, how
to woik with images, anu how to make the UI look pietty.
Oui appioach will locus on Lest piactices in UI uevelopment so that youi application
looks goou anu woiks well on any Anuioiu uevice, iegaiuless ol scieen size anu
iesolution.
Networking and Multithreading
Once we have a woiking scieen, we will want to post the usei input to the clouu seivice.
Foi that puipose, we aie going to use a thiiu-paity liLiaiy to help us with the Twittei
API weL seivice calls.
Vhile making the netwoik calls, you`ll notice that the UI staits Lehaving sluggishly,
uue to the unpieuictaLle natuie ol the netwoik. The netwoik latency might even cause
oui application to stop iesponuing. At that point, we will intiouuce multithieauing in
Anuioiu anu explain how to uevelop an app that woiks well iegaiuless ol exteinal
ciicumstances.
Debugging Android Apps
A lew things aie going to go wiong in this section ol the Look. This is Ly uesign, Lecause
ueLugging is a noimal pait ol application uevelopment. Ve`ll show you how to use the
Anuioiu SDK tools to guickly linu anu lix pioLlems. DeLugging will Lecome seconu
natuie to you.
Part 2: Preferences, Filesystem, Options Menu, and Intents
This pait, coveieu in Chaptei 7, is all aLout the pieleiences scieen. At the enu ol this
pait, youi YamLa application will have two scieens, one loi status upuates anu the
othei loi setting up the pieleiences. At this point, YamLa is conliguiaLle loi vaiious
useis anu staits Leing a uselul app. The elements we`ll cieate at this stage aie the activity,
the menu system anu intents, anu the lilesystem.
The Activity
Fiist, we`ll cieate the scieen, which is an activity, one ol Anuioiu`s Lasic Luiluing
Llocks. You will see the steps involveu anu unueistanu what it takes to cieate new
scieens.
Part 2: Preferences, Filesystem, Options Menu, and Intents | 41
Menu System and Intents
Next, we`ll neeu a way to get to that scieen. Foi that puipose, we`ll intiouuce a menu
system in Anuioiu anu show how it woiks. You will also leain aLout intents anu how
to senu these to open up a specilic activity.
Filesystem
Finally, we`ll leain aLout the lilesystem on a typical Anuioiu uevice. You will gain a
ueepei unueistanuing ol how the opeiating system is put togethei, anu you will also
leain moie aLout Anuioiu secuiity.
Part 3: Android Services
In this pait, coveieu in Chaptei S, intiouuces Lackgiounu seivices. By the enu ol this
pait, youi YamLa application will Le aLle to peiiouically connect to the clouu anu pull
uown youi liienus` status upuates.
Services
Anuioiu seivices aie veiy uselul Luiluing Llocks. They allow a piocess to iun in the
Lackgiounu without ieguiiing any usei inteilace. This is peilect loi YamLa, as we`ll
have an upuate piocess connect to the clouu peiiouically anu pull the uata. In this
section, you will also leain aLout multithieauing consiueiations as they apply to Lack-
giounu seivices.
Application Object
At this point, we`ll notice iepetition in the coue anu iecognize that oui system is no
longei as elegant as it coulu Le. So we aie going to intiouuce the Application oLject as
a way to ielactoi YamLa anu make it easiei to scale.
Part 4: Working with Databases
Ve now have the uata liom oui upuatei seivice Lut still neeu a place to stoie it. In this
pait, coveieu in Chaptei 9, we`ll intiouuce you to Anuioiu`s suppoit loi uataLases. By
the enu ol that chaptei, oui uata liom the clouu will Le peisisteu in the uataLase.
SQLite and Androids Support for It
Anuioiu ships with a Luilt-in uataLase calleu SQLite. In auuition to this cool little
uataLase, the Anuioiu liamewoik olleis a iich API that makes SQLite easiei loi us to
use. In this section, you will leain how to use SQLite anu the API loi it. You uo not
42 | Chapter 5:Yamba Project Overview
have to Le an SQL Lull to unueistanu what is going on, Lut some Lasic unueistanuing
ol SQL always helps.
Refactoring the Code Again
At this point, we`ll have yet anothei oppoitunity to ielactoi anu stieamline oui coue.
Theie will Le a stiong motivation loi ielactoiing at that moment, anu the elloit will Le
luithei iewaiueu in latei chapteis.
Part 5: Lists and Adapters
It might sounu like we`ie Lack in UI moue, Lut Lists anu Auapteis aie moie oiganiza-
tional aius than usei inteilace elements in Anuioiu. They loim veiy poweilul compo-
nents that allow oui tiny UI to connect to veiy laige uatasets in an ellicient anu scalaLle
mannei. In othei woius, useis will Le aLle to use YamLa in the ieal woilu without any
peiloimance hits in the long iun.
Cuiiently the uata is all theie in the uataLase, Lut we have no way to view it. In this
pait, coveieu in Chaptei 10, the YamLa application will get the much-neeueu Timeline
Activity anu a way loi the usei to see what his liienus aie chatting aLout online.
Timeline Activity
Ve`ie going to uevelop this thiiu anu linal activity in multiple stages. Fiist, we`ll use
oui existing knowleuge ol the Anuioiu UI anu put something togethei. It will woik,
soit ol. Next, we`ll impiove on that uesign. The app will look Lettei, Lut it still won`t
Le ieauy loi the piime time Lecause oui uesign won`t Le aLle to hanule ieal-woilu usage.
Finally, we`ll get it iight Ly intiouucing Lists anu Auapteis to the mix. Finally, we`ll get
it iight Ly intiouucing Lists anu Auapteis to the mix anu use them to tie the uata to
oui usei inteilace.
More Refactoring?
Ve`ll have yet anothei oppoitunity to ielactoi oui coue Ly intiouucing a Lase activity
loi all oui common activity neeus. This will give the usei a moie consistent leel loi the
app acioss multiple scieens anu will make it easiei loi us to manage the coue going
loiwaiu.
Part 6: Broadcast Receivers
In this pait, coveieu in Chaptei 11, we`ll eguip YamLa with ieceiveis so it can ieact to
events aiounu it in an intelligent way. Foi that puipose, we`ll use Lioaucast ieceiveis.
Part 6: Broadcast Receivers | 43
Boot and Network Receivers
In oui example, we want to stait oui upuates when the uevice is poweieu up. Ve also
want to stop pulling the uata liom the clouu when the netwoik is unavailaLle, anu stait
it again only when we`ie Lack online. This goal will intiouuce us to one type ol Lioau-
cast ieceivei.
Timeline Receiver
This type ol ieceivei will exist only at ceitain times. Also, it won`t ieceive messages
liom the Anuioiu system, Lut liom othei paits ol oui own YamLa application. This
will uemonstiate how we can use ieceiveis to put togethei loosely coupleu components
in an elegant anu llexiLle way.
Permissions
At this point in the uevelopment piocess you know how to ask loi system peimissions,
such as access to the Inteinet oi lilesystem. In this section we`ll leain how to ueline oui
own peimissions anu how to enloice them. Altei all, YamLa components might not
want to iesponu to any othei application loi some YamLa-specilic actions.
Part 7: Content Providers
In this pait, coveieu in Chaptei 12, we`ll ievisit content pioviueis anu ielactoi oui
uataLase coue to use them. To uemonstiate that it all woiks, we`ll thiow in an Anuioiu
App Viuget.
Status Data
Oui status uata is OK the way it is il noLouy else caies aLout it. But what il we want
to expose some ol this uata to the iest ol the system? Altei all, othei applications might
leveiage oui liienus` timelines in new anu cieative ways. To uo that, we`ll cieate a
content pioviuei anu expose oui status uata.
Android Widgets
But who will iememLei to pull up oui app? To uemonstiate the uselulness ol oui new
status uata, we`ll put togethei an app wiuget. App wiugets aie those little components
that the usei can put on the home scieen to see weathei upuates anu such. Ve`ll cieate
a wiuget that will pull the latest status upuate liom the YamLa uataLase via the status
uata content pioviuei anu uisplay it on the home scieen.
44 | Chapter 5:Yamba Project Overview
Part 8: System Services
The Anuioiu OS comes with many uselul system seivices, which incluue piocesses you
can access easily to ask loi things such as youi location, sensoi ieauings, ViFi hotspots,
anu much moie. In this pait, coveieu in Chaptei 13, you will auu some cool new leatuies
to YamLa, such as the usei`s cuiient location.
Compass and Location
This example will illustiate how system seivices woik in geneial, anu you will walk
away unueistanuing some common patteins loi using these seivices. Ve`ll illustiate
Luiluing a compass app using sensois, anu latei, we`ll put this knowleuge to use Ly
letting YamLa uisplay the usei`s location when posting status upuates.
Intent Service, Alarms, and Notifications
It tuins out that some ol the cool leatuies pioviueu Ly Anuioiu seivices can make oui
Upuatei seivice much simplei. So we`ll ielactoi oui coue yet again. This time, we`ll
intiouuce Intent Seivices that iesponu to intents. But we`ie going to neeu something
to liie oll these intents on a iegulai Lasis, anu loi that we`ll use the Alaim seivice. Ve`ll
also auu a leatuie to notily the usei ol new upuates Ly putting a notilication in the
notilication Lai. Foi that, we`ll use the Notilication seivice. All this ielactoiing will
cieate a suLstantially moie elegant solution to oui Upuatei seivice neeus.
Summary
This chaptei is intenueu as a ioau map loi the next eight chapteis. By the enu ol all
these iteiations, you will have Luilt a meuium-size Anuioiu app liom sciatch. Even
moie, you will unueistanu vaiious constiucts anu how to put them togethei into a
meaninglul whole. The hope is that you`ll stait ueveloping a way ol thin|ing in Anuioiu.
Summary | 45
CHAPTER 6
Android User Interface
In this chaptei, you will leain how to Luilu a usei inteilace in Anuioiu. You will cieate
youi liist Activity, leain how to cieate an XML layout loi it, anu see how to connect it
to ]ava. You will leain aLout Views (aka wiugets) anu Layouts, anu leain how to hanule
]ava events, such as Lutton clicks. Auuitionally, you`ll auu suppoit loi a Twittei-like
API into youi pioject as an exteinal .jar lile so youi app can make weL seivice calls to
the clouu.
By the enu ol this chaptei, you will have wiitten youi own Twittei-like Anuioiu app.
The app will leatuie a single scieen that will piompt the usei loi hei cuiient status
upuate anu post that upuate online.
Two Ways to Create a User Interface
Theie aie two ways to cieate a usei inteilace (UI) in Anuioiu. One is ueclaiative, anu
the othei one is piogiammatic. They aie guite uilleient Lut olten aie useu togethei to
get the joL uone.
Declarative User Interface
The ueclaiative appioach involves using XML to ueclaie what the UI will look like,
similai to cieating a weL page using HTML. You wiite tags anu specily elements to
appeai on youi scieen. Il you have evei hanucoueu an HTML page, you uiu pietty
much the same woik as cieating an Anuioiu scieen.
One auvantage ol the ueclaiative appioach is that you can use what-you-see-is-what-
you-get (VYSIVYG) tools. Some ol these tools ship with the Eclipse Anuioiu Devel-
opment Tools (ADT) extension, anu otheis come liom thiiu paities. Auuitionally, XML
is laiily human-ieauaLle, anu even people who aie unlamiliai with the Anuioiu plat-
loim anu liamewoik can ieauily ueteimine the intent ol the usei inteilace.
47
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
The uisauvantage ol a ueclaiative UI appioach is that you can get only so lai with XML.
XML is gieat loi ueclaiing the look anu leel ol youi usei inteilace, Lut it uoesn`t pioviue
a goou way ol hanuling usei input. That`s wheie the piogiammatic appioach comes in.
Programmatic User Interface
A piogiammatic usei inteilace involves wiiting ]ava coue to uevelop UI. Il you have
evei uone any ]ava AVT oi ]ava Swing uevelopment, Anuioiu is pietty much the same
in that iespect. It is similai to many UI toolkits in othei languages as well.
Basically, il you want to cieate a Lutton piogiammatically, you have to ueclaie the
Lutton vaiiaLle, cieate an instance ol it, auu it to a containei anu set any Lutton piop-
eities that may make sense, such as coloi, text, text size, Lackgiounu, anu so on. You
pioLaLly also want to ueclaie what the Lutton uoes once it`s clickeu, so that`s anothei
piece ol coue. All in all, you enu up wiiting guite a lew lines ol ]ava.
Eveiything you can uo ueclaiatively, you can also uo piogiammatically. But ]ava also
allows you to specily what happens when that Lutton is actually clickeu. This is the
main auvantage ol a piogiammatic appioach to the usei inteilace.
The Best of Both Worlds
So which appioach to use? The Lest piactice is to use Loth. You woulu use a ueclaiative
(XML) appioach to ueclaie eveiything aLout the usei inteilace that is static, such as
the layout ol the scieen, all the wiugets, etc. You woulu then switch to a piogiammatic
(]ava) appioach to ueline what goes on when the usei inteiacts with the vaiious wiugets
in the usei inteilace. In othei woius, you`u use XML to ueclaie what the Lutton looks
like anu ]ava to specily what it uoes.
Note that theie aie two appioaches to ueveloping the actual usei intei-
lace, Lut at the enu ol the uay, all the XML is actually inllateu into
]ava memoiy space as il you actually wiote ]ava coue. So, it`s only ]ava
coue that iuns.
Views and Layouts
Anuioiu oiganizes its UI elements into layouts anu views. Eveiything you see, such as
a Lutton, laLel, oi text Lox, is a view. Layouts oiganize views, such as giouping togethei
a Lutton anu laLel oi a gioup ol these elements.
Il you have piioi expeiience with ]ava AVT oi Swing, layouts aie similai to ]ava con-
taineis anu views aie similai to ]ava components. Views in Anuioiu aie sometimes
ieleiieu to as wiugets.
48 | Chapter 6:Android User Interface
Don`t conluse wiugets in the Anuioiu UI with App Viugets. The lattei
aie miniatuie application views that can Le emLeuueu in othei appli-
cations (such as the Home scieen application). Heie, we aie ieleiiing to
wiugets as the views in oui activities.
So, a layout can contain othei chiluien. Those chiluien can luitheimoie Le layouts
themselves, allowing loi a complex usei inteilace stiuctuie.
A layout is iesponsiLle loi allocating space loi each chilu. Dilleient layouts use uilleient
appioaches to laying out theii chilu wiugets, as shown in Figuie 6-1.
Iigurc -1. Layouts and \icws rc|ationship
Theie aie seveial main layouts that we use moie lieguently than otheis, such as
LinearLayout, TableLayout, FrameLayout, RelativeLayout, anu AbsoluteLayout.
LinearLayout
LineaiLayout is one ol the simplest anu most common layouts. It simply lays out its
chiluien next to each othei, eithei hoiizontally oi veitically. The oiuei ol the chiluien
matteis. As LineaiLayout asks its chiluien how much space they neeu, it allocates the
uesiieu space to each chilu in the oiuei they aie auueu. So, il an oluei chilu comes
along anu asks loi all the space on the scieen, theie won`t Le much lelt loi the suLse-
guent wiugets in this layout.
One impoitant piopeity loi LineaiLayout is layout_orientation. Its valiu options aie
vertical oi horizontal.
Views and Layouts | 49
Although Lineai Layout is pioLaLly the simplest anu most commonly
useu layout, it is not always the Lest choice. A goou iule ol thumL is
that il you stait to nest multiple Lineai Layouts, you shoulu pioLaLly
use a uilleient layout, such as Relative Layout. Too many nesteu layouts
can have majoi conseguences on the time neeueu to inllate the UI anu
on oveiall CPU anu Latteiy consumption.
TableLayout
TaLleLayout lays out its chiluien in a taLle anu consists ol only othei TaLleRow wiug-
ets. TaLleRow iepiesents a iow in a taLle anu can contain othei UI wiugets. TaLleRow
wiugets aie laiu out next to each othei hoiizontally, soit ol like LineaiLayout with a
hoiizontal oiientation.
Foi those lamiliai with HTML, TaLle Layout is similai to the <table> element, anu
TaLle Row is similai to the <tr> element. Vheieas in HTML we also have <td> to
iepiesent each cell in the taLle, in Anuioiu the columns aie ueteimineu uynamically
Laseu on the numLei ol views we auu to a taLle iow.
An impoitant piopeity loi TaLleLayout is stretch_columns, inuicating which column
ol the taLle to stietch. You can also use * to stietch all columns.
FrameLayout
FiameLayout places its chiluien on top ol each othei so that the latest chilu is coveiing
the pievious, like a ueck ol caius. This layout policy is uselul loi taLs, loi example.
FiameLayout is also useu as a placeholuei loi othei wiugets that will Le auueu pio-
giammatically at some latei point in time.
RelativeLayout
RelativeLayout lays out its chiluien ielative to each othei. As such, it is veiy poweilul
Lecause it uoesn`t ieguiie you to nest unnecessaiy layouts to achieve a ceitain look. At
the same time, using RelativeLayout can minimize the total numLei ol wiugets that
neeu to Le uiawn, thus impioving the oveiall peiloimance ol youi application. Having
saiu that, RelativeLayout ieguiies each ol its chilu views to have an ID set so that we
can position it ielative to othei chiluien.
AbsoluteLayout
ALsoluteLayout positions its chiluien at aLsolute cooiuinates on the scieen. It is the
lavoiite layout loi VYSIVYG tools, anu although it is veiy simple, it is not veiy llexiLle.
Youi usei inteilace woulu look goou on one paiticulai scieen, Lut as soon as the scieen
size, oiientation, oi uensity changeu, ALsoluteLayout woulu not Le aLle to aujust.
50 | Chapter 6:Android User Interface
Starting the Yamba Project
Ve aie aLout to stait oui YamLa pioject. So, liie up Eclipse anu click on
FileNewAnuioiu Pioject.
You will get a uialog winuow asking you aLout youi new Anuioiu pioject (see Fig-
uie 6-2). Let`s explain again all the signilicant lielus:
Projcct nanc
The name unuei which Eclipse oiganizes oui pioject. It is a goou iuea not to use
any spaces in youi pioject name. This makes it easiei to access liom the commanu
line latei. Entei YamLa heie.
Contcnts
Leave this as isset to cieating a new piojectsince that`s what we intenu to uo.
Bui|d Targct
This lielu inuicates the type ol Anuioiu system we intenu to iun this application
on. This coulu Le any Anuioiu platloim, eithei stanuaiu oi piopiietaiy. I assume
we`ie woiking with Anuioiu 2.3 (API level 9) anu thus will choose the Anuioiu 2.3
option.
App|ication nanc
Simply a plain-text name loi youi application. It can Le any text. Foi oui app, leel
liee to entei YamLa.
Pac|agc nanc
This lielu uesignates a ]ava package, anu as such it neeus to auheie to ]ava package
naming conventions. In a nutshell, you want to use the ieveise ol youi uomain
name loi youi package. I`m going to use com.maiakana.yamLa heie.
Crcatc Activity
An option to cieate an activity as pait ol this pioject. You can leave it checkeu.
Foi the activity name, we must auheie to ]ava class naming conventions. Doing
that simply means using uppei CamelCase. I`m going to entei StatusActivity
heie.
Min SDK \crsion
Repiesents the minimum veision ol Anuioiu SDK that must Le installeu on the
uevice loi it to iun this paiticulai application. Typically, this numLei will coiie-
sponu to the API level that you pickeu loi youi taiget, in oui case, Anuioiu 9.
Howevei, il the app uoesn`t uepenu on the latest anu gieatest API oi is capaLle ol
scaling giacelully to a lowei API, you shoulu iethink this numLei. In oui case, the
app will Le aLle to woik on API level + (Anuioiu 1.6), so entei + heie. This is a
goou choice Lecause we can uistiiLute oui app to way moie people than il the
minimum weie Anuioiu 2.3.
Click on Finish. Youi YamLa pioject shoulu now appeai in Eclipse`s Package Exploiei.
Starting the Yamba Project | 51
The StatusActivity Layout
Let`s stait Ly uesigning the usei inteilace loi oui scieen wheie we`ll entei the new status
anu click a Lutton to upuate it.
By uelault, Eclipse cieateu a lile calleu nain.xn| unuei the rcs/|ayout loluei. Foi con-
sistency puiposes, we shoulu iename this lile to status.xn| to match oui StatusActivity.
Iigurc -2. Ncw projcct dia|og
52 | Chapter 6:Android User Interface
To iename a lile in Eclipse, iight-click on it, choose RelactoiRename., anu entei the
new name. Eclipse is somewhat smait aLout ienaming liles anu uoes moie than just
change the name. It also olleis to look up all ieleiences to this lile anu upuate those as
well. Although this leatuie woiks well when ienaming a ]ava lile, it is not lully auto-
matic with XML liles. So, ienaming this lile ieguiies us to change the line in ]ava wheie
we ielei to it via the R class. To uo that, in youi StatusActivity`s onCreate(), change
setContentView(R.layout.main); to setContentView(R.layout.status);.
This scieen will have loui components:
A title at the top ol the scieen. This will Le a TextView wiuget.
A Lig text aiea to type oui 1+0-chaiactei status upuate. Ve`ll use an EditText
wiuget loi this puipose.
A Lutton to click to upuate the status. This will Le a Button wiuget.
A layout to contain all these wiugets anu lay them out one altei anothei in a veitical
lashion. Foi this scieen, we`ll use LinearLayout, one ol the moie common ones.
Example 6-1 contains the souice coue loi oui StatusActivity layout.
Exanp|c -1. rcs/|ayout/status.xn|
<?xml version="1.0" encoding="utf-8"?>
<!-- Main Layout of Status Activity -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Title TextView-->
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:gravity="center"
android:textSize="30sp"
android:layout_margin="10dp" android:text="@string/titleStatus"/>
<!-- Status EditText -->
<EditText android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_weight="1"
android:hint="@string/hintText" android:id="@+id/editText"
android:gravity="top|center_horizontal"></EditText>
<!-- Update Button -->
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/buttonUpdate"
android:textSize="20sp" android:id="@+id/buttonUpdate"></Button>
</LinearLayout>
This coue was geneiateu Ly Eclipse Giaphical Layout, shown in Figuie 6-3. Anuioiu
Development Tools (ADT) loi the Eclipse plug-in pioviues this to help you woik with
Anuioiu-specilic XML liles. Since ADT knows that you aie woiking on a UI layout, it
opens status.xn| in Giaphical Layout moue. You can also view the iaw XML Ly choos-
The StatusActivity Layout | 53
ing the status.xml taL at the Lottom ol this winuow. That will give you the XML souice
coue loi this scieen, as uisplayeu in this example.
Iigurc -3. Graphica| Layout nodc jor status.xn|
Although we uiscusseu the Lasic meanings ol these XML iesouices in a pievious chap-
tei, theie aie some uetails in the coue that you shoulu know moie aLout, which we`ll
examine in the lollowing section.
Important Widget Properties
The piopeities you aie most likely to use iegulaily aie:
layout_height and layout_width
Delines how much space this wiuget is asking liom its paient layout to uisplay
itsell. Although you coulu entei a value in pixels, inches, oi something similai, that
is not a goou piactice. Since youi application coulu iun on many uilleient uevices
with vaiious scieen sizes, you want to use ielative size loi youi components, not
aLsolute. So, Lest piactice woulu Le to use eithei fill_parent oi wrap_content loi
the value. fill_parent means that youi wiuget wants all the availaLle space liom
its paient. wrap_content means that it ieguiies only as much space as it neeus to
uisplay its own content. Note that in API Level S anu highei, fill_parent has Leen
ienameu to match_parent.
54 | Chapter 6:Android User Interface
layout_weight
Layout weight is a numLei Letween 0 anu 1. It implies the weight ol oui layout
ieguiiements. Foi example, il oui Status EditText hau a uelault layout weight ol
0 anu ieguiieu a layout height ol fill_parent, then the Upuate Lutton woulu Le
pusheu out ol the scieen Lecause Status anu its ieguest loi space came Leloie the
Lutton. Howevei, when we set the Status wiuget`s layout weight to 1, we aie saying
we want all availaLle space height-wise, Lut aie yieluing to any othei wiuget that
also may neeu space, such as the Upuate Lutton.
layout_gravity
Specilies how this paiticulai wiuget is positioneu within its layout, Loth hoiizon-
tally anu veitically. Values coulu Le top, center, left, anu so on. Notice the uil-
leience Letween this piopeity anu gravity, explaineu next. Foi example, il you
have a wiuget that has its wiuth set to fill_parent, tiying to centei it woulun`t uo
much, Lecause it`s alieauy taking all availaLle space. Howevei, il oui Title Text
View hau its wiuth set to wrap_content, centeiing it with layout_gravity woulu
geneiate the uesiieu iesults.
gravity
Specilies how the content ol this wiuget is positioneu within the wiuget itsell. It is
commonly conluseu with layout_gravity. Vhich one to use will uepenu on the
size ol youi wiuget anu the uesiieu look. Foi example, il oui Title TextView hau
the wiuth fill_parent, then centeiing it with gravity woulu woik, Lut centeiing
it with layout_gravity woulun`t uo anything.
text
Not all wiugets have this piopeity, Lut many uo, such as Button, EditText, anu
TextView. It simply specilies the text loi the wiuget. Howevei, it is not a goou
piactice to just entei the text, Lecause then youi layout will woik in only one locale/
language. Best piactice is to ueline all text in a strings.xn| iesouice anu ielei to a
paiticulai stiing using this notation: @string/titleStatusUpdate.
id
id is simply the unigue iuentiliei loi this paiticulai wiuget in a paiticulai layout
iesouice lile. Not eveiy wiuget neeus an id, anu I iecommenu iemoving unneces-
saiy ids to minimize cluttei. But wiugets that we`ll neeu to manipulate latei liom
]ava uo neeu ids. id has the loimat @+id/someName, wheie someName is whatevei you
want to call youi wiuget. My naming convention is to use the type lolloweu Ly the
name, loi example, @+id/buttonUpdateStatus.
Strings Resource
Anuioiu tiies haiu to keep uata in sepaiate liles. So, layouts aie uelineu in theii own
iesouices, anu all text values (such as Lutton text, title text, etc.) shoulu Le uelineu in
theii own lile calleu strings.xn|. This latei allows you to pioviue multiple veisions ol
stiings iesouices loi vaiious languages, such as English, ]apanese, oi Russian.
The StatusActivity Layout | 55
Example 6-2 shows what oui strings.xn| lile looks like at this point.
Exanp|c -2. rcs/va|ucs/strings.xn|
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Yamba 1</string>
<string name="titleYamba">Yamba</string>
<string name="titleStatus">Status Update</string>
<string name="hintText">Please enter your 140-character status</string>
<string name="buttonUpdate">Update</string>
</resources>
The lile simply contains sets ol name/value paiis.
I use a ceitain naming convention loi my iesouice names. Let`s look at
titleYamba, loi example. Fiist, I pielix the iesouice with the name ol
what it is, in this case a title ol the activity. Seconu, I give it a name,
YamLa. This naming convention helps keep many uilleient iesouices
soiteu in an easy-to-linu way. Finally, I use CamelCase loi my names,
though some may pielei to use unueiscoies to sepaiate woius.
The StatusActivity Java Class
Now that we have oui UI uesigneu in XML, we aie ieauy to switch ovei to ]ava. Re-
memLei liom eailiei in this chaptei that Anuioiu pioviues two ways loi Luiluing usei
inteilaces. One is Ly ueclaiing it in XML, which is what we just uiu, anu we got as lai
as we coulu (loi now). The othei one is to Luilu it piogiammatically in ]ava. Ve also
saiu eailiei that the Lest piactice is to get as lai as possiLle in XML anu then switch
ovei to ]ava.
Oui ]ava class loi this is StatusActivity.java, anu the Eclipse New Pioject uialog has
alieauy cieateu the stuL loi this class. The class is pait ol the com.marakana.yamba1 ]ava
package, anu as such is pait ol that uiiectoiy.
Creating Your Application-Specific Object and Initialization Code
As with all main Luiluing Llocks in Anuioiu, such as activities, seivices, Lioaucast
ieceiveis, anu content pioviueis, you usually stait Ly suLclassing a Lase class pioviueu
Ly the Anuioiu liamewoik anu oveiiiuing ceitain inheiiteu methous. In this case, we
suLclass Anuioiu`s Activity class anu oveiiiue its onCreate() methou. As you iecall,
activities have a ceitain lile cycle (see Activity Lile Cycle on page 2S), oi state machine
thiough which they go. Ve as uevelopeis uo not contiol what state the activity is in,
Lut we uo get to say what happens uuiing a tiansition to a paiticulai state. In this case,
the tiansition we want to oveiiiue is the onCreate() methou that the system`s
56 | Chapter 6:Android User Interface
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
ActivityManager invokes when the activity is liist cieateu (i.e., when it goes liom a
staiting to a iunning state). This soit ol piogiamming, when we suLclass a system class
anu lill in the Llanks, is also known as the Template pattein.
In auuition to uoing some stanuaiu housekeeping, oui onCreate() will caiiy out two
majoi tasks that the application neeus uone just once, at the Leginning: set up oui
Lutton so it iesponus to clicks anu connect to the clouu.
Notice that onCreate() takes a Bundle as a paiametei. This is a small amount ol uata
that can Le passeu into the activity via the intent that staiteu it. The uata pioviueu in
a Bundle is typically limiteu to Lasic uata types; moie complex ones neeu to Le specially
encoueu. Foi the most pait, we`ie not going to Le using Bundle in oui YamLa example,
as theie`s no ieal neeu loi it.
Keep in minu that whenevei you oveiiiue a methou, you liist want to make a call to
the oiiginal methou pioviueu Ly the paient. That`s why we have a super.onCreate()
call heie.
So, once you suLclass the liamewoik`s class, oveiiiue the appiopiiate methou, anu call
super`s methou in it, you aie still Lack wheie you staiteu: youi coue uoes the same
thing the oiiginal class uiu. But now we have a placeholuei wheie we can auu oui own
coue.
The veiy liist thing we typically uo in an activity`s onCreate() is to loau the UI liom the
XML lile anu inj|atc it into the ]ava memoiy space. In othei woius, we wiite some ]ava
coue that opens up oui XML layout lile, paises it, anu loi each element in XML, cieates
a coiiesponuing ]ava oLject in oui memoiy space. Foi each attiiLute ol a paiticulai
XML element, this coue will set that attiiLute on oui ]ava oLject. This piocess is calleu
inj|ating jron XML, anu the line ol coue that uoes all this is setContentView(R.lay
out.status);.
RememLei that the R class is the automatically geneiateu set ol pointeis that helps
connect the woilu ol ]ava to oui woilu ol XML anu othei iesouices in the /rcs loluei.
Similaily, R.layout.status points to oui /rcs/|ayout/status.xn| lile.
This setContentView() methou uoes a lot ol woik, in othei woius. It ieaus the XML
lile, paises it, cieates all the appiopiiate ]ava oLjects to coiiesponu to XML elements,
sets oLject piopeities to coiiesponu to XML attiiLutes, sets up paient/chilu ielation-
ships Letween oLjects, anu oveiall inllates the entiie view. At the enu ol this one line,
oui scieen is ieauy loi uiawing.
Youi oLjects aie not the only ones that ueline methous anu iesponu to exteinal stimuli.
Anuioiu`s usei inteilace oLjects uo that too. Thus, you can tell youi Button to execute
ceitain coue when its clickeu. To uo that, you neeu to ueline a methou nameu
onClick() anu put the coue theie that you want executeu. You also have to iun the
setOnClickListener methou on the Button. You pass this as an aigument to setOnClick
Listener Lecause youi oLject is wheie you ueline onClick(). Example 6-3 shows oui
The StatusActivity Java Class | 57
liist veision ol StatusActivity.java, with some auuitional explanation lollowing the
coue.
Exanp|c -3. StatusActivity.java, vcrsion 1
package com.marakana.yamba1;
import winterwell.jtwitter.Twitter;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class StatusActivity1 extends Activity implements OnClickListener { //
private static final String TAG = "StatusActivity";
EditText editText;
Button updateButton;
Twitter twitter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.status);
// Find views
editText = (EditText) findViewById(R.id.editText); //
updateButton = (Button) findViewById(R.id.buttonUpdate);
updateButton.setOnClickListener(this); //
twitter = new Twitter("student", "password"); //
twitter.setAPIRootUrl("http://yamba.marakana.com/api");
}
// Called when button is clicked //
public void onClick(View v) {
twitter.setStatus(editText.getText().toString()); //
Log.d(TAG, "onClicked");
}
}
To make StatusActivity capaLle ol Leing a Lutton listenei, it neeus to implement
the OnClickListener inteilace.
Finu views inllateu liom the XML layout anu assign them to ]ava vaiiaLles.
Registei the Lutton to notily this (i.e., StatusActivity) when it gets clickeu.
Connect to the online seivice that suppoits the Twittei API. At this point, we haiu-
coue the useiname anu passwoiu.
58 | Chapter 6:Android User Interface
The methou that is calleu when Lutton is clickeu, as pait ol the OnClickListener
inteilace.
Make the weL seivice API call to the clouu to upuate oui status.
Compiling Code and Building Your Projects: Saving Files
Once you make changes to youi ]ava oi XML liles, make suie you save them Leloie
moving on. Eclipse Luilus youi pioject automatically eveiy time you choose FileSave
oi piess Ctil-S. So, it is impoitant to save liles anu make suie you uo not move to anothei
lile until the cuiient lile is line. You will know youi lile is line when theie aie no little
ieu x symLols in youi coue anu the pioject Luilus successlully. Because ]ava uepenus
on XML anu vice veisa, moving to anothei lile while the cuiient one is Lioken just
makes it even moie uillicult to linu eiiois.
]ava eiiois typically aie easy to linu since the little ieu x in the coue navigates you
stiaight uown to the line numLei wheie the eiioi occuiieu (see Figuie 6-+). By putting
youi mouse iight on that eiioi, Eclipse will tell you what the eiioi is anu will also ollei
you some possiLle lixes. This Eclipse leatuie is veiy uselul anu is analogous to the
spellcheckei in a woiu piocessoi.
Iigurc -1. Tracing java crrors
Adding the jtwitter.jar Library
Ve aie connecting to the online seivice that implements the Twittei-compatiLle API
in oui application. This connection is uone via a seiies ol weL seivice calls. Since An-
uioiu uses stanuaiu ]ava netwoiking capaLilities, Anuioiu uoesn`t ollei much moie
The StatusActivity Java Class | 59
with iespect to weL seivices than we alieauy have in ]ava. So, as such, theie`s little value
in ieinventing the wheel.
To make oui lile with weL seivices anu the Twittei API easiei, we`ie going to use a
thiiu-paity liLiaiy, jtwittcr.jar, pioviueu Ly Vinteiwell Associates. This liLiaiy con-
tains a simple ]ava class that inteiacts with the online seivice anu aLstiacts all the
intiicacies ol making netwoik calls anu passing the uata Lack anu loith. Il no one hau
Leen kinu enough to pioviue a high-level liLiaiy loi what we neeu to uo, we coulu
always use stanuaiu ]ava netwoiking liLiaiies to get the joL uone. It just woulu have
Leen moie woik.
The jtwittcr.jar liLiaiy pioviueu with this coue has Leen slightly moui-
lieu liom the ollicial Vinteiwell veision to make it woik in oui YamLa
pioject.
Once you uownloau this liLiaiy, you can put it insiue youi pioject in Eclipse. Simply
uiag the jtwitter.jar lile anu uiop it in the ioot ol youi Eclipse pioject in the Package
Managei winuow. This makes the lile pait ol the pioject, Lut oui ]ava coue is still unaLle
to locate it.
]ava seaiches loi all the classes in its classpath. To auu jtwittcr.jar to the classpath,
iight-click on youi pioject, select Piopeities, anu you will get a Piopeities loi YamLa
uialog winuow (see Figuie 6-5). Select ]ava Builu Path, anu choose the LiLiaiies taL.
In theie, click on Auu ]ARs. anu locate youi jtwittcr.jar lile.
Iigurc -5. Propcrtics jor Yanba dia|og window in Ec|ipsc, whcrc wc add thc jtwittcr.jar ji|c
60 | Chapter 6:Android User Interface
Updating the Manifest File for Internet Permission
Beloie this application can woik, we must ask the usei to giant us the iight to use the
Inteinet. Anuioiu manages secuiity Ly specilying the peimissions neeueu loi ceitain
uangeious opeiations. The usei then must explicitly giant those peimissions to each
application when he liist installs the application. The usei must giant all oi no pei-
missions that the application asks loi; theie`s no miuule giounu. Also, the usei is not
piompteu aLout peimissions when upgiauing an existing app.
Because we aie iunning this application in ueLug moue anu installing
it via a USB caLle, Anuioiu uoesn`t piompt us loi peimissions like it
woulu the enu usei. Howevei, we still must specily that the application
ieguiies ceitain peimissions.
In this case, we want to ask the usei to giant this application the INTERNET peimission.
Ve neeu Inteinet access to connect to the online seivice. So, open up the
AndroidManijcst.xn|
lile Ly uouLle-clicking on it. Note that Eclipse typically opens this lile in a VYSIVYG
euitoi with many taLs on the Lottom. As always, you can make most ol the changes to
this lile via this inteilace, Lut since Eclipse tools aie limiteu anu sometimes Luggy, we
pielei to go stiaight into the XML view ol this lile. So, choose the iight-most taL at the
Lottom that says AnddroidManijcst.xn|, anu auu a <uses-permission
android:name="android.permission.INTERNET" /> element within the <manifest> Llock
(see Example 6-+).
Exanp|c -1. AndroidManijcst.xn|
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionName="1.0" package="com.marakana.yamba1">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".StatusActivity" android:label="@string/titleStatus">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- -->
</manifest>
Delines the <uses-permission> element loi the INTERNET peimission.
The StatusActivity Java Class | 61
Logging in Android
Anuioiu olleis a system-wiue logging capaLility. You can log liom anywheie in youi
coue Ly calling Log.d(TAG, message), wheie TAG anu ncssagc aie some stiings. TAG
shoulu Le a tag that is meaninglul to you given youi coue. Typically, a tag woulu Le
the name ol youi app, youi class, oi some mouule. Goou piactice is to ueline TAG as
a ]ava constant loi youi entiie class, such as:
private static final String TAG = "StatusActivity";
Beloie youi coue will compile, you neeu to impoit the Log class. Eclipse
has a uselul leatuie unuei SouiceOiganize Impoits, oi Ctil-O loi
shoit. Usually, this leatuie will automatically oiganize youi impoit
statements. Howevei, in the case ol Log, olten theie is a conllict Lecause
theie aie multiple classes nameu Log. This is wheie you have to use youi
common sense anu liguie it out. In this case, the amLiguity is Letween
the Anuioiu Log anu Apache Log classes, so choice shoulu Le easy.
Note that Log takes uilleient seveiity levels. .d() is loi ueLug level, Lut you can also
specily .e() loi eiioi, .w() loi waining, oi .i() loi inlo. Theie`s also a .wtf() seveiity
level loi eiiois that shoulu nevei happen. (It stanus loi Vhat a TeiiiLle Failuie, in case
you weie wonueiing.) Eclipse coloi-coues log messages Laseu on theii seveiity level.
Eclipse`s Oiganize Impoits tool can sometimes leau to haiu-to-linu
pioLlems. Foi example, il youi pioject uoesn`t have R.java geneiateu
(which might happen Lecause theie`s an eailiei pioLlem with one ol the
XML iesouices), then Oiganize Impoits will impoit the android.R class.
This othei R class is pait ol the Anuioiu liamewoik anu has the same
name as youi local R class, making it haiu to notice. So, il you have many
compilation eiiois aiounu youi ieleiences to R iesouices, check that
android.R is not impoiteu.
LogCat
The Anuioiu system log is outputteu to LogCat, a stanuaiuizeu system-wiue logging
mechanism. LogCat is ieauily availaLle to all ]ava anu C/C-- coue. The uevelopei can
easily view the logs anu liltei theii output Laseu on seveiity, such as ueLug, inlo,
waining, oi eiioi, oi Laseu on custom-uelineu tags. As with most things in Anuioiu
uevelopment, theie aie two ways to view the LogCat: via Eclipse oi via the commanu
line.
62 | Chapter 6:Android User Interface
LogCat from the Eclipse DDMS perspective
To view LogCat in Eclipse, you neeu to open the LogCat View (see Figuie 6-6). You
can switch to the DDMS peispective Ly clicking on the DDMS Lutton in the top-iight
coinei ol Eclipse:
oi Ly selecting VinuowOpen PeispectiveDDMS in the Eclipse menu.
DDMS stanus loi Dalvik DeLug Monitoi Seivei. DDMS is the connection Letween youi
application iunning on the uevice anu youi uevelopment enviionment, such as Eclipse.
Iigurc -. LogCat in Ec|ipsc
You can ueline lilteis loi LogCat as well. Click on the little gieen plus Lutton, anu the
LogCat Filtei uialog will come up (see Figuie 6-7). You can ueline a liltei Laseu on a
tag, seveiity level, oi piocess ID. This will cieate anothei winuow within LogCat that
shows you only the log entiies that match youi liltei.
Logging in Android | 63
Iigurc -7. LogCat Ii|tcr
DDMS might not show up in the top-iight coinei il you haven`t useu it
Leloie. Il that`s the case, go to VinuowOpen Peispective anu choose
DDMS theie. Fiom theie on, it shoulu show up in youi winuow taL as
well.
LogCat from the command line
]ust like all the tools, anything you can uo in Eclipse also can Le uone liom the com-
manu line. To view LogCat, open up youi teiminal winuow anu type:
[user:~]> adb logcat
This will give you the tail ol the cuiient LogCat anu will Le upuateu as youi uevice
keeps geneiating log entiies. You can also liltei log entiies on the commanu line, Lut
the syntax is not the most intuitive. To only see StatusActivity-taggeu entiies, you
specily StatusActivity:*, meaning you want all seveiity levels loi this tag. Howevei,
you also have to specily what you uon`t want to see. To uo that, you auu *:S, meaning
silence all othei tags. The lollowing commanu line illustiates that:
[user:~]> adb logcat StatusActivity:* *:S
I linu it uselul to keep a commanu-line winuow open with adb logcat
iunning in it at all times. This makes it easy loi me to guickly see what`s
going on with my app anu is ceitainly much lastei than switching to the
DDMS peispective in Eclipse.
64 | Chapter 6:Android User Interface
Threading in Android
A thieau is a seguence ol instiuctions executeu in oiuei. Although each CPU can pioc-
ess only one instiuction at a time, most opeiating systems aie capaLle ol hanuling
multiple thieaus on multiple CPUs, oi inteileaving them on a single CPU. Dilleient
thieaus neeu uilleient piioiities, so the opeiating system ueteimines how much time
to give each one il they have to shaie a CPU.
The Anuioiu opeiating system is Laseu on Linux anu as such is lully capaLle ol iunning
multiple thieaus at the same time. Howevei, you neeu to Le awaie ol how applications
use thieaus in oiuei to uesign youi application piopeily.
Single Thread
By uelault, an Anuioiu application iuns on a single thieau. Single-thieaueu applications
iun all commanus seiially, meaning the next commanu is not completeu until the pie-
vious one is uone. Anothei way ol saying this is that each call is b|oc|ing.
This single thieau is also known as the UI thieau Lecause it`s the thieau that piocesses
all the usei inteilace commanus as well. The UI thieau is iesponsiLle loi uiawing all
the elements on the scieen as well as piocessing all the usei events, such as touches on
the scieen, clicks ol the Lutton, anu so on. Figuie 6-S shows the execution ol oui coue
on a single UI thieau.
Iigurc -8. Sing|c-thrcadcd cxccution
The pioLlem with iunning StatusActivity on the single thieau is oui netwoik call to
upuate the status. As with all netwoik calls, the time it takes to execute is outsiue ol
oui contiol. Oui call to twitter.updateStatus() is suLject to all the netwoik availaLility
anu latency issues. Ve uon`t know whethei the usei is on a supei-last ViFi connection
oi is using a much slowei piotocol to connect to the clouu. In othei woius, oui appli-
cation cannot iesponu until the netwoik call is completeu.
The Anuioiu system will ollei to kill any application that is not ie-
sponuing within a ceitain time peiiou, typically aiounu live seconus loi
activities. This is known as the Application Not Responuing uialog, oi
ANR loi shoit (see Figuie 6-9).
Threading in Android | 65
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Iigurc -9. App|ication Not Rcsponding dia|og
Multithreaded Execution
A much Lettei solution is to have the potentially long opeiations iun on a sepaiate
thieau. Vhen multiple tasks iun on multiple thieaus at the same time, the opeiating
system slices the availaLle CPU so that no one task uominates the execution. As a iesult,
it appeais that multiple tasks aie iunning in paiallel at the same time.
In oui example, we coulu put the actual netwoik call loi upuating oui status in the
clouu in a sepaiate thieau. That way oui main UI thieau will not Llock while we`ie
waiting loi the netwoik, anu the application will appeai much moie iesponsive. Ve
tenu to talk ol the main thieau as iunning in the loiegiounu anu the auuitional thieaus
as iunning in the Lackgiounu. They`ie ieally all egual in status, alteinating theii exe-
cution on the uevice`s CPU, Lut liom the point ol view ol the usei, the main thieau is
in the loiegiounu Lecause it ueals with the UI. Figuie 6-10 shows the execution ol oui
coue`s two thieausthe main UI thieau, as well as the auxiliaiy thieau we use to
peiloim potentially long-iunning netwoik calls.
Iigurc -10. Mu|tithrcadcd cxccution
Theie aie multiple ways ol accomplishing multithieauing. ]ava has a Thread class that
allows loi many ol these opeiations. Ve coulu ceitainly use any ol the iegulai ]ava
leatuies to put the netwoik call in the Lackgiounu.
Howevei, using the stanuaiu ]ava Thread class is pioLlematic Lecause anothei thieau
is not alloweu to upuate the elements in the main UI thieau. This makes sense Lecause
to upuate the UI thieau, we woulu neeu to synchionize with the cuiient state ol its
oLjects, anu that woulu Le a joL on its own.
In auuition to stanuaiu ]ava thieauing suppoit, Anuioiu pioviues the utility class
AsyncTask specilically uesigneu loi this puipose.
66 | Chapter 6:Android User Interface
AsyncTask
AsyncTask is an Anuioiu mechanism cieateu to help hanule long opeiations that neeu
to iepoit to the UI thieau. To take auvantage ol this class, we neeu to cieate a new
suLclass ol AsyncTask anu implement the doInBackground(), onProgressUpdate(), anu
onPostExecute() methous. In othei woius, we aie going to lill in the Llanks loi what to
uo in the Lackgiounu, what to uo when theie`s some piogiess, anu what to uo when
the task completes.
Ve`ll extenu oui eailiei example with an asynchionous posting to the clouu. The liist
pait ol Example 6-5 is veiy similai to the coue in Example 6-3, Lut hanus oll the posting
to the asynchionous thieau. A new AsyncTask uoes the posting in the Lackgiounu.
Exanp|c -5. StatusActivity.java, vcrsion 2
package com.marakana.yamba1;
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class StatusActivity2 extends Activity implements OnClickListener {
private static final String TAG = "StatusActivity";
EditText editText;
Button updateButton;
Twitter twitter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.status);
// Find views
editText = (EditText) findViewById(R.id.editText);
updateButton = (Button) findViewById(R.id.buttonUpdate);
updateButton.setOnClickListener(this);
twitter = new Twitter("student", "password");
twitter.setAPIRootUrl("http://yamba.marakana.com/api");
}
// Asynchronously posts to twitter
class PostToTwitter extends AsyncTask<String, Integer, String> { //
// Called to initiate the background activity
Threading in Android | 67
@Override
protected String doInBackground(String... statuses) { //
try {
Twitter.Status status = twitter.updateStatus(statuses[0]);
return status.text;
} catch (TwitterException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return "Failed to post";
}
}
// Called when there's a status to be updated
@Override
protected void onProgressUpdate(Integer... values) { //
super.onProgressUpdate(values);
// Not used in this case
}
// Called once the background activity has completed
@Override
protected void onPostExecute(String result) { //
Toast.makeText(StatusActivity2.this, result, Toast.LENGTH_LONG).show();
}
}
// Called when button is clicked
public void onClick(View v) {
String status = editText.getText().toString();
new PostToTwitter().execute(status); //
Log.d(TAG, "onClicked");
}
}
The PostToTwitter class in this case is an innei class ol StatusActivity. It also suL-
classes AsyncTask. Notice the use ol ]ava geneiics to uesciiLe the uata types that this
AsyncTask will use in its methous. I`ll explain these thiee types next. The liist uata
type is useu Ly doInBackground, the seconu Ly onProgressUpdate, anu the thiiu Ly
onPostExecute.
doInBackground() is the callLack that specilies the actual woik to Le uone on the
sepaiate thieau, as il it`s executing in the Lackgiounu. The aigument String... is
the liist ol the thiee uata types that we uelineu in the list ol geneiics loi this innei
class. The thiee uots inuicate that this is an aiiay ol Strings, anu you have to ueclaie
it that way, even though you want to pass only a single status.
onProgressUpdate() is calleu whenevei theie`s piogiess in the task execution. The
piogiess shoulu Le iepoiteu liom the doInBackground() call. In this case, we uo not
have any meaninglul piogiess to iepoit. Il this example weie insteau a lile uownloau,
loi instance, this coulu iepoit the peicentage ol completion oi amount ol uata
68 | Chapter 6:Android User Interface
uownloaueu thus lai. The actual uata typein this case, Integerieleis to the
seconu aigument in the geneiics uelinition ol this class.
onPostExecute() is calleu when oui task completes. This is oui callLack methou to
upuate the usei inteilace anu tell the usei that the task is uone. In this paiticulai
case, we aie using a Toast leatuie ol the Anuioiu UI to uisplay a guick message on
the scieen. Notice that Toast uses the makeText() static methou to make the actual
message. Also, uo not loiget to incluue show(); otheiwise, youi message will nevei
Le uisplayeu, anu theie won`t Le any eiioisa haiu Lug to linu. The aigument that
this methou gets is the value that doInBackground() ietuins, in this case a Stiing. This
also coiiesponus to the thiiu geneiics uatatype in the class uelinition.
Once we have oui AsyncTask set up, we can use it. To use it, we simply instantiate
it anu call execute() on it. The aigument that we pass in is what goes into the
doInBackground() call. Note that in this case we aie passing a single stiing that is
Leing conveiteu into a stiing aiiay in the actual methou latei on, which is an example
ol ]ava`s vaiiaLle numLei ol aiguments leatuie.
At this point, when the usei clicks on the Upuate Status Lutton, oui activity will cieate
a sepaiate thieau using AsyncTask anu place the actual netwoik opeiation on that
thieau. Vhen uone, the AsyncTask will upuate the main UI thieau Ly popping up a
Toast message to tell the usei that the opeiation eithei succeeueu oi laileu. This ap-
pioach makes oui application much moie iesponsive, anu useis shoulu nevei get the
Application Not Responuing: Foice Close oi Vait message shown in Figuie 6-9. At
this point, oui application looks like Figuie 6-11 when iunning.
Iigurc -11. StatusActivity, part 1
Threading in Android | 69
Other UI Events
So lai, you have seen how to hanule the click events Ly implementing OnClick
Listener anu pioviuing the onClick() methou, which is invokeu when the Lutton is
clickeu. Imagine that we want to pioviue a little countei telling the usei how many
chaiacteis ol input aie still availaLle out ol the maximum ol 1+0. To uo that, we neeu
anothei type ol listenei.
Anuioiu pioviues many uilleient listeneis loi vaiious events, such as touch, click, anu
so on. In this case, we`ie going to use TextWatcher to watch loi text changes in the euit
text lielu. Steps loi this listenei aie similai to the steps loi OnClickListener anu many
othei listeneis.
Fiom the usei`s stanupoint, we`ll auu anothei TextView to oui layout to inuicate how
many chaiacteis aie still availaLle. This text will change coloi, liom gieen to yellow to
ieu, as the usei appioaches the 1+0-chaiactei limit.
In ]ava, we`ll implement TextWatcher anu attach it to the lielu wheie the usei is typing
the actual text. The TextWatcher methous will Le invokeu as the usei changes the text,
anu Laseu on the amount ol text enteieu, we`ll upuate the countei. See Example 6-6.
Exanp|c -. rcs/|ayout/status2.xn|
<?xml version="1.0" encoding="utf-8"?>
<!-- Main Layout of Status Activity -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Title TextView-->
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:gravity="center"
android:text="@string/titleStatus" android:textSize="30sp"
android:layout_margin="10dp" />
<!-- Text Counter TextView -->
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="right"
android:id="@+id/textCount" android:text="000"
android:layout_marginRight="10dp" />
<!-- Status EditText -->
<EditText android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_weight="1"
android:hint="@string/hintText" android:id="@+id/editText"
android:gravity="top|center_horizontal"></EditText>
<!-- Update Button -->
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/buttonUpdate"
android:textSize="20sp" android:id="@+id/buttonUpdate"></Button>
70 | Chapter 6:Android User Interface
</LinearLayout>
New TextView that iepiesents how many chaiacteis aie still availaLle loi the usei to
type. Ve stait at 1+0 anu then go uown as the usei enteis text.
The veision ol StatusActivity shown in Example 6-7 implements the TextWatcher in-
teilace, anu the new methous in this example appeai at the enu ol the class. Initially
the text ol the countei is in gieen to inuicate we can keep on typing. As we appioach
the maximum, the text tuins yellow anu eventually changes to ieu to inuicate we aie
Leyonu the maximum message size.
Exanp|c -7. StatusActivity.java, jina| vcrsion
package com.marakana.yamba1;
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class StatusActivity extends Activity implements OnClickListener,
TextWatcher { //
private static final String TAG = "StatusActivity";
EditText editText;
Button updateButton;
Twitter twitter;
TextView textCount; //
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.status);
// Find views
editText = (EditText) findViewById(R.id.editText);
updateButton = (Button) findViewById(R.id.buttonUpdate);
updateButton.setOnClickListener(this);
textCount = (TextView) findViewById(R.id.textCount); //
textCount.setText(Integer.toString(140)); //
textCount.setTextColor(Color.GREEN); //
Other UI Events | 71
editText.addTextChangedListener(this); //
twitter = new Twitter("student", "password");
twitter.setAPIRootUrl("http://yamba.marakana.com/api");
}
// Called when button is clicked
public void onClick(View v) {
String status = editText.getText().toString();
new PostToTwitter().execute(status);
Log.d(TAG, "onClicked");
}
// Asynchronously posts to twitter
class PostToTwitter extends AsyncTask<String, Integer, String> {
// Called to initiate the background activity
@Override
protected String doInBackground(String... statuses) {
try {
Twitter.Status status = twitter.updateStatus(statuses[0]);
return status.text;
} catch (TwitterException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return "Failed to post";
}
}
// Called when there's a status to be updated
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Not used in this case
}
// Called once the background activity has completed
@Override
protected void onPostExecute(String result) {
Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG).show();
}
}
// TextWatcher methods
public void afterTextChanged(Editable statusText) { //
int count = 140 - statusText.length(); //
textCount.setText(Integer.toString(count));
textCount.setTextColor(Color.GREEN); //
if (count < 10)
textCount.setTextColor(Color.YELLOW);
if (count < 0)
textCount.setTextColor(Color.RED);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { //
}
72 | Chapter 6:Android User Interface
public void onTextChanged(CharSequence s, int start, int before, int count) { //
}
}
Ve ueclaie that StatusActivity now implements TextWatcher. This means we neeu
to actually pioviue the implementation loi this inteilace, which we uo latei on in
this class.
textCount is oui text view, uelineu in Example 6-6.
Fiist, we neeu to linu the textCount in the inllateu layout.
Ve set the initial text to 140 Lecause that`s the maximum length ol a status message
in oui app. Note that TextView takes text as value, so we conveit a numLei to text
heie.
The textCount lielu will change coloi uynamically Laseu on the numLei ol iemaining
chaiacteis. In this case, we stait with gieen. Notice that the Color class is pait ol the
Anuioiu liamewoik anu not ]ava. In othei woius, we`ie using android.graph
ics.Color anu not java.awt.Color. Color.GREEN is one ol the lew colois uelineu as a
constant in this class (moie on colois in the next section).
Heie we attach TextWatcher to oui editText lielu. In othei woius, editText will call
the TextWatcher instance, in this case this, which ieleis to this oLject itsell.
afterTextChanged() is one ol the methous pioviueu Ly the TextWatcher inteilace.
This methou is calleu whenevei the text changes in the view that this TextWatcher is
watching. In oui case, whenevei the usei changes the unueilying text in editText,
this methou is invokeu with the cuiient text.
Heie we uo some math to liguie out how many chaiacteis aie lelt, given the 1+0-
chaiactei limit.
Next, Laseu on the availaLility ol the text, we upuate the coloi ol the countei. So, il
moie than 10 chaiacteis aie availaLle, we aie still in the gieen. Fewei than 10 means
we aie appioaching the limit, thus the countei tuins yellow. Il we aie past the limit
ol 1+0 chaiacteis, the countei tuins ieu.
This methou is calleu just Leloie the actual text ieplacement is completeu. In this
case, we uon`t neeu this methou, Lut as pait ol implementing the TextWatcher in-
teilace, we must pioviue its implementation, event though it`s empty.
Similaily, we aie not using onTextChanged() in this case, Lut must pioviue its Llank
implementation.Figuie 6-12 shows what the TextVatchei looks like in oui appli-
cation when iunning.
Other UI Events | 73
Iigurc -12. StatusActivity, part 1
Adding Color and Graphics
Oui application woiks well, Lut it`s a Lit uull looking. A little Lit ol coloi anu some
giaphics coulu go a long way. Anuioiu olleis a lot ol suppoit to make youi application
snazzy. Ve`ie going to see some Lasics heie.
Adding Images
Foi staiteis, we want to auu a Lackgiounu to oui scieen. This Lackgiounu is going to
Le some kinu ol giaphics lile. In Anuioiu, most images go to a iesouice loluei calleu
drawab|c. You may notice that you alieauy have thiee lolueis with this name:
/rcs/drawab|c-hdpi loi uevices with high-uensity scieens
/rcs/drawab|c-ndpi loi uevices with meuium-uensity scieens
/rcs/drawab|c-|dpi loi uevices with low-uensity scieens
Ve aie going to cieate anothei drawab|c loluei calleu simply /rcs/drawab|c. To uo that,
iight-click on the rcs loluei anu choose NewFoluei. Foi the name, entei drawab|c.
You can now put youi giaphics that aie inuepenuent ol scieen uensity in this loluei.
Ve`ie going to assume you lounu some cool Lackgiounu giaphics anu that you saveu
the lile in this new loluei unuei the name bac|ground.png. Although Anuioiu suppoits
many uilleient lile loimats, PNG is pieleiieu to the GIF stanuaiu Lecause PNG is loss-
less anu uoesn`t ieguiie any patent licenses.
74 | Chapter 6:Android User Interface
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Although PNG ollicially stanus loi PoitaLle Netwoik Giaphics, it is also
commonly known as PNG`s Not Gil, to iellect its uepaituie liom the
contioveisial GIF stanuaiu.
RememLei that all iesouices aie Leing watcheu Ly Eclipse, anu the moment we put
something in theie, Eclipse will use its Anuioiu SDK tools to upuate the R class auto-
matically. So at this point, we`ll have a ieleience to R.drawable.background anu coulu
use this iesouice liom ]ava. But we won`t.
Ve aie going to upuate the status activity layout lile rcs/|ayout/status.xn| next. Oui
goal is to make this Lackgiounu lile the Lackgiounu giaphic loi the entiie scieen. To
uo that, we`ll upuate the top layout in oui lile anu set its Lackgiounu to point to this
new Lackgiounu PNG lile, which means we have to open the status.xn| layout. Now
we have two ways ol auuing the Lackgiounu to the top layout.
Using the WYSIWYG editor in Eclipse
One way is to use Eclipse`s VYSIVYG tool, as shown in Figuie 6-13. In this tool, we
neeu to liist select the main layout, which might Le uillicult since many othei compo-
nents aie in liont ol it. The ieu Loiuei inuicates which view oi layout is selecteu.
Anothei way ol making youi selection is to open up youi Outline view in Eclipse anu
select the top element theie. This view might not Le cuiiently visiLle in youi Eclipse,
uepenuing on how you aiiangeu the many availaLle winuows. One suie way to get the
Outline view is to go to VinuowShow ViewOutline anu open it up that way. Once
you open this view, you can select the top layout, in this case oui LineaiLayout. You
will know it`s selecteu il a ieu Loiuei is aiounu youi entiie activity.
Next, you want to open up the Piopeities view in Eclipse. Again, this view might alieauy
Le openeu, Lut il it`s not visiLle as a winuow in Eclipse, go to VinuowShow
ViewOthei, anu unuei the Geneial section, pick Piopeities. This will open up a view
in which you can change vaiious piopeities loi this paiticulai view.
The piopeity we want to mouily is bac|ground. You can now click on the little .
Lutton, which will Liing up the Releience Choosei uialog (see Figuie 6-1+). In this
uialog, choose DiawaLleBackgiounu.
This will set the Lackgiounu ol youi top layout to @drawable/background. As you iecall,
this is the way that one XML iesouice ieleis to anothei iesouice. In this case, oui
status.xn| layout is ieleiiing to the bac|ground.png uiawaLle. Notice that we uo not
use extensions when ieleiiing to othei lile iesouices. Anuioiu liguies out the Lest
lile loimat automatically, in case theie aie liles with the same name Lut uilleient
extensions.
Adding Color and Graphics | 75
Updating directly in XML code
Anothei appioach is to go stiaight into the XML coue anu make changes theie. Re-
memLei that eveiything you can uo with Eclipse tools, you can also uo in a plain-text
euitoi. To switch to the XML coue view, select the status.xml taL at the Lottom ol the
winuow, next to the Layout taL. This will open up the lile with youi stanuaiu XML
euitoi.
In this case, to auu the Lackgiounu iesouice to oui entiie activity, we simply auu
android:background="@drawable/background" to oui <LinearLayout> element.
Fiom now on, we`ie going to Le making changes uiiectly in the XML coue Lecause it`s
much simplei to explain. Also, the VYSIVYG euitoi can uo only so much, anu olten
you iun into its limitations.
Adding Color
Ve now have the Lackgiounu loi the entiie scieen, Lut what aLout the actual text Lox
that useis type the text into? The cuiient uesign is stock. Ve coulu impiove on it Ly
auuing some coloi anu tianspaiency.
Iigurc -13. Ec|ipsc Graphica| Layout Editor
76 | Chapter 6:Android User Interface
Anuioiu uses the stanuaiu RGB coloi set, Lut it also optionally expanus it with an
Alpha channel. So, you can expiess coloi as RGB oi ARGB, wheie A is the amount ol
tianspaiency, R is the amount ol ieu, G is loi gieen, anu B stanus loi Llue. The com-
Lination ol these thiee colois anu optional tianspaiency gives you eveiy conceivaLle
coloi liom white to Llack, anu liom opague to lully tianspaient! That`s the whole point
ol ARGB. Ol couise, the gianulaiity isn`t exactly what Monet woulu Le happy with;
each value has only 256 possiLilities.
Amounts ol each channel can Le iepiesenteu eithei as values Letween 0 anu 255 oi Ly
using the hexauecimal system values Letween 0 anu FF. So, the actual values coulu Le
AARRGGBB, wheie each lettei can Le ieplaceu with a value Letween 0 anu F. Theie`s
also a shoitei veision ol ARGB, wheie each value is iepeateu. Foi example, =3A9F is
the same as =33AA99FF anu coiiesponus to =33 loi alpha, =AA loi ieu, =99 loi gieen,
anu =FF loi Llue. Notice that we use the = symLol in liont ol hexauecimal values to
uistinguish them liom uecimal values.
So, we coulu upuate the Lackgiounu ol oui EditText element to Le #cfff, which is a
somewhat tianspaient white coloi.
Next, we can upuate the coloi ol the title text Ly changing the textColor piopeity loi
that TextView. A goou coloi woulu Le white, loi example. One way to specily white is
#fff, Lut alteinatively we coulu entei @android:color/white. The android: pait ol that
Iigurc -11. Rcjcrcncc Chooscr
Adding Color and Graphics | 77
statement ieleis to the Anuioiu opeiating system`s set ol iesouices, in this case a pie-
uelineu coloi white. Example 6-S shows these new auuitions to oui status.xn| coue.
Exanp|c -8. rcs/|ayout/status.xn|
<?xml version="1.0" encoding="utf-8"?>
<!-- Main Layout of Status Activity -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="@drawable/background"><!-- -->
<!-- Title TextView-->
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:gravity="center"
android:text="@string/titleStatus" android:textSize="30sp"
android:layout_margin="10dp" android:textColor="@android:color/white" /><!-- -->
<!-- Text Counter TextView -->
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="right"
android:id="@+id/textCount" android:text="000"
android:layout_marginRight="10dp" />
<!-- Status EditText -->
<EditText android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_weight="1"
android:hint="@string/hintText" android:id="@+id/editText"
android:gravity="top|center_horizontal" android:background="#cfff" /><!-- -->
<!-- Update Button -->
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/buttonUpdate"
android:textSize="20sp" android:id="@+id/buttonUpdate" />
</LinearLayout>
Ve set the Lackgiounu ol the main layout to point to the bac|ground.png lile in
oui /rcs/drawab|c/ uiiectoiy.
Ve set the coloi ol the title text to point to the coloi uelineu in the system coloi
iesouice white.
Ve set the Lackgiounu ol the EditText aiea to a tianspaient white Ly specilying
#cfff, a hexauecimal ARGB value.
At this point you`ve seen multiple ways to specily colois loi uilleient piopeities ol
vaiious views in youi activity. Anuioiu olleis many piopeities anu many uilleient
wiugets. You shoulu Le aLle to extiapolate liom this how to set othei piopeities anu
make youi application UI look exactly the way you want.
78 | Chapter 6:Android User Interface
Alternative Resources
Anuioiu suppoits multiple competing sets ol iesouices. Foi example, you coulu have
multiple veisions ol a strings.xn| lile, status.xn| layout, oi bac|ground.png image. You
might want multiple veisions ol same iesouice so that the Lest veision can Le useu
unuei uilleient ciicumstances. Ve toucheu on this in Auuing Images on page 7+.
Imagine that youi application is useu in anothei countiy with a uilleient language. In
that case, you coulu pioviue a strings.xn| veision specilically loi that language. Oi
imagine that a usei iuns youi application on a uilleient uevice, with a uilleient scieen
that has moie pixels. In that case, you`u want veisions ol youi images specilically loi
this scieen`s pixel uensity. Similaily, useis might simply iotate the uevice liom poitiait
to lanuscape moue. Oui application will ieuiaw piopeily, Lut theie aie luithei en-
hancements we coulu make to the layout ol the UI given the oiientation ol the scieen.
Anuioiu pioviues loi all these cases in an elegant way. Basically, you simply neeu to
cieate alteinative lolueis loi specilic constiaints. Foi example, oui stanuaiu layout
liles go into the /rcs/|ayout loluei, Lut il we wanteu to pioviue an alteinative layout
specilically loi lanuscape moue, we`u simply cieate a new lile calleu /rcs/|ayout-|and/
status.xn|. Anu il you wanteu to pioviue a tianslateu veision ol youi strings.xn| lile
loi useis who aie in a Fiench-speaking pait ol Canaua, you`u put it in lile calleu rcs/
va|ucs-jr-rCA/strings.xn|.
As you see liom these examples, alteinative iesouices woik Ly specilying the gualilieis
in the names ol theii iesouice lolueis. In the case ol the Fiench Canauian stiings, An-
uioiu knows that the liist gualiliei -fr ieleis to language, anu the seconu gualiliei
-rCA specilies that the iegion is Canaua. In Loth cases, we use two-lettei ISO coues to
specily the countiy. So in this case, il the usei is in QueLec anu hei uevice is conliguieu
to lavoi the Fiench language, Anuioiu will look loi stiing iesouices in the /rcs/va|ucs-
jr-rCA/strings.xn| ji|c. Il it uoesn`t linu a specilic iesouice, it will lall Lack to the ue-
lault /rcs/va|ucs/strings.xn| lile. Also, il the usei in Fiance, in this case Anuioiu will use
the uelault iesouice, Lecause oui Fiench Canauian gualilieis uo not match Fiench loi
Fiance.
Using gualilieis, you can cieate alteinative iesouices loi languages anu iegions, scieen
sizes anu oiientations, uevice input moues (touch scieen, stylus), keyLoaiu oi no key-
Loaiu, anu so on. But how uo you liguie out this naming convention loi iesouice loluei
names? The easiest solution is to use Eclipse`s New Anuioiu XML File uialog (see
Figuie 6-15). To open the New Anuioiu XML File uialog, choose FileNew.Anuioiu
XML File liom the Eclipse menu.
Alternative Resources | 79
Iigurc -15. A|tcrnativc rcsourccs with Ncw Android XML Ii|c dia|og
Optimizing the User Interface
The usei inteilace is one ol the most expensive paits ol a typical Anuioiu application.
To cieate a simple scieen, youi application has to inllate the XML liom iesouices. Foi
each element, it has to cieate a new ]ava oLject anu assign its piopeities to it. Then, it
neeus to uiaw each wiuget on the scieen. All this takes many computing cycles.
Given this, it is woith keeping in minu lew optimization points. You may want to tiy
to limit the numLei ol wiugets you have on the scieen. This is specially tiue when you
aie using nesteu layouts to achieve a uesiieu look. This layout appioach can sometimes
get out ol contiol, anu il you aie nesting unnecessaiy oLjects in a loop (say, uisplaying
iows ol uata on the scieen), then the numLei ol wiugets guickly exploues, anu youi
usei inteilace Lecomes sluggish.
80 | Chapter 6:Android User Interface
Geneially, you want youi stiuctuie to Le llat insteau ol ueep. You can accomplish this
Ly ieplacing nesteu layouts with ielative layouts.
Hierarchy Viewer
Theie`s a veiy uselul tool that ships with the Anuioiu SDK calleu Hieiaichy Viewei
(see Figuie 6-16). Go aheau anu stait it; it is in youi SDK/too|s uiiectoiy.
Hieiaichy Viewei allows you to attach to any Anuioiu uevice, emulatoi, oi physical
phone anu then intiospect the stiuctuie ol the cuiient view. It shows you all the wiugets
cuiiently loaueu in memoiy, theii ielationships to each othei, anu all theii piopeities.
You can intiospect not just youi scieens, Lut the scieens ol any application on youi
uevice. This is also a goou way to see how some othei applications aie stiuctuieu.
Iigurc -1. Hicrarchy \icwcr
Optimizing the User Interface | 81
Summary
By the enu ol this section, youi application shoulu iun anu shoulu look like Fig-
uie 6-17. It shoulu also successlully post youi tweets to youi Twittei account. You can
veiily it is woiking Ly logging into an online seivice ol youi choice that suppoits the
Twittei API, such as http://yanba.nara|ana.con, using the same useiname anu pass-
woiu that aie haiucoueu in the application.
Iigurc -17. StatusActivity
Figuie 6-1S illustiates what we have uone so lai as pait ol the uesign outlineu in
Figuie 5-+.
Iigurc -18. Yanba conp|ction
82 | Chapter 6:Android User Interface
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
CHAPTER 7
Preferences, the Filesystem,
the Options Menu, and Intents
In this chaptei, you will leain how to cieate pieleiences loi youi application, how the
lilesystem is oiganizeu, anu how to use intents anu the options menu to jump liom one
activity to anothei.
Preferences
Pieleiences aie usei-specilic settings loi an application. Pieleiences usually consist ol
some conliguiation uata as well as a usei inteilace to manipulate that uata.
Fiom the usei inteilace point ol view, pieleiences can Le simple text values, check-
Loxes, selections liom a pull-uown menu, oi similai items. Fiom a uata point ol view,
pieleiences aie a collection ol name-value paiis, also known as key-value oi attiiLute-
value paiis. The values aie Lasic uata types, such as integeis, Looleans, anu stiings.
Oui micio-Llogging application neeus to connect to a specilic seivei in the clouu using
specilic usei account inloimation. Foi that, YamLa neeus to know the useiname anu
passwoiu loi that account as well as the URL ol the seivei it`s connecting to. This URL
is also known as the API ioot. So, in oui case, we`ll have thiee lielus wheie the usei can
entei anu euit his useiname, passwoiu, anu the API ioot. This uata will Le stoieu as
stiings.
To enaLle oui app to hanule usei-specilic pieleiences, we neeu to Luilu a scieen to
entei the inloimation, ]ava coue to valiuate anu piocess that inloimation, anu some
kinu ol mechanism to stoie this inloimation.
All this sounus like a lot ol woik, Lut Anuioiu pioviues a liamewoik to help stieamline
woiking with usei pieleiences. Fiist, we`ll ueline what oui pieleience uata looks like
in a Pieleience iesouice lile.
To cieate pieleiences loi oui application, we neeu to:
83
1. Cieate a Pieleience iesouice lile calleu prcjs.xn|.
2. Implement the PrcjsActivity.java lile that inllates that iesouice lile.
3. Registei this new activity with the AndroidManijcst.xn| lile.
+. Pioviue a way to stait that activity liom the iest ol the application.
Prefs Resource
Ve aie going to stait Ly cieating prcjs.xn|, a iesouice lile that outlines what oui piel-
eience scieen will look like. The easiest way to cieate it is to use the New Anuioiu XML
File tool in Eclipse, as shown in Figuie 7-1. To stait the New Anuioiu XML File uialog,
go to FileNewAnuioiu XML File, oi click on the little a- icon in Eclipse`s top menu
Lai:
The key is to give the new lile a name, in this case prcjs.xn|, anu to choose Pieleience
loi the type ol iesouice. The tool shoulu automatically suggest cieating this new lile in
the /rcs/xn| loluei anu that the ioot element loi the XML lile shoulu Le
PreferenceScreen. As uiscusseu Leloie in Alteinative Resouices on page 79, we coulu
cieate alteinative veisions ol this same iesouice Ly applying vaiious gualilieis, such as
scieen size anu oiientation, language anu iegion, etc.
Ve`ie using Eclipse tools wheie applicaLle to get the joL uone moie
guickly. Il you weie to use anothei tool, you`u have to cieate this lile
manually anu put it in the coiiect loluei.
Once you click on Finish, Eclipse will cieate a new lile loi you anu open it up. Eclipse
typically opens the XML liles it knows aLout in its uevelopei-liienuly view.
In this view, you can cieate the useiname pieleience entiy Ly selecting PieleienceScieen
on the lelt, anu then choosing AuuEuitTextPieleience. On the iight-hanu siue, ex-
panu the AttiiLutes liom Pieleiences section. Eclipse will ollei you a numLei ol
attiiLutes to set loi this EditTextPreference.
Not all attiiLutes aie egually impoitant. Typically, you will caie aLout the lollowing:
Kcy
A unigue iuentiliei loi each pieleience item. This is how we`ll look up a paiticulai
pieleience latei.
Tit|c
The pieleience name that the usei will see. It shoulu Le a shoit name that lits on
a single line ol the pieleience scieen.
Sunnary
A shoit uesciiption ol this pieleience item. This is optional, Lut using it is highly
iecommenueu.
84 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
Foi the useiname pieleience, we`ll put useiname loi its key. Ve will ueline the Title
anu Summaiy in strings.xn|, as this is the Lest piactice.
Insteau ol mouilying the strings.xn| lile uiiectly, you can use an Eclipse shoitcut. Heie`s
how it goes:
1. Click on Biowse anu select New Stiing.. This will open a uialog to cieate a new
stiing iesouice.
2. Entei titleUsername loi the R.stiing. value anu Username loi the Stiing value.
3. Click OK, anu this will inseit a new stiing iesouice in strings.xn|.
+. You can now pick that value liom the list ol iesouices.
Using these instiuctions loi auuing the Useiname pieleience item, you can now iepeat
the same steps loi Passwoiu anu API Root items.
You can switch to the actual XML coue Ly clicking on the taL at the Lottom ol the
winuow, shown in Figuie 7-2.
Iigurc 7-1. Ncw Android XML Ii|c
Preferences | 85
Iigurc 7-2. Prcjs.xn| in dcvc|opcr-jricnd|y vicw
The iaw XML loi the pieleience iesouice looks like the coue shown in Example 7-1.
Exanp|c 7-1. rcs/xn|/prcjs.xn|
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference android:title="@string/titleUsername"
android:summary="@string/summaryUsername" android:key="username"></EditTextPreference>
<EditTextPreference android:title="@string/titlePassword"
android:password="true" android:summary="@string/summaryPassword"
android:key="password"></EditTextPreference>
<EditTextPreference android:title="@string/titleApiRoot"
android:summary="@string/summaryApiRoot" android:key="apiRoot"></EditTextPreference>
</PreferenceScreen>
<PreferenceScreen> is the ioot element that uelines oui main pieleience scieen. It has
thiee chiluien, all <EditTextPreference>. This is simply a piece ol euitaLle text. Othei
common elements heie coulu Le <CheckBoxPreference>, <ListPreference>, anu so on.
The main piopeity ol any ol these elements is the key. The key is how we`ll look up
these values latei on. RememLei, pieleiences is just a set ol name-value paiis at the enu
ol the uay.
86 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
Like we saiu a couple ol times eailiei, although Eclipse uoes pioviue uevelopei-liienuly
tools to manage XML liles, you olten iun into ceitain limitations with Eclipse. Foi
example, we woulu like to hiue the actual text that the usei types in the passwoiu lielu,
which is a common piactice. Anuioiu uoes pioviue suppoit loi that, Lut Eclipse tools
haven`t yet integiateu this lunction. Since we can always euit the XML uiiectly, in this
case we auu an android:password="true" piopeity to oui passwoiu piopeity. This will
cause the passwoiu to Le maskeu while the usei types it in.
PrefsActivity
Now that we have the pieleiences uelineu in theii own XML iesouice lile, we can cieate
the activity to uisplay these pieleiences. You may iecall liom <<Activities> that eveiy
scieen in an Anuioiu app is an activity. So, to uisplay the scieen wheie a usei enteis
the useiname anu passwoiu loi his online account, we`ll cieate an activity to hanule
that scieen. This will Le a special pieleience-awaie activity.
To cieate an activity, we cieate a new ]ava class. In Eclipse, select youi package unuei
youi src loluei, iight-click on the package, anu select NewClass. A New ]ava Class
winuow will pop up. You just neeu to entei PrefsActivity loi the Name anu click
Finish. This will cieate a PrcjsActivity.java lile unuei youi package in youi souice loluei.
Oui PrefsActivity class, shown in Example 7-2, is a veiy simple ]ava lile. This is Le-
cause we inheiit liom PreferenceActivity, an Anuioiu liamewoik class that knows
how to hanule pieleiences.
Exanp|c 7-2. PrcjsActivity.java
package com.marakana.yamba2;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class PrefsActivity extends PreferenceActivity { //
@Override
protected void onCreate(Bundle savedInstanceState) { //
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs); //
}
}
Unlike iegulai activities, PrefsActivity will suLclass (i.e., extenu) the Preference
Activity class.
]ust like any othei activity, we oveiiiue the onCreate() methou to initialize the
activity.
Unlike iegulai activities that usually call setContentView(), oui pieleience activity
will set its content liom the prcjs.xn| lile via a call to addPreferencesFromResource().
Preferences | 87
Il you uon`t want to type the long signatuie ol onCreate() anu othei
methous that we olten have to implement oi oveiiiue, you coulu use an
Eclipse tool to help you with that. Vhile in youi PrcjsActivity.java lile
anu altei you auu ...extends PreferenceActivity..., you can choose
SouiceOveiiiue/Implement Methous.. This will Liing up a uialog
Lox with an appiopiiate selection ol methous you coulu oveiiiue oi
implement, given that you aie suLclassing the PreferenceActivity class.
In heie, you can choose onCreate(), anu Eclipse will inseit the stuL loi
this methou into youi coue.
Update the Manifest File
Vhenevei we cieate one ol these main Luiluing Llocks (Activities, Seivices, Bioaucast
Receiveis, oi Content Pioviueis), we neeu to ueline them in the AndroidManijcst.xn|
lile. In this case, we have a new PrefsActivity anu must auu it to the manilest lile.
]ust like with any Anuioiu XML lile, opening AndroidManijcst.xn| in Eclipse typically
will Liing up the uevelopei-liienuly view ol that lile. In this lile view, you coulu choose
the Application taL, anu then unuei Application Noues, choose AuuActivity anu
name it .PrefsActivity.
Howevei, we can also uo this stiaight liom the iaw XML Ly clicking on the Anuioiu-
Manilest.xml taL on the Lottom ol this winuow. I linu that Eclipse is uselul when it
comes to cieating XML liles, Lut olten euiting the iaw XML is lastei anu gives you
much moie contiol.
Vhen euiting coue in Eclipse, you can use the Ctil-space Lai key shoit-
cut to invoke the type-aheau leatuie ol Eclipse. This is veiy uselul loi
Loth XML anu ]ava coue anu is context-sensitive, meaning Eclipse is
smait enough to know what coulu possiLly Le enteieu at that point in
the coue. Using Ctil-space Lai makes youi lile as a piogiammei much
easiei Lecause you uon`t have to iememLei long methou names anu
tags, anu it helps avoiu typos.
So oui manilest lile now looks like the coue shown in Example 7-3.
Exanp|c 7-3. AndroidManijcst.xn|
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionName="1.0" package="com.marakana.yamba2">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".StatusActivity" android:label="@string/titleStatus">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
88 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
</activity>
<activity android:name=".PrefsActivity"
android:label="@string/titlePrefs" /> <!-- -->
</application>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Delines the new PrefsActivity.
Ve now have a new pieleience activity, Lut theie`s no goou way ol getting to it yet.
Ve neeu a way to launch this new activity. Foi that, we use the options menu.
The Options Menu
The options menu is an Anuioiu usei inteilace component that pioviues stanuaiuizeu
menus to applications. The menus appeai at the Lottom ol the scieen when the usei
piesses the Menu Lutton on the uevice.
To auu suppoit loi the options menu to an application, we neeu to uo the lollowing:
1. Cieate the ncnu.xn| iesouice wheie we specily what the menu consists ol.
2. Auu onCreateOptionsMenu() to the activity that shoulu have this menu. This is
wheie we inllate the ncnu.xn| iesouice.
3. Pioviue hanuling ol menu events in onOptionsItemSelected().
The Menu Resource
Ve stait Ly uelining the menus in an XML iesouice loi the options menu. ]ust like
with othei Anuioiu XML liles, we can use the little a- icon in the Eclipse toolLai oi
choose FileNew.Anuioiu XML to launch the New Anuioiu XML File uialog. In
this uialog, entei menu.xml in the lile lielu, anu loi Type, select Menu. Click the
Finish Lutton, anu Eclipse will cieate a new loluei calleu /rcs/ncnu that contains the
ncnu.xn| lile anu will open this lile in the uevelopei-liienuly view (see Figuie 7-3).
In this view, you can click on AuuItem, which will auu a new menu item to youi
menu. In the AttiiLutes section on the iight, you can see ovei a uozen attiiLutes that
we can set loi this menu item. ]ust like Leloie, not all attiiLutes aie egually impoitant:
|d
The unigue iuentiliei ol this iesouice. ]ust as when we uesigneu the layout in
Chaptei 6, this iuentiliei is typically ol the loim @+id/someId , wheie someId is the
name that you give it. This name shoulu contain only letteis, numLeis, anu the
unueiscoie chaiactei.
The Options Menu | 89
Tit|c
The title ol this menu as it will appeai on the uisplay. Keep in minu that scieen
space typically is limiteu, so keep the title shoit. Auuitionally, you can pioviue a
Title conuenseu attiiLute to specily a shoitei veision ol the title that will Le
shown insteau il space is limiteu. ]ust like Leloie, Lest piactice is to ueline the
actual text value ol the title in the strings.xn| iesouice anu just ieleience it heie.
|con
The icon that uisplays along with the menu item`s title. Although not ieguiieu, it
is a veiy uselul visual cue liom a usaLility point ol view. In this case it also illustiates
how to point to Anuioiu system iesouices.
The next section uesciiLes these iesouices in moie uetail.
Android System Resources
]ust like youi application can have iesouices, so can the Anuioiu system. Like most
othei opeiating systems, Anuioiu comes with some pieloaueu images, giaphics, sounu
clips, anu othei types ol iesouices. Recall that oui app iesouices aie in /rcs/. To ielei
to Anuioiu system iesouices, pielix them with the android: keywoiu in XML, loi ex-
ample, @android:drawable/ic_menu_preferences. Il you aie ieleiiing to an Anuioiu sys-
tem iesouice liom ]ava, then you use android.R insteau ol the usual R ieleience.
Iigurc 7-3. Mcnu.xn| in dcvc|opcr-jricnd|y vicw
90 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
The actual iesouice liles aie in youi SDK, insiue a specilic platloim
loluei. Foi example, il you aie using Anuioiu 9 (GingeiLieau), the ie-
souice loluei woulu Le android-sdk/platforms/android-9/data/res/.
The iaw XML ol ncnu.xn| is shown in Example 7-+.
Exanp|c 7-1. rcs/ncnu/ncnu.xn|
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/itemPrefs" android:title="@string/titlePrefs"
android:icon="@android:drawable/ic_menu_preferences"></item>
</menu>
As you can see, theie`s just one <item> element within oui <menu> element, making this
a single-item menu.
Update StatusActivity to Load the Menu
Recall that the options menu is loaueu Ly youi activity when the usei clicks on hei
uevice`s Menu Lutton. The liist time the Menu Lutton is piesseu, the system will call
the activity`s onCreateOptionsMenu() methou to inllate the menu liom the ncnu.xn|
iesouice. This piocess is similai to inllating the usei inteilace liom layout iesouices,
uiscusseu in The StatusActivity ]ava Class on page 56. Basically, the inj|atcr ieaus
the XML coue, cieates a coiiesponuing ]ava oLject loi each element, anu sets each XML
oLject`s piopeities accoiuingly.
Fiom that point on, the menu is in memoiy, anu onCreateOptionsMenu() uoesn`t get
calleu again until the activity is uestioyeu. Each time the usei selects a menu item,
though, onOptionsItemSelected() gets calleu to piocess that click. Ve`ll talk aLout this
in the next section.
Ve neeu to upuate the StatusActivity to loau up the options menu. To uo that, auu
an onCreateOptionsMenu() methou to StatusActivity. This methou gets calleu only the
liist time the usei clicks on the menu Lutton:
// Called first time user clicks on the menu button
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater(); //
inflater.inflate(R.menu.menu, menu); //
return true; //
}
Ve get the MenuInflater oLject liom the context.
Use the inllatei to inllate the menu liom the XML iesouice.
Ve must ietuin true loi this menu to Le uisplayeu.
The Options Menu | 91
Update StatusActivity to Handle Menu Events
Ve also neeu a way to hanule vaiious clicks on the menu items. To uo that, we auu
anothei callLack methou, onOptionsItemSelected(). This methou is calleu eveiy time
the usei clicks on a menu item:
// Called when an options item is clicked
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { //
case R.id.itemPrefs:
startActivity(new Intent(this, PrefsActivity.class)); //
break;
}
return true; //
}
Since the same methou is calleu iegaiuless ol which item the usei clicks, we neeu to
liguie out the ID ol that item, anu Laseu on that, switch to a specilic case to hanule
each item. At this point, we have only one menu item, Lut that might change in the
lutuie. Switching an item ID is a veiy scalaLle appioach anu will auapt nicely as oui
application giows in complexity.
The startActivity() methou in context allows us to launch a new activity. In this
case, we aie cieating a new intent that specilies staiting the PrefsActivity class.
Retuin true to consume the event heie.
]ust like Leloie, you coulu use the Eclipse shoitcut SouiceOveiiiue/
Implement Methous to auu Loth onCreateOptionsMenu() anu
onOptionsItemSelected().
Strings Resource
Oui upuateu strings.xn| now looks like the coue shown in Example 7-5.
Exanp|c 7-5. rcs/va|ucs/strings.xn|
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Yamba 2</string>
<string name="titleYamba">Yamba 2</string>
<string name="hintText">Please enter your 140-character status</string>
<string name="buttonUpdate">Update</string>
<string name="titleStatus">Status Update</string>
<string name="titlePrefs">Prefs</string>
<string name="titleUsername">Username</string>
<string name="titlePassword">Password</string>
92 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
<string name="titleApiRoot">API Root</string>
<string name="summaryUsername">Please enter your username</string>
<string name="summaryPassword">Please enter your password</string>
<string name="summaryApiRoot">URL of Root API for your service</string>
</resources>
You shoulu Le aLle to iun youi application at this point anu see the new Prefs
Activity Ly clicking on MenuPiels in StatusActivity (see Figuie 7-+). Tiy changing
youi useiname anu passwoiu, then ieLoot youi phone, iestait the app, anu veiily that
the inloimation is still theie.
Iigurc 7-1. PrcjsActivity
Shared Preferences
Now that we have a pieleience activity anu a way to save oui useiname, passwoiu, anu
API ioot, it is time to make use ol it. To piogiammatically access youi pieleiences, we`ll
use the SharedPreference class pioviueu Ly the Anuioiu liamewoik.
This class is calleu SharedPreference Lecause this pieleience is easily accessiLle liom
any component ol this application (activities, seivices, Lioaucast ieceiveis, anu content
pioviueis).
In StatusActivity, auu a uelinition loi the prefs oLject gloLally to the class:
SharedPreferences prefs;
Now, to get the pieleience oLject, auu the lollowing to onCreate():
@Override
public void onCreate(Bundle savedInstanceState) {
...
// Setup preferences
Shared Preferences | 93
prefs = PreferenceManager.getDefaultSharedPreferences(this); //
prefs.registerOnSharedPreferenceChangeListener(this); //
}
Each application has its own shaieu pieleiences availaLle to all components ol
this application context. To get the instance ol this SharedPreferences, we
use PreferenceManager.getDefaultSharedPreferences() anu pass it this as the cui-
ient context loi this app. The name shaieu coulu Le conlusing. To claiily, it means
that this pieleience oLject contains uata shaieu Ly vaiious paits ol this application
only; it is not shaieu with any othei application.
The usei can anu will change pieleiences. So we neeu a mechanism to notily this
activity that the olu values aie stale. To uo that, we iegistei this, meaning oui
StatusActivity with oui shaieu pieleiences. Foi this to woik, we`ll neeu to
auu ...implements OnSharedPreferenceChangeListener to oui class uelinition as well
as implement the ieguiieu onSharedPreferenceChanged() methou. This methou will
Le explaineu in a Lit.
Now that we have the useiname, passwoiu, anu API ioot coming liom usei-uelineu
pieleiences, we can ielactoi oui Twittei coue so it no longei haiucoues them. To uo
that, we auu a piivate methou to StatusActivity iesponsiLle loi ietuining a valiu
twitter oLject. This methou lazily initializes twitter, which means that il twitter ex-
ists, it ietuins it as-is; otheiwise, the methou cieates it:
private Twitter getTwitter() {
if (twitter == null) { //
String username, password, apiRoot;
username = prefs.getString("username", ""); //
password = prefs.getString("password", "");
apiRoot = prefs.getString("apiRoot", "http://yamba.marakana.com/api");
// Connect to twitter.com
twitter = new Twitter(username, password); //
twitter.setAPIRootUrl(apiRoot); //
}
return twitter;
}
Only il twitter is null (i.e., unuelineu), we cieate it.
Get the useiname anu passwoiu liom the shaieu pieleience oLject. The liist pa-
iametei in getString() is the key we assigneu to each pieleience item, such as
username anu password. The seconu aigument is the uelault value in case such a
pieleience is not lounu. Keep in minu that the liist time a usei iuns youi application,
the pieleience lile uoesn`t exist, so uelaults will Le useu. So, il the usei hasn`t set up
hei pieleiences in PrefsActivity, this coue will attempt to log in with an empty
useiname anu passwoiu, anu thus lail. Howevei, the lailuie will happen when the
usei tiies to uo the actual status upuate Lecause that`s how the jtwittcr liLiaiy is
uesigneu.
Ve log into the Twittei seivice with usei-uelineu pieleiences.
94 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
RememLei that we neeu to upuate the actual seivice that we aie using Ly upuating
the API ioot URL loi that seivice.
Now we uon`t use the twitter oLject uiiectly anymoie, Lut insteau call getTwitter()
to get it. So, onClick() Lecomes like this:
public void onClick(View v) {
// Update twitter status
try {
getTwitter().setStatus(editText.getText().toString());
} catch (TwitterException e) {
Log.d(TAG, "Twitter setStatus failed: " + e);
}
}
Note that although we moveu the coue wheie we initialize oui connection to the clouu,
we still neeu the AsyncTask to ueal with the lact that this call is still Llocking anu may
take a while to complete, as it`s suLject to netwoik availaLility anu latency.
As we mentioneu Leloie when upuating onCreate() anu iegisteiing loi pieleience up-
uates, we neeu to hanule what happens when the usei changes his useiname oi pass-
woiu. By iegisteiing prefs.registerOnSharedPreferenceChangeListener(this) in
onCreate() anu implementing OnSharedPreferenceChangeListener, we got a callLack
methou onSharedPreferenceChanged() that the system will invoke whenevei pieleien-
ces change. In this methou, we simply invaliuate the twitter oLject, so the next time
it is neeueu, getTwitter() will iecieate it:
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// invalidate twitter object
twitter = null;
}
The Filesystem Explained
So, wheie uoes the uevice stoie these pieleiences? How secuie is my useiname anu
passwoiu? To answei that, we neeu to look at how the Anuioiu lilesystem is oiganizeu.
Exploring the Filesystem
Theie aie two ways loi you to access the lilesystem on an Anuioiu uevice: via Eclipse
oi the commanu line.
In Eclipse, we use the File Exploiei view to access the lilesystem. To open up the File
Exploiei view, go to VinuowShow ViewOthei.AnuioiuFile Exploiei. You can
also access the File Exploiei view via the DDMS peispective. Select the DDMS pei-
spective icon in the top-iight coinei ol Eclipse:
The Filesystem Explained | 95
oi go to VinuowOpen PeispectiveOthei.DDMS. Il you have multiple uevices
connecteu to youi woikstation, make suie you select which one you aie woiking with
in the Devices view. You shoulu now Le aLle to navigate thiough the uevice`s lilesystem.
Il you pielei the commanu line, you can always use adb shell to get to the shell ol the
uevice. Fiom theie you can exploie the lilesystem like you woulu on any othei Unix
platloim.
Filesystem Partitions
Theie aie thiee main paits ol the lilesystem on eveiy Anuioiu uevice. As shown in
Figuie 7-5, they aie:
The system paitition (/systcn/)
The SDCaiu paitition (/sdcard/)
The usei uata paitition at (/data/)
System Partition
Youi entiie Anuioiu opeiating system is locateu in the system paitition. This is the
main paitition that contains all youi pieinstalleu applications, system liLiaiies, An-
uioiu liamewoik, Linux commanu-line tools, anu so on.
The system paitition is mounteu ieau-only, meaning that you as uevelopei have veiy
little inlluence ovei it. As such, this paitition is ol limiteu inteiest to us.
The system paitition in the Emulatoi coiiesponus to the systcn.ing lile in youi platloim
images uiiectoiy, locateu in the android-sd|/p|atjorns/android-8/inagcs/ loluei.
SDCard Partition
The SDCaiu paitition is a liee-loi-all mass stoiage aiea. Youi app can ieau liles liom
this paitition as well as wiite liles to it il it holus WRITE_TO_EXTERNAL_STORAGE peimission.
This is a gieat place to stoie laige liles, such as music, photos, viueos, anu similai items.
Note that since the FioYo veision ol Anuioiu, the /sdcard mount point appeais in the
Eclipse File Exploiei unuei the /nnt/sdcard location. This is uue to the new leatuie in
FioYo that allows loi stoiing anu iunning applications on the SDCaiu as well.
As an app uevelopei, the SDCaiu paitition is veiy uselul anu impoitant to you. At the
same time, this paitition is not veiy stiuctuieu.
This paitition typically coiiesponus to sdcard.ing in youi Anuioiu Viitual Device
(AVD) uiiectoiy. This uiiectoiy is in youi -/.android/avd/ loluei anu will have a suL-
uiiectoiy loi each specilic viitual uevice. On the physical uevice, it is an actual SD caiu.
96 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
The User Data Partition
As usei anu app uevelopei, the most impoitant paitition is the usei uata paitition. This
is wheie all youi usei uata is stoieu, all the uownloaueu apps aie locateu, anu most
impoitantly, all the applications` uata. This incluues Loth pieinstalleu apps as well as
usei-uownloaueu apps.
So, while usei apps aie stoieu in the /data/app/ loluei, the most impoitant loluei to us
as app uevelopeis is the /data/data/ loluei. Moie specilically, within this loluei theie`s
a suLloluei coiiesponuing to each app. This loluei is iuentilieu Ly the ]ava package
Iigurc 7-5. Thc ji|csystcn as sccn via Ii|c Exp|orcr in Ec|ipsc
The Filesystem Explained | 97
that this app useu to sign itsell. Again, this is why ]ava packages aie impoitant to
Anuioiu secuiity.
The Anuioiu liamewoik pioviues a numLei ol hanuy methous as pait ol its context
that help you access the usei uata lilesystem liom within youi application. Foi example,
take a look at getFilesDir().
This paitition typically coiiesponus to uscr-data.ing in youi Anuioiu Viitual Device
(AVD) uiiectoiy. As Leloie, this uiiectoiy is in youi -/.android/avd/ loluei anu will have
a suLuiiectoiy loi each specilic viitual uevice.
Vhen you cieate a new app, you assign youi ]ava coue to a specilic package. Typically,
this package lollows the ]ava convention ol ieveise uomain name plus app name. Foi
example, the YamLa app is in the com.marakana.yamba package. So, once installeu,
Anuioiu cieates a special loluei just loi this app unuei /data/data/con.nara|ana
.yanba/. This loluei is the coineistone ol oui piivate, secuieu lilesystem ueuicateu to
each app.
Theie will Le suLlolueis in /data/data/con.nara|ana.yanba2/, Lut they aie
well-uelineu. Foi example, the pieleiences aie in /data/data/con.nara|ana.yanba2/
sharcd_prcjs/. As a mattei ol lact, il you open up the DDMS peispective in Eclipse anu
select File Exploiei, you can navigate to this paitition. You will pioLaLly see the
con.nara|ana.yanba2_prcjcrcnccs.xn| lile in theie. You coulu pull this lile anu ex-
amine it, oi you coulu use adb shell.
adb shell is anothei one ol those common adb suLcommanus to access the shell ol youi
uevice (eithei physical oi viitual). Foi instance, you coulu just open up youi commanu-
line teiminal anu type:
[user:~]> adb shell
# cd /data/data/com.marakana.yamba2/shared_prefs
# cat com.marakana.yamba2_preferences.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="password">password</string>
<string name="apiRoot">http://yamba.marakana.com/api</string>
<string name="username">student</string>
</map>
#
This XML lile iepiesents the stoiage loi all oui pieleience uata loi this application. As
you can see, oui useiname, passwoiu, anu API ioot aie all stoieu in theie.
Filesystem Security
So, how secuie is this? This is a common guestion poseu Ly secuiity lolks. Stoiing
useinames anu passwoius in cleai text always iaises eyeLiows.
To answei this guestion, I usually compaie it to linuing someone`s laptop on the stieet.
Although we can easily gain access to the haiu uiive via the adb tool, that uoesn`t
98 | Chapter 7:Preferences, the Filesystem, the Options Menu, and Intents
mean we can ieau its uata. Each loluei unuei /data/data/ Lelongs to a sepaiate usei
account manageu Ly Linux. Unless oui app is that app, it won`t have access to that
loluei. So, shoit ol us ieauing Lyte-Ly-Lyte on the physical uevice, even cleai-text uata
is secuie.
On the Emulatoi, we have root peimissions, meaning we can exploie the entiie lile-
system. This is uselul loi uevelopment puiposes.
Summary
At this point, the usei can specily hei useiname anu passwoiu loi the micio-Llogging
site. This makes the app usaLle to way moie people than the pievious veision in which
this inloimation was haiucoueu.
Figuie 7-6 illustiates what we have uone so lai as pait ol the uesign outlineu eailiei in
Figuie 5-+.
Iigurc 7-. Yanba conp|ction
Summary | 99
CHAPTER 8
Services
Seivices aie among the main Luiluing Llocks in Anuioiu. Unlike an activity, a seivice
uoesn`t have a usei inteilace; it is simply a piece ol coue that iuns in the Lackgiounu
ol youi application.
Seivices aie useu loi piocesses that shoulu iun inuepenuently ol activities, which may
come anu go. Oui YamLa application, loi example, neeus to cieate a seivice to peii-
ouically connect to the clouu anu check loi new statuses liom the usei`s liienus. This
seivice will Le always on anu always iunning, iegaiuless ol whethei the usei evei staits
the activity.
]ust like an activity, a seivice has a well-uelineu lile cycle. You as the uevelopei get to
ueline what happens uuiing tiansitions Letween states. Vheieas an activity`s state is
manageu Ly the iuntime`s ActivityManager, seivice state is contiolleu moie Ly intents.
Essentially, whenevei an activity neeus youi seivice, it will invoke it thiough an intent
that staits the seivice. An alieauy iunning seivice can ieceive the stait message iepeat-
euly anu at unanticipateu times. You can also stop a seivice, which is also calleu ue-
stioying it.
A seivice can Le Lounu oi unLounu. Bounu seivices can pioviue moie specilic APIs to
othei applications via an inteilace calleu AIDL (Anuioiu Inteilace Delinition Language;
see Chaptei 1+). Foi now, we`ll locus on unLounu seivices, wheie the lile cycle ol a
seivice is not tieu to the lile cycle ol the activities that staiteu them. The only states loi
Lounu seivices aie staiteu anu stoppeu (uestioyeu).
In this chaptei, you will cieate a seivice. The puipose ol this seivice is to iun in the
Lackgiounu anu upuate youi app with the latest timeline liom the usei`s Twittei ac-
count. Initially, the seivice will just piint youi liienus` timeline to the loglile. The seivice
will cieate a sepaiate thieau, so you will leain aLout concuiiency in this chaptei as well.
You will also leain aLout Toasts anu unueistanu the context in which seivices anu
activities iun.
By the enu ol this chaptei, you will have a woiking app that can Loth post to Twittei
anu peiiouically check what liienus aie up to.
101
The Yamba Application Object
Ve now have suppoit loi pieleiences in oui StatusActivity. Ve also have the utility
methou getTwitter() to help us get the actual Twitter oLject that we use to connect to
the online seivice.
It is likely that we`ll neeu some ol these leatuies in othei paits ol oui application. Insteau
ol copying them liom lile to lile, it woulu Le uselul il we coulu put this coue in a sepaiate
place that is accessiLle Ly most paits ol oui app. Anuioiu pioviues just a place loi that
in the loim ol an Application oLject.
An Application oLject iepiesents the common state ol youi entiie application. As long
as any pait ol youi application is iunning, the application oLject will Le cieateu. Most
applications use the uelault android.app.Application class that the liamewoik pio-
viues. Howevei, you can implement youi own instance ol this oLject anu auu the com-
mon app leatuies to it.
Ve aie going to cieate oui own instance ol this oLject anu call it YambaApplication. The
steps loi cieating the YambaApplication class aie:
1. Cieate the ]ava class iepiesenting YambaApplication.
2. Registei the new class with the AndroidManijcst.xn| lile.
The YambaApplication Class
Fiist, we aie going to cieate a new ]ava class in the same package as the iest ol oui
classes. Ve`ll call this class YambaApplication, anu it will extenu the Application Lase
class liom the liamewoik.
Next, we`ie going to move common tasks into this Lase oLject. Ve anticipate that moie
paits ol oui application aie going to neeu to connect to the online seivice as well as
ieau the pieleience uata.
Notice in Example S-1 that the Application oLject has the usual onCreate() methou,
Lut it also pioviues the onTerimante() callLack as a place to implement any cleanup
that we might want to uo. At this point we uon`t have anything to clean up, Lut this is
a goou oppoitunity to cieate some logging inloimation so we can see when the appli-
cation actually shuts uown. Ve might expanu on this latei.
Exanp|c 8-1. YanbaApp|ication.java
package com.marakana.yamba3;
import winterwell.jtwitter.Twitter;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.text.TextUtils;
102 | Chapter 8:Services
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
import android.util.Log;
public class YambaApplication1 extends Application implements
OnSharedPreferenceChangeListener { //
private static final String TAG = YambaApplication1.class.getSimpleName();
public Twitter twitter; //
private SharedPreferences prefs;
@Override
public void onCreate() { //
super.onCreate();
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
this.prefs.registerOnSharedPreferenceChangeListener(this);
Log.i(TAG, "onCreated");
}
@Override
public void onTerminate() { //
super.onTerminate();
Log.i(TAG, "onTerminated");
}
public synchronized Twitter getTwitter() { //
if (this.twitter == null) {
String username = this.prefs.getString("username", "");
String password = this.prefs.getString("password", "");
String apiRoot = prefs.getString("apiRoot",
"http://yamba.marakana.com/api");
if (!TextUtils.isEmpty(username) && !TextUtils.isEmpty(password)
&& !TextUtils.isEmpty(apiRoot)) {
this.twitter = new Twitter(username, password);
this.twitter.setAPIRootUrl(apiRoot);
}
}
return this.twitter;
}
public synchronized void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) { //
this.twitter = null;
}
}
Foi YambaApplication to Le a valiu application oLject, it must suLclass the liame-
woik-pioviueu Application class. Notice that we also moveu iesponsiLility loi Leing
the OnSharedPreferenceChangeListener liom StatusActivity to YambaApplication.
Twitter anu SharedPreferences aie now pait ol this common oLject anu no longei
pait ol StatusActivity.
onCreate() is calleu when the application is liist cieateu. The application is cieateu
whenevei any ol its paits, such as an activity oi a seivice, is liist neeueu.
The Yamba Application Object | 103
onTerminate() is a placeholuei loi us to uo some cleanup when the application is
aLout to shut uown. At this point, we just use it loi logging puiposes.
Ve also moveu getTwitter() liom StatusActivity to YambaApplication Lecause it`s
going to Le useu Ly othei paits ol oui application anu we want to maximize the coue
ieuse. Notice the use ol the synchronized keywoiu heie. A synchionizeu methou in
]ava means that only one thieau can Le insiue ol such a methou at one time. This is
now impoitant Lecause this methou coulu Le useu Ly uilleient thieaus that oui
application might have.
onSharedPreferenceChanged() is now also pait ol YambaApplication insteau ol
StatusActivity.
Now that we have YambaApplication anu have moveu some iesponsiLilities liom
StatusActivity to this new class, we can simplily StatusActivity even luithei, as shown
in Example S-2.
Exanp|c 8-2. StatusActivity using YanbaApp|ication
...
Twitter.Status status = ((YambaApplication) getApplication())
.getTwitter().updateStatus(statuses[0]); //
...
Ve now use the getTwitter() methou liom YambaApplication insteau ol keeping it
locally. This way, the same methou can Le ieuseu Ly othei paits ol the application
that neeu access to the clouu seivice.
Update the Manifest File
The linal step is to tell oui application to use the YambaApplication class insteau ol the
uelault Application class. To uo that, we neeu to upuate the Anuioiu manilest lile anu
auu an attiiLute to the <application> element:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionName="1.0" package="com.marakana.yamba2">
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:name=".YambaApplication"> <!-- -->
...
</application>
...
</manifest>
The attiiLute android:name=".YambaApplication" in the <application> element tells
the Anuioiu system to instantiate oui YambaApplication oLject as the application.
So, at this point we have successlully moveu common lunctionality liom
StatusActivity to YambaApplication. This piocess is also known as coue ielactoiing
anu is a goou piactice as we keep on auuing new leatuies to oui application.
104 | Chapter 8:Services
Simplifying StatusActivity
Now that the lunctionality loi getting the Twitter oLject has Leen moveu to
YambaApplication, we can simplily StatusActivity to ielei to that lunctionality theie.
Heie`s what oui new PostToTwitter AsyncTask woulu look like:
class PostToTwitter extends AsyncTask<String, Integer, String> {
// Called to initiate the background activity
@Override
protected String doInBackground(String... statuses) {
try {
YambaApplication yamba = ((YambaApplication) getApplication()); //
Twitter.Status status = yamba.getTwitter().updateStatus(statuses[0]); //
return status.text;
} catch (TwitterException e) {
Log.e(TAG, "Failed to connect to twitter service", e);
return "Failed to post";
}
}
...
}
Ve get the ieleience to the Application oLject via the getApplication() call in the
cuiient context. Since we have a custom YambaApplication oLject, we neeu to cast
the geneiic Application into YambaApplication.
Once we have the ieleience to oui application oLject, we can call its methous, such
as the getTwitter() methou.
You have seen how we have ielactoieu oui StatusActivity to move some ol the com-
mon lunctionality into a shaieu Application oLject. Now that we have uone that, we
can cieate oui UpdaterService, which will use some ol this common lunctionality.
UpdaterService
As mentioneu in the intiouuction to this chaptei, we neeu a seivice to iun as an always-
on Lackgiounu piocess pulling the latest Twittei statuses into a local uataLase. The
puipose ol this pull mechanism is to cache upuates locally so oui app can have uata
even when it`s ollline. Ve`ll call this seivice UpdaterService.
Steps to cieating a seivice aie:
1. Cieate the ]ava class iepiesenting youi seivice.
2. Registei the seivice in the Anuioiu manilest lile.
3. Stait the seivice.
UpdaterService | 105
Creating the UpdaterService Java Class
The Lasic pioceuuie loi cieating a seivice, as with activities anu othei main Luiluing
Llocks, is to suLclass a Service class pioviueu Ly the Anuioiu liamewoik.
To cieate the new seivice, we neeu to cieate a new ]ava lile. Go aheau anu select youi
]ava package in the src loluei, iight-click anu choose NewClass, anu type in
UpuateiSeivice as the class name. This will cieate a new UpdatcrScrvicc.java lile as
pait ol youi package.
You may iecall liom Seivices on page 31 that a typical seivice goes thiough the lile
cycle illustiateu in Figuie S-1.
Iigurc 8-1. Scrvicc |ijc cyc|c
Next, we want to oveiiiue some ol the main lile cycle methous:
onCreate()
Calleu when the seivice is cieateu loi the liist time
onStartCommand()
Calleu when the seivice is staiteu
onDestroy()
Calleu when the seivice is teiminateu
To uo that, you can use Eclipse tool SouiceOveiiiue/Implement Methous anu select
those thiee methous.
At this point, in the spiiit ol piouucing a minimally woiking app at each stage ol leain-
ing, we`ll wiite just a little coue that logs a note in each ol the oveiiiuuen methous. So
the shell ol oui seivice looks like the coue in Example S-3.
Exanp|c 8-3. UpdatcrScrvicc.java, vcrsion 1
package com.marakana.yamba3;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
106 | Chapter 8:Services
public class UpdaterService1 extends Service {
static final String TAG = "UpdaterService"; //
@Override
public IBinder onBind(Intent intent) { //
return null;
}
@Override
public void onCreate() { //
super.onCreate();
Log.d(TAG, "onCreated");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) { //
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStarted");
return START_STICKY;
}
@Override
public void onDestroy() { //
super.onDestroy();
Log.d(TAG, "onDestroyed");
}
}
As in all majoi classes, I like to auu the TAG constant Lecause I use Log.d() guite a Lit.
onBind() is useu in Lounu seivices to ietuin the actual implementation ol something
calleu a bindcr. Since we aie not using a Lounu seivice, we can just ietuin null heie.
onCreate() is calleu when the seivice is initially cieateu. It is not calleu loi suLseguent
startService() calls, so it is a goou place to uo woik that neeus to Le uone only once
uuiing the lile ol a seivice.
onStartCommand() is calleu each time the seivice ieceives a startService() intent. A
seivice that is alieauy stateu coulu get multiple ieguests to stait again, anu each will
cause onStartCommand() to execute.
onDestroy() is calleu just Leloie the seivice is uestioyeu Ly the stopService() ie-
guest. This is a goou place to clean up things that might have Leen initializeu in
onCreate().
Update the Manifest File
Now that we have the shell ol oui seivice, we have to ueline it in the manilest lile, just
like any othei main Luiluing Llock; otheiwise, we won`t Le aLle to call oui seivice.
Simply open AndroidManijcst.xn|, click on the iight-most taL to see the iaw XML coue,
anu auu the lollowing within the <application> element:
UpdaterService | 107
...
<application android:icon="@drawable/icon" android:label="@string/app_name">
...
<service android:name=".UpdaterService" /> <!-- -->
...
</application>
...
UpdaterService uelinition.
Seivices aie egual to activities as Anuioiu Luiluing Llocks, so they appeai at the same
level in the manilest lile.
Add Menu Items
Now that we have the seivice uelineu anu ueclaieu, we neeu a way to stait anu stop it.
The easiest way woulu Le to auu a menu Lutton to oui options menu that we have
alieauy cieateu. Latei on, we`ll have a moie intelligent way ol staiting seivices, Lut loi
now this manual appioach is easiei to unueistanu.
To auu stait/stop menu Luttons, we`ll auu two moie menu items to oui ncnu.xn|
iesouice, just as we cieateu the Prefs menu item Leloie in The Menu Re-
souice on page S9. The upuateu ncnu.xn| now looks like the coue in Example S-+.
Exanp|c 8-1. ncnu.xn|
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/itemPrefs" android:title="@string/titlePrefs"
android:icon="@android:drawable/ic_menu_preferences"></item> <!-- -->
<item android:title="@string/titleServiceStart" android:id="@+id/itemServiceStart"
android:icon="@android:drawable/ic_media_play"></item> <!-- -->
<item android:title="@string/titleServiceStop" android:id="@+id/itemServiceStop"
android:icon="@android:drawable/ic_media_pause"></item> <!-- -->
</menu>
This is the item we uelineu in the pievious chaptei.
The ServiceStart item has the usual id, title, anu icon attiiLutes. This icon is
anothei Anuioiu system iesouice.
The ServiceStop item is similai to the ServiceStart item.
Now that the menu iesouice has Leen upuateu, it`s time to hanule those items when
the usei clicks on them.
108 | Chapter 8:Services
Update the Options Menu Handling
To hanule new menu items, we neeu to upuate the onOptionsItemSelected()
methou in StatusActivity, just as we uiu in Upuate StatusActivity to Hanule Menu
Events on page 92. So open youi StatusActivity.java lile anu locate the onOptionsItem
Selected() methou. Ve now have a liamewoik in this methou to suppoit any numLei
ol menu items. To auu suppoit loi staiting anu stopping oui seivice, we launch intents
pointing to oui UpdaterService via startService() anu stopService() calls. The linal
coue looks like this:
// Called when an options item is clicked
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.itemServiceStart:
startService(new Intent(this, UpdaterService.class)); //
break;
case R.id.itemServiceStop:
stopService(new Intent(this, UpdaterService.class)); //
break;
case R.id.itemPrefs:
startActivity(new Intent(this, PrefsActivity.class));
break;
}
return true;
}
Cieates an intent to stait UpdaterService. Il the seivice uoesn`t alieauy exist, the
iuntime calls the seivice`s onCreate() methou. Then onStartCommand() is calleu, ie-
gaiuless ol whethei this seivice is new oi alieauy iunning.
Similaily, this uses the stopService() call to senu an intent intenueu loi Updater
Service. This will cause onDestroy() to Le calleu on the seivice il the seivice is
iunning. Il it isn`t, nothing happens, anu this intent is simply ignoieu.
In this example, we aie using explicit intents to specily exactly which class the intents
aie intenueu loi, namely UpdaterService.class.
Testing the Service
At this point, you can iestait youi application. Note that you uo not neeu to iestait the
emulatoi. Vhen youi application staits up, click on the menu, anu youi new Luttons
shoulu appeai in the menu options. You can now lieely click on the stait anu stop
seivice Luttons.
To veiily that youi seivice is woiking, open up youi LogCat anu look loi the appiopiiate
log messages that you geneiateu in youi seivice coue. RememLei liom Logging in
Anuioiu on page 62 that you can view the LogCat Loth in Eclipse anu via the commanu
line.
UpdaterService | 109
Anothei way to veiily that the seivice is iunning is to go to the Anuioiu Settings app
anu see whethei it is listeu. To uo that, go to the Home scieen, piess Menu, anu choose
Settings. Then go to ApplicationsRunning seivices. You shoulu see youi seivice listeu,
as shown in Figuie S-2.
Iigurc 8-2. Running scrviccs
Youi seivice is now woiking, although it`s not uoing much at this point.
Looping in the Service
By uesign, oui seivice is supposeu to wake up eveiy so olten, check the online seivice
loi new status upuates, an then go Lack to sleep loi some time. Anu this woik neeus
to keep on happening loievei, until the seivice is stoppeu. A goou way to implement
this is to have oui seivice iun in a loop anu pause execution Letween iteiations. ]ava
pioviues a Thread.sleep() methou that we can use to make the cuiiently iunning thieau
pause anu ielinguish CPU loi some numLei ol milliseconus.
Anothei consiueiation to keep in minu is that the seivice coulu ieguiie a goou ueal ol
time to make its connection to Twittei anu pull in liienus` status uata. The Lehavioi
ol netwoiking calls uepenus on the type ol netwoik connection we have at the moment,
the iesponsiveness ol the seivei, anu all soits ol othei lactois that collectively make up
the netwoik latency.
Il we iun oui upuate opeiation on the uelault thieau, any uelay causeu Ly the netwoik
upuate will cause oui usei inteilace to Llock. This in tuin will make oui application
appeai sluggish to the usei anu may even leau to the Anuioiu system olleiing to kill
oui application Ly Liinging up the Foice Close oi Vait uialog winuow, as uiscusseu
in Thieauing in Anuioiu on page 65.
110 | Chapter 8:Services
The Lest solution to this pioLlem is to put the actual woik ol the netwoik upuate in a
sepaiate thieau. To uo this, we can use stanuaiu ]ava thieauing suppoit, as shown in
Example S-5. The woik ol a seivice shoulu olten Le in a sepaiate thieau liom the main
UI thieau, iegaiuless ol how little time you expect the seivice to take. You always neeu
to sepaiate the noninteiactive piocessing liom usei inteiaction. Vhen you have net-
woik activity, as in YamLa, it`s even moie impoitant to keep it sepaiate, Lut the piin-
ciple applies to any seivice.
Exanp|c 8-5. UpdatcrScrvicc.java, vcrsion 2
package com.marakana.yamba3;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class UpdaterService2 extends Service {
private static final String TAG = "UpdaterService";
static final int DELAY = 60000; // a minute
private boolean runFlag = false; //
private Updater updater;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
this.updater = new Updater(); //
Log.d(TAG, "onCreated");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
this.runFlag = true; //
this.updater.start();
Log.d(TAG, "onStarted");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
this.runFlag = false; //
Looping in the Service | 111
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
this.updater.interrupt(); //
this.updater = null;
Log.d(TAG, "onDestroyed");
}
/**
* Thread that performs the actual update from the online service
*/
private class Updater extends Thread { //
public Updater() {
super("UpdaterService-Updater"); //
}
@Override
public void run() { //
UpdaterService2 updaterService = UpdaterService2.this; //
while (updaterService.runFlag) { //
Log.d(TAG, "Updater running");
try {
// Some work goes here...
Log.d(TAG, "Updater ran");
Thread.sleep(DELAY); //
} catch (InterruptedException e) { //
updaterService.runFlag = false;
}
}
}
} // Updater
}
Specilies the constant loi the uelay Letween netwoik upuates. Ve coulu make this
conliguiaLle via pieleiences as well.
This llag helps us know whethei the seivice is cuiiently iunning.
Updater is the sepaiate thieau that peiloims the actual netwoik upuate. Because the
thieau neeus to Le cieateu only once, we uo so in the seivice`s onCreate() methou.
Vhen the seivice is to stait, its onStartCommand() methou is calleu. This is also a
goou place to stait oui Updater thieau anu upuate the llag iuentilying it as iunning.
Similaily, onDestroy() is a goou place to stop oui netwoik upuate thieau anu upuate
the llag to show that it is no longei iunning.
To stop the actual thieau liom iunning, we invoke interrupt() on it. Ve also set it
to null to help the gaiLage collection piocess clean it up.
This is wheie we ueline the Updater class. It is a thieau, so it extenus ]ava`s Thread
class.
The puipose ol this is to simply give oui thieau a name. Having a name helps iuentily
vaiious iunning thieaus anu aius in ueLugging.
112 | Chapter 8:Services
A ]ava thieau must pioviue a run() methou. This is wheie the actual woik is uone.
This simply cieates a ieleience to oui seivice, ol which this thieau is an innei class.
This is the loop that keeps this netwoik upuate going as long as the seivice is not
stoppeu. RememLei that runFlag is set in the seivice`s onStartCommand() anu
onDestroy() methous.
The call to Thread.sleep() pauses the execution ol this paiticulai Updater thieau loi
some numLei ol milliseconus. Eailiei we set oui DELAY constant to one minute.
Vhen we signal interrupt() to a iunning thieau, it will cause an InterruptedExcep
tion in the run() methou. Ve hanule the exception simply Ly setting the runFlag to
lalse so the thieau uoesn`t keep tiying to iun again until it is iestaiteu.
Testing the Service
At this point, you can iun the application anu stait the seivice. Il you oLseive the loglile,
you`ll notice that eveiy minute oi so the seivice logs that it ian oui joL. Also, stopping
the seivice will stop luithei execution ol the joL.
Heie`s the LogCat output ol what is going on with oui seivice:
D/UpdaterService( 3494): onCreated
D/UpdaterService( 3494): onStarted
D/UpdaterService( 3494): Updater running
D/UpdaterService( 3494): Updater ran
D/UpdaterService( 3494): Updater running
D/UpdaterService( 3494): Updater ran
...
D/UpdaterService( 3494): onDestroyed
As you can see, the seivice was cieateu anu staiteu. It also ian couple ol times Leloie
it linally got uestioyeu.
Pulling Data from Twitter
Ve now have a liamewoik anu aie ieauy to make the actual connection to the online
Twittei-like seivice, pull the status uata, anu uisplay that uata in oui application. Twit-
tei anu Twittei-like seivices ollei many uilleient APIs to ietiieve oui liienus` upuates.
The jtwittcr.jar liLiaiy exposes most ol them to us via the Twitter class. Peihaps one
ol the most appiopiiate methous is getFriendsTimeline(), which ietuins the 20 most
iecent posts maue ovei the past 2+ houis liom the usei anu hei liienus.
To use this Twittei API leatuie, we neeu to connect to the online seivice. Anu to uo
that, we neeu the useiname, passwoiu, anu ioot API loi oui online seivice. As you iecall
liom the pievious chaptei, we have alieauy ielactoieu most ol this lunctionality into
the YambaApplication oLject (see The YamLa Application OLject on page 102). Ve
Pulling Data from Twitter | 113
can ieuse all those leatuies heie Lecause oui seivice is pait ol the same application anu
as such has access to the same Application oLject.
Howevei, we uo neeu to make a minoi upuate to YambaApplication, Lecause we woulu
also like to know whethei oui seivice is iunning. To uo that, we`ll auu a llag to
YambaApplication anu pioviue settei anu gettei methous to access anu upuate that llag:
public class YambaApplication extends Application
implements OnSharedPreferenceChangeListener {
private boolean serviceRunning; //
...
public boolean isServiceRunning() { //
return serviceRunning;
}
public void setServiceRunning(boolean serviceRunning) { //
this.serviceRunning = serviceRunning;
}
}
The llag that inuicates whethei the seivice is iunning. Note that this llag is piivate
to this class, so noLouy else can uiiectly access it anu change it.
The puLlic methou to check the status ol the serviceRunning llag.
Anothei puLlic methou to set the state ol the serviceRunning llag.
Now we can wiite new coue loi UpdaterService anu have it connect to the online API
to pull the latest status upuates liom oui liienus. Example S-6 shows the linal veision.
Exanp|c 8-. UpdatcrScrvicc.java, jina| vcrsion
package com.marakana.yamba3;
import java.util.List;
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class UpdaterService extends Service {
private static final String TAG = "UpdaterService";
static final int DELAY = 60000; // wait a minute
private boolean runFlag = false;
private Updater updater;
private YambaApplication yamba; //
@Override
public IBinder onBind(Intent intent) {
return null;
}
114 | Chapter 8:Services
@Override
public void onCreate() {
super.onCreate();
this.yamba = (YambaApplication) getApplication(); //
this.updater = new Updater();
Log.d(TAG, "onCreated");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
this.runFlag = true;
this.updater.start();
this.yamba.setServiceRunning(true); //
Log.d(TAG, "onStarted");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
this.runFlag = false;
this.updater.interrupt();
this.updater = null;
this.yamba.setServiceRunning(false); //
Log.d(TAG, "onDestroyed");
}
/**
* Thread that performs the actual update from the online service
*/
private class Updater extends Thread {
List<Twitter.Status> timeline; //
public Updater() {
super("UpdaterService-Updater");
}
@Override
public void run() {
UpdaterService updaterService = UpdaterService.this;
while (updaterService.runFlag) {
Log.d(TAG, "Updater running");
try {
// Get the timeline from the cloud
try {
timeline = yamba.getTwitter().getFriendsTimeline(); //
} catch (TwitterException e) {
Log.e(TAG, "Failed to connect to twitter service", e); //
Pulling Data from Twitter | 115
}
// Loop over the timeline and print it out
for (Twitter.Status status : timeline) { //
Log.d(TAG, String.format("%s: %s", status.user.name, status.text)); //
}
Log.d(TAG, "Updater ran");
Thread.sleep(DELAY);
} catch (InterruptedException e) {
updaterService.runFlag = false;
}
}
}
} // Updater
}
This vaiiaLle allows access to the YambaApplication oLject that contains oui shaieu
leatuies, such as a way to ieau pieleiences anu connect to the online seivice.
Ve get the ieleience to oui YambaApplication oLject Ly using the getApplica
tion() call.
Once we stait the seivice, we upuate the serviceRunning llag in the shaieu applica-
tion oLject, YambaApplication.
Similaily, when the seivice stops, we upuate the llag in the application oLject.
Ve aie using ]ava geneiics to ueline the timeline vaiiaLle as a List ol Twitter.Sta
tus instances.
Ve call getTwitter() in YambaApplication to get the twitter oLject, anu then call
getFriendsTimeline() on it to get the last 20 status posts liom the past 2+ houis.
Note that this is the actual methou that implements the weL seivice call to oui clouu
seivice. As such, it coulu take some time to complete, uepenuing on the netwoik
latency. Because we iun this in oui ueuicateu thieau, we won`t allect the main usei
inteilace thieau while we wait loi the netwoik opeiation to complete.
A netwoik call can lail loi any numLei ol ieasons. Heie we hanule lailuie Ly piinting
the stack tiace ol what went wiong. The actual piintout will Le visiLle in LogCat.
Now that we have initializeu the timeline list, we can loop ovei it. The easiest ap-
pioach is to use ]ava`s loi each loop, which automatically iteiates ovei oui list,
assigning each element in tuin to the status vaiiaLle.
Foi now, we simply piint out the statuses ol who saiu what to the LogCat output.
116 | Chapter 8:Services
Testing the Service
Now we can iun oui application, stait the seivice, anu see the list ol oui liienus` statuses
in the LogCat:
D/UpdaterService( 310): Marko Gargenta: it is great that you got my message
D/UpdaterService( 310): Marko Gargenta: hello this is a test message from my phone
D/UpdaterService( 310): Marko Gargenta: Test
D/UpdaterService( 310): Marko Gargenta: right!
...
Summary
Ve now have a woiking seivice, which we stait anu stop anu in a ielatively ciuue,
manual way. The seivice connects to the clouu seivice anu pulls uown the status posts
liom oui liienus. Foi now, we just piint this uata in the LogCat, Lut in the next chaptei
we`ll inseit the uata into the uataLase.
Figuie S-3 illustiates what we have uone so lai as pait ol the uesign outlineu eailiei in
Figuie 5-+.
Iigurc 8-3. Yanba conp|ction
Summary | 117
CHAPTER 9
The Database
The Anuioiu system uses uataLases to stoie uselul inloimation that neeus to Le pei-
sisteu even when the usei kills the app oi even shuts uown the uevice anu poweis it
Lack on. The uata incluues contacts, system settings, Lookmaiks, anu so on.
So, why use a uataLase in a moLile application? Altei all, isn`t it Lettei to keep oui uata
in a clouu wheie it`s always Lackeu up insteau ol stoiing it in a moLile uevice that is
easily lost oi uamageu?
A uataLase in a moLile uevice is veiy uselul as a supplement to the online woilu. Al-
though in many cases it is much Lettei to count on the uata living in the clouu, it is
uselul to stoie it locally in oiuei to access it moie guickly anu have it availaLle even
when the netwoik is not availaLle. In this case, we aie using a local uataLase as a cache.
This is also how we use it in oui YamLa application.
In this chaptei, you will leain how Anuioiu suppoits uataLases. You will leain to cieate
anu use a uataLase insiue the YamLa application to stoie oui status upuates locally.
Local uata will help YamLa uisplay statuses to the usei guickly, without having to wait
loi the netwoik to pioviue the uata. Oui seivice will iun in the Lackgiounu anu peii-
ouically upuate the uataLase so that the uata is ielatively liesh. This will impiove the
oveiall usei expeiience ol the application.
About SQLite
SQLite is an open souice uataLase that has Leen aiounu loi a long time, is guite staLle,
anu is populai on many small uevices, incluuing Anuioiu. Theie aie couple ol goou
ieasons why SQLite is a gieat lit loi Anuioiu app uevelopment:
It`s a zeio-conliguiation uataLase. That means theie`s aLsolutely no uataLase con-
liguiation loi you as the uevelopei. This makes it ielatively simple to use.
It uoesn`t have a seivei. Theie`s no SQLite uataLase piocess iunning. It is Lasically
a set ol liLiaiies that pioviue the uataLase lunctionality. Not having a seivei to
woiiy aLout is also a goou thing.
119
It`s a single-lile uataLase. This makes uataLase secuiity stiaightloiwaiu, as it Loils
uown to lilesystem secuiity. Ve alieauy know that Anuioiu sets asiue a special,
secuie sanuLox loi each application.
It`s open souice.
The Anuioiu liamewoik olleis seveial ways to use SQLite easily anu ellectively, anu
we`ll look at the Lasic usage in this chaptei. You may Le pleaseu to linu that, although
SQLite uses SQL, Anuioiu pioviues a highei-level liLiaiy with an inteilace that is much
easiei to integiate into an application.
Although SQLite suppoit is Luilt into Anuioiu, it is Ly no means youi
only option when it comes to uata peisistence loi youi app. You can
always use anothei uataLase system, such as ]avaDB oi MongoDB, Lut
you`u have to Lunule the ieguiieu liLiaiies with youi app anu woulu
not Le aLle to iely on Anuioiu`s Luilt-in uataLase suppoit. SQLite is not
an alteinative to a lull SQL seivei; insteau, it is an alteinative to using a
local lile with an aiLitiaiy loimat.
DbHelper
Anuioiu pioviues an elegant inteilace loi youi app to inteiact with an SQLite uataLase.
To access the uataLase, you liist neeu a helpei class that pioviues a connection to
the uataLase, cieating the connection il it uoesn`t alieauy exist. This class, pioviueu to
you Ly the Anuioiu liamewoik, is calleu SQLiteOpenHelper. The uataLase class it ietuins
is an instance ol SQLiteDatabase.
In the lollowing suLsections I`ll explain some ol the Lackgiounu concepts you shoulu
unueistanu when woiking with DbHelper. I`m not going to explain SQL oi Lasic uata-
Lase concepts such as noimalization, Lecause theie aie hunuieus ol goou places to linu
that inloimation, anu I expect most ol my ieaueis alieauy know it. Howevei, this
chaptei shoulu give you enough to get staiteu, even il youi knowleuge ol uataLases is
spotty.
The Database Schema and Its Creation
A schema is just a uesciiption ol what`s in a uataLase. In oui YamLa uataLase, loi
instance, we want lielus loi the lollowing inloimation aLout each tweet we ietiieve
liom Twittei:
created_at
The uate when the tweet was sent
txt
The text ol the tweet
120 | Chapter 9:The Database
user
The usei who sent the tweet
So each iow in oui taLle will contain the uata loi one tweet, anu these loui items will
Le the columns in oui schema, along with a unigue ID loi each tweet. Ve neeu the ID
so we can easily ielei to a tweet. SQLite, like most uataLases, allows us to ueclaie the
ID as a piimaiy key anu even assigns a unigue numLei automatically to each tweet loi
us.
The schema has to Le cieateu when oui application staits, so we`ll uo it in the
onCreate() methou ol DLHelpei. Ve might auu new lielus oi change existing ones in
a latei veision ol oui application, so we`ll assign a veision numLei to oui schema anu
pioviue an onUpgrade() methou that we can call to altei the schema.
onCreate() anu onUpgrade() aie the only methous in oui application when we neeu to
use SQL. Ve`ll execute CREATE TABLE in onCreate() to cieate a taLle in oui uataLase.
In a piouuction application, we`u use ALTER TABLE in onUpgrade() when the schema
changes, Lut that ieguiies a lot ol complex intiospection ol the uataLase, so loi now
we`ll use DROP TABLE anu iecieate the taLle. Ol couise, DROP TABLE uestioys any uata
cuiiently in the taLle, Lut that`s not a pioLlem loi oui YamLa application. It always
ielills the taLle with tweets liom the past 2+ houis, which aie the only ones oui useis
will caie aLout.
Four Major Operations
The DbHelper class olleis you a high-level inteilace that`s much simplei than SQL. The
uevelopeis iealizeu that most applications use uataLases loi only loui majoi opeiations,
which go Ly the appealing acionym CRUD: cieate, ieau (gueiy), upuate, anu uelete.
To lullill these ieguiiements, DbHelper olleis:
insert()
Inseits one oi moie iows into the uataLase
query()
Reguests iows matching the ciiteiia you specily
update()
Replaces ones oi moie iows that match the ciiteiia you specily
delete()
Deletes iows matching the ciiteiia you specily
Each ol these methous has vaiiants that enhance it with othei lunctions. To use one ol
the methous, cieate a ContentValues containei anu place in it the inloimation you want
inseiteu, upuateu, etc. This chaptei will show you the piocess loi an inseit, anu the
othei opeiations woik in similai ways.
So, why not use SQL uiiectly? Theie aie thiee goou ieasons why.
DbHelper | 121
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Fiist, liom a secuiity point ol view, an SQL statement is a piime canuiuate loi a secuiity
attack on youi application anu uata, known as an SQL injection attack. That is Lecause
the SQL statement takes usei input, anu unless you check anu isolate it veiy caielully,
this input coulu emLeu othei SQL statements with unuesiiaLle ellects.
Seconu, liom a peiloimance point ol view, executing SQL statements iepeateuly is
highly inellicient Lecause you`u have to paise the SQL eveiy time the statement iuns.
Finally, the DbHelper methous aie moie ioLust anu less likely to pass thiough the com-
pilei with unuetecteu eiiois. Vhen you incluue SQL in a piogiam, it`s easy to cieate
eiiois that tuin up only at iuntime.
Anuioiu's uataLase liamewoik only suppoits piepaieu statements loi stanuaiu CRUD
opeiations: INSERT, UPDATE, DELETE, anu SELECT. Foi othei SQL statements, we
pass them uiiectly to SQLite. That`s why we useu execSQL() to iun the coue to CREATE
TABLE.... This is OK Lecause that coue uoesn`t uepenu on any usei input, anu as such
SQL injection is not possiLle. Auuitionally, that coue iuns veiy iaiely, so theie`s no
neeu to woiiy aLout the peiloimance implications.
Cursors
A gueiy ietuins a set ol iows along with a pointei calleu a cursor. You can ietiieve
iesults one at a time liom the cuisoi, causing it to auvance each time to the next iow.
You can also move the cuisoi aiounu in the iesult set. An empty cuisoi inuicates that
you`ve ietiieveu all the iows.
In geneial, anything you uo with SQL coulu leau to an SQL exception Lecause it`s coue
is inteiacting with a system that`s outsiue ol oui uiiect contiol. Foi example, the
uataLase coulu Le iunning out ol space oi somehow coiiupteu. So, it is a goou piactice
to hanule all the SQLExceptions Ly suiiounuing youi uataLase calls in tiy/catch Llocks.
It`s easy to uo this using the Eclipse shoitcut:
1. Select the coue loi which you`u like to hanule exceptions. Typically this woulu Le
most ol youi SQL calls.
2. In the Eclipse menu, choose SouiceSuiiounu VithTiy/catch Block. Eclipse will
geneiate the appiopiiate tiy/catch statements aiounu youi coue loi the piopei
exception class.
3. Hanule this exception in the catch Llock. This might Le a simple call to Log.e() to
pass the tag, message, anu the exception oLject itsell.
First Example
So now we`ie going to cieate oui own helpei class to help us open oui YamLa uataLase
(see Example 9-1). Ve`ll call the class DbHelper. It will cieate the uataLase lile il one
122 | Chapter 9:The Database
uoesn`t alieauy exist, oi it will upgiaue the usei`s uataLase il the schema has changeu
Letween veisions.
Like many othei classes in Anuioiu, we usually stait Ly suLclassing a liamewoik class,
in this case SQLiteOpenHelper. Ve then neeu to implement the class`s constiuctoi, as
well as onCreate() anu onUpgrade() methous.
Exanp|c 9-1. DbHc|pcr.java, vcrsion 1
package com.marakana.yamba4;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
import android.util.Log;
public class DbHelper1 extends SQLiteOpenHelper { //
static final String TAG = "DbHelper";
static final String DB_NAME = "timeline.db"; //
static final int DB_VERSION = 1; //
static final String TABLE = "timeline"; //
static final String C_ID = BaseColumns._ID;
static final String C_CREATED_AT = "created_at";
static final String C_SOURCE = "source";
static final String C_TEXT = "txt";
static final String C_USER = "user";
Context context;
// Constructor
public DbHelper1(Context context) { //
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
}
// Called only once, first time the DB is created
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table " + TABLE + " (" + C_ID + " int primary key, "
+ C_CREATED_AT + " int, " + C_USER + " text, " + C_TEXT + " text)"; //
db.execSQL(sql); //
Log.d(TAG, "onCreated sql: " + sql);
}
// Called whenever newVersion != oldVersion
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //
// Typically do ALTER TABLE statements, but...we're just in development,
// so:
db.execSQL("drop table if exists " + TABLE); // drops the old database
Log.d(TAG, "onUpdated");
onCreate(db); // run onCreate to get new database
First Example | 123
}
}
Stait Ly suLclassing SQLiteOpenHelper.
This is the uataLase lilename.
This is the veision ol oui uataLase. The veision numLei is impoitant so that latei,
when you change the schema, you can pioviue existing useis with a way to upgiaue
theii uataLase to the latest schema.
The lollowing aie some uataLase constants specilic to oui application. It is hanuy
to ueline these as constants to that we can ielei to them liom othei classes.
Ve oveiiiue SQLiteOpenHelper Ly passing the constants to super anu ietaining the
local ieleience to the context.
This is the actual SQL that we`ll pass on to the uataLase to have it cieate the appio-
piiate SQL schema that we neeu.
Once we have oui SQL to cieate the uataLase, iun execSQL () on the uataLase oLject
that was passeu into onCreate().
onUpgrade() is calleu whenevei the usei`s uataLase veision is uilleient than the ap-
plication veision. This typically happens when you change the schema anu ielease
the application upuate to useis who alieauy have oluei veision ol youi app.
As mentioneu eailiei, you woulu typically execute ALTER TABLE ... SQL
statements in onUpgrade(). Since we uon`t have an olu uataLase to altei,
we aie assuming this application is still in pieielease moue anu aie just
ueleting any usei uata when iecieating the uataLase.
Next, we neeu to upuate the seivice in oiuei to have it open up the uataLase connection,
letch the uata liom the netwoik, anu inseit it into the uataLase.
Update UpdaterService
RememLei that oui UpdaterService connects to the clouu anu gets the uata. So
UpdaterService also is iesponsiLle loi inseiting this uata into the local uataLase.
In Example 9-2, we upuate the UpdaterService to pull the uata liom the clouu anu stoie
it in the uataLase.
Exanp|c 9-2. UpdatcrScrvicc.java, vcrsion 1
package com.marakana.yamba4;
import java.util.List;
124 | Chapter 9:The Database
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Service;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.IBinder;
import android.util.Log;
public class UpdaterService1 extends Service {
private static final String TAG = "UpdaterService";
static final int DELAY = 60000; // wait a minute
private boolean runFlag = false;
private Updater updater;
private YambaApplication yamba;
DbHelper1 dbHelper; //
SQLiteDatabase db;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
this.yamba = (YambaApplication) getApplication();
this.updater = new Updater();
dbHelper = new DbHelper1(this); //
Log.d(TAG, "onCreated");
}
@Override
public int onStartCommand(Intent intent, int flag, int startId) {
if (!runFlag) {
this.runFlag = true;
this.updater.start();
((YambaApplication) super.getApplication()).setServiceRunning(true);
Log.d(TAG, "onStarted");
}
return Service.START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
this.runFlag = false;
this.updater.interrupt();
this.updater = null;
Update UpdaterService | 125
this.yamba.setServiceRunning(false);
Log.d(TAG, "onDestroyed");
}
/**
* Thread that performs the actual update from the online service
*/
private class Updater extends Thread {
List<Twitter.Status> timeline;
public Updater() {
super("UpdaterService-Updater");
}
@Override
public void run() {
UpdaterService1 updaterService = UpdaterService1.this;
while (updaterService.runFlag) {
Log.d(TAG, "Updater running");
try {
// Get the timeline from the cloud
try {
timeline = yamba.getTwitter().getFriendsTimeline(); //
} catch (TwitterException e) {
Log.e(TAG, "Failed to connect to twitter service", e);
}
// Open the database for writing
db = dbHelper.getWritableDatabase(); //
// Loop over the timeline and print it out
ContentValues values = new ContentValues(); //
for (Twitter.Status status : timeline) { //
// Insert into database
values.clear(); //
values.put(DbHelper1.C_ID, status.id);
values.put(DbHelper1.C_CREATED_AT, status.createdAt.getTime());
values.put(DbHelper1.C_SOURCE, status.source);
values.put(DbHelper1.C_TEXT, status.text);
values.put(DbHelper1.C_USER, status.user.name);
db.insertOrThrow(DbHelper1.TABLE, null, values); //
Log.d(TAG, String.format("%s: %s", status.user.name, status.text));
}
// Close the database
db.close(); //
Log.d(TAG, "Updater ran");
Thread.sleep(DELAY);
} catch (InterruptedException e) {
updaterService.runFlag = false;
}
}
126 | Chapter 9:The Database
}
} // Updater
}
Because we likely neeu db anu dbHelper oLjects thioughout the class, we ueclaie
them gloLally to the class.
Cieate the instance ol DbHelper anu pass this as its context. This woiks Lecause the
Anuioiu Service class is a suLclass ol Context. DbHelper will liguie out whethei the
uataLase neeus to Le cieateu oi upgiaueu.
Ve neeu to connect to the online seivice, get the latest upuates, anu inseit them into
the uataLase. getTwitter() in YambaApplication is oui lazy initialization ol the
Twitter oLject. Then, we call the actual Twittei API call getFriendsTimeline() to
get the last 20 statuses liom liienus posteu in the last 2+ houis.
Get the wiitaLle uataLase so we can inseit new statuses into it. The liist time we
make this call, onCreate() in DbHelper will iun anu cieate the uataLase lile loi this
usei.
ContentValues is a simple name-value paii uata stiuctuie that maps uataLase taLle
names to theii iespective values.
Ve loop ovei all the status uata that we ieceiveu. In this case, we aie using a ]ava
loi-each loop to make the iteiation simple.
Foi each iecoiu, we cieate a content value. Ve aie ieusing the same ]ava oLject,
cleaiing it each time we stait the loop anu populating appiopiiate values loi the
status uata.
Ve inseit the content value into the uataLase via an insert() call to the SQLiteData
base oLject. Notice that we aie not piecing togethei an SQL statement heie, Lut
iathei using a prcparcd statcncnt appioach to inseiting into the uataLase.
Finally, iememLei to close the uataLase. This is impoitant Lecause anothei activity
coulu Le tiying to ieau oi wiite liom this shaieu iesouice.
Ve aie now ieauy to iun oui coue anu test it to make suie eveiything woiks.
Testing the Service
At this point, we can test whethei the uataLase was cieateu piopeily anu whethei the
seivice has populateu it with some uata. Ve`ie going to uo this step Ly step.
Verify that the database was created
Il the uataLase lile was cieateu successlully, it will Le locateu in the /data/data/
con.nara|ana.yanba/databascs/tinc|inc.db lile. You can use the Eclipse DDMS pei-
spective anu File Exploiei view to look at the lilesystem ol the uevice, oi you can use
Update UpdaterService | 127
adb shell on youi commanu line, anu then iun ls /data/data/com.marakana.yamba/
databases/timeline.db to make suie the lile is theie.
To use File Exploiei in Eclipse, eithei open the DDMS peispective in the top-iight
coinei ol youi Eclipse oi go to VinuowsShow ViewOthei.AnuioiuFile Ex-
ploiei. This will open the view ol the lilesystem ol the uevice you aie cuiiently looking
at.
So lai, you know that the uataLase lile is theie, Lut uon`t ieally know whethei the
uataLase schema was cieateu piopeily. The next section auuiesses that.
Using sqlite3
Anuioiu ships with the commanu-line tool sqlite3. This tool gives you access to the
uataLase itsell.
To see whethei youi uataLase schema was cieateu piopeily:
1. Open up youi teiminal oi commanu-line winuow.
2. Type adb shell to connect to youi iunning emulatoi oi physical phone.
3. Change the uiiectoiy to the location ol youi uataLase lile Ly typing cd /data/data/
com.marakana.yamba/databases/.
+. Connect to the uataLase with the sqlite3 timeline.db commanu.
At this point, you shoulu Le connecteu to the uataLase. Youi piompt shoulu Le
sqlite>, inuicating that you aie insiue the SQLite:
[user:~]> adb shell
# cd /data/data/com.marakana.yamba/databases/
# ls
timeline.db
# sqlite3 timeline.db
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
At this point, you can senu two types ol commanus to youi SQLite uataLase:
Stanuaiu SQL commanus, such as insert ..., update ..., delete ..., anu
select ..., as well as create table ..., alter table ..., anu so on. Note that
SQL is anothei language altogethei, anu as such is not coveieu in this Look. Ve
assume heie that you have a veiy Lasic knowleuge ol SQL. Also note that in
sqlite3, you must teiminate youi SQL statements with a semi-colon (;).
sqlite3 commanus. These aie commanus that aie specilic to SQLite. You can see
the list ol all commanus Ly typing .help at the sqlite3> piompt. Foi now, we`ll
just use .schema to veiily that the schema was cieateu:
# sqlite3 timeline.db
SQLite version 3.6.22
128 | Chapter 9:The Database
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .schema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE timeline ( _id integer primary key,created_at integer, source text,
txt text, user text );
The last line tells us that oui uataLase taLle timeline inueeu was cieateu anu looks like
we expecteu, with the columns _id, created_at, source, txt, anu user.
New Anuioiu uevelopeis olten execute the sqlite3 timeline.db com-
manu in a wiong loluei, anu then wonuei why the uataLase taLle wasn`t
cieateu. SQLite will not complain il the lile you aie ieleiiing to uoesn`t
exist; it will simply cieate a Lianu-new uataLase. So, make suie you
aie eithei in the coiiect loluei (/data/data/con.nara|ana.yanba/data-
bascs/) when you execute sqlite3 timeline.db, oi iun the commanu
specilying the lull path to youi lile: sqlite3 /data/data/com.mara
kana.yamba/databases/timeline.db.
Now that we have a way to cieate anu open up oui uataLase, we aie ieauy to upuate
the seivice that will inseit the uata into the uataLase.
At this point we shoulu Le getting the uata liom the online seivice as well as inseiting
that uata in the uataLase. Ve can also veiily that the uata is inueeu in the uataLase Ly
using sqlite3.
Database Constraints
Vhen youi seivice iuns loi the seconu time, you`ll notice that it lails anu that you get
many SQLExceptions in the LogCat. You will also notice that it complains aLout the
uataLase constiaint lailing.
This happens Lecause we have uuplicate IDs. Il you iememLei, we aie letching all the
uata liom the online seivice, incluuing the IDs useu online. Ve aie then inseiting this
in to oui local uataLase. But we get the uata via the getFriendsTimeline() call, which
ietuins the 20 most iecent posts maue in the past 2+ houis, anu we uo this eveiy minute
oi so. So, unless you have liienus who post moie than 20 posts a minute, you`ll likely
get uuplicates. That means we`ie attempting to inseit uuplicate IDs into a uataLase that
is set up with _id as the piimaiy key, which means they must Le unigue. This lails loi
uuplicate entiies, anu that`s why the uataLase complains anu thiows an SQLException.
Ve coulu check with the uataLase that theie aie no uuplicates Leloie peiloiming an
inseit, Lut that woulu mean wiiting that logic. Since the uataLase is alieauy goou at
uataLase stull, it is moie ellicient to attempt to inseit uuplicate entiies, lail at it, anu
ignoie that lailuie.
To uo that, we neeu to change db.insert() to db.insertOrThrow(), catch the SQL
Exception, anu ignoie it:
Update UpdaterService | 129
...
try {
db.insertOrThrow(DbHelper.TABLE, null, values); //
Log.d(TAG, String.format("%s: %s", status.user.name, status.text));
} catch (SQLException e) { //
// Ignore exception
}
...
Attempts to inseit into the uataLase, Lut il it lails, it thiows an exception.
Ve catch this exception anu ignoie it. Ve will impiove on this latei in the next
section.
At this point, oui coue woiks, Lut it`s not iueal. Theie`s an oppoitunity to ielactoi it
luithei.
Refactoring Status Data
The woik we uiu pieviously loi the UpdaterService is not iueal loi suppoiting oui next
usei ol this uata: the TimelineActivity. Since TimelineActivity will also neeu to access
the same uataLase anu letch the same uata, it woulu Le Lettei il we woulu shaie some
ol the same lunctionality Letween the UpdaterService anu the TimelineActivity.
In oiuei to uo that, we`ll cieate a new ]ava class, StatusData, anu make it the common
containei loi uataLase-ielateu lunctionality (see Example 9-3). It will Le hiuing (en-
capsulating) SQLite in a highei-level class accessiLle to othei paits ol the YamLa ap-
plication. The iest ol oui app will then just ask loi StatusData anu will not Le conceineu
with how that uata is geneiateu. This is a Lettei uesign anu latei will allow us to impiove
it even luithei with Content Pioviueis, as explaineu in Chaptei 12.
Exanp|c 9-3. StatusData.java
package com.marakana.yamba4;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class StatusData { //
private static final String TAG = StatusData.class.getSimpleName();
static final int VERSION = 1;
static final String DATABASE = "timeline.db";
static final String TABLE = "timeline";
public static final String C_ID = "_id";
public static final String C_CREATED_AT = "created_at";
public static final String C_TEXT = "txt";
130 | Chapter 9:The Database
public static final String C_USER = "user";
private static final String GET_ALL_ORDER_BY = C_CREATED_AT + " DESC";
private static final String[] MAX_CREATED_AT_COLUMNS = { "max("
+ StatusData.C_CREATED_AT + ")" };
private static final String[] DB_TEXT_COLUMNS = { C_TEXT };
// DbHelper implementations
class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DATABASE, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "Creating database: " + DATABASE);
db.execSQL("create table " + TABLE + " (" + C_ID + " int primary key, "
+ C_CREATED_AT + " int, " + C_USER + " text, " + C_TEXT + " text)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table " + TABLE);
this.onCreate(db);
}
}
private final DbHelper dbHelper; //
public StatusData(Context context) { //
this.dbHelper = new DbHelper(context);
Log.i(TAG, "Initialized data");
}
public void close() { //
this.dbHelper.close();
}
public void insertOrIgnore(ContentValues values) { //
Log.d(TAG, "insertOrIgnore on " + values);
SQLiteDatabase db = this.dbHelper.getWritableDatabase(); //
try {
db.insertWithOnConflict(TABLE, null, values,
SQLiteDatabase.CONFLICT_IGNORE); //
} finally {
db.close(); //
}
}
/**
*
* @return Cursor where the columns are _id, created_at, user, txt
Refactoring Status Data | 131
*/
public Cursor getStatusUpdates() { //
SQLiteDatabase db = this.dbHelper.getReadableDatabase();
return db.query(TABLE, null, null, null, null, null, GET_ALL_ORDER_BY);
}
/**
*
* @return Timestamp of the latest status we ahve it the database
*/
public long getLatestStatusCreatedAtTime() { //
SQLiteDatabase db = this.dbHelper.getReadableDatabase();
try {
Cursor cursor = db.query(TABLE, MAX_CREATED_AT_COLUMNS, null, null, null,
null, null);
try {
return cursor.moveToNext() ? cursor.getLong(0) : Long.MIN_VALUE;
} finally {
cursor.close();
}
} finally {
db.close();
}
}
/**
*
* @param id of the status we are looking for
* @return Text of the status
*/
public String getStatusTextById(long id) { //
SQLiteDatabase db = this.dbHelper.getReadableDatabase();
try {
Cursor cursor = db.query(TABLE, DB_TEXT_COLUMNS, C_ID + "=" + id, null,
null, null, null);
try {
return cursor.moveToNext() ? cursor.getString(0) : null;
} finally {
cursor.close();
}
} finally {
db.close();
}
}
}
Most ol the StatusData coue is a uiiect cut-anu-paste liom DbHc|pcr.java. This is
Lecause it now makes sense to make DbHelper an innei class Lecause DbHelper now
exists only in the context ol StatusData anu is piivate to it. In othei woius, outsiue
ol StatusData, no othei pait ol the system is conceineu with the lact that we aie
using a uataLase to stoie oui uata. That also makes oui system llexiLle, which we
will see latei with the use ol Content Pioviueis.
132 | Chapter 9:The Database
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
This is the piivate anu linal ieleience to the dbHelper instance. Making it final en-
suies that this oLject is cieateu only once, whichevei pait ol the system ieguests it
liist.
The constiuctoi simply constiucts a new instance ol DbHelper.
Ve neeu to expose close() loi the dbHelper so useis ol it close it piopeily.
This is the new anu impioveu veision ol the db.insert...() methou that we hau in
DbHelper pieviously.
Ve open the uataLase only when we neeu it, which is iight Leloie wiiting to it.
In this case, we use insertWithOnConflict() anu pass SQLiteDatabase.CON
FLICT_IGNORE as the linal paiametei to inuicate that when theie`s a conllict, the ex-
ception shoulu Le ignoieu. RememLei that we uiu have a conllict with the uuplicate
IDs, as explaineu in DataLase Constiaints on page 129.
Notice that we close the uataLase iight altei we aie uone. Ve uo this in the
finally section ol oui exception hanuling. This ensuies the uataLase is shut uown
piopeily, iegaiuless ol whethei
something went wiong. This theme is something we iepeat in getLatestStatus
CreatedAtTime() anu getStatusTextById().
This methou simply ietuins all the statuses in the uataLase, with the latest liist.
getLatestStatusCreatedAtTime() ietuins the timestamp ol the latest status in the
uataLase. Having a way to ueteimine the newest locally cacheu status is uselul latei,
to ensuie we auu only new statuses into the uataLase.
Foi a given ID, getStatusTextById() ietuins the actual text ol this status.
Now that we have a new common place to hanule status uata, we can have it hang
oll ol oui common Application oLject so that any pait ol the application can access
the uata easily (see Example 9-+). Conseguently, the UpdaterService anu
TimelineActivity classes aie in a has-a ielationship to StatusData via the YambaAppli
cation oLject.
Exanp|c 9-1. YanbaApp|ication.java
...
private StatusData statusData; //
...
public StatusData getStatusData() { //
return statusData;
}
// Connects to the online service and puts the latest statuses into DB.
// Returns the count of new statuses
public synchronized int fetchStatusUpdates() { //
Log.d(TAG, "Fetching status updates");
Twitter twitter = this.getTwitter();
Refactoring Status Data | 133
if (twitter == null) {
Log.d(TAG, "Twitter connection info not initialized");
return 0;
}
try {
List<Status> statusUpdates = twitter.getFriendsTimeline();
long latestStatusCreatedAtTime = this.getStatusData()
.getLatestStatusCreatedAtTime();
int count = 0;
ContentValues values = new ContentValues();
for (Status status : statusUpdates) {
values.put(StatusData.C_ID, status.getId());
long createdAt = status.getCreatedAt().getTime();
values.put(StatusData.C_CREATED_AT, createdAt);
values.put(StatusData.C_TEXT, status.getText());
values.put(StatusData.C_USER, status.getUser().getName());
Log.d(TAG, "Got update with id " + status.getId() + ". Saving");
this.getStatusData().insertOrIgnore(values);
if (latestStatusCreatedAtTime < createdAt) {
count++;
}
}
Log.d(TAG, count > 0 ? "Got " + count + " status updates"
: "No new status updates");
return count;
} catch (RuntimeException e) {
Log.e(TAG, "Failed to fetch status updates", e);
return 0;
}
}
...
The YamLa application now encapsulates the status uata as a piivate StatusData
oLject.
This oLject is availaLle to the iest ol the application loi viewing only via this accessoi
methou.
This is wheie we moveu most ol the coue liom the pievious veision ol the Updater
Service. This was the coue that was iunning on the Updater thieau, connecting to
the online seivice to get the uata, anu then saving that uata in the uataLase.
Ve can now simplily the UpdaterService so it uses the ielactoieu coue in the
YambaApplication to get the latest uata (see Example 9-5). Note that most ol the
Updater`s run() methou has Leen moveu to YambaApplication`s fetchStatusUpdates()
methou. In auuition, the Updater uoesn`t neeu any access to the StatusData oLject,
which is totally hiuuen liom it.
Exanp|c 9-5. UpdatcrScrvicc.java
...
private class Updater extends Thread {
134 | Chapter 9:The Database
public Updater() {
super("UpdaterService-Updater");
}
@Override
public void run() {
UpdaterService updaterService = UpdaterService.this;
while (updaterService.runFlag) {
Log.d(TAG, "Running background thread");
try {
YambaApplication yamba = (YambaApplication) updaterService
.getApplication(); //
int newUpdates = yamba.fetchStatusUpdates(); //
if (newUpdates > 0) { //
Log.d(TAG, "We have a new status");
}
Thread.sleep(DELAY);
} catch (InterruptedException e) {
updaterService.runFlag = false;
}
}
}
} // Updater
...
Ve get the ieleience to the YambaApplication oLject, which is ieauily availaLle to
the Anuioiu Service anu thus oui own UpdaterService instance.
Ve use the newly cieateu fetchStatusUpdates() methou in YambaApplication, which
now houses most ol the lunctionality that was pieviously pait ol this run() methou.
One leatuie ol fetchStatusUpdates() is that it ietuins the numLei ol new iecoius
that weie letcheu. Ve can use this inlo loi ueLugging loi now, Lut latei will use it
loi an auuitional puipose.
Summary
At this point, YamLa can pull the statuses ol oui liienus liom the clouu anu post them
into the local uataLase. Ve still uon`t have a way to view this uata, Lut we can veiily
that the uata is theie in the uataLase.
Figuie 9-1 illustiates what we have uone so lai as pait ol the uesign outlineu eailiei in
Figuie 5-+.
Summary | 135
Iigurc 9-1. Yanba conp|ction
136 | Chapter 9:The Database
CHAPTER 10
Lists and Adapters
In this chaptei, you will leain how to cieate selection wiugets, such as a ListView. But
this isn`t just a chaptei aLout usei inteilace elements. Ve aie ueepening oui unuei-
stanuing ol uata liom the pievious chaptei Ly leaining how to ieau uata liom the status
uataLase anu liist simply output it to the scieen as sciollaLle text. You will then leain
aLout auapteis in oiuei to connect youi uataLase uiiectly with the list anu cieate a
custom auaptei to implement some auuitional lunctionality. You will link this new
activity with youi main activity so that the usei can Loth post anu ieau tweets.
By the enu ol this chaptei, youi app will Le aLle to post new tweets, as well as pull them
liom Twittei, stoie them in the local uataLase, anu let the usei ieau the statuses in a
nice anu ellicient UI. At that point, youi app will have thiee activities anu a seivice.
TimelineActivity
Ve`ie going to cieate a new activity calleu TimelineActivity to uisplay all the statuses
liom oui liienus. This activity pulls the uata liom the uataLase anu uisplays it on the
scieen. Initially, we uo not have a lot ol uata in the uataLase, Lut as we keep on using
the application, the amount ol statuses might exploue. Oui application neeus to ac-
count loi that.
Ve aie going to Luilu this activity in a lew steps, keeping the application whole anu
complete as we make each impiovement:
1. The liist iteiation ol TimelineActivity uses a TextView to uisplay all the output
liom the uataLase. Since theie may Le guite a Lit ol uata, we will use ScrollView
to wiap oui text anu pioviue scioll Lais.
2. The seconu iteiation uses the much moie scalaLle anu ellicient ListView anu
Adapter appioach. In this step, you will leain how auapteis anu lists woik.
137
3. Finally, we will cieate a custom Adapter to hanule some auuitional Lusiness logic.
At this point, we aie going unuei the hoou ol an auaptei anu auuing custom pio-
cessing. You`ll unueistanu the puipose anu usage ol auapteis Lettei altei this
exeicise.
Basic TimelineActivity Layout
In this liist iteiation, we aie cieating a new layout loi the TimelineActivity. This layout
initially uses a TextView to uisplay all the uata that we have in the uataLase. This is line
initially when we uon`t have too many statuses to show.
Introducing ScrollView
Since it`s unlikely that all oui uata will lit on a single page, we neeu a way to scioll the
text. To uo that, we use ScrollView. ScrollView is like a winuow that uses scioll Lais
to uisplay pait ol a laigei component that takes moie space than the scieen pioviues.
To make some potentially laige views sciollaLle, you wiap them with this Scroll
View. Foi example, we have a piintout ol liienus` statuses in the loim ol a TextView. As
moie statuses aie auueu, this TextView coulu Lecome laige. In oiuei to make it sciollaLle
on a small scieen, we put it into a ScrollView.
A ScrollView can contain only one uiiect chilu. Il you want to comLine multiple views
into a single view that sciolls, you liist neeu to oiganize those views into anothei layout,
like you uiu pieviously in The StatusActivity Layout on page 52, anu than auu that
layout into the ScrollView.
Typically you want ScrollView to take all the availaLle space on the scieen, so you will
specily its layout wiuth anu height as fill_parent.
A ScrollView usually is not manipulateu liom ]ava, so it uoesn`t ieguiie an id.
In Example 10-1, we wiap oui TextView with a ScrollView so that when theie`s a lot ol
text to uisplay, ScrollView automatically auus scioll Lais.
Exanp|c 10-1. rcs/|ayout/tinc|inc_basic.xn|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:background="@drawable/background">
<!-- Title -->
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center"
android:layout_margin="10dp" android:text="@string/titleTimeline"
android:textColor="#fff" android:textSize="30sp" />
<!-- Text output wrapper -->
<ScrollView android:layout_height="fill_parent"
138 | Chapter 10:Lists and Adapters
android:layout_width="fill_parent">
<!-- Text output -->
<TextView android:layout_height="fill_parent"
android:layout_width="fill_parent" android:id="@+id/textTimeline"
android:background="#6000" />
</ScrollView>
</LinearLayout>
This is the title that we show at the top ol this activity`s scieen. Notice that we uelineu
the titleTimeline stiing iesouice in the /rcs/va|ucs/strings.xn| lile, just like we uiu
Leloie in Stiings Resouice on page 55.
The ScrollView that wiaps oui TextView anu auus scioll Lais as neeueu.
The TextView that shows the actual text, in this case oui liienus` statuses liom the
uataLase.
Creating the TimelineActivity Class
Now that we have the layout lile, we neeu to cieate the TimelineActivity class. ]ust
as with any othei ]ava lile, go to the Eclipse Package Exploiei, iight-click on youi
com.marakana.yamba package, choose NewClass, anu name it TimelineActivity.
Anu just as Leloie, whenevei we cieate a new ]ava class that is also a main Luiluing
Llockan activity, seivice, Lioaucast ieceivei, oi content pioviueiwe liist suLclass
a Lase class pioviueu Ly the Anuioiu liamewoik. In the case ol activities, that class is
Activity.
The methou we almost univeisally oveiiiue in any activity is onCreate(). This is a gieat
place loi us to initialize the uataLase. The llip siue ol the coin is onDestroy(), a goou
place to clean up anything that we cieate in onCreate(). In this case, we close the ua-
taLase in onDestroy(). Because we`u like the uata to Le as liesh as possiLle, we put the
coue loi gueiying the uataLase anu outputting the uata in onResume(), the methou calleu
eveiy time this activity is Liought up liont. Example 10-2 shows oui coue.
Exanp|c 10-2. Tinc|incActivity.java, vcrsion 1
package com.marakana.yamba5;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.widget.TextView;
public class TimelineActivity1 extends Activity { //
DbHelper dbHelper;
SQLiteDatabase db;
Cursor cursor;
TextView textTimeline;
Basic TimelineActivity Layout | 139
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timeline);
// Find your views
textTimeline = (TextView) findViewById(R.id.textTimeline);
// Connect to database
dbHelper = new DbHelper(this); //
db = dbHelper.getReadableDatabase(); //
}
@Override
public void onDestroy() {
super.onDestroy();
// Close the database
db.close(); //
}
@Override
protected void onResume() {
super.onResume();
// Get the data from the database
cursor = db.query(DbHelper.TABLE, null, null, null, null, null,
DbHelper.C_CREATED_AT + " DESC"); //
startManagingCursor(cursor); //
// Iterate over all the data and print it out
String user, text, output;
while (cursor.moveToNext()) { //
user = cursor.getString(cursor.getColumnIndex(DbHelper.C_USER)); //
text = cursor.getString(cursor.getColumnIndex(DbHelper.C_TEXT));
output = String.format("%s: %s\n", user, text); //
textTimeline.append(output); //
}
}
}
This is an activity, so we stait Ly suLclassing the Anuioiu liamewoik`s Activity class.
Ve neeu access to the uataLase to get the timeline uata. onCreate() is a goou place
to connect to the uataLase.
Once dbHelper opens the uataLase lile, we neeu to ask it loi the actual uataLase
oLject. To uo that, we can use eithei getReadableDatabase() oi getWritableData
base(). In this case, we aie only ieauing the uata liom the timeline, so we open the
uataLase loi ieauing only.
140 | Chapter 10:Lists and Adapters
At some point we neeu to close the uataLase anu ielease that iesouice. Il the uataLase
was openeu in onCreate(), the counteipait to that woulu Le onDestroy(). So, we
close the uataLase theie. RememLei that onDestroy() is calleu only when the system
has to liee up iesouices.
To gueiy the uata liom the uataLase, we use the query() methou. This methou seems
to contain almost enuless paiameteis, Lut most ol them map nicely to vaiious paits
ol the SQL SELECT statement. So this line is eguivalent to SQL`s SELECT * FROM time
line ORDER BY created_at DESC. The vaiious null values ielei to paits ol the
SELECT statement we aie not using, such as WHERE, GROUPING, anu HAVING. The uata
ietuineu to us is ol type Cursor, which is an iteiatoi.
startManagingCursor() is a convenience methou that tells the activity to stait man-
aging the cuisoi`s lile cycle the same way it manages its own. This means that when
this activity is aLout to Le uestioyeu, it will make suie to ielease any uata ieleiieu
to Ly the cuisoi, thus helping ]ava`s gaiLage collectoi clean up memoiy moie
guickly. The alteinative is loi us to auu coue manually in vaiious oveiiiue methous
anu woiiy aLout cuisoi management ouiselves.
cursor, il you iecall liom Cuisois on page 122, iepiesents all the uata we ieceiveu
liom the uataLase SELECT statement that was ellectively executeu Ly oui query()
methou. This uata is geneially in the loim ol a taLle, with many iows anu columns.
Each iow iepiesents a single iecoiu, such as a single status in oui timeline. Each iow
also has columns that we pieuelineu, such as _id, created_at, user, anu txt. As we
mentioneu Leloie, cursor is an iteiatoi, meaning we can step thiough all its uata one
iecoiu at a time. The liist call to cursor`s moveToNext() positions the cuisoi at the
stait. moveToNext() stops when theie`s no moie uata to piocess.
Foi each iecoiu that the cuisoi cuiiently points to, we can ask loi its value Ly type
anu column inuex. So cursor.getString(3) ietuins a stiing value ol the status, anu
cursor.getLong(1) gives us the timestamp inuicating when this iecoiu was cieateu.
Relei Lack to Chaptei 9 to see how we ueline stiings such as C_USER anu C_TEXT in
oui piogiam that map to column names in the uataLase. Howevei, having
haiucoueu column inuices is not a goou piactice, Lecause il we evei change the
schema, we`ll have to iememLei to upuate this coue. Also, the coue is not veiy
ieauaLle in this loim. A Lettei piactice is to ask the uataLase loi the inuex ol each
column. Ve uo that with the cursor.getColumnIndex() call.
Ve use String.format() to loimat each line ol the output. Because we chose the
TextView wiuget to uisplay the uata, we can only uisplay text, oi in othei woius,
loimatteu stiings. In a latei iteiation ol this coue, we`ll impiove on this.
Ve linally appenu that new line ol output to oui text view textTimeline so the usei
can see it on the scieen.
Although this appioach woiks loi smallei uata sets, it is not optimal oi iecommenueu.
The Lettei appioach is to use a ListView to iepiesent the list ol statuses stoieu in the
Basic TimelineActivity Layout | 141
uataLase. ListView, which we`ll use in the next veision ol oui TimelineActivity, is much
moie scalaLle anu ellicient.
About Adapters
A ScrollView will woik loi a lew uozen iecoius. But what il youi status uataLase has
hunuieus oi even thousanus ol iecoius? Vaiting to get anu piint them all woulu Le
highly inellicient. The usei pioLaLly uoesn`t even caie aLout all ol the uata anyhow.
To auuiess this issue, Anuioiu pioviues auapteis. These aie a smait way to connect a
View with some kinu ol uata souice (see Figuie 10-1). Typically, youi view woulu Le a
ListView anu the uata woulu come in the loim ol a Cursor oi Array. So auapteis come
as suLclasses ol CursorAdapter oi ArrayAdapter.
Iigurc 10-1. Adaptcr
Adding a ListView to TimelineActivity
As Leloie, oui liist stop in upgiauing oui applications is oui iesouices lile. Ve`ll auu
a ListView to the timeline layout Ly euiting tinc|inc.xn|, shown in Example 10-3.
Exanp|c 10-3. rcs/|ayout/tinc|inc.xn|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:background="@drawable/background">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center"
android:layout_margin="10dp" android:text="@string/titleTimeline"
android:textColor="#fff" android:textSize="30sp" />
<!-- -->
<ListView android:layout_height="fill_parent"
android:layout_width="fill_parent" android:id="@+id/listTimeline"
android:background="#6000" />
142 | Chapter 10:Lists and Adapters
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
</LinearLayout>
Auuing ListView to youi layout is like auuing any othei wiuget. The main attiiLutes
aie id, layout_height, anu layout_width.
ListView versus ListActivity
Ve coulu have useu ListActivity as the paient class loi oui TimelineActivity.
ListActivity is an activity that has a ListView. Eithei appioach woulu woik, Lut we
chose to suLclass Activity anu cieate ListView sepaiately to pioviue step-Ly-step, in-
ciemental leaining.
ListActivity is slightly easiei to use in cases wheie the Luilt-in ListView is the only
wiuget in the activity. ListActivity also makes it veiy easy to assign an existing aiiay
ol elements to its list via the XML Linuing. Howevei, we aie using a Cursor loi uata
anu not an aiiay (Lecause oui uata comes liom the uataLase), anu we uo have an
auuitional TextView loi the sciollview`s title, so the simplicity ol ListActivity in this
case is outweigheu Ly the customization we ieguiie.
Creating a Row Layout
Theie`s one moie XML lile to take caie ol. Although tinc|inc.xn| uesciiLes the entiie
activity, we also neeu to specily what a single iow ol uata looks likethat is, a single
line item on the scieen that will show inloimation such as who saiu what anu when.
The easiest way to uo that is to cieate anothei XML lile just loi that iow. As loi any
new XML lile, we use the Anuioiu New XML File uialog winuow: FileNewAnuioiu
New XML File. Let`s name this lile row.xn| anu select Layout loi the type.
Foi this layout, we chose one LinearLayout with two lines aiiangeu veitically. The liist
line consists ol the usei anu timestamp, anu the seconu contains the actual status mes-
sage. Notice that the liist line uses anothei LinearLayout to position the usei anu time-
stamp hoiizontally next to each othei.
The iow ol uata in the ListView is iepiesenteu Ly a custom layout uelineu in the
row.xn| lile, shown in Example 10-+.
Exanp|c 10-1. rcs/|ayout/row.xn|
<?xml version="1.0" encoding="utf-8"?>
<!-- -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:orientation="vertical"
android:layout_width="fill_parent">
<!-- -->
<LinearLayout android:layout_height="wrap_content"
android:layout_width="fill_parent">
About Adapters | 143
<!-- -->
<TextView android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_weight="1"
android:id="@+id/textUser" android:text="Slashdot"
android:textStyle="bold" />
<!-- -->
<TextView android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_weight="1"
android:gravity="right" android:id="@+id/textCreatedAt"
android:text="10 minutes ago" />
</LinearLayout>
<!-- -->
<TextView android:layout_height="wrap_content"
android:layout_width="fill_parent" android:id="@+id/textText"
android:text="Firefox comes to Android" />
</LinearLayout>
The main layout loi the entiie iow. It is veitical Lecause oui iow consists ol two lines.
A layout that iuns hoiizontally anu iepiesents the liist line ol uata, namely the usei
anu timestamp.
The usei who posteu this upuate.
The timestamp inuicating when it was posteu. It shoulu Le a ielative time (e.g., 10
minutes ago).
The actual status.
Creating an Adapter in TimelineActivity.java
Now that we have the XML liles soiteu out, we aie ieauy to upuate the ]ava coue,
shown in Example 10-5. Fiist, we neeu to cieate the auaptei. Auapteis geneially come
in two llavois: those that iepiesent aiiay uata anu those that iepiesent cuisoi uata.
Since oui uata is coming liom the uataLase, we aie going to use the cuisoi-Laseu
auaptei. One ol the simplest ol those is SimpleCursorAdapter.
SimpleCursorAdapter ieguiies us to uesciiLe a single iow ol uata (which we uo in
row.xn|), the uata (a cuisoi in oui case), anu the mapping loi a single iecoiu ol uata
to the single iow in the list. The last paiametei maps each cuisoi column to a view in
the list.
Exanp|c 10-5. Tinc|incActivity.java, vcrsion 2
package com.marakana.yamba5;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
144 | Chapter 10:Lists and Adapters
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public class TimelineActivity2 extends Activity {
DbHelper dbHelper;
SQLiteDatabase db;
Cursor cursor; //
ListView listTimeline; //
SimpleCursorAdapter adapter; //
static final String[] FROM = { DbHelper.C_CREATED_AT, DbHelper.C_USER,
DbHelper.C_TEXT }; //
static final int[] TO = { R.id.textCreatedAt, R.id.textUser, R.id.textText }; //
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timeline);
// Find your views
listTimeline = (ListView) findViewById(R.id.listTimeline); //
// Connect to database
dbHelper = new DbHelper(this);
db = dbHelper.getReadableDatabase();
}
@Override
public void onDestroy() {
super.onDestroy();
// Close the database
db.close();
}
@Override
protected void onResume() {
super.onResume();
// Get the data from the database
cursor = db.query(DbHelper.TABLE, null, null, null, null, null,
DbHelper.C_CREATED_AT + " DESC");
startManagingCursor(cursor);
// Set up the adapter
adapter = new SimpleCursorAdapter(this, R.layout.row, cursor, FROM, TO); //
listTimeline.setAdapter(adapter); //
}
}
Cuisoi to all the status upuates that we have in the uataLase.
listTimeline is oui ListView that uisplays the uata.
adapter is oui custom auaptei, explaineu in the text that lollows this example.
About Adapters | 145
FROM is a stiing aiiay specilying which columns in the cuisoi we`ie Linuing liom. Ve
use the same stiings alieauy useu to ielei to columns in oui piogiam.
TO is an aiiay ol integeis iepiesenting IDs ol views in the row.xn| layout to which
we aie Linuing uata. The numLei ol elements in FROM anu TO must Le the same, so
that element at inuex 0 in FROM maps to element 0 in TO, anu so on.
Ve get the ListView liom the XML layout.
Once we have the uata as a cuisoi, the layout ol a single iow liom the row.xn| lile,
anu the FROM anu TO constants loi mapping the uata, we aie ieauy to cieate the
SimpleCursorAdapter.
Finally, we neeu to tell oui ListView to use this auaptei.
At this point, TimelineActivity is complete, Lut not yet iegisteieu with the manilest
lile. Ve`ll uo that in the next section. Howevei, il we weie to iun this activity, you`u
guickly notice that the timestamp uoesn`t look guite the way we imagineu it.
RememLei that we aie stoiing the status cieation time in the uataLase as a long value
iepiesenting the numLei ol milliseconus since ]anuaiy 1st, 1970. Anu since that`s the
value in the uataLase, that`s the value we show on the scieen as well. This is the stanuaiu
Unix time, which is veiy uselul loi iepiesenting actual points in time. But the value is
not veiy meaninglul to useis. Insteau ol showing value 1287603266359, it woulu Le much
nicei to iepiesent it to the usei as 10 Minutes Ago. This liienuly time loimat is known
as rc|ativc tinc, anu Anuioiu pioviues a methou to conveit liom one loimat to the othei.
The guestion is wheie to inject this conveision. As it stanus iight now, the
SimpleCursorAdapter is capaLle only ol mapping stiaight liom a uataLase value to layout
view. This uoesn`t woik loi oui neeus, Lecause we neeu to auu some Lusiness logic in
Letween the uata anu the view. To uo this, we`ll cieate oui own auaptei.
TimelineAdapter
TimelineAdapter is oui custom auaptei, shown in Example 10-6. Although SimpleCursor
Adapter uiu a stiaightloiwaiu mapping ol uata in the uataLase to views on the scieen,
we hau an issue with the timestamp. The joL ol TimelineAdapter is to inject some Lusi-
ness logic to conveit the Unix timestamp to ielative time. The methou in
SimpleCursorAdapter that cieates a uisplayaLle view liom input uata is bindView(), so
we`ll oveiiiue that methou anu ask it to massage the uata Leloie it is uisplayeu.
Typically, il you aie not suie which methou to oveiiiue, look at the online uocumen-
tation loi the paiticulai system class that you aie mouilying (in this case, http://dcvc|opcr
.android.con/rcjcrcncc/android/widgct/Sinp|cCursorAdaptcr.htn|).
Exanp|c 10-. Tinc|incAdaptcr.java
package com.marakana.yamba5;
146 | Chapter 10:Lists and Adapters
import android.content.Context;
import android.database.Cursor;
import android.text.format.DateUtils;
import android.view.View;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
public class TimelineAdapter extends SimpleCursorAdapter { //
static final String[] FROM = { DbHelper.C_CREATED_AT, DbHelper.C_USER,
DbHelper.C_TEXT }; //
static final int[] TO = { R.id.textCreatedAt, R.id.textUser, R.id.textText }; //
// Constructor
public TimelineAdapter(Context context, Cursor c) { //
super(context, R.layout.row, c, FROM, TO);
}
// This is where the actual binding of a cursor to view happens
@Override
public void bindView(View row, Context context, Cursor cursor) { //
super.bindView(row, context, cursor);
// Manually bind created at timestamp to its view
long timestamp = cursor.getLong(cursor
.getColumnIndex(DbHelper.C_CREATED_AT)); //
TextView textCreatedAt = (TextView) row.findViewById(R.id.textCreatedAt); //
textCreatedAt.setText(DateUtils.getRelativeTimeSpanString(timestamp)); //
}
}
To cieate oui own custom auaptei, we suLclass one ol the Anuioiu stanuaiu auapt-
eis, in this case the same SimpleCursorAdapter we useu in the pievious section.
This constant uelines the columns ol inteiest to us in the uataLase, as in the pievious
example.
This constant specilies the IDs ol views that we`ll map those columns to.
Because we`ie uelining a new class, we neeu a constiuctoi. It simply calls the paient
constiuctoi using super.
The only methou we oveiiiue is bindView(). This methou is calleu loi each iow to
map its uata to its views, anu it`s wheie the gist ol the auaptei woik happens. In
oiuei to ieuse most ol the uata-to-views mapping pioviueu Ly SimpleCursor
Adapter, we call super.bindView() liist.
To oveiiiue uelault mapping loi the timestamp, we liist get the actual timestamp
value liom the uataLase.
Next, we linu the specilic TextView in the row.xn| lile.
TimelineAdapter | 147
Finally, we set the value ol textCreatedAt to the ielative time since the timestamp.
To uo this, we use the Anuioiu SDK methou DateUtils.getRelativeTimeSpan
String().
At this point, we can luithei simplily oui TimelineActivity class Lecause we moveu
some ol the auaptei uetails to TimelineAdapter. Example 10-7 shows this simplilieu
coue.
Exanp|c 10-7. Tinc|incActivity.java, vcrsion 3
package com.marakana.yamba5;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.widget.ListView;
public class TimelineActivity3 extends Activity {
DbHelper dbHelper;
SQLiteDatabase db;
Cursor cursor;
ListView listTimeline;
TimelineAdapter adapter; //
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timeline);
// Find your views
listTimeline = (ListView) findViewById(R.id.listTimeline);
// Connect to database
dbHelper = new DbHelper(this);
db = dbHelper.getReadableDatabase();
}
@Override
public void onDestroy() {
super.onDestroy();
// Close the database
db.close();
}
@Override
protected void onResume() {
super.onResume();
// Get the data from the database
cursor = db.query(DbHelper.TABLE, null, null, null, null, null,
DbHelper.C_CREATED_AT + " DESC");
startManagingCursor(cursor);
148 | Chapter 10:Lists and Adapters
// Create the adapter
adapter = new TimelineAdapter(this, cursor); //
listTimeline.setAdapter(adapter); //
}
}
Ve change SimpleCursorAdapter to TimelineAdapter.
Cieate a new instance ol the TimelineAdapter, anu pass it the context anu the uata.
Set oui ListView to connect to the uata via the auaptei.
One ol the shoitcomings ol oveiiiuing bindView() is that we use super.bindView() to
Linu all views liist, anu then ieplace its Lehavioi loi one paiticulai element. This is
somewhat wastelul. The linal veision ol oui application in this chaptei will optimize
the piocess.
ViewBinder: A Better Alternative to TimelineAdapter
Insteau ol cieating a new TimelineAdapter that is a suLclass ol SimpleCursorAdapter anu
oveiiiuing its bindView() methou, we coulu attach the Lusiness logic uiiectly to the
existing SimpleCursorAdapter. This appioach is moie ellicient Lecause we aie not ovei-
iiuing bindView() anu we uo not ieguiie a sepaiate custom auaptei class.
To attach Lusiness logic to an existing SimpleCursorAdapter, use its setViewBinder()
methou. Ve will neeu to supply the methou with an implementation ol ViewBinder.
ViewBinder is an inteilace that specilies setViewValue(), wheie the actual Linuing ol a
paiticulai uate element to a paiticulai view happens.
Again, we uiscoveieu the setViewBinder() leatuie ol this SimpleCursorAdapter liame-
woik class Ly ieauing its ieleience uocumentation.
In oui linal iteiation ol TimelineAdapter, we cieate a custom ViewBinder as a constant
anu attach it to the stock SimpleCursorAdapter, as shown in Example 10-S.
Exanp|c 10-8. Tinc|incActivity.java with \icwBindcr
...
@Override
protected void onResume() {
...
adapter.setViewBinder(VIEW_BINDER); //
...
}
// View binder constant to inject business logic that converts a timestamp to
// relative time
static final ViewBinder VIEW_BINDER = new ViewBinder() { //
ViewBinder: A Better Alternative to TimelineAdapter | 149
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
public boolean setViewValue(View view, Cursor cursor, int columnIndex) { //
if (view.getId() != R.id.textCreatedAt)
return false; //
// Update the created at text to relative time
long timestamp = cursor.getLong(columnIndex); //
CharSequence relTime = DateUtils.getRelativeTimeSpanString(view
.getContext(), timestamp); //
((TextView) view).setText(relTime); //
return true; //
}
};
...
Ve attach a custom ViewBinder instance to oui stock auaptei. VIEW_BINDER is uelineu
latei in oui coue.
The actual implementation ol a ViewBinder instance. Notice that we aie implement-
ing it as an innei class. Theie`s no ieason loi any othei class to use it, anu thus it
shoulun`t Le exposeu to the outsiue woilu. Also notice that it is static final,
meaning that it`s a constant.
The only methou that we neeu to pioviue is setViewValue(). This methou is calleu
loi each uata element that neeus to Le Lounu to a paiticulai view.
Fiist we check whethei this view is the view we caie aLout, i.e., oui TextView iep-
iesenting when the status was cieateu. Il not, we ietuin false, which causes the
auaptei to hanule the Linu itsell in the stanuaiu mannei. Il it is oui view, we move
on anu uo the custom Linu.
Ve get the iaw timestamp value liom the cuisoi uata.
Using the same Anuioiu helpei methou we useu in oui pievious example,
DateUtils.getRelativeTimeSpanString(), we conveit the timestamp to a human-
ieauaLle loimat. This is that Lusiness logic that we aie injecting.
Upuate the text on the actual view.
Retuin true so that SimpleCursorAdapter uoes not piocess bindView() on this ele-
ment in its stanuaiu way.
Updating the Manifest File
Now that we have the TimelineActivity, it woulu make sense to make it the main
activity loi oui YamLa application. Altei all, useis aie moie likely to check what theii
liienus aie uoing than to upuate theii own status.
150 | Chapter 10:Lists and Adapters
To uo that, we neeu to upuate the manilest lile. As usual, we`ll list TimelineActivity
within the <activity> element in the AndroidManijcst.xn| lile, just as we auueu the
pieleience activity to the manilest lile in Upuate the Manilest File on page SS:
<activity android:name=".TimelineActivity" />
Now, in oiuei to make TimelineActivity the main entiy point into oui application, we
neeu to iegistei it to iesponu to ceitain intcnts. Basically, when the usei clicks to stait
youi application, the system senus an intent. You have to ueline an activity to listen
to this intent. The activity uoes that Ly lilteiing the intents with an IntentFilter. In
XML, this is within the <intent-filter> element, anu it usually contains at least an
<action> element iepiesenting the actual intent action we`ie inteiesteu in.
You might have noticeu that StatusActivity hau some extia XML compaieu to
PrefsActivity. The extia coue is the intent liltei Llock, along with the action that
it`s lilteiing loi.
Theie is a special action nameu android.intent.action.MAIN that simply inuicates this
is the main component that shoulu Le staiteu when the usei wants to stait youi appli-
cation. Auuitionally, the <category> element tells the system that this application
shoulu Le auueu to the main Launchei application so that the usei can see its app icon
along with all the othei icons, click on it, anu stait it. This categoiy is uelineu as
android.intent.category.LAUNCHER.
So, to make TimelineActivity the main entiy point, we simply list it anu move the coue
liom the StatusActivity ueclaiation ovei to the TimelineActivity ueclaiation, as
shown in Example 10-9.
Exanp|c 10-9. AndroidManijcst.xn|
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionName="1.0" package="com.marakana.yamba5">
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:name=".YambaApplication">
<activity android:name=".TimelineActivity" android:label="@string/titleTimeline">
<intent-filter> <!-- -->
<action android:name="android.intent.action.MAIN" /> <!-- -->
<category android:name="android.intent.category.LAUNCHER" /> <!-- -->
</intent-filter>
</activity>
<activity android:name=".PrefsActivity" android:label="@string/titlePrefs" />
<activity android:name=".StatusActivity"
android:label="@string/titleStatus" /> <!-- -->
<service android:name=".UpdaterService" />
</application>
<uses-sdk android:minSdkVersion="8" />
Updating the Manifest File | 151
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
<intent_filter> iegisteis this paiticulai activity with the system to iesponu to cei-
tain intents.
Tells the system that this is the main activity to stait when useis stait youi
application.
The categoiy LAUNCHER tells the Home application to auu this application into the
list uisplayeu in the launchei uiawei.
StatusActivity no longei neeus any intent lilteis.
Initial App Setup
Now when the usei iuns oui application, the Timeline scieen will show up liist. But
unless the usei knows she shoulu set up the pieleiences anu stait the seivice, theie will
Le no uata anu veiy little hanu-holuing telling hei what to uo.
One solution is to check whethei pieleiences exist, anu il they uo not, ieuiiect the usei
to the Pieleience activity with a message telling hei what to uo next:
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// Check whether preferences have been set
if (yamba.getPrefs().getString("username", null) == null) { //
startActivity(new Intent(this, PrefsActivity.class)); //
Toast.makeText(this, R.string.msgSetupPrefs, Toast.LENGTH_LONG).show(); //
}
...
}
...
Ve check whethei a paiticulai pieleience has Leen set. In this case, I`ve chosen to
check username Lecause it`s likely to Le set il any pieleiences at all aie set. Since the
pieleiences uo not exist the liist time the usei iuns the application, this means
the value ol username (oi any othei pieleience item we choose) will Le null.
Ve stait the PrefsActivity. Note that startActivity() will uispatch an intent to the
system, Lut the iest ol onCreate() will execute as well. This is goou Lecause we`ie
likely going to come Lack to the Timeline activity once we`ie uone setting up
pieleiences.
Ve uisplay a little pop-up message, i.e., a Toast, telling the usei what to uo. This
assumes that you have cieateu the appiopiiate msgSetupPrefs in youi strings.xn| lile.
152 | Chapter 10:Lists and Adapters
Base Activity
Now that we have a Timeline activity, we neeu to give it an options menu, just as we
uiu loi oui Status activity in The Options Menu on page S9. This is especially im-
poitant Lecause the Timeline activity is the entiy point into oui application, anu with-
out the menu, the usei cannot easily get to any othei activity oi stait anu stop the seivice.
As one appioach, we coulu copy anu paste the coue we alieauy have liom the Status
activity, Lut that`s iaiely a goou stiategy. Insteau, we`ll uo what we usually uo: ielactoi
the coue. In this case, we can take out the common lunctionality liom the Status activity
anu place it in anothei activity that will seive as the Lase. See Figuie 10-2.
Iigurc 10-2. BascActivity rcjactor
To uo that, we`ll cieate a new class calleu BaseActivity anu move the common lunc-
tionality into it. Foi us, the common lunctionality incluues getting the ieleience to the
YambaApplication oLject, as well as the onCreateOptionsMenu() anu onOptionsItem
Selected() methous that suppoit the options menu.
Base Activity | 153
Toggle Service
Vhile we`ie at it, insteau ol having Stait Seivice anu Stop Seivice menu Luttons, it
woulu Le nice to pioviue just one Lutton that toggles Letween Stait anu Stop. To uo
that, we`ll change oui menu anu auu onMenuOpened() to the Lase activity to uynamically
upuate the title anu images loi this toggle item.
Fiist, we`ll upuate the ncnu.xn| lile to incluue oui new toggle menu item, as shown in
Example 10-10. At the same time, we`ll iemove the Stait Seivice anu Stop Seivice items
Lecause oui toggle leatuie makes them oLsolete.
Exanp|c 10-10. rcs/ncnu/ncnu.xn|jj
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/itemStatus" android:title="@string/titleStatus"
android:icon="@android:drawable/ic_menu_edit"></item>
<item android:title="@string/titleTimeline" android:id="@+id/itemTimeline"
android:icon="@android:drawable/ic_menu_sort_by_size"></item>
<item android:id="@+id/itemPrefs" android:title="@string/titlePrefs"
android:icon="@android:drawable/ic_menu_preferences"></item>
<item android:icon="@android:drawable/ic_menu_delete"
android:title="@string/titlePurge" android:id="@+id/itemPurge"></item>
<!-- -->
<item android:id="@+id/itemToggleService" android:title="@string/titleServiceStart"
android:icon="@android:drawable/ic_media_play"></item>
</menu>
This new itemToggleService now ieplaces Loth itemServiceStart anu itemService
Stop.
Next, we neeu to oveiiiue onMenuOpened() in the Lase activity to change the menu item
uynamically, shown in Example 10-11.
Exanp|c 10-11. BascActivity.java
package com.marakana.yamba5;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
/**
* The base activity with common features shared by TimelineActivity and
* StatusActivity
*/
public class BaseActivity extends Activity { //
YambaApplication yamba; //
154 | Chapter 10:Lists and Adapters
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
yamba = (YambaApplication) getApplication(); //
}
// Called only once first time menu is clicked on
@Override
public boolean onCreateOptionsMenu(Menu menu) { //
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
// Called every time user clicks on a menu item
@Override
public boolean onOptionsItemSelected(MenuItem item) { //
switch (item.getItemId()) {
case R.id.itemPrefs:
startActivity(new Intent(this, PrefsActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
break;
case R.id.itemToggleService:
if (yamba.isServiceRunning()) {
stopService(new Intent(this, UpdaterService.class));
} else {
startService(new Intent(this, UpdaterService.class));
}
break;
case R.id.itemPurge:
((YambaApplication) getApplication()).getStatusData().delete();
Toast.makeText(this, R.string.msgAllDataPurged, Toast.LENGTH_LONG).show();
break;
case R.id.itemTimeline:
startActivity(new Intent(this, TimelineActivity.class).addFlags(
Intent.FLAG_ACTIVITY_SINGLE_TOP).addFlags(
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
break;
case R.id.itemStatus:
startActivity(new Intent(this, StatusActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
break;
}
return true;
}
// Called every time menu is opened
@Override
public boolean onMenuOpened(int featureId, Menu menu) { //
MenuItem toggleItem = menu.findItem(R.id.itemToggleService); //
if (yamba.isServiceRunning()) { //
toggleItem.setTitle(R.string.titleServiceStop);
toggleItem.setIcon(android.R.drawable.ic_media_pause);
} else { //
Base Activity | 155
toggleItem.setTitle(R.string.titleServiceStart);
toggleItem.setIcon(android.R.drawable.ic_media_play);
}
return true;
}
}
BaseActivity is an Activity.
Ve ueclaie the shaieu YambaApplication to make it accessiLle to all the othei
suLclasses.
In onCreate(), we get the ieleience to yamba.
onCreateOptionsMenu() is moveu heie liom StatusActivity.
onOptionsItemSelected() is also moveu ovei liom StatusActivity. Notice, howevei,
that it now checks loi itemToggleService insteau ol stait anu stop seivice items.
Baseu on the state ol the seivice, which we know liom the llag in yamba, we ieguest
eithei to stait oi to stop the upuatei seivice.
onMenuOpened() is the new methou calleu Ly the system when the options menu is
openeu. This is a goou callLack loi us to implement the toggle lunctionality. Ve`ie
given the menu oLject that iepiesents the options menu.
Vithin the menu oLject, we linu oui new toggle item so that we can upuate it Laseu
on the cuiient state ol the upuatei seivice.
Ve check whethei the seivice is alieauy iunning, anu il it is, we set the appiopiiate
title anu icon loi the toggle item. Notice that heie we`ie setting up the title anu icon
piogiammatically using the ]ava APIs insteau ol the XML, which we useu initially
to set up the menu in ncnu.xn|.
Il the seivice is stoppeu, we set the icon anu title so that usei can click on it anu stait
the seivice. This way oui single toggle Lutton communicates the seivice`s cuiient
state.
Now that we have a BaseActivity class, let`s upuate oui Timeline activity to use it.
Example 10-12 shows what the completeu Timeline activity looks like.
Exanp|c 10-12. Tinc|incActivity.java, jina| vcrsion
package com.marakana.yamba5;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;
156 | Chapter 10:Lists and Adapters
import android.widget.SimpleCursorAdapter.ViewBinder;
public class TimelineActivity extends BaseActivity { //
Cursor cursor;
ListView listTimeline;
SimpleCursorAdapter adapter;
static final String[] FROM = { DbHelper.C_CREATED_AT, DbHelper.C_USER,
DbHelper.C_TEXT };
static final int[] TO = { R.id.textCreatedAt, R.id.textUser, R.id.textText };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timeline);
// Check if preferences have been set
if (yamba.getPrefs().getString("username", null) == null) { //
startActivity(new Intent(this, PrefsActivity.class));
Toast.makeText(this, R.string.msgSetupPrefs, Toast.LENGTH_LONG).show();
}
// Find your views
listTimeline = (ListView) findViewById(R.id.listTimeline);
}
@Override
protected void onResume() {
super.onResume();
// Setup List
this.setupList(); //
}
@Override
public void onDestroy() {
super.onDestroy();
// Close the database
yamba.getStatusData().close(); //
}
// Responsible for fetching data and setting up the list and the adapter
private void setupList() { //
// Get the data
cursor = yamba.getStatusData().getStatusUpdates();
startManagingCursor(cursor);
// Setup Adapter
adapter = new SimpleCursorAdapter(this, R.layout.row, cursor, FROM, TO);
adapter.setViewBinder(VIEW_BINDER); //
listTimeline.setAdapter(adapter);
}
// View binder constant to inject business logic for timestamp to relative
// time conversion
Base Activity | 157
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
static final ViewBinder VIEW_BINDER = new ViewBinder() { //
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (view.getId() != R.id.textCreatedAt)
return false;
// Update the created at text to relative time
long timestamp = cursor.getLong(columnIndex);
CharSequence relTime = DateUtils.getRelativeTimeSpanString(view
.getContext(), timestamp);
((TextView) view).setText(relTime);
return true;
}
};
}
Foi staiteis, we now suLclass oui BaseActivity insteau ol just the system`s
Activity. This way we inheiit the yamba oLject as well as all the suppoit loi the
options menu.
This is wheie we check whethei pieleiences aie alieauy set. Il not, we`ll ieuiiect the
usei to the Pieleience activity liist.
On iesuming this activity, we set up the list. This is a piivate methou, shown latei
in the coue.
Vhen this activity is closeu, we want to make suie we close the uataLase to ielease
this iesouice. The uataLase is openeu Ly the call to getStatusUpdates() in the
yamba application.
setupList() is the convenience methou that gets the uata, sets up the auaptei, anu
connects it all to the list view.
This is wheie we attach the view Linuei to the list, as uiscusseu eailiei in View-
Binuei: A Bettei Alteinative to TimelineAuaptei on page 1+9.
ViewBinder is uelineu heie.
At this point, we`ve uone a lot ol the ielactoiing woik on oui Timeline activity. Ve can
also simplily the Status activity Ly cutting out the coue ielateu to the options menu.
This also helps sepaiate lunctional conceins among BaseActivity, StatusDate, anu
TimelineActivity.
Figuie 10-3 shows what the linal Timeline activity scieen looks like.
158 | Chapter 10:Lists and Adapters
Iigurc 10-3. Tinc|incActivity
Summary
At this point, YamLa can post a new status as well as list the statuses ol oui liienus.
Oui application is complete anu usaLle.
Figuie 10-+ illustiates what we have uone so lai as pait ol the uesign outlineu eailiei
in Figuie 5-+.
Summary | 159
Iigurc 10-1. Yanba conp|ction
160 | Chapter 10:Lists and Adapters
CHAPTER 11
Broadcast Receivers
In this chaptei, you will leain aLout Lioaucast ieceiveis anu when to use them. Ve`ll
cieate a couple ol uilleient ieceiveis that illustiate uilleient usage scenaiios. Fiist, you`ll
cieate a Lioaucast ieceivei that will stait up youi upuate seivice at Loot time, so that
useis always have theii liienus` latest timelines the liist time they check loi them (as-
suming theii pieleiences aie set). Next, you will cieate a ieceivei that will upuate the
timeline when it changes while the usei is viewing it. This will illustiate the piogiam-
matic iegistiation ol ieceiveis anu intiouuce you to Lioaucasting intents. Ve`ll imple-
ment a ieceivei that is tiiggeu Ly changes in netwoik availaLility. Anu linally, we`ll
leain how to suiiounu oui app with some secuiity Ly uelining peimissions.
By the enu ol this chaptei, youi app has most ol the lunctionality that a usei woulu
neeu. The app can senu status upuates, get liienus` timelines, upuate itsell, anu stait
automatically. It woiks even when the usei is not connecteu to the netwoik (although
ol couise it cannot senu oi ieceive new messages).
About Broadcast Receivers
Bioaucast ieceiveis aie Anuioiu`s implementation ol the PuLlish/SuLsciiLe messaging
pattein, oi moie piecisely, the OLseivei pattein. Applications (known as pub|ishcrs)
can geneiate Lioaucasts to simply senu events without knowing who, il anyone, will
get them. Receiveis (known as subscribcrs) that want the inloimation suLsciiLe to spe-
cilic messages via lilteis. Il the message matches a liltei, the suLsciiLei is activateu (il
it`s not alieauy iunning) anu notilieu ol the message.
As you may iecall liom Chaptei +, a BroadcastReceiver is a piece ol coue to which an
app suLsciiLes in oiuei to get notilieu when an action happens. That action is in the
loim ol an intcnt broadcast. Vhen the iight intent is liieu, the ieceivei wakes up anu
executes. The wakeup happens in the loim ol an onReceive() callLack methou.
161
BootReceiver
In oui YamLa application, the UpdaterService is iesponsiLle loi peiiouically upuating
the uata liom the online seivice. Cuiiently, the usei neeus to stait the seivice manually,
which she uoes Ly staiting the application anu then clicking on the Stait Seivice menu
option.
It woulu Le much cleanei anu simplei il somehow the system automatically staiteu
UpdaterService when the uevice poweieu up. To uo this, we cieate BootReceiver, a
Lioaucast ieceivei that the system will launch when the Loot is complete, which in tuin
will launch oui TimelineActivity activity. Example 11-1 sets up oui Lioaucast ieceivei.
Exanp|c 11-1. BootRcccivcr.java
package com.marakana.yamba6;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootReceiver extends BroadcastReceiver { //
@Override
public void onReceive(Context context, Intent intent) { //
context.startService(new Intent(context, UpdaterService.class)); //
Log.d("BootReceiver", "onReceived");
}
}
Ve cieate BootReceiver Ly suLclassing BroadcastReceiver, the Lase class loi all
ieceiveis.
The only methou that we neeu to implement is onReceive(). This methou gets calleu
when an intent matches this ieceivei.
Ve launch an intent to stait oui Upuatei seivice. The system passeu us a Context
oLject when it invokeu oui onReceive() methou, anu we aie expecteu to pass it on
to the Upuatei seivice. The seivice uoesn`t happen to use the Context oLject loi
anything, Lut we`ll see an impoitant use loi it latei.
At this point, we have oui Loot ieceivei. But in oiuei loi it to get calleuin othei woius,
in oiuei loi the activity to stait at Lootwe must iegistei it with the system.
Registering the BootReceiver with the AndroidManifest File
To iegistei BootReceiver, we auu it to the manilest lile, shown in Example 11-2. Ve
also auu an intcnt ji|tcr to this lile. This intent liltei specilies which Lioaucasts tiiggei
the ieceivei to Lecome activateu.
162 | Chapter 11:Broadcast Receivers
Exanp|c 11-2. AndroidManijcst.xn|: <app|ication> scction
...
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
...
In oiuei to get notilications loi this paiticulai intent liltei, we must also specily that
we`ie using a specilic peimission it ieguiies, in this case android.permission
.RECEIVE_BOOT_COMPLETED (see Example 11-3).
Exanp|c 11-3. AndroidManijcst.xn|: <nanijcst> scction
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
Il we uon`t specily the peimission we ieguiie, we simply won`t Le no-
tilieu when this event occuis, anu we won`t have the chance to iun oui
staitup coue. Ve won`t even know we aien`t getting notilieu, so this is
potentially a haiu Lug to linu.
Testing the Boot Receiver
At this point, you can ieLoot youi uevice. Once it comes Lack up, youi
UpdaterService shoulu Le up anu iunning. You can veiily this eithei Ly looking at the
LogCat loi oui output oi Ly using System Settings anu checking that the seivice is
iunning.
To veiily via System Settings, at the Home scieen, click on the Menu Lutton anu choose
SettingsApplicationsRunning Seivices. You shoulu see UpdaterService listeu theie.
At this point, you know the BootReceiver uiu inueeu get the Lioaucast anu has staiteu
the UpdaterService.
The TimelineReceiver
Cuiiently, il you view youi Timeline activity while a new status upuate comes in, you
won`t know aLout it. That`s Lecause the UpdaterService uoesn`t have a way to notily
TimelineActivity to ieliesh itsell.
To auuiess this, we cieate anothei Lioaucast ieceivei, this time as an innei class ol
TimelineActivity, as shown in Example 11-+.
The TimelineReceiver | 163
Exanp|c 11-1. Tinc|incActivity.java with Tinc|incRcccivcr inncr c|ass
...
class TimelineReceiver extends BroadcastReceiver { //
@Override
public void onReceive(Context context, Intent intent) { //
cursor.requery(); //
adapter.notifyDataSetChanged(); //
Log.d("TimelineReceiver", "onReceived");
}
}
...
As Leloie, to cieate a Lioaucast ieceivei, we suLclass the BroadcastReceiver class.
The only methou we neeu to oveiiiue is onReceive(). This is wheie we put the woik
we want uone when this ieceivei is tiiggeieu.
The woik we want uone is simply to tell the cursor oLject to ieliesh itsell. Ve uo
this Ly invoking requery(), which executes the same gueiy that was executeu ini-
tially to oLtain this cuisoi oLject.
Notilies the auaptei that the unueilying uata has changeu.
At this point, oui ieceivei is ieauy Lut not iegisteieu. Unlike BootReceiver, wheie we
iegisteieu oui ieceivei with the system statically via the manilest lile, we`ll iegistei
TimelineReceiver piogiammatically, as shown in Example 11-5. This is Lecause Time
lineReceiver makes sense only within TimelineActivity Lecause puipose is ielieshing
the list when the usei is looking at the Timeline activity.
Exanp|c 11-5. Tinc|incActivity.java with Tinc|incRcccivcr
...
@Override
protected void onResume() {
super.onResume();
// Get the data from the database
cursor = db.query(DbHelper.TABLE, null, null, null, null, null,
DbHelper.C_CREATED_AT + " DESC");
startManagingCursor(cursor);
// Create the adapter
adapter = new TimelineAdapter(this, cursor);
listTimeline.setAdapter(adapter);
// Register the receiver
registerReceiver(receiver, filter); //
}
@Override
protected void onPause() {
super.onPause();
164 | Chapter 11:Broadcast Receivers
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
// UNregister the receiver
unregisterReceiver(receiver); //
}
...
Ve iegistei the ieceivei in onResume() so that it`s iegisteieu whenevei the
TimelineActivity is iunning. Recall that all paths to the iunning state go thiough
the onResume() methou, as uesciiLeu in Running state on page 29.
Similaily, we uniegistei the ieceivei on the way to the stoppeu state (iecall Stoppeu
state on page 30). onPause() is a goou place to uo that.
Vhat`s missing now is the explanation ol filter. To specily what tiiggeis the ieceivei,
we neeu an instance ol IntentFilter, which simply inuicates which intent actions we
want to Le notilieu aLout. In this case, we make up an action stiing thiough which we
liltei intents, as shown in Example 11-6.
Exanp|c 11-. Tinc|incActivity.java with updatc onCrcatc()
...
filter = new IntentFilter("com.marakana.yamba.NEW_STATUS"); //
...
Cieate a new instance ol IntentFilter to liltei loi the com.marakana.yamba.NEW_STA
TUS intent action. Since this is a text constant, we`ll ueline it as such anu ielei to it
as a constant latei on. A goou place to ueline it is the UpdaterService, Lecause that`s
the coue that geneiates the events we`ie waiting loi.
Broadcasting Intents
Finally, to tiiggei the liltei, we neeu to Lioaucast an intent that matches the action the
intent liltei is listening loi. In the case ol BootReceiver, eailiei, we uiun`t have to uo
this, Lecause the system was alieauy Lioaucasting the appiopiiate intent. Howevei, loi
TimelineReceiver, the Lioaucast is ouis to make Lecause the intent is specilic to oui
application.
Il you iecall liom Chaptei S, oui UpdaterService hau an innei class calleu Updater (see
Example 11-7). This innei class was the sepaiate thieau that connecteu to the online
seivice anu pulleu uown the uata. Because this is wheie we know whethei theie aie any
new statuses, this is a goou choice loi senuing notilications as well.
Exanp|c 11-7. UpdatcrScrvicc.java with thc Updatcr inncr c|ass
...
private class Updater extends Thread {
Intent intent;
public Updater() {
super("UpdaterService-Updater");
}
Broadcasting Intents | 165
@Override
public void run() {
UpdaterService updaterService = UpdaterService.this;
while (updaterService.runFlag) {
Log.d(TAG, "Running background thread");
try {
YambaApplication yamba =
(YambaApplication) updaterService.getApplication(); //
int newUpdates = yamba.fetchStatusUpdates(); //
if (newUpdates > 0) { //
Log.d(TAG, "We have a new status");
intent = new Intent(NEW_STATUS_INTENT); //
intent.putExtra(NEW_STATUS_EXTRA_COUNT, newUpdates); //
updaterService.sendBroadcast(intent); //
}
Thread.sleep(60000); //
} catch (InterruptedException e) {
updaterService.runFlag = false; //
}
}
}
}
...
Ve get the application oLject to access oui common application methous.
Il you iecall, oui application pioviues fetchStatusUpdates() to get all the latest status
upuates anu populate the uataLase. This methou ietuins the numLei ol new statuses.
Ve check whethei theie aie any new statuses.
This is the intent we aie aLout to Lioaucast. NEW_STATUS_INTENT is a constant
that iepiesents an aiLitiaiy action. In oui case, we ueline it as com.mara
kana.yamba.NEW_STATUS, Lut it coulu Le any stiing without spaces. Howevei, using
something that iesemLles youi package name is a goou piactice.
Theie`s a way to auu uata to an intent. In oui case, it woulu Le uselul to communicate
to otheis as pait ol this Lioaucast how many new statuses theie aie. In this line, we
use Intent`s putExtra() methou to auu the numLei ol new statuses unuei a key
nameu NEW_STATUS_EXTRA_COUNT, which is just oui aiLitiaiy constant.
At this point, we know theie`s at least one new status. sendBroadcast() is pait ol
Context, which is a supeiclass ol Service anu theieloie also a supeiclass ol oui
UpdaterService. Since we`ie insiue the Updater innei class, we have to ielei to the
paient`s updaterService instance in oiuei to call sendBroadcast(). This methou sim-
ply takes the intent we just cieateu.
Ve tell this thieau to sleep loi a minute so that it uoesn`t oveiloau the uevice`s CPU
while checking iegulaily loi upuates.
In case this thieau is inteiiupteu loi some ieason, we upuate this seivice`s runFlag
so we know it`s not cuiiently iunning.
166 | Chapter 11:Broadcast Receivers
UpdaterService might senu Lioaucasts even when the Timeline
Receiver is not iegisteieu. That is peilectly line. Those Lioaucasts will
simply Le ignoieu.
At this point, a new status ieceiveu Ly UpdaterService causes an intent to Le Lioaucast
ovei to the TimelineActivity, wheie the message is ieceiveu Ly the TimelineReceiver,
which in tuin ielieshes the ListView ol statuses.
The Network Receiver
Vith the cuiient uesign, oui seivice will stait automatically at Loot time anu attempt
to connect to the clouu anu ietiieve the latest upuates appioximately eveiy minute.
One pioLlem with the cuiient uesign is that the seivice will tiy to connect even when
theie`s no Inteinet connection availaLle. This auus unnecessaiy attempts to wake up
the iauio anu connect to the seivei, all ol which taxes the Latteiy. Imagine how many
wastelul attempts woulu Le maue while youi phone is in llight moue on a cioss-countiy
llight. This highlights some ol the inheiit constiaints when piogiamming loi moLile
uevices: we`ie limiteu Ly the Latteiy lile anu netwoik connectivity.
A Lettei appioach is to listen to netwoik availaLility Lioaucasts anu use that inloima-
tion to intelligently tuin oll the seivice when the Inteinet is unavailaLle anu tuin it Lack
on when uata connection comes Lack up. The system uoes senu an intent whenevei
connection availaLility changes. Anothei system seivice allows us to linu out what
changeu anu act accoiuingly.
In this case, we`ie cieating anothei ieceivei, NetworkReceiver, shown in Exam-
ple 11-S. ]ust as Leloie, we neeu to cieate a ]ava class that suLclasses BroadcastRe
ceiver, anu then iegistei it via the Anuioiu manilest lile.
Exanp|c 11-8. Nctwor|Rcccivcr.java
package com.marakana.yamba6;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.util.Log;
public class NetworkReceiver extends BroadcastReceiver { //
public static final String TAG = "NetworkReceiver";
@Override
public void onReceive(Context context, Intent intent) {
boolean isNetworkDown = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); //
The Network Receiver | 167
if (isNetworkDown) {
Log.d(TAG, "onReceive: NOT connected, stopping UpdaterService");
context.stopService(new Intent(context, UpdaterService.class)); //
} else {
Log.d(TAG, "onReceive: connected, starting UpdaterService");
context.startService(new Intent(context, UpdaterService.class)); //
}
}
}
As we saiu Leloie, when you cieate a new Lioaucast ieceivei, you typically stait Ly
suLclassing Anuioiu`s own BroadcastReceiver class.
Vhen the system Lioaucasts the paiticulai intent action that this ieceivei suLsciiLes,
the intent will have an extia piece ol inloimation inuicating whethei the netwoik is
up oi uown. In this case, the vaiiaLle is a Boolean value keyeu to the Connectivity
Manager.EXTRA_NO_CONNECTIVITY constant. In the pievious section, we associateu a
value to a stiing ol oui own invention; heie we`ie on the othei enu ol the message,
extiacting a value liom a Boolean. A value ol true inuicates that the netwoik is uown.
Il the netwoik is uown, we simply senu an intent to oui UpdaterService. Ve now
have a use loi the Context oLject that the system passeu to this methou. Ve call its
stopService() methou, passing the Intent.
Il the llag is false, we know that the netwoik has changeu anu is now availaLle. So
we stait oui UpdaterService, the inveise ol oui pievious stop action.
Insiue an activity oi a seivice, we simply useu the methous start
Activity(), startService(), stopService(), anu so on. This is Lecause
activities anu seivices aie suLclasses ol Context, anu thus they inheiiteu
these methous. So, theie`s an is-a ielationship Letween them anu Con
text. Bioaucast ieceiveis, on the othei hanu have a Context oLject
passeu into them, anu thus have a has-a ielationship with the oLject.
Now that we have cieateu this new ieceivei, we neeu to iegistei it with the manilest
lile, shown in Example 11-9.
Exanp|c 11-9. AndroidManijcst.xn|: <app|ication> scction
...
<receiver android:name=".NetworkReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
...
168 | Chapter 11:Broadcast Receivers
Ve also neeu to upuate oui application`s peimissions (Example 11-10) Lecause the
action liltei loi a netwoik change is piotecteu anu ieguiies us to ask the usei to giant
us this paiticulai peimission.
Exanp|c 11-10. AndroidManijcst.xn|: <nanijcst> scction
...
<uses-permission android:name="android.permission.INTERNET" /> <!-- -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- -->
...
Useu Ly oui Twitter oLject to connect to the Inteinet to get anu post status upuates.
Ve saw this peimission alieauy in Chaptei 6. Not having this peimission will cause
oui app to ciash when it attempts to access the netwoik (unless we catch anu hanule
that netwoik exception).
Reguiieu in oiuei to ieceive Lioaucasts that the system has Looteu. As mentioneu
eailiei, il we uon`t have this peimission, we will silently Le ignoieu at Loot time anu
oui Loot coue won`t iun.
Neeueu in oiuei to ieceive netwoik state upuates. ]ust as with the Loot ieceivei, il
we uon`t have this peimission, we will Le silently passeu Ly when the netwoik state
changes.
Adding Custom Permissions to Send and Receive Broadcasts
As uiscusseu in Upuating the Manilest File loi Inteinet Peimission on page 61, an
application must Le gianteu peimissions to access ceitain iestiicteu leatuies ol the
system, such as connecting to the Inteinet, senuing SMS messages, making phone calls,
ieauing the usei`s contacts, taking photos, anu so on. The usei has to giant all oi none
ol the peimissions to the application at installation time, anu it is the joL ol the appli-
cation uevelopei to list all the peimissions the app neeus Ly auuing the <uses-permis
sion> element to the manilest lile. So lai, we`ve auueu peimissions to YamLa in oiuei
to access the Inteinet, kick oll oui Loot-time seivice, anu leain aLout netwoik changes.
But now that we have oui Upuatei seivice senuing a Lioaucast action to oui Timeline
ieceivei, we might want to iestiict peimission to senu anu ieceive that Lioaucast to oui
own app. Otheiwise, anothei app, knowing what oui action looks like, coulu senu it
anu cause actions in oui application that we uiun`t intenu.
To lill up this secuiity hole, we ueline oui own peimission anu ask the usei to giant it
to the YamLa application. Next, we`ll enloice Loth senuing anu ieceiving the
peimissions.
Adding Custom Permissions to Send and Receive Broadcasts | 169
Declaring Permissions in the Manifest File
The liist step is to ueclaie oui peimissions, explaining what they aie, how they aie to
Le useu, anu setting theii piotection level, shown in Example 11-11.
Exanp|c 11-11. Adding pcrnissions to nanijcst ji|c
<manifest>
...
<!-- -->
<permission android:name="com.marakana.yamba.SEND_TIMELINE_NOTIFICATIONS"
<!-- -->
android:label="@string/send_timeline_notifications_permission_label"
<!-- -->
android:description="@string/send_timeline_notifications_permission_description"
<!-- -->
android:permissionGroup="android.permission-group.PERSONAL_INFO"
<!-- -->
android:protectionLevel="normal" />
<!-- -->
<permission android:name="com.marakana.yamba.RECEIVE_TIMELINE_NOTIFICATIONS"
android:label="@string/receive_timeline_notifications_permission_label"
android:description="@string/receive_timeline_notifications_permission_description"
android:permissionGroup="android.permission-group.PERSONAL_INFO"
android:protectionLevel="normal" />
<!-- -->
<uses-permission android:name="com.marakana.yamba.SEND_TIMELINE_NOTIFICATIONS" />
<uses-permission android:name="com.marakana.yamba.RECEIVE_TIMELINE_NOTIFICATIONS" />
</manifest>
This is the name ol oui peimission, which we ielei to latei Loth when we ieguest
the peimission anu when we enloice it. In oui app, we`ll Le using the peimission to
secuiely senu timeline notilications.
LaLel that will Le uisplayeu to the usei when she is piompteu to giant this peimission
to oui app at installation time. It shoulu Le ielatively shoit. Note that we have uelineu
this laLel in oui strings.xn| iesouice lile.
A uesciiption shoulu Le pioviueu to ollei inloimation aLout why this peimission is
neeueu anu how it`s going to Le useu.
The peimission gioup is optional, Lut it helps the system gioup youi peimission
with othei common peimissions in one ol the system-uelineu peimission gioups
http://d.android.con/rcjcrcncc/android/Manijcst.pcrnission_group.htn|. You coulu
also ueline youi own gioup, Lut that is iaiely uone.
The peimission level, a ieguiieu value, specilies the seveiity oi iisk poseu Ly gianting
the peimission. A normal level is the lowest anu most Lasic ol the loui stanuaiu
peimission levels.
170 | Chapter 11:Broadcast Receivers
Ve uo the same to ueline the othei peimission, which allows us to ieceive the time-
line notilications we aie geneiating.
Once oui peimissions aie uelineu, we neeu to ask the usei to giant them to the
application. Ve uo that via the <uses-permission> element, just as we uiu loi the
othei system peimissions we specilieu eailiei.
At this point, we have uelineu oui two custom peimissions anu have ieguesteu them
loi oui application. Next, we neeu to make suie the senuei anu ieceivei Loth play Ly
the iules.
Updating the Services to Enforce Permissions
Oui Upuatei seivice Lioaucasts the intent to the iest ol the system once theie`s a new
status upuate. Because we uo not want eveiyone to ieceive this intent, in Exam-
ple 11-12 we ensuie that the ieceivei won`t Le alloweu to ieceive it unless the ieceivei
uelines the iight peimission.
Exanp|c 11-12. Updatcr in UpdatcrScrvicc
...
private class Updater extends Thread {
static final String RECEIVE_TIMELINE_NOTIFICATIONS =
"com.marakana.yamba.RECEIVE_TIMELINE_NOTIFICATIONS"; //
Intent intent;
public Updater() {
super("UpdaterService-Updater");
}
@Override
public void run() {
UpdaterService updaterService = UpdaterService.this;
while (updaterService.runFlag) {
Log.d(TAG, "Running background thread");
try {
YambaApplication yamba = (YambaApplication) updaterService
.getApplication();
int newUpdates = yamba.fetchStatusUpdates();
if (newUpdates > 0) {
Log.d(TAG, "We have a new status");
intent = new Intent(NEW_STATUS_INTENT);
intent.putExtra(NEW_STATUS_EXTRA_COUNT, newUpdates);
updaterService.sendBroadcast(intent, RECEIVE_TIMELINE_NOTIFICATIONS); //
}
Thread.sleep(DELAY);
} catch (InterruptedException e) {
updaterService.runFlag = false;
}
}
}
Adding Custom Permissions to Send and Receive Broadcasts | 171
} // Updater
...
This is the name ol the peimission that the ieceivei must have. It neeus to Le the
same as the peimission name in the manilest lile that we specilieu pieviously.
To enloice the peimission on the ieceivei, we simply auu it to the sendBroad
cast() call as the optional seconu paiametei. Il the ieceivei uoesn`t have this pai-
ticulai peimission gianteu to it Ly the usei, the ieceivei won`t Le notilieu anu will
nevei know that oui message just got uioppeu.
To complete the secuiity in the senuing uiiection, we uon`t have to uo anything to
TimelineReceiver. It will Le aLle to ieceive the peimission Lecause the usei gianteu it.
But theie is a coiiesponuing iesponsiLility on the TimelineReceiver siue. It shoulu
check that the senuei hau peimission to senu the message it is ieceiving.
Updating TimelineReceiver to Enforce Permissions
Now we will check on the ieceivei siue that the Lioaucastei is alloweu to talk to us.
Vhen we iegistei oui ieceivei, we auu the Lioaucast peimission that the senuei shoulu
have, as shown in Example 11-13.
Exanp|c 11-13. Tinc|incRcccivcr in Tinc|incActivity.java
...
public class TimelineActivity extends BaseActivity {
static final String SEND_TIMELINE_NOTIFICATIONS =
"com.marakana.yamba.SEND_TIMELINE_NOTIFICATIONS"; //
...
@Override
protected void onResume() {
super.onResume();
...
// Register the receiver
super.registerReceiver(receiver, filter,
SEND_TIMELINE_NOTIFICATIONS, null); //
}
...
}
Ve ueline the peimission name as a constant. This neeus to Le the same name as
the one we ueclaieu loi this peimission in the manilest lile.
In the onResume() methou wheie we iegistei oui TimelineReceiver, we now auu a
paiametei specilying this peimission is a ieguiiement loi anyone who wants to senu
us this type ol Lioaucast.
Ve now have a paii ol custom peimissions, anu we aie enloicing them in Loth the
senuei anu the ieceivei ol the Lioaucast. This illustiates some ol the capaLilities ol
Anuioiu to line-tune the peimission system.
172 | Chapter 11:Broadcast Receivers
Summary
YamLa is now complete anu ieauy loi piime time. Oui application can now senu status
upuates to oui online seivice, get the latest statuses liom oui liienus, stait automatically
at Loot time, anu ieliesh the uisplay when a new status is ieceiveu.
Figuie 11-1 illustiates what we have uone so lai as pait ol the uesign outlineu eailiei
in Figuie 5-+.
Iigurc 11-1. Yanba conp|ction
Summary | 173
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
CHAPTER 12
Content Providers
Content pioviueis aie Anuioiu Luiluing Llocks that can expose uata acioss the Loun-
uaiies Letween application sanuLoxes. As you iecall, each application in Anuioiu iuns
in its own piocess with its own peimissions. This means that an application cannot see
anothei app`s uata. But sometimes you want to shaie uata acioss applications. This is
wheie content pioviueis Lecome veiy uselul.
Take youi contacts, loi example. You might have a laige uataLase ol contacts on youi
uevice, which you can view via the Contacts app as well as via the Dialei app. Some
uevices, such as HTC Anuioiu mouels, might even have multiple veisions ol the Con-
tacts anu Dialei apps. It woulu not make a lot ol sense to have similai uata live in
multiple uataLases.
Content pioviueis let you centialize content in one place anu have many uilleient ap-
plications access it as neeueu. In the case ol the contacts on youi phone, theie is actually
a ContactPioviuei application that contains a content pioviuei, anu othei applications
access the uata via this inteilace. The inteilace itsell is laiily simple: it has the same
insert(), update(), delete(), anu query() methous we saw in Chaptei 9.
Anuioiu uses content pioviueis guite a Lit inteinally. In auuition to contacts, youi
settings iepiesent anothei example, as uo all youi Lookmaiks. All the meuia in the
system is also iegisteieu with MeuiaStoie, a content pioviuei that uispenses images,
music, anu viueos in youi uevice.
Creating a Content Provider
To cieate a content pioviuei:
1. Cieate a new ]ava class that suLclasses the system`s ContentProvider class.
2. Declaie youi CONTENT_URI.
3. Implement all the unimplementeu methous, such as insert(), update(), delete(),
query(), getID(), anu getType().
+. Declaie youi content pioviuei in the AndroidManijcst.xn| lile.
175
Ve aie going to stait Ly cieating a Lianu-new ]ava class in the same package as all othei
classes. Its name will Le StatusProvider. This class, like any ol Anuioiu`s main Luiluing
Llocks, will suLclass an Anuioiu liamewoik class, in this case ContentProvider.
In Eclipse, select youi package, click on FileNew]ava Class, anu entei StatusPio-
viuei. Then, upuate the class to suLclass ContentProvider, anu oiganize the impoits
(Ctil-Shilt-O) to impoit the appiopiiate ]ava packages. The iesult shoulu look like this:
package com.marakana.yamba7;
import android.content.ContentProvider;
public class StatusProvider extends ContentProvider {
}
Ol couise, this coue is now Lioken Lecause we neeu to pioviue implementations loi
many ol its methous. The easiest way to uo that is to click on the class name anu choose
Auu unimplementeu methous liom the list ol guick lixes. Eclipse will then cieate
stuLs, oi templates, ol the missing methous.
Defining the URI
OLjects within a single app shaie an auuiess space, so they can ielei to each othei
simply Ly vaiiaLle names. But oLjects in uilleient apps uon`t iecognize the uilleient
auuiess spaces, so they neeu some othei mechanism to linu each othei. Anuioiu uses
a Uniloim Resouice Iuentiliei, a stiing that iuentilies a specilic iesouice, to locate a
content pioviuei. A URI has thiee oi loui paits, shown in Example 12-1.
Exanp|c 12-1. Parts oj a UR|
content://com.marakana.yamba.statusprovider/status/47
A B C D
Pait A, content://, is always set to this value. This is wiitten in stone.
Pait B, com.marakana.yamba.provider, is the so-calleu authority. It is typically the
name ol the class, all in loweicase. This authoiity must match the authoiity that
we specily loi this pioviuei when we latei ueclaie it in the manilest lile.
Pait C, status, inuicates the type ol uata that this paiticulai pioviuei pioviues. It
coulu contain any numLei ol scgncnts sepaiateu with a slash, incluuing none at all.
Pait D, 47, is an optional ID loi the specilic item that we aie ieleiencing. Il not set,
the URI will iepiesent the entiie set. NumLei +7 is an aiLitiaiy numLei pickeu loi
this example.
Sometimes you neeu to ielei to the content pioviuei in its entiiety, anu sometimes to
only one ol the items ol uata it contains. Il you ielei to it in its entiiety, you leave oll
Pait D; otheiwise, you incluue that pait to iuentily one item within the content pio-
viuei. Actually, since we have only one taLle, we uo not neeu Pait C ol the URI.
176 | Chapter 12:Content Providers
One way to ueline the constants loi oui example is like this:
public static final Uri CONTENT_URI = Uri
.parse("content://com.marakana.yamba7.statusprovider");
public static final String SINGLE_RECORD_MIME_TYPE =
"vnd.android.cursor.item/vnd.marakana.yamba.status";
public static final String MULTIPLE_RECORDS_MIME_TYPE =
"vnd.android.cursor.dir/vnd.marakana.yamba.mstatus";
In Getting the Data Type on page 1S0, we`ll exploie the ieason loi two MIME types.
Ve aie also going to ueline the status uata oLject in a class-gloLal vaiiaLle so that we
can ielei to it:
StatusData statusData;
Ve`ll Le using the status uata oLject all ovei oui app Lecause all oui uataLase connec-
tivity is centializeu in that class. So now the StatusProvider class has a ieleience to an
oLject ol class StatusData.
Inserting Data
To inseit a iecoiu into a uataLase via the content pioviuei inteilace, we neeu to oveiiiue
the insert() methou. The callei pioviues the URI ol this content pioviuei (without an
ID) anu the values to Le inseiteu. A successlul call to inseit the new iecoiu ietuins the
ID loi that iecoiu. Ve enu Ly ietuining a new URI concatenating the pioviuei`s URI
with the ID we just got Lack:
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = statusData.dbHelper.getWritableDatabase(); //
try {
long id = db.insertOrThrow(StatusData.TABLE, null, values); //
if (id == -1) {
throw new RuntimeException(String.format(
"%s: Failed to insert [%s] to [%s] for unknown reasons.", TAG,
values, uri)); //
} else {
return ContentUris.withAppendedId(uri, id); //
}
} finally {
db.close(); //
}
}
Ve neeu to open the uataLase loi wiiting.
Ve attempt to inseit the values into the uataLase anu, upon a successlul inseit,
ieceive the ID ol the new iecoiu liom the uataLase.
Il anything lails uuiing the inseit, the uataLase will ietuin -1. Ve can than thiow a
iuntime exception Lecause this is an eiioi that shoulu nevei have happeneu.
Creating a Content Provider | 177
Il the inseit was successlul, we use the ContentUris.withAppendedId() helpei methou
to cialt a new URI containing the ID ol the new iecoiu appenueu to the stanuaiu
pioviuei`s URI.
Ve neeu to close the uataLase no mattei what, so a finally Llock is a goou place to
uo that.
Updating Data
To upuate the uata via the Content Pioviuei API, we neeu:
Thc UR| oj thc providcr
This may oi may not contain an ID. Il it uoes, the ID inuicates the specilic iecoiu
that neeus to Le upuateu, anu we can ignoie the selection. Il the ID is not specilieu,
it means that we aie upuating many iecoius anu neeu the selection to inuicate
which aie to Le changeu.
Thc va|ucs to bc updatcd
The loimat ol this paiametei is a set ol name/value paiis that iepiesent column
names anu new values.
Any sc|cction and arguncnts that go with it
These togethei make up a WHERE clause in SQL, selecting the iecoius that will
change. The selection anu its aiguments aie omitteu when theie is an ID, Lecause
the ID is enough to select the iecoiu that is Leing upuateu.
The coue that hanules Loth types ol upuateLy ID anu Ly selectioncan Le as lollows:
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
long id = this.getId(uri); //
SQLiteDatabase db = statusData.dbHelper.getWritableDatabase(); //
try {
if (id < 0) {
return db.update(StatusData.TABLE, values, selection, selectionArgs); //
} else {
return db.update(StatusData.TABLE, values,
StatusData.C_ID + "=" + id, null); //
}
} finally {
db.close(); //
}
}
Ve use the local helpei methou getId() to extiact the ID liom the URI. Il no ID is
piesent, this methou ietuins -1. getId() will Le uelineu latei in this chaptei.
Ve neeu to open the uataLase loi wiiting the upuates.
Il theie`s no ID, that means we`ie simply upuating all the uataLase iecoius that match
the selection anu selectionArgs constiaints.
178 | Chapter 12:Content Providers
Il an ID is piesent, we aie using that ID as the only pait ol the WHERE clause to limit
the single iecoiu that we`ie upuating.
Don`t loiget to close the uataLase.
Deleting Data
Deleting uata is similai to upuating uata. The URI may oi may not contain the ID ol
the paiticulai iecoiu to uelete:
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
long id = this.getId(uri); //
SQLiteDatabase db = statusData.dbHelper.getWritableDatabase(); //
try {
if (id < 0) {
return db.delete(StatusData.TABLE, selection, selectionArgs); //
} else {
return db.delete(StatusData.TABLE, StatusData.C_ID + "=" + id, null); //
}
} finally {
db.close(); //
}
}
The getId() helpei methou extiacts the ID liom the URI that we get. Il no ID is
piesent, this methou ietuins -1.
Ve neeu to open the uataLase loi wiiting the upuates.
Il theie`s no ID, we simply uelete all the uataLase iecoius that match the selec
tion anu selectionArgs constiaints.
Il an ID is piesent, we use that ID as the only pait ol the WHERE clause to limit the
opeiation to the single iecoiu the usei wants to uelete.
Don`t loiget to close the uataLase.
Querying Data
To gueiy the uata via a content pioviuei, we oveiiiue the query() methou. This methou
has a long list ol paiameteis, Lut usually we just loiwaiu most ol them to the uataLase
call with the same name:
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
long id = this.getId(uri); //
SQLiteDatabase db = statusData.dbHelper.getReadableDatabase(); //
if (id < 0) {
return db.query(StatusData.TABLE, projection, selection, selectionArgs, null,
null, sortOrder); //
Creating a Content Provider | 179
} else {
return db.query(StatusData.TABLE, projection,
StatusData.C_ID + "=" + id, null, null, null, null); //
}
}
The getId() helpei methou extiacts the ID liom the URI that we get.
Ve neeu to open the uataLase, in this case just loi ieauing.
Il theie`s no ID, we simply loiwaiu what we got loi the content pioviuei to the
eguivalent uataLase call. Note that the uataLase call has two auuitional paiameteis
that coiiesponu to the SQL GROUPING anu HAVING components. Because content pio-
viueis uo not suppoit this leatuie, we simply pass in null.
Il an ID is piesent, we use that ID as the WHERE clause to limit what iecoiu to ietuin.
Ve uo not close the uataLase heie, Lecause closing the uataLase will
uestioy the cuisoi anu we still neeu it on the ieceiving enu to go ovei
the uata ietuineu Ly the gueiy. One way to hanule the cuisoi is to have
the ieceivei manage it. Activities have a simple startManagingCursor()
methou loi this puipose.
Getting the Data Type
A content pioviuei must ietuin the MIME type ol the uata it is ietuining. The MIME
type inuicates eithei a single item oi all the iecoius loi the given URI. Eailiei in this
chaptei we uelineu the single-iecoiu MIME type as vnd.android.cursor.item/vnd.mar
akana.yamba.status anu the uiiectoiy ol all statuses as vnd.android.cursor.dir/vnd.mar
akana.yamba.status. To let otheis ietiieve the MIME type, we must ueline the call
getType().
The liist pait ol the MIME type is eithei vnd.android.cursor.item oi vnd.android
.cursor.dir, uepenuing on whethei the type iepiesents a specilic item oi all items loi
the given URI. The seconu pait, vnd.marakana.yamba.status oi vnd.marakana
.yamba.mstatus loi oui app, is a comLination ol the constant vnd lolloweu Ly youi
company oi app name anu the actual content type.
As you may iecall, the URI can enu with a numLei. Il it uoes, that numLei is the ID ol
the specilic iecoiu. Il it uoesn`t, the URI ieleis to the entiie collection.
The lollowing souice shows the implementation ol getType() as well as the getId()
helpei methou that we`ve alieauy useu seveial times:
@Override
public String getType(Uri uri) {
return this.getId(uri) < 0 ? MULTIPLE_RECORDS_MIME_TYPE
: SINGLE_RECORD_MIME_TYPE; //
}
180 | Chapter 12:Content Providers
private long getId(Uri uri) {
String lastPathSegment = uri.getLastPathSegment(); //
if (lastPathSegment != null) {
try {
return Long.parseLong(lastPathSegment); //
} catch (NumberFormatException e) { //
// at least we tried
}
}
return -1; //
}
getType() uses the helpei methou getId() to ueteimine whethei the URI has an ID
pait. Il it uoes notas inuicateu Ly a negative ietuin valuewe ietuin
vnd.android.cursor.dir/vnd.marakana.yamba.mstatus loi the MIME type. Othei-
wise, we`ie ieleiiing to a single iecoiu anu the MIME type is vnd.android.cur
sor.item/vnd.marakana.yamba.status. Ol couise, we pieviously uelineu these values
as class constants.
To extiact the ID in oui implementation ol getId(), we take the last pait ol the URI.
Il that last pait is not null, we tiy to paise it as a long anu ietuin it.
It coulu Le that the last pait is not a numLei at all, in which case the paise will lail.
Ve ietuin -1 to inuicate that the given URI uoesn`t contain a valiu ID.
Updating the Android Manifest File
As with any majoi Luiluing Llock, we want to ueline oui content pioviuei in the An-
uioiu manilest XML lile. Notice that in this case the android:authorities piopeity
specilies the URI authoiity peimitteu to access this content pioviuei. Typically, this
authoiity woulu Le youi content pioviuei classwhich we use heieoi youi package:
<application>
...
<provider android:name=".StatusProvider"
android:authorities="com.marakana.yamba7.statusprovider" />
...
</application>
At this point oui content pioviuei is complete, anu we aie ieauy to use it in othei
Luiluing Llocks ol YamLa. But since oui application alieauy centializes all uata access
in a StatusData oLject that is ieauily accessiLle via YambaApplication, we uon`t ieally
have a goou use loi this content pioviuei within the same application. Besiues, content
pioviueis mostly make sense when we want to expose the uata to anothei application.
Using Content Providers Through Widgets
As mentioneu Leloie, content pioviueis make the most sense when you want to expose
the uata to othei applications. It is a goou piactice to always think ol youi application
Using Content Providers Through Widgets | 181
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
as pait ol a laigei Anuioiu ecosystem anu, as such, a potential pioviuei ol uselul uata
to othei applications.
To uemonstiate how content pioviueis can Le uselul, we`ll cieate a Home scieen
wiuget. Ve`ie not using the teim widgct heie as a synonym loi Anuioiu`s View class,
Lut as a uselul emLeuueu seivice olleieu Ly the Home scieen.
Anuioiu typically ships with a lew Home scieen wiugets. You can access them Ly going
to youi Home scieen, long-piessing on it to pull up an Auu to Home Scieen uialog,
anu choosing Viugets. Viugets that come with Anuioiu incluue Alaim Clock, Pictuie
Fiame, Powei Contiols, Music, anu Seaich. Oui goal is to cieate oui own YamLa wiuget
that the usei will Le aLle to auu to the Home scieen.
The YamLa wiuget will Le simple, uisplaying just the latest status upuate. To cieate it,
we`ll make a new YambaWidget class that suLclasses AppWidgetProviderInfo. Ve`ll also
have to iegistei the wiuget with the manilest lile.
Implementing the YambaWidget class
YambaWidget is the main class loi oui wiuget. It is a suLclass ol AppWidgetProvider, a
special system class that makes wiugets. This class itsell is a suLclass ol Broadcast
Receiver, so oui YamLa wiuget is a Lioaucast ieceivei automatically. Basically, when-
evei oui wiuget is upuateu, ueleteu, enaLleu, oi uisaLleu, we`ll get a Lioaucast intent
with that inloimation. So this class inheiits the onUpdate(), onDeleted(), onEnabled(),
onDisabled(), anu onReceive() callLacks. Ve can oveiiiue any ol these, Lut typically
we caie mostly aLout the upuates anu geneial Lioaucasts we ieceive.
Now that we unueistanu the oveiall uesign ol the wiuget liamewoik, Example 12-2
shows how we implement it.
Exanp|c 12-2. YanbaWidgct.java
package com.marakana.yamba7;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.text.format.DateUtils;
import android.util.Log;
import android.widget.RemoteViews;
public class YambaWidget extends AppWidgetProvider { //
private static final String TAG = YambaWidget.class.getSimpleName();
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) { //
182 | Chapter 12:Content Providers
Cursor c = context.getContentResolver().query(StatusProvider.CONTENT_URI,
null, null, null, null); //
try {
if (c.moveToFirst()) { //
CharSequence user = c.getString(c.getColumnIndex(StatusData.C_USER)); //
CharSequence createdAt = DateUtils.getRelativeTimeSpanString(context, c
.getLong(c.getColumnIndex(StatusData.C_CREATED_AT)));
CharSequence message = c.getString(c.getColumnIndex(StatusData.C_TEXT));
// Loop through all instances of this widget
for (int appWidgetId : appWidgetIds) { //
Log.d(TAG, "Updating widget " + appWidgetId);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.yamba_widget); //
views.setTextViewText(R.id.textUser, user); //
views.setTextViewText(R.id.textCreatedAt, createdAt);
views.setTextViewText(R.id.textText, message);
views.setOnClickPendingIntent(R.id.yamba_icon, PendingIntent
.getActivity(context, 0, new Intent(context,
TimelineActivity.class), 0));
appWidgetManager.updateAppWidget(appWidgetId, views); //
}
} else {
Log.d(TAG, "No data to update");
}
} finally {
c.close(); //
}
Log.d(TAG, "onUpdated");
}
@Override
public void onReceive(Context context, Intent intent) { //
super.onReceive(context, intent);
if (intent.getAction().equals(UpdaterService.NEW_STATUS_INTENT)) { //
Log.d(TAG, "onReceived detected new status update");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); //
this.onUpdate(context, appWidgetManager, appWidgetManager
.getAppWidgetIds(new ComponentName(context, YambaWidget.class))); //
}
}
}
As mentioneu Leloie, oui wiuget is a suLclass ol AppWidgetProvider, which itsell is
a BroadcastReceiver.
This methou is calleu whenevei oui wiuget is to Le upuateu, so it`s wheie we`ll
implement the main lunctionality ol the wiuget. Vhen we iegistei the wiuget with
the system in the manilest lile latei, we`ll specily the upuate lieguency we`u like. In
oui case, this methou will Le calleu aLout eveiy 30 minutes.
Ve linally get to use oui content pioviuei. The whole puipose ol this wiuget in this
chaptei is to illustiate how to use the StatusProvider that we cieateu eailiei. As you
saw eailiei when we implementeu the content pioviuei, its API is guite similai to
Using Content Providers Through Widgets | 183
the SQLite uataLase API. The main uilleience is that insteau ol passing a taLle name
to a uataLase oLject, we`ie passing a content URI to the ContentResolver. Ve still
get Lack the veiy same Cursor oLject as we uiu with uataLases in Chaptei 9.
In this paiticulai example, we caie only aLout the veiy latest status upuate liom the
online seivice. So we position the cuisoi to the liist element. Il one exists, it`s oui
latest status upuate.
In the next lew ol lines ol coue, we extiact uata liom the cuisoi oLject anu stoie it
in local vaiiaLles.
Since the usei coulu have multiple YamLa wiugets installeu, we neeu to loop
thiough them anu upuate them all. Ve uon`t paiticulaily caie aLout the specilic
appWidgetId Lecause we`ie uoing iuentical woik to upuate eveiy instance ol the
YamLa wiuget. The appWidgetId Lecomes an opague hanule we use to access each
wiuget in tuin.
The actual view iepiesenting oui wiuget is in anothei piocess. To Le piecise, oui
wiuget is iunning insiue the Home application, which acts as its host anu is the
piocess we aie upuating. Hence the RemoteViews constiuctoi. The RemoteViews
liamewoik is a special shaieu memoiy system uesigneu specilically loi wiugets.
Once we have the ieleience to oui wiuget views` ]ava memoiy space in anothei
piocess, we can upuate those views. In this case, we`ie setting the status uata in the
iow that iepiesents oui wiuget.
Once we upuate the iemote views, the AppWidgetManager call to updateAppWidget()
actually posts a message telling the system to upuate oui wiuget. This will happen
asynchionously, Lut shoitly altei onUpdate() completes.
Regaiuless ol whethei the StatusProvider lounu a new status, we ielease the uata
that we might have gotten liom the content pioviuei. This is just a goou piactice.
The call to onReceive() is not necessaiy in a typical wiuget. But since a wiuget is a
Lioaucast ieceivei, anu since oui Upuatei seivice uoes senu a Lioaucast when we
get a new status upuate, this methou is a goou oppoitunity to invoke onUpdate()
anu get the latest status uata upuateu on the wiuget.
Ve check whethei the intent was loi the new status Lioaucast.
Il it was, we get the instance ol AppWidgetManager loi this context.
Ve then invoke onUpdate().
At this point, we have coueu the YamLa wiuget, anu as a ieceivei, it will Le notilieu
peiiouically oi when theie aie new upuates, anu it will loop thiough all instances ol
this wiuget on the Home scieen anu upuate them.
Next, we neeu to set up the layout loi oui wiuget.
184 | Chapter 12:Content Providers
Creating the XML Layout
The layout loi the wiuget is laiily stiaightloiwaiu. Note that we`ie ieusing oui existing
row.xn| lile that uisplays status uata piopeily in the Timeline activity. In Exam-
ple 12-3, we just incluue it along with a little title anu an icon to make it look goou on
the Home scieen.
Exanp|c 12-3. rcs/|ayout/yanba_widgct.xn|
<?xml version="1.0" encoding="utf-8"?>
<!-- -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:background="@color/edit_text_background"
android:layout_margin="5dp" android:padding="5dp">
<!-- -->
<ImageView android:layout_width="wrap_content" android:src="@drawable/icon"
android:layout_height="fill_parent" android:id="@+id/yamba_icon"
android:clickable="true" />
<!-- -->
<include layout="@layout/row" />
</LinearLayout>
Ve`ie using LinearLayout to holu oui wiuget togethei. It iuns hoiizontally, with the
icon on the lelt anu the status uata on the iight.
This is oui stanuaiu YamLa icon.
Notice the use ol the <include> element. This is how we incluue oui existing
row.xn| into this layout so we uon`t have to uuplicate the coue.
This layout is simple enough, Lut it uoes the joL loi oui paiticulai neeus. Next, we
neeu to ueline some Lasic inloimation aLout this wiuget anu its Lehavioi.
Creating the AppWidgetProviderInfo File
The XML lile shown in Example 12-+ is iesponsiLle loi uesciiLing the wiuget. It typi-
cally specilies which layout this wiuget uses, how lieguently it shoulu Le upuateu Ly
the system, anu its size.
Exanp|c 12-1. rcs/xn|/yanba_widgct_injo.xn|
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/yamba_widget" android:minWidth="294dp"
android:minHeight="72dp" android:label="@string/msgLastTimelineUpdate"
android:updatePeriodMillis="1800000" />
In this case we specily that we`u like to have oui wiuget upuateu eveiy 30 minutes oi
so (1,S00,000 milliseconus). Heie, we also specily the layout to use, the title ol this
wiuget, anu its size.
Using Content Providers Through Widgets | 185
Updating the Manifest File
Finally, we neeu to upuate the manilest lile anu iegistei the wiuget:
...
<application .../>
...
<receiver android:name=".YambaWidget"
android:label="@string/msgLastTimelineUpdate">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="com.marakana.yamba.NEW_STATUS" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/yamba_widget_info" />
</receiver>
...
</application>
...
Notice that the wiuget is a ieceivei, as we mentioneu Leloie. So, just like othei Lioaucast
ieceiveis, we ueclaie it within a <receiver> tag insiue an <application> element. It is
impoitant to iegistei this ieceivei to ieceive ACTION_APPWIDGET_UPDATE upuates. Ve uo
that via the <intent-filter>. The <meta-data> specilies the meta inloimation loi this
wiuget in the yamba_widget_info XML lile uesciiLeu in the pievious section.
That`s it. Ve now have the wiuget anu aie ieauy to test it.
Testing the Widget
To test this wiuget, install youi latest application on the uevice. Next, go to the Home
scieen, long-piess it, anu click on the Viugets choice. You shoulu Le aLle to navigate
to the YamLa wiuget at this point. Altei auuing it to the Home scieen, the wiuget shoulu
uisplay the latest status upuate.
Il youi Upuatei seivice is iunning, the latest upuates shoulu show up on the Home
scieen. This means youi wiuget is iunning piopeily.
Summary
At this point, the YamLa app is complete. Congiatulations! You aie ieauy to line-tune
it, customize it, anu puLlish it to the maiket.
Figuie 12-1 illustiates what we have uone so lai as pait ol the uesign outlineu eailiei
in Figuie 5-+.
186 | Chapter 12:Content Providers
Iigurc 12-1. Yanba conp|ction
Summary | 187
CHAPTER 13
System Services
Like many mouein opeiating systems, Anuioiu comes with a numLei ol system seivices
that aie always on, always iunning, anu ieauily availaLle loi uevelopeis to tap into.
These system seivices incluue things like the Location seivice, Sensoi seivice, ViFi
seivice, Alaim seivice, Telephony seivice, Bluetooth seivice, anu so on. System seivices
aie staiteu at Loot time anu aie guaianteeu to Le iunning Ly the time youi application
launches.
In this chaptei, we`ll see how we can use some ol the system seivices to luithei expanu
the YamLa application. Fiist, we`ll take a look at the Sensoi seivice in a small example
to uemonstiate some ol the concepts that aie common to most ol the system seivices.
Then, we`ll auu suppoit loi location inloimation to oui status upuates via the Location
seivice.
Auuitionally, we`ie going to ielactoi the YamLa application to take auvantage ol Intent
Seivice suppoit. This will uemonstiate how to use the Alaim seivice anu will make oui
Upuatei slightly simplei anu moie ellicient.
Compass Demo
To stait with system seivices, we aie going to look at a simple, sell-containeu example
ol a compass application. This application uses the Sensoi seivice to get upuates liom
the oiientation sensoi anu use its inloimation to iotate a Rose, oui custom UI compo-
nent. The Sensoi seivice is veiy typical ol system seivices anu a ielatively easy one to
unueistanu.
To Luilu this example, we`ll cieate an activity that will get the Sensoi seivice anu iegistei
loi upuates liom a paiticulai sensoi. Next, we`ll Luilu the Rose that will iotate on the
scieen Laseu on the sensoi ieauings.
189
Common Steps in Using System Services
To get any system seivice, issue the getSystemService() call. This ietuins a Manager
oLject iepiesenting that system seivice, which you then use to access the seivice. Most
system seivices woik on some soit ol puLlish/suLsciiLe mechanism. In othei woius,
you geneially iegistei youi app loi notilications liom that seivice anu pioviue youi own
callLack methous that the seivice will invoke when an event happens. To uo this in
]ava, cieate a listenei that implements an inteilace so that the seivice can call the call-
Lack methous.
Keep in minu that ieguesting notilications liom a system seivice can Le costly in teims
ol Latteiy usage. Foi example, getting a GPS signal oi piocessing sensoi upuates takes
a lot ol eneigy liom the uevice. To pieseive the Latteiy, we typically want to Le uoing
the woik ol piocessing upuates only when the usei is looking at the activity itsell. In
teims ol the activity lile cycle (see Activity Lile Cycle on page 2S), this means we want
to get the notilications only while in the iunning state (see Running state
on page 29).
To ensuie that you ieguest seivice upuates only while in the iunning state, iegistei loi
upuates in onResume() anu uniegistei in onPause(). This is Lecause all ioaus into the
iunning state go via onResume() anu all ioaus out ol it go via onPause(). In ceitain othei
situations, you may want to cast the net wiuei anu iegistei the activity Letween
onStart() anu onStop(), oi even Letween onCreate() anu onDestroy(). In oui case, we
uon`t want to iegistei in onCreate(), Lecause it woulu waste a lot ol Latteiy anu pio-
cessing time Ly making us listen anu piocess sensoi upuates even when oui activity is
not in the loiegiounu. You can now see how unueistanuing the activity lile cycle plays
an impoitant iole in optimizing the usage ol system seivices loi Latteiy consumption.
Getting Updates from the Compass
To coue oui Compass uemo application, we get SensorManager, the class that iepiesents
the Sensoi system seivice. Ve make oui main activity implement SensorEvent
Listener so that we can iegistei it (i.e., this) to get upuates loi a specilic sensoi. Ve
iegistei anu uniegistei the listenei in onResume() anu onPause(), iespectively. To im-
plement the sensoi listeneis, oui activity pioviues onAccuracyChanged() anu onSensorCh
anged(). The loimei is a ieguiiement, Lut we`ll leave it empty Lecause the accuiacy ol
the oiientation sensoi is not expecteu to change. The lattei call is what`s ieally ol in-
teiest to us.
Vhen the oiientation sensoi changes, the Sensoi seivice calls Lack oui sensoi listenei
via onSensorChanged() anu iepoits the new sensoi uata. The uata always comes Lack
as an aiiay ol float values that iepiesent uegiees anu theieloie iange liom 0 to 359. In
the case ol the oiientation sensoi, the elements iepiesent the lollowing uimensions,
illustiateu in Figuie 13-1:
190 | Chapter 13:System Services
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
|ndcx j0j, thc azinuth
The amount ol iotation aiounu the Z axis liom the veitical position aiounu the
Lack anu then aiounu the Lottom towaiu the liont
|ndcx j1j, thc pitch
The amount ol iotation aiounu the X axis liom the liont to the lelt anu then aiounu
the Lack towaiu the iight
|ndcx j2j, thc ro||
The amount ol iotation aiounu the Y axis liom the veitical position to the lelt anu
then the aiounu the Lottom towaiu the iight
Foi the Compass uemo, we aie inteiesteu only in the liist element, i.e., the azimuth.
The uata ietuineu Ly each sensoi has a uilleient meaning, anu you shoulu look up the
paiticulais in the uocumentation at http://d.android.con/rcjcrcncc/android/hardwarc/
ScnsorManagcr.htn|.
Iigurc 13-1. Axis
Compass Main Activity
Example 13-1, the main Compass activity, sets the Rose as its only wiuget on the scieen.
It also iegisteis with SensorManager to listen to sensoi events anu upuates the Rose
oiientation accoiuingly.
Compass Demo | 191
Exanp|c 13-1. Conpass.java
package com.marakana;
import android.app.Activity;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
// implement SensorListener
public class Compass extends Activity implements SensorEventListener { //
SensorManager sensorManager; //
Sensor sensor;
Rose rose;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) { //
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Create new instance of custom Rose and set it on the screen
rose = new Rose(this); //
setContentView(rose); //
// Get sensor and sensor manager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); //
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); //
Log.d("Compass", "onCreated");
}
// Register to listen to sensors
@Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_NORMAL); //
}
// Unregister the sensor listener
@Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this); //
}
192 | Chapter 13:System Services
// Ignore accuracy changes
public void onAccuracyChanged(Sensor sensor, int accuracy) { //
}
// Listen to sensor and provide output
public void onSensorChanged(SensorEvent event) { //
int orientation = (int) event.values[0]; //
Log.d("Compass", "Got sensor event: " + event.values[0]);
rose.setDirection(orientation); //
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
Since Compass listens to sensoi events, it neeus to implement the SensorEvent
Listener inteilace.
Ve ueline the local vaiiaLle loi the sensoi, the sensoi managei, anu the Rose.
Because accessing the sensoi is a one-time activity, we uo it when oui app is cieateu.
The winuow managei llags set the activity into lull-scieen moue.
Ve cieate a new instance ol the Rose wiuget, oui custom compass iose.
In this case, the activity content is the single Rose wiuget. This is unlike the usual
ieleience to an XML layout iesouice.
Ve get the sensoi managei liom the system seivice.
Fiom the sensoi managei, we can oLtain the actual sensoi oLject that we aie intei-
esteu in.
Ve iegistei to listen to sensoi upuates in the activity`s onResume() methou, as ue-
sciiLeu eailiei.
Ve uniegistei liom sensoi upuates in onPause(), the counteipait to onResume().
onAccuracyChanged() is implementeu Lecause it is ieguiieu Ly the SensorEvent
Listener inteilace, Lut is lelt empty loi the ieasons explaineu eailiei.
onSensorChanged() is calleu whenevei the sensoi changes, inuicating a iotation ol
the uevice in some uiiection. The paiticulai inloimation aLout the change is stoieu
in SensorEvent.
Ve aie inteiesteu in the liist element ol the aiiay ol new values.
Once we have the new oiientation, we upuate oui Rose wiuget to iotate accoiuingly.
Compass Demo | 193
The way a uevice iepoits sensoi uata can Le veiy eiiatic, coming at
uneven inteivals. Theie aie ways to suggest to the system how lieguently
we`u like the sensoi upuates, Lut these aie just suggestions anu not a
guaiantee. Also, sensois aie not suppoiteu Ly the emulatoi, so to ieally
test youi application, you`ll neeu a physical uevice with suppoit loi the
oiientation sensoi. Most Anuioiu phones have that suppoit.
Custom Rose Widget
Shown in Example 13-2, Rose is oui custom UI wiuget showing a compass iose that
can Le iotateu like a ieal compass. Eveiy UI wiuget in Anuioiu neeus to Le a suLclass
ol View. But Lecause this is an image, we`ll choose a highei staiting point, in this case
the ImageView class, which is a View. By suLclassing ImageView, oui Rose inheiits some
uselul methous to loau an image anu uiaw it on the scieen.
Vith any custom UI wiuget, one ol the most impoitant methous is onDraw(), which
uiaws the wiuget onto a Canvas that is pioviueu to the methou. In the case ol oui Rose,
we iotate this canvas aiounu its miuule point loi the same numLei ol uegiees as ie-
poiteu Ly the oiientation sensoi. Next, we uiaw the image onto this iotateu sensoi as
it woulu noimally Le uiawn Ly the supei class. The iesult is a iotateu compass iose
iepiesenting the uiiection in which we aie pointing.
Exanp|c 13-2. Rosc.java
package com.marakana;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.ImageView;
public class Rose extends ImageView { //
int direction = 0;
public Rose(Context context) {
super(context);
this.setImageResource(R.drawable.compassrose); //
}
// Called when component is to be drawn
@Override
public void onDraw(Canvas canvas) { //
int height = this.getHeight(); //
int width = this.getWidth();
canvas.rotate(direction, width / 2, height / 2); //
super.onDraw(canvas); //
}
// Called by Compass to update the orientation
public void setDirection(int direction) { //
194 | Chapter 13:System Services
this.direction = direction;
this.invalidate(); // request to be redrawn
}
}
Oui wiuget has to Le a suLclass ol View, Lut since oui wiuget is an image, we get
moie lunctionality Ly staiting liom ImageView.
ImageView alieauy knows how to set an image as its content. Ve just specily to
super which image iesouice to use. Note that the lile conpassrosc.jpg is in
oui /rcs/drawab|c loluei.
onDraw() is the methou that the layout managei calls to have each wiuget uiaw itsell.
The layout managei passes the Canvas to this methou. This methou is wheie you
typically uo any custom uiawing to the canvas.
Once we have the canvas, we can liguie out its size.
Ve simply iotate the entiie canvas loi some amount (in uegiees) aiounu its
miupoint.
Ve tell super to uiaw the image on this iotateu canvas. At this point we have oui
iose uiawn at the piopei angle.
setDirection() is calleu Ly the Compass activity to upuate the uiiection ol the iose
Laseu on the values that the sensoi managei iepoiteu.
Calling invalidate() on a view maiks it loi ieuiawing, which happens latei via a
call to onDraw().
At this point, youi compass application is woiking. The compass iose shoulu Le pointing
noith, moie oi less, when the uevice is helu upiight as usual. Keep in minu that you
shoulu iun this application on a physical uevice Lecause the emulatoi uoesn`t
suppoit it.
Location Service
Now that you have seen how the sensoi managei woiks, we can look at the Location
API, anothei system seivice pioviueu Ly Anuioiu. ]ust like sensois, the Location API
is suppoiteu via the Location managei. Anu just like sensois, we get the Location man-
agei via a getSystemService() call.
Once we have access to the Location seivice, we neeu to iegistei a Location listenei
with it so the seivice can call Lack when theie`s a change in location. Again, we`ll uo
this Ly implementing a Location listenei inteilace.
Il you iecall liom Common Steps in Using System Seivices on page 190, piocessing
GPS anu othei location upuates can Le veiy taxing loi the Latteiy. To minimize the
Latteiy consumption, we want to listen to location upuates only while in the iunning
Location Service | 195
state. To uo that, we`ll iegistei loi the upuates in onResume() anu uniegistei in
onPause(), taking auvantage ol the activity lile cycle.
Where Am I? Demo
This example illustiates how to use location-Laseu seivices in Anuioiu. Fiist, we use
LocationManager to liguie out oui cuiient location Laseu on the iesouices in the envi-
ionment availaLle to the uevice, such as GPS oi a wiieless netwoik. Seconu, we use
Geocoder to conveit this location to an auuiess.
The layout
The layout loi this example is tiivial, as you can see in Example 13-3. Oui iesouice lile
pioviues a TextView wiuget loi the title anu anothei TextView wiuget loi the output.
Since the output coulu Le longei than the scieen size, we wiap the output in a Scroll
View wiuget.
Exanp|c 13-3. rcs/|ayout/nain.xn|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:background="#fff" android:orientation="vertical">
<!-- -->
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center"
android:textColor="#333" android:textSize="30dp" android:text="@string/title"/>
<!-- -->
<ScrollView android:layout_height="fill_parent"
android:layout_width="fill_parent">
<!-- -->
<TextView android:textColor="#333" android:layout_gravity="center"
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:gravity="center" android:textSize="25dp" android:text="Waiting..."
android:id="@+id/textOut"></TextView>
</ScrollView>
</LinearLayout>
The title loi oui application.
A ScrollView to enaLle sciolling il the output giows Leyonu the size ol the scieen.
A TextView to iepiesent the output. It will Le piogiammatically set liom the Vheie-
AmI activity.
The activity for our Location listener
The coue in Example 13-+ is oui main activity, which sets up the scieen, connects to
LocationManager, anu uses the Geocoder to liguie out oui auuiess. The Location
Manager uses location pioviueis, such as GPS oi Netwoik, to liguie out oui cuiient
location. The location is expiesseu as latituue anu longituue values. The Geocoder
196 | Chapter 13:System Services
seaiches an online uataLase loi known auuiesses in the vicinity ol the location pioviueu.
It may come up with multiple iesults, some moie specilic than otheis.
Exanp|c 13-1. WhcrcAn|.java
package com.marakana;
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class WhereAmI extends Activity implements LocationListener { //
LocationManager locationManager; //
Geocoder geocoder; //
TextView textOut; //
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textOut = (TextView) findViewById(R.id.textOut);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); //
geocoder = new Geocoder(this); //
// Initialize with the last known location
Location lastLocation = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER); //
if (lastLocation != null)
onLocationChanged(lastLocation);
}
@Override
protected void onResume() { //
super.onRestart();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,
10, this);
}
@Override
protected void onPause() { //
super.onPause();
locationManager.removeUpdates(this);
}
Location Service | 197
// Called when location has changed
public void onLocationChanged(Location location) { //
String text = String.format(
"Lat:\t %f\nLong:\t %f\nAlt:\t %f\nBearing:\t %f", location
.getLatitude(), location.getLongitude(), location.getAltitude(),
location.getBearing()); //
textOut.setText(text);
// Perform geocoding for this location
try {
List<Address> addresses = geocoder.getFromLocation(
location.getLatitude(), location.getLongitude(), 10); //
for (Address address : addresses) {
textOut.append("\n" + address.getAddressLine(0)); //
}
} catch (IOException e) {
Log.e("WhereAmI", "Couldn't get Geocoder data", e);
}
}
// Methods required by LocationListener
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
Notice that WhereAmI implements LocationListener. This is the inteilace that Location
Manager uses to notily us ol changes to the location.
Local ieleience to LocationManager.
Local ieleience to Geocoder.
textOut is the text view to which we piint oui output so the usei can see it.
To get the local ieleience to LocationManager, we ask the context to get the
location managei system seivice. Foi moie aLout context, see Application Con-
text on page 3+.
Ve cieate a new instance ol Geocoder anu pass the cuiient context to it.
The location managei memoiizes its last known location. This is uselul Lecause it
might take a while until we get the location lock via eithei a netwoik oi a GPS
pioviuei.
As usual, we iegistei in onResume(), since that is the methou that is calleu en ioute
to the iunning state. Ve use the location managei`s requestLocationUpdates()
methou to iegistei loi upuates.
198 | Chapter 13:System Services
Ve uniegistei in onPause(), which will Le calleu just Leloie the activity goes into the
stoppeu state.
onLocationChanged() is the callLack methou calleu Ly the location managei when it
uetects that the location has changeu.
Ve get the Location oLject, which contains a lot ol uselul inloimation aLout the
cuiient location. Ve cieate a human-ieauaLle stiing with this inlo.
Once we have the location, we can tiy to geocoue the location, a piocess ol con-
veiting latituue anu longituue to a known auuiess.
Il we uo linu known auuiesses loi this location, we piint them out.
Some othei callLack methous aie ieguiieu to implement the LocationListener in-
teilace. Ve uon`t use them loi this example.
The manifest file
As shown in Example 13-5, the manilest lile loi this app is laiily stanuaiu. Notice that
in oiuei to iegistei as a location listenei, we have to holu the appiopiiate peimissions.
Keep in minu that although we have GPS anu Netwoik as the two most commonly
useu location pioviueis, Anuioiu is Luilt with extensiLility in minu. In the lutuie, we
might have othei types ol pioviueis as well. Foi that ieason, Anuioiu Lieaks uown the
location peimissions into aLstiact jinc |ocation anu coarsc |ocation peimissions.
Exanp|c 13-5. AndroidManijcst.xn|
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.marakana" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".WhereAmI" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
<!-- -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
Declaies that this app uses location pioviueis. The location peimissions coulu Le
android.permission.ACCESS_FINE_LOCATION loi a GPS pioviuei oi android.permis
sion.ACCESS_COARSE_LOCATION loi a wiieless netwoik pioviuei.
At this point, youi VheieAmI application is complete. It illustiates how to use
LocationManager to get the actual location via a specilic location pioviuei anu how to
Location Service | 199
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
conveit that location into a known auuiess via Geocouei. An example ol the iesult is
shown in Figuie 13-2.
Iigurc 13-2. WhcrcAn|
Updating Yamba to Use the Location Service
The VheieAmI application was a small stanualone test to make suie we can get location
inloimation. Now we`ll incoipoiate location inloimation into oui laigei YamLa app.
Updating Our Preferences
Fiist, the usei might not want to Lioaucast hei location to the woilu, so we shoulu ask.
A goou place to ask woulu Le the Pieleiences. This time aiounu, we`ll use a List
Preference piopeity. This is somewhat uilleient liom the EditTextPreferences we`ve
seen Leloie in Chaptei 7, in that it ieguiies a list ol items. In lact, it ieguiies two lists:
one to uisplay anu one to use loi actual values.
So we`ll auu a couple ol stiings to oui strings.xn| lile anu cieate two new stiing ie-
souices: one to iepiesent names ol oui location pioviueis in a loim liienuly to human
ieaueis anu the othei to iepiesent theii values. To uo that, we`ll auu the lollowing to
oui strings.xn| lile:
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<string-array name="providers">
<item>None, please</item>
<item>GPS via satellites!</item>
<item>Mobile Network will do</item>
</string-array>
200 | Chapter 13:System Services
<string-array name="providerValues">
<item>NONE</item>
<item>gps</item>
<item>network</item>
</string-array>
</resources>
Notice that Loth stiing aiiays have the same numLei ol elements. They Lasically iep-
iesent name-value paiis anu match each othei.
Now that we have the names anu values loi oui location pioviueis, we can upuate
prcjs.xn| with that inloimation, as shown in Example 13-6.
Exanp|c 13-. Updatcd rcs/xn|/prcjs.xn|
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference android:title="@string/titleUsername"
android:summary="@string/summaryUsername" android:key="username"></EditTextPreference>
<EditTextPreference android:title="@string/titlePassword"
android:password="true" android:summary="@string/summaryPassword"
android:key="password"></EditTextPreference>
<EditTextPreference android:title="@string/titleApiRoot"
android:summary="@string/summaryApiRoot" android:key="apiRoot"></EditTextPreference>
<ListPreference android:title="@string/titleProvider"
android:summary="@string/summaryProvider" android:key="provider"
android:entryValues="@array/providerValues" android:entries="@array/providers" />
<!-- -->
<ListPreference android:entryValues="@array/intervalValues"
android:summary="@string/summaryUpdaterInterval"
android:title="@string/titleUpdaterInterval"
android:entries="@array/interval" android:key="interval"></ListPreference>
</PreferenceScreen>
The new ListPreference uisplaying the names anu values ol vaiious location pio-
viueis that we suppoit: GPS, netwoik, anu none at all.
Updating the Yamba Application
Now that we have the location pioviuei pieleiences, we have to expose those pielei-
ences via YambaApplication to iest ol the app, namely StatusActivity.
To uo that, auu a gettei methou to YanbaApp|ication.java (see Example 13-7).
Exanp|c 13-7. YanbaApp|ication.java
public class YambaApplication extends Application implements
OnSharedPreferenceChangeListener {
...
public static final String LOCATION_PROVIDER_NONE = "NONE";
...
public String getProvider() {
return prefs.getString("provider", LOCATION_PROVIDER_NONE);
Updating Yamba to Use the Location Service | 201
}
}
Now that we have suppoit loi pioviueis in the pieleiences anu in the YamLa app oLject,
we`ie ieauy to upuate the Status activity.
Updating the Status Activity
The Status activity is the main place wheie we use the location inloimation. ]ust as in
the VheieAmI uemo, we`ie going to get the Location managei Ly calling getSys
temService() anu iegistei loi location upuates. Ve`ie also going to implement the
LocationListener inteilace, which means auuing a numLei ol new callLack methous
to this activity. Vhen the location uoes change, we`ll upuate the location oLject, anu
next time aiounu when we upuate oui status online, we`ll have the piopei location
inloimation. Example 13-S shows the upuateu coue.
Exanp|c 13-8. StatusActivity.java
package com.marakana.yamba8;
import winterwell.jtwitter.Twitter;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class StatusActivity extends BaseActivity implements OnClickListener,
TextWatcher, LocationListener { //
private static final String TAG = "StatusActivity";
private static final long LOCATION_MIN_TIME = 3600000; // One hour
private static final float LOCATION_MIN_DISTANCE = 1000; // One kilometer
EditText editText;
Button updateButton;
TextView textCount;
LocationManager locationManager; //
Location location;
String provider;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
202 | Chapter 13:System Services
super.onCreate(savedInstanceState);
setContentView(R.layout.status);
// Find views
editText = (EditText) findViewById(R.id.editText);
updateButton = (Button) findViewById(R.id.buttonUpdate);
updateButton.setOnClickListener(this);
textCount = (TextView) findViewById(R.id.textCount);
textCount.setText(Integer.toString(140));
textCount.setTextColor(Color.GREEN);
editText.addTextChangedListener(this);
}
@Override
protected void onResume() {
super.onResume();
// Setup location information
provider = yamba.getProvider(); //
if (!YambaApplication.LOCATION_PROVIDER_NONE.equals(provider)) { //
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); //
}
if (locationManager != null) {
location = locationManager.getLastKnownLocation(provider); //
locationManager.requestLocationUpdates(provider, LOCATION_MIN_TIME,
LOCATION_MIN_DISTANCE, this); //
}
}
@Override
protected void onPause() {
super.onPause();
if (locationManager != null) {
locationManager.removeUpdates(this); //
}
}
// Called when button is clicked
public void onClick(View v) {
String status = editText.getText().toString();
new PostToTwitter().execute(status);
Log.d(TAG, "onClicked");
}
// Asynchronously posts to twitter
class PostToTwitter extends AsyncTask<String, Integer, String> {
// Called to initiate the background activity
@Override
protected String doInBackground(String... statuses) {
try {
// Check if we have the location
if (location != null) { //
Updating Yamba to Use the Location Service | 203
double latlong[] = {location.getLatitude(), location.getLongitude()};
yamba.getTwitter().setMyLocation(latlong);
}
Twitter.Status status = yamba.getTwitter().updateStatus(statuses[0]);
return status.text;
} catch (RuntimeException e) {
Log.e(TAG, "Failed to connect to twitter service", e);
return "Failed to post";
}
}
// Called once the background activity has completed
@Override
protected void onPostExecute(String result) {
Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG).show();
}
}
// TextWatcher methods
public void afterTextChanged(Editable statusText) {
int count = 140 - statusText.length();
textCount.setText(Integer.toString(count));
textCount.setTextColor(Color.GREEN);
if (count < 10)
textCount.setTextColor(Color.YELLOW);
if (count < 0)
textCount.setTextColor(Color.RED);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
// LocationListener methods
public void onLocationChanged(Location location) { //
this.location = location;
}
public void onProviderDisabled(String provider) { //
if (this.provider.equals(provider))
locationManager.removeUpdates(this);
}
public void onProviderEnabled(String provider) { //
if (this.provider.equals(provider))
locationManager.requestLocationUpdates(this.provider, LOCATION_MIN_TIME,
LOCATION_MIN_DISTANCE, this);
}
public void onStatusChanged(String provider, int status, Bundle extras) { //
}
}
204 | Chapter 13:System Services
StatusActivity now implements LocationListener, the inteilace loi callLacks liom
the location managei.
Heie we ueline local vaiiaLles loi LocationManager, Location, anu oui pioviuei.
Ve get the pioviuei liom the YamLa application oLject, as we explaineu eailiei. Anu
ultimately, the usei chooses the pioviuei in the pieleiences.
Ve check whethei the usei wants us to pioviue hei location inloimation at all.
Il we pass that test, we get the location inloimation via getSystemService(). This
call is ielatively inexpensive, even il it happens eveiy time the methou iuns, Lecause
we`ie just getting a ieleience to an alieauy iunning system seivice.
Get the cacheu location il the location managei has it.
Registei with the location managei to ieceive location upuates. Heie, we get to
specily how olten we`u like to ieceive notilications anu loi what kinu ol change in
location. In oui example, we caie only aLout the geneial vicinity at a city level, so
we set these values to 1,000 meteis (one kilometei) anu 3,600,000 milliseconus (one
houi). Note that this is just a hint to the system.
Vhen this activity is no longei visiLle, we uniegistei liom the location managei anu
no longei ieceive any upuates to help save Latteiy powei.
Once the usei is aLout to upuate hei status, we check whethei we have a location.
Il we uo, we pack it into the ieguiieu double aiiay anu pass it on to
setMyLocation() in YamLa`s Twitter oLject.
Now we implement the methous that the location managei calls. onLocation
Changed() is calleu whenevei theie`s a change in location anu pioviues us with the
actual new Location oLject.
This methou is calleu when the pioviuei is no longei availaLle. Ve can simply ie-
move any upuates so that we uon`t waste the Latteiy.
Vhen the pioviuei we caie aLout Lecomes availaLle, we can ieguest location up-
uates again.
This methou is calleu when theie`s a change with the pioviuei in geneial. In this
case, we ignoie it.
At this point oui YamLa application suppoits location upuates. The usei can set piel-
eiences to inuicate what location pioviuei to use, il any.
Next, we`ie going to see anothei system seivice, this time the Alaim seivice, which we`ll
use to tiiggei an Intent seivice.
Updating Yamba to Use the Location Service | 205
Intent Service
Now that we unueistanu how system seivices woik, we can use anothei seivice concept
to suLstantially simplily oui Upuatei seivice. Il you iecall, oui Upuatei seivice is an
always-on, always-iunning seivice that peiiouically goes to the clouu anu pulls uown
the latest timeline upuates. Since Ly uelault a seivice iuns in the same thieau as the
usei inteilace (i.e., it iuns on the UI thieau), we hau to cieate a sepaiate thieau calleu
Updater within the Upuatei seivice that is iesponsiLle loi the actual netwoik connec-
tion. Ve then staiteu this thieau in the seivice`s onCreate() anu onStartCommand()
methous. Ve ian it loievei until onDestroy() got calleu. Howevei, oui Upuatei thieau
woulu sleep Letween the upuates loi some amount ol time. All this woikeu well in
Chaptei S, Lut theie`s a simplei way to accomplish this task, shown in Example 13-9.
An IntentService is a suLclass ol Service anu is also activateu Ly a startService()
intent. Unlike a iegulai seivice, it iuns on its own wor|cr thieau, so it uoesn`t Llock
oui piecious UI thieau. Also, once it`s uone, it`s uone. This means it iuns only once,
Lut we will use an Alaim latei to iun it peiiouically. Any call to the intent`s startSer
vice() will iecieate it.
Unlike a iegulai seivice, we uon`t oveiiiue onCreate(), onStartCommand(),
onDestroy(), anu onBind(), Lut iathei a new onHandleIntent() methou. This methou
is wheie we want to put oui coue that goes online anu hanules the netwoik upuates.
Also, unlike a iegulai seivice, an IntentService has a uelault constiuctoi that must Le
pioviueu.
In shoit, insteau ol cieating a sepaiate thieau anu uelaying netwoik upuates as in a
iegulai seivice, we can simplily oui coue Ly using an IntentService to iun status up-
uates on its woikei thieau. Now we just neeu something to peiiouically wake up oui
IntentService so it knows it neeus to hanule the upuating joL. Foi that, we`ll use the
Alaim managei, anothei system seivice.
The key to Intent seivices is the onHandleIntent() methou, a Llock ol coue that will iun
on a sepaiate thieau.
Exanp|c 13-9. UpdatcrScrvicc.java bascd on |ntcntScrvicc
package com.marakana.yamba8;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
public class UpdaterService1 extends IntentService { //
private static final String TAG = "UpdaterService";
public static final String NEW_STATUS_INTENT = "com.marakana.yamba.NEW_STATUS";
public static final String NEW_STATUS_EXTRA_COUNT = "NEW_STATUS_EXTRA_COUNT";
public static final String RECEIVE_TIMELINE_NOTIFICATIONS
= "com.marakana.yamba.RECEIVE_TIMELINE_NOTIFICATIONS";
206 | Chapter 13:System Services
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
public UpdaterService1() { //
super(TAG);
Log.d(TAG, "UpdaterService constructed");
}
@Override
protected void onHandleIntent(Intent inIntent) { //
Intent intent;
Log.d(TAG, "onHandleIntent'ing");
YambaApplication yamba = (YambaApplication) getApplication();
int newUpdates = yamba.fetchStatusUpdates();
if (newUpdates > 0) { //
Log.d(TAG, "We have a new status");
intent = new Intent(NEW_STATUS_INTENT);
intent.putExtra(NEW_STATUS_EXTRA_COUNT, newUpdates);
sendBroadcast(intent, RECEIVE_TIMELINE_NOTIFICATIONS);
}
}
}
Ve now suLclass IntentService insteau ol its paient, Service.
A uelault constiuctoi is neeueu. This is a goou place to give youi seivice a name,
which can Le uselul in TiaceView, loi example, to help iuentily vaiious thieaus.
This is the key methou. The woik insiue ol it takes place on a sepaiate woikei thieau
anu uoesn`t inteileie with the main UI thieau.
The iest ol the coue in this section Lioaucasts the change, as uesciiLeu in Bioau-
casting Intents on page 165.
At this point, oui seivice is upuateu. An easy way to test it woulu Le to change the
Stait/Stop Seivice menu item to a Reliesh Lutton. To uo that, upuate youi ncnu.xn|
lile to incluue the new item shown in Example 13-10, anu change its hanuling in oui
BaseActivity class.
Exanp|c 13-10. rcs/xn|/ncnu.xn|
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
...
<item android:title="@string/titleRefresh" android:id="@+id/itemRefresh"
android:icon="@android:drawable/ic_menu_rotate"></item>
</menu>
I`ve ieplaceu itemToggle with itemRefresh so that the names make moie sense. Ve
must also auu the appiopiiate stiing to the strings.xn| lile.
Now we neeu to upuate oui BascActivity.java lile to hanule this new Reliesh Lutton
(see Example 13-11). To uo that, we change the appiopiiate case statement in
onOptionsItemSelected(). Auuitionally, we can now iemove onMenuOpened() altogethei
Intent Service | 207
Lecause we no longei neeu to change the state ol that toggle Luttonit uoesn`t exist
any moie.
Exanp|c 13-11. BascActivity.java with support jor thc Rcjrcsh button
public class BaseActivity extends Activity {
...
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
...
case R.id.itemRefresh:
startService(new Intent(this, UpdaterService.class)); //
break;
...
}
return true;
}
...
}
Ve simply liie oll an intent to stait oui Upuatei seivice.
So oui options menu now has a Reliesh Lutton that will stait a seivice anu have it
upuate the status uata in the Lackgiounu. Ve can use this Lutton to test whethei this
new leatuie woiks well.
Anothei way to auu the same lunctionality woulu have Leen to use an AsyncTask. In
lact, AsyncTask woulu pioLaLly Le slightly moie appiopiiate in this case liom a uesign
point ol view, to keep all the lunctionality at the UI level, Lut we`ve alieauy uiscusseu
it in Thieauing in Anuioiu on page 65. Heie we wanteu to uemonstiate guickly how
an IntentService is staiteu, anu as you can see, it woiks just like any othei seivice.
Next, we want to have oui Upuatei seivice tiiggeieu peiiouically. To uo that, we`ll use
the Alaim managei.
Alarms
The pievious incaination ol oui Upuatei seivice hau a iegulai seivice that was always
iunning in a loop, pulling netwoik upuates, then sleeping loi some amount ol time,
anu then looping again. Vith IntentService, we tuineu the piocess aiounu. Oui Up-
uatei seivice now iuns only once when liieu up Ly the startService() intent. Now we
neeu a way to have something liie these intents eveiy so olten.
Anuioiu comes with yet anothei system seivice just loi that. The Alaim seivice, iep-
iesenteu Ly the AlarmManager class, lets you scheuule ceitain things to happen at ceitain
times. The time can Le iecuiiing, which makes it easy to stait oui seivice eveiy so olten.
Anu the event that happens is an intent, oi moie piecisely, a PendingIntent.
208 | Chapter 13:System Services
Pending intents
A PendingIntent is a comLination ol an intent anu an action to Le executeu on it.
Typically this is useu loi lutuie intents that you aie passing to someone else. Cieate a
penuing intent via one ol the static methous in the PendingIntent class. Since theie aie
only a hanulul ol ways to senu an intent, theie aie only a hanulul ol static methous to
cieate penuing intents along with theii actions. Il you iecall, you typically use an intent
to stait an activity via startActivity(), stait a seivice via startService(), oi senu a
Lioaucast via sendBroadcast(). So, to cieate a penuing intent that will execute start
Service() with oui intent in the lutuie, we call the getService() static methou.
Adding an Interval to Preferences
Now that we know how to leave an intent loi someone to execute latei anu how to tell
an Alaim seivice to iepeat that peiiouically, we neeu to choose wheie to implement
this leatuie. One goou place is oui existing BootReceiver, Lut Leloie we uo that, we`ll
auu anothei option to oui pieleiences, shown in Example 13-12.
Exanp|c 13-12. strings.xn| with arrays jor intcrva| options
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<!-- -->
<string-array name="interval">
<item>Never</item>
<item>Fifteen minutes</item>
<item>Half hour</item>
<item>An hour</item>
<item>Half day</item>
<item>Day</item>
</string-array>
<!-- -->
<string-array name="intervalValues">
<item>0</item>
<item>900000</item>
<item>1800000</item>
<item>3600000</item>
<item>43200000</item>
<item>86400000</item>
</string-array>
</resources>
These will Le the names ol options that show up in the list.
These will Le theii coiiesponuing values.
Now that we have these aiiays, we can upuate prcjs.xn| as shown in Example 13-13
to auu to oui list ol inteivals.
Intent Service | 209
Exanp|c 13-13. prcjs.xn| with support jor intcrva| prcjcrcncc sctting
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
...
<!-- -->
<ListPreference android:entryValues="@array/intervalValues"
android:summary="@string/summaryUpdaterInterval"
android:title="@string/titleUpdaterInterval"
android:entries="@array/interval" android:key="interval" />
</PreferenceScreen>
This is the list pieleience. It shows a list ol entities, as iepiesenteu Ly android:enti
ties. The value associateu with it comes liom android:entityValues.
Now we aie ieauy to upuate BootReceiver anu auu the Alaim seivice alaims.
Updating BootReceiver
Il you iecall liom BootReceivei on page 162, a BootReceiver wakes up eveiy time the
uevice is Looteu up. So lai, oui BootReceiver just staits oui Upuatei seivice. That was
line when the Upuatei seivice was always on anu iunning, Lut now it woulu cause only
a one-time execution ol the Upuatei.
Ve can use the Alaim seivice insteau to peiiouically liie intents that stait oui Upuatei
seivice, as shown in Example 13-1+. To uo that, we`ll get the ieleience to the Alaim
managei, cieate a penuing intent to Le staiteu each time, anu set up the inteival at
which to stait the upuates. Because oui penuing intent is meant to stait a seivice, we`ll
use the PendingIntent.getService() call, as uesciiLeu in Penuing intents
on page 209.
Exanp|c 13-11. BootRcccivcr.java updatcd with A|arn scrvicc ca||s to pcriodica||y start thc Updatcr
scrvicc
package com.marakana.yamba8;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent callingIntent) {
// Check if we should do anything at boot at all
long interval = ((YambaApplication) context.getApplicationContext())
.getInterval(); //
if (interval == YambaApplication.INTERVAL_NEVER) //
210 | Chapter 13:System Services
return;
// Create the pending intent
Intent intent = new Intent(context, UpdaterService.class); //
PendingIntent pendingIntent = PendingIntent.getService(context, -1, intent,
PendingIntent.FLAG_UPDATE_CURRENT); //
// Setup alarm service to wake up and start service periodically
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE); //
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, System
.currentTimeMillis(), interval, pendingIntent); //
Log.d("BootReceiver", "onReceived");
}
}
The pievious coue assumes that the phone is awake anu will not woik
when the uevice is asleep. Vhen youi uevice is asleep, a uilleient ap-
pioach is neeueu (not uiscusseu in this Look).
Oui YamLa application has a simple gettei methou to ietuin the value ol the inteival
pieleience.
Ve check the usei`s pieleience to set the lieguency ol checks loi netwoik upuates.
A value ol INTERVAL_NEVER (zeio) means not to check loi upuates at all.
This is the intent that will iun to stait oui Upuatei seivice.
Heie we wiap that intent with the action to stait a seivice anu get a new penuing
intent. The value -1 is loi a ieguest coue that is cuiiently not Leing useu. The llag
in the linal aigument inuicates whethei this intent alieauy exists. Ve neeu just to
upuate it anu not iecieate it.
Ve get the ieleience to AlarmManager via the usual getSystemService() call.
setInexactRepeating() specilies that we`u like this penuing intent to Le sent iepeat-
euly, Lut we`ie not conceineu with Leing exactly on time. The ELAPSED_REALTIME llag
will keep the alaim liom waking up the phone just to iun the upuates. The othei
paiameteis aie the cuiient time as the stait time loi this alaim, oui uesiieu inteival,
anu the actual penuing intent to execute when the alaim iuns.
You can now install this application on a uevice (anu thus install the upuateu
BootReceiver), anu then ieLoot the uevice. Once the uevice staits, the LogCat shoulu
inuicate that the BootReceiver ian anu staiteu the Upuatei seivice Ly posting a penuing
intent to the Alaim seivice.
Intent Service | 211
Sending Notifications
Heie`s an oppoitunity to intiouuce yet anothei system seivicethis time the Notili-
cation seivice. Ve woikeu haiu to have oui Upuatei seivice iun in the Lackgiounu anu
get the latest status upuates, Lut what`s the point ol all this woik il the usei is not maue
awaie that theie`s something new to look at? A stanuaiu Anuioiu UI appioach to this
woulu Le to post a notilication to the notilication Lai up at the top ol the scieen. To
uo that, we use the Notilication system seivice.
Ve`ie going to make the Upuatei seivice iesponsiLle loi posting the notilications, since
it is the pait ol the app that knows ol new statuses in the liist place. To uo that, we`ll
get the ieleience to the system Notilication seivice, cieate a new Notification oLject,
anu upuate it with the latest inloimation. The notilication itsell will contain a penuing
intent so that when the usei clicks on it, it takes the usei to Timeline activity to view
the latest status upuates. Example 13-15 shows the new coue.
Exanp|c 13-15. UpdatcrScrvicc.java with Notijications
package com.marakana.yamba8;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.util.Log;
public class UpdaterService extends IntentService {
private static final String TAG = "UpdaterService";
public static final String NEW_STATUS_INTENT = "com.marakana.yamba.NEW_STATUS";
public static final String NEW_STATUS_EXTRA_COUNT = "NEW_STATUS_EXTRA_COUNT";
public static final String RECEIVE_TIMELINE_NOTIFICATIONS = "com.marakana.yamba.
RECEIVE_TIMELINE_NOTIFICATIONS";
private NotificationManager notificationManager; //
private Notification notification; //
public UpdaterService() {
super(TAG);
Log.d(TAG, "UpdaterService constructed");
}
@Override
protected void onHandleIntent(Intent inIntent) {
Intent intent;
this.notificationManager = (NotificationManager) getSystemService(NOTIFICATION_
SERVICE); //
this.notification = new Notification(android.R.drawable.stat_notify_chat,
"", 0); //
212 | Chapter 13:System Services
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Log.d(TAG, "onHandleIntent'ing");
YambaApplication yamba = (YambaApplication) getApplication();
int newUpdates = yamba.fetchStatusUpdates();
if (newUpdates > 0) {
Log.d(TAG, "We have a new status");
intent = new Intent(NEW_STATUS_INTENT);
intent.putExtra(NEW_STATUS_EXTRA_COUNT, newUpdates);
sendBroadcast(intent, RECEIVE_TIMELINE_NOTIFICATIONS);
sendTimelineNotification(newUpdates); //
}
}
/**
* Creates a notification in the notification bar telling user there are new
* messages
*
* @param timelineUpdateCount
* Number of new statuses
*/
private void sendTimelineNotification(int timelineUpdateCount) {
Log.d(TAG, "sendTimelineNotification'ing");
PendingIntent pendingIntent = PendingIntent.getActivity(this, -1,
new Intent(this, TimelineActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT); //
this.notification.when = System.currentTimeMillis(); //
this.notification.flags |= Notification.FLAG_AUTO_CANCEL; //
CharSequence notificationTitle = this
.getText(R.string.msgNotificationTitle); //
CharSequence notificationSummary = this.getString(
R.string.msgNotificationMessage, timelineUpdateCount);
this.notification.setLatestEventInfo(this, notificationTitle,
notificationSummary, pendingIntent); //
this.notificationManager.notify(0, this.notification);
Log.d(TAG, "sendTimelineNotificationed");
}
}
This is just oui local ieleience to the NotificationManager class, which is oui access
to the Notilication system seivice.
Ve cieate a class-gloLal Notification oLject anu upuate it each time theie`s a new
notilication loi oui listeneis.
Ve oLtain the ieleience to the Notilication seivice Ly using the usual getSystem
Service() call.
Ve cieate the notilication oLject that we`ll ieuse latei. Foi now, we just specily the
stanuaiu icon to use with oui notilication, anu leave the text anu timestamp to Le
upuateu latei when we aie aLout to post this notilication.
Ve call oui piivate sendTimelineNotification() methou once we know theie aie
new statuses loi the usei.
Sending Notifications | 213
This penuing intent will Le kickeu oll when the usei checks the notilication in the
notilication Lai anu clicks on the actual item. In this case, we want to take the usei
to the Timeline activity, so we cieate an intent loi that.
Ve`ie now upuating the uata loi the most iecent notilication. This is the timestamp
that inuicates when it happeneu.
This llag tells the Notilication managei to cancel this notilication as soon as the usei
clicks on it. The notilication will Le iemoveu liom the notilication Lai at that point.
Heie we get the notilication`s title anu summaiy liom oui strings.xn| lile. Notice
that the summaiy has paiameteis, so we can use String.format() to upuate the
actual numLei ol new statuses.
Finally, we tell the Notilication managei to post this notilication. In this case, we
uo not neeu the ID, so we specily zeio. An ID can Le useu to ielei to a notilication
latei, usually in oiuei to cancel it.
At this point oui application is yet again complete. Ve now have a way to notily the
usei ol any new status upuates so he can stay on top ol what is going on in the woilu.
Summary
At this point you have seen a lew system seivicesSensoi, Location, Alaim, anu
Notilicationanu Anuioiu pioviues a lew moie seivices in auuition to these. You
might have noticeu that most ol them have a lot ol similaiities, anu hopelully you have
staiteu extiapolating ceitain patteins. Ve have also useu this chaptei to somewhat
simplily oui Upuatei seivice anu intiouuce Intent seivices anu penuing intents.
214 | Chapter 13:System Services
CHAPTER 14
The Android Interface
Definition Language
Each application in Anuioiu iuns in its own piocess. Foi secuiity ieasons, an applica-
tion cannot uiiectly access the uata ol anothei application. Howevei, a couple ol mech-
anisms allow communication Letween applications. One such mechanism that you`ve
seen thioughout this Look is Intents. Intents aie asynchionous, meaning that you can
post a message loi someone to ieceive at some lutuie point in time anu just continue
with youi application.
Eveiy once in a while we neeu a moie uiiect, synchionous access to anothei piocess.
Theie aie many ways to implement this acioss piocess Lounuaiies, anu collectively
they aie calleu Inteipiocess Communication, oi IPC loi shoit.
To allow cioss-application communication, Anuioiu pioviues its own veision ol an
IPC piotocol. One ol the Liggest challenges in IPC is passing uata aiounu, such as when
passing paiameteis to methou calls on the iemote systems. IPC piotocols tenu to get
complicateu Lecause they have to conveit uata liom its in-memoiy loimat to a loimat
that`s convenient loi senuing to anothei piocess. This is calleu narsha|ing, anu the
unpacking at the ieceivei is calleu unnarsha|ing.
To help with this, Anuioiu pioviues the Anuioiu Inteilace Delinition Language, oi
AIDL. This lightweight implementation ol IPC uses a syntax that is veiy lamiliai to ]ava
uevelopeis, anu theie is a tool that automatically cieates the hiuuen coue ieguiieu to
connect a client anu a iemote seivice.
To illustiate how to use AIDL to cieate an inteipiocess communication, we`ll cieate
two applications: a iemote seivice calleu LogService anu a client calleu LogClient that
will Linu to that iemote seivice.
Implementing the Remote Service
Oui iemote seivice, LogService, will simply allow iemote clients to log a message to it.
215
Ve aie going to stait Ly cieating the intcrjacc loi the iemote seivice. This inteilace
iepiesents the API, oi set ol capaLilities that the seivice pioviues. Ve wiite this inteilace
in the AIDL language anu save it in the same uiiectoiy as oui ]ava coue with an .aid|
extension.
The AIDL syntax is veiy similai to a iegulai ]ava inteilace. You simply ueline the
methou signatuie. The uatatypes suppoiteu Ly AIDL aie somewhat uilleient liom ieg-
ulai ]ava inteilaces. Howevei, all ]ava piimitive uatatypes aie suppoiteu, anu so aie
the String, List, Map, anu CharSequence classes.
Il you have a custom complex uata type, such as a class, you neeu to make it
Parcelable so that the Anuioiu iuntime can maishal anu unmaishal it. In this example,
we`ll cieate a Message as a custom type.
Writing the AIDL
Ve stait Ly uelining the inteilace loi oui seivice. As you can see in Example 1+-1, the
inteilace veiy much iesemLles a typical ]ava inteilace. Foi ieaueis who might have
woikeu with CORBA in the past, AIDL has its ioots in CORBA`s IDL.
Exanp|c 11-1. |LogScrvicc.aid|
package com.marakana.logservice; //
import com.marakana.logservice.Message; //
interface ILogService { //
void log_d(String tag, String message); //
void log(in Message msg); //
}
]ust as in ]ava, oui AIDL coue specilies what package it`s pait ol.
Howevei, unlike ]ava, we have to explicitly impoit othei AIDL uelinitions, even il
they aie in the same package.
Ve specily the name ol oui inteilace. Inteilace names conventionally stait with |
loi inteilace.
This methou is simple Lecause it uoesn`t ietuin anything anu takes only piimitives
as inputs. Note that the String class is not a ]ava piimitive, Lut AIDL consiueis it
to Le one.
This methou takes oui custom Message paicel as its input. Ve`ll ueline Message next.
Next, we`ll look at the implementation ol the Message AIDL, shown in Example 1+-2.
Exanp|c 11-2. Mcssagc.aid|
package com.marakana.logservice; //
216 | Chapter 14:The Android Interface Definition Language
/* */
parcelable Message;
Specilies the package it`s in.
Declaies that Message is a paicelaLle oLject. Ve will ueline this oLject latei in ]ava.
At this point, we aie uone with the AIDL. As you save youi liles, Eclipse automatically
Luilus the coue to which the client will connect, calleu the stub Lecause it looks like a
complete methou to the client Lut actually just passes on the client ieguest to youi
iemote seivice. The new ]ava lile is locateu in the gcn loluei unuei /gcn/con/nara|ana/
|ogscrvicc/LogScrvicc.java. Because this lile is ueiiveu liom youi AIDL, you shoulu
nevei mouily it. The aid| tool that comes with the Anuioiu SDK will iegeneiate it
whenevei you make changes to youi AIDL liles.
Now that we have the AIDL anu the geneiateu ]ava stuL, we aie ieauy to implement
the seivice.
Implementing the Service
]ust like any Anuioiu seivice, we implement LogService in a ]ava class that suLclasses
the system Service class. But unlike oui eailiei Seivice implementations, wheie we
ignoieu onBind() Lut implementeu onCreate(), onStartCommand(), anu onDestroy(),
heie we`ie going to uo the opposite. A methou in a iemote seivice staits when the client
makes its ieguest, which is calleu binding to the seivice, anu theieloie the client ieguest
tiiggeis the seivice`s onBind() methou.
To implement oui iemote seivice, we`ll ietuin an IBinder oLject liom the onBind()
methou in oui seivice class. IBinder iepiesents the implementation ol the iemote
seivice. To implement IBinder, we suLclass the ILogService.Stub class liom the auto-
geneiateu ]ava coue, anu pioviue the implementation loi oui AIDL-uelineu methous,
in this case vaiious log() methous. Example 1+-3 shows the coue.
Exanp|c 11-3. LogScrvicc.java
package com.marakana.logservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class LogService extends Service { //
@Override
public IBinder onBind(Intent intent) { //
final String version = intent.getExtras().getString("version");
return new ILogService.Stub() { //
Implementing the Remote Service | 217
public void log_d(String tag, String message) throws RemoteException { //
Log.d(tag, message + " version: " + version);
}
public void log(Message msg) throws RemoteException { //
Log.d(msg.getTag(), msg.getText());
}
};
}
}
LogService is an Anuioiu class ueiiveu liom Service. Ve`ve seen many seivices, Lut
this time aiounu, it`s a Lounu seivice, as opposeu to UpdaterService, which was
unLounu.
Since this is a Lounu seivice, we must implement onBind() anu have it ietuin a coiiect
instance ol IBinder class. The client passes us an Intent, liom which we extiact some
stiing uata. Duiing the client implementation, we`ll see how it sets this, anu thus
how we can pass small amounts ol uata into the iemote seivice as pait ol the Linuing
piocess.
This instance ol IBinder is iepiesenteu Ly ILogService.Stub(), a helpei methou that
is geneiateu loi us in the ]ava stuL lile cieateu Ly the aid| tool when we saveu oui
AIDL inteilace. This coue is pait ol /gcn/con/nara|ana/|ogscrvicc/LogScrvicc.java.
log_d() is the simple methou that takes two stiings anu logs them. Oui implemen-
tation simply invokes the system`s Log.d().
Ve also pioviue a log() methou that gets oui Message paicel as its input paiametei.
Out ol this oLject we extiact the tag anu the message. Again, loi this tiivial imple-
mentation, we just invoke Anuioiu`s logging mechanism.
Now that we have implementeu the seivice in ]ava, we have to pioviue the ]ava im-
plementation ol the Message paicel as well.
Implementing a Parcel
Since Message is a ]ava oLject that we`ie passing acioss piocesses, we neeu a way to
encoue anu uecoue this oLjectmaishal anu unmaishal itso that it can Le passeu.
In Anuioiu, the oLject that can uo that is calleu a Parcel anu implements the
Parcelable inteilace.
To Le a paicel, this oLject must know how to wiite itsell to a stieam anu how to iecieate
itsell. Example 1+-+ shows the coue.
Exanp|c 11-1. Mcssagc.java
package com.marakana.logservice;
import android.os.Parcel;
218 | Chapter 14:The Android Interface Definition Language
import android.os.Parcelable;
public class Message implements Parcelable { //
private String tag;
private String text;
public Message(Parcel in) { //
tag = in.readString();
text = in.readString();
}
public void writeToParcel(Parcel out, int flags) { //
out.writeString(tag);
out.writeString(text);
}
public int describeContents() { //
return 0;
}
public static final Parcelable.Creator<Message> CREATOR
= new Parcelable.Creator<Message>() { //
public Message createFromParcel(Parcel source) {
return new Message(source);
}
public Message[] newArray(int size) {
return new Message[size];
}
};
// Setters and Getters
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
As we saiu Leloie, Message implements the Parcelable inteilace.
Implementing the Remote Service | 219
To Le paicelaLle, this oLject must pioviue a constiuctoi that takes in a Parcel anu
iecieates the oLject. Heie we ieau the uata liom the paicel into oui local vaiiaLles.
The oiuei in which we ieau in uata is impoitant: it must coiiesponu to the oiuei in
which the uata was wiitten out.
writeToParcel() is the counteipait to the constiuctoi. This methou is iesponsiLle
loi taking the cuiient state ol this oLject anu wiiting it out into a paicel. Again, the
oiuei in which vaiiaLles aie wiitten out must match the oiuei in which they aie ieau
in Ly the constiuctoi that gets this paicel as its input.
Ve`ie not using this methou, Lecause we have no special oLjects within oui paicel.
A paicelaLle oLject must pioviue a Creator. This Creator is iesponsiLle loi cieating
the oLject liom a paicel. It simply calls oui othei methous.
These aie just vaiious settei anu gettei methous loi oui piivate uata.
At this point, we have implementeu the ieguiieu ]ava coue. Ve now neeu to iegistei
oui seivice with the manilest lile.
Registering with the Manifest File
As always, whenevei we pioviue one ol the new main Luiluing Llocks loi an application,
we must iegistei it with the system. The most common way to uo that is to ueline it in
the manilest lile.
]ust as we iegisteieu UpdaterService eailiei, we pioviue a <service> element specilying
oui seivice. The uilleience this time aiounu is that this seivice is going to Le invokeu
iemotely, so we shoulu specily what action this seivice iesponus to. To uo that, we
specily the action anu the intent liltei as pait ol this seivice iegistiation:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.marakana.logservice" android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<!-- -->
<service android:name=".LogService">
<!-- -->
<intent-filter>
<action android:name="com.marakana.logservice.ILogService" />
</intent-filter>
</service>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>
This is wheie we ueline oui seivice. It is a <service> element within the application
Llock.
220 | Chapter 14:The Android Interface Definition Language
The uilleience Letween this seivice anu oui UpdaterService is that this seivice is
going to Le iemote to the client. Theieloie, calling it Ly an explicit class name
woulun`t woik well, Lecause the client might not have access to the same set ol
classes. So insteau, we pioviue the intent liltei anu action to which this seivice is
iegisteieu to iesponu.
At this point, oui seivice is complete. Ve can now move on to the client
implementation.
Implementing the Remote Client
Now that we have the iemote seivice, we aie going to cieate a client that connects to
that seivice to test that it all woiks well. Note that in this example we puiposely sepa-
iateu the client anu the seivei into two sepaiate piojects with uilleient ]ava packages
altogethei, in oiuei to uemonstiate how they aie sepaiate apps.
So we`ie going to cieate a new Anuioiu pioject in Eclipse loi this client, just as we`ve
uone Leloie loi vaiious othei applications. Howevei, this time aiounu we aie also going
to make this pioject uepenu on the LogService pioject. This is impoitant Lecause
LogClient has to linu the AIDL liles we cieateu as pait ol LogService in oiuei to know
what that iemote inteilace looks like. To uo this in Eclipse:
1. Altei you have cieateu youi LogClient pioject, iight-click on youi pioject in Pack-
age Exploiei anu choose Piopeities.
2. In the Piopeities loi LogClient uialog Lox, choose ]ava Builu Path, anu then click
on the Piojects taL.
3. In this taL, click on Auu., anu point to youi LogService pioject.
This pioceuuie will auu LogService as a uepenuent pioject loi LogClient.
Binding to the Remote Service
Oui client is going to Le an activity so that we can see it woiking giaphically. In this
activity, we`ie going to Linu to the iemote seivice, anu liom that point on, use it as il
it weie just like any othei local class. Behinu the scenes, the Anuioiu Linuei will maishal
anu unmaishal the calls to the seivice.
The Linuing piocess is asynchionous, meaning we ieguest it anu it happens at some
latei point in time. To hanule that, we neeu a callLack mechanism to hanule iemote
seivice connections anu uisconnections.
Once we have the seivice connecteu, we can make calls to it as il it weie any othei local
oLject. Howevei, il we want to pass any complex uata types, such as a custom ]ava
oLject, we have to cieate a paicel loi it liist. In oui case, we have Message as a custom
type, anu we have alieauy maue it paicelaLle. Example 1+-5 shows the coue.
Implementing the Remote Client | 221
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Exanp|c 11-5. LogActivity.java
package com.marakana.logclient;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.marakana.logservice.ILogService;
import com.marakana.logservice.Message;
public class LogActivity extends Activity implements OnClickListener {
private static final String TAG = "LogActivity";
ILogService logService;
LogConnection conn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Request bind to the service
conn = new LogConnection(); //
Intent intent = new Intent("com.marakana.logservice.ILogService"); //
intent.putExtra("version", "1.0"); //
bindService(intent, conn, Context.BIND_AUTO_CREATE); //
// Attach listener to button
((Button) findViewById(R.id.buttonClick)).setOnClickListener(this);
}
class LogConnection implements ServiceConnection { //
public void onServiceConnected(ComponentName name, IBinder service) { //
logService = ILogService.Stub.asInterface(service); //
Log.i(TAG, "connected");
}
public void onServiceDisconnected(ComponentName name) { //
logService = null;
Log.i(TAG, "disconnected");
}
}
public void onClick(View button) {
222 | Chapter 14:The Android Interface Definition Language
try {
logService.log_d("LogClient", "Hello from onClick()"); //
Message msg = new Message(Parcel.obtain()); //
msg.setTag("LogClient");
msg.setText("Hello from inClick() version 1.1");
logService.log(msg); //
} catch (RemoteException e) { //
Log.e(TAG, "onClick failed", e);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroyed");
unbindService(conn); //
logService = null;
}
}
LogConnection is oui class that Loth connects to anu hanules uisconnections liom
the iemote seivice. The class is explaineu latei.
This is the action intent that we`ie using to connect to the iemote seivice. It must
match the action that LogService specilieu in the manilest lile as pait ol its intent
liltei.
Heie is wheie we auu the uata to the intent, to Le extiacteu Ly the iemote methou.
The bindService() methou asks the Anuioiu iuntime to Linu this activity to the
iemote seivice specilieu Ly the intent action. In auuition to the intent, we pass
on the Service Connection class to hanule the actual connection. The BIND_AUTO_
CREATE llag inuicates that il the seivice we`ie tiying to connect to uoesn`t alieauy
exist, it shoulu Le cieateu.
LogConnection is the class that will Le calleu Lack upon successlul connection
to the iemote seivice anu whenevei the seivice uisconnects. This class neeus
to suLclass ServiceConnection anu implement onServiceConnected() anu onService
Disconnected().
onServiceConnected() is calleu once the Linu succeeus. At this point, the IBinder
instance iepiesents oui iemote seivice.
Ve now neeu to cast the Lounu seivice into oui LogService instance. To uo that,
we use a helpei methou nameu ILogService.Stub.asInterface(), pioviueu Ly that
]ava stuL that was cieateu automatically Ly the aid| tool when we saveu oui AIDL
liles.
Implementing the Remote Client | 223
onServiceDisconnected() is calleu once the iemote seivice is no longei availaLle. It
is an oppoitunity to hanule any necessaiy cleanup. In this case, we just set log
Service to null to help with the gaiLage collection.
Assuming that we have successlully Lounu to the iemote seivice, we can now make
calls to it as il it weie a local call. logService.log_d() simply passes two stiings to
the log_d() methou that we saw uelineu in LogService.
As mentioneu eailiei, il we want to pass a Message to the iemote methou, we have
to cieate a paicel loi it liist. This is possiLle Lecause Message is a paicelaLle oLject.
Ve then set its piopeities using appiopiiate setteis.
Once we have the paicel, we simply call logService.log() anu pass it to LogSer
vice, wheie it gets loggeu.
Vhenevei we make a iemote call, it coulu lail loi a vaiiety ol ieasons outsiue ol oui
contiol. Because ol that, it is a goou piactice to hanule a possiLle RemoteException.
Vhen this activity is aLout to Le uestioyeu, we ask to unLinu the seivice anu liee
those iesouices.
At this point oui client is complete. Theie`s a simple UI with a single Lutton that tiiggeis
an onClick() call. Once the usei clicks the Lutton, oui client shoulu invoke the iemote
call in the seivice.
Testing That It All Works
Tiy to iun the client liom within Eclipse. Since Eclipse knows that LogClient is ue-
penuent on LogService, it shoulu install Loth packages onto youi uevice. Once the
client staits, it shoulu Linu to the seivice. Tiy clicking on the Lutton anu check that
LogService is inueeu logging. Youi adb logcat call shoulu give you something like this:
...
I/LogActivity( 613): connected
...
D/LogClient( 554): Hello from onClick() version: 1.0
D/LogClient( 554): Hello from inClick() version 1.1
...
The liist line is liom the LogConnection in the client, inuicating that we`ve successlully
Lounu to the seivice. The othei two lines aie liom the iemote seivice, one loi Log
Service.log_d() anu the othei one loi LogService.log(), wheie we passeu in the
Message paicel.
224 | Chapter 14:The Android Interface Definition Language
Il you iun adb shell ps to see the iunning piocesses on youi uevice, you`ll notice two
sepaiate line items loi the client anu the seivei:
app_43 554 33 130684 12748 ffffffff afd0eb08 S com.marakana.logservice
app_42 613 33 132576 16552 ffffffff afd0eb08 S com.marakana.logclient
This inuicates that inueeu the client anu seivei aie two sepaiate applications.
Summary
Anuioiu pioviues an inteipiocess communication mechanism Laseu on its Linuei, a
high-peiloimance, shaieu-memoiy system. To cieate a iemote seivice, we ueline it
using the Anuioiu Inteilace Delinition Language (AIDL), in a way similai to ]ava in-
teilaces. Ve then implement the iemote inteilace anu connect to it via the IBinder
oLject. This allows us to connect oui client to a iemote seivice in a uilleient piocess
altogethei.
Summary | 225
CHAPTER 15
The Native Development Kit (NDK)
The Native Development Kit, oi NDK, is an auu-on to SDK that helps you integiate
native couecoue that uses platloim-specilic leatuies, geneially exposeu thiough C
oi C-- language APIswithin youi Anuioiu application. The NDK allows youi An-
uioiu application to call some native coue anu even incluue some native liLiaiies.
In the GingeiLieau ielease ol Anuioiu, NDK takes suppoit loi native coue even luithei
with the intiouuction ol the NativeActivity class. You can now wiite youi entiie ac-
tivity in C oi C--. Howevei, NativeActivity is not the suLject ol this chaptei. Heie,
we`ll look at integiating native C coue within youi ]ava Anuioiu application.
What Is and Isnt the NDK For?
The main motivation loi ueveloping paits ol youi app in native coue is peiloimance.
As you can see, the NDK suppoits math anu giaphics liLiaiies well, as well as some
suppoiting system liLiaiies. So giaphically anu computationally intensive applications
aie the Lest canuiuates loi NDK. One coulu aigue that the iecent Loom in the popu-
laiity ol moLile games is uiiving this uevelopment as well.
Note that any native coue accessiLle liom youi app via the ]ava Native Inteilace (]NI)
still iuns insiue youi application`s Dalvik VM. So it`s suLject to the same secuiity sanu-
Loxing iules that an Anuioiu application lives Ly. Viiting paits ol youi application in
C oi C-- just so you can uo something that might not Le possiLle in ]ava usually is
not a goou ieason loi NDK. Keep in minu that most ol the low-level haiuwaie leatuies
aie alieauy elegantly exposeu via the Anuioiu liamewoik in ]ava anu aie usually what
you want to use anyhow.
Problems Solved by the NDK
The NDK auuiesses seveial ol the majoi issues you`u have to ueal with il you weie
uoing native uevelopment uiiectly.
227
The Toolchain
]ava olleis access to native coue via the ]ava Native Inteilace (]NI). To make it woik,
you woulu typically have to compile eveiything on youi host computei loi the taiget
aichitectuie, which woulu ieguiie you to have the entiie tool chain on youi uevelop-
ment machine. Setting up the piopei cioss-compilei anu othei tools is not easy.
NDK pioviues the complete toolchain you neeu to compile anu Luilu youi native coue
so it can iun on youi taiget platloim. The Luilu system makes it veiy easy to set up
youi enviionment anu integiate youi native coue into youi pioject.
Packaging Your Libs
Il you hau a native liLiaiy anu wanteu it to Le availaLle to youi application, you`u have
to make suie it is pait ol the liLiaiy path wheie the system seaiches loi liLiaiies to loau.
This is typically LD_LIBRARY_PATH on Linux. On an Anuioiu uevice, only the /systcn/
|ib uiiectoiy is pait ol this path. This is a pioLlem Lecause the entiie /systcn paitition
is ieau-only anu thus unavailaLle loi installing liLiaiies.
NDK solves this pioLlem Ly pioviuing loi a mechanism to ship youi native liLiaiy as
pait ol youi Application Package (APK) lile. Basically, when the usei installs an APK
that contains a native liLiaiy, the system cieates a uiiectoiy nameu /data/data/
your.pac|agc/|ib/. Il you iecall liom The Filesystem Explaineu on page 95, this pai-
tition is piivate just to youi application anu thus is a sale place to keep youi liLiaiies
loi the usei, while Llocking othei applications liom loauing anu using youi liLiaiies.
This packaging mechanism is a uiamatic change to the iules loi uistiiLuting applica-
tions on Anuioiu uevices, anu is a Lig ueal Lecause it Liings the huge iange ol legacy
anu new native coue into the game.
Documentation and Standardized Headers
The NDK comes with helplul uocumentation anu a sample application explaining how
to get things uone in native coue. It also stanuaiuizes on ceitain guaianteeu C anu
C-- heaueis, such as:
libc (C liLiaiy) heaueis
libm (math liLiaiy) heaueis
]NI inteilace heaueis
libz (ZliL compiession) heaueis
liblog (Anuioiu logging) heauei
OpenGL ES 1.1 anu OpenGL ES 2.0 (3D giaphics liLiaiies) heaueis
libjnigraphics (Pixel Lullei access) heauei (loi Anuioiu 2.2 anu aLove)
A minimal set ol heaueis loi C-- suppoit
228 | Chapter 15:The Native Development Kit (NDK)
OpenSL ES native auuio liLiaiies
Anuioiu native application APIs
Given this set ol stanuaiu heaueis, you might have extiapolateu what NDK is well
suiteu loi. Ve`ll examine that in the next section.
An NDK Example: Fibonacci
Because the NDK is well-suiteu loi computationally intensive applications, I wanteu
to linu an example wheie we can implement a ielatively simple algoiithm in Loth native
coue anu ]ava to compaie theii ielative speeus.
So I pickeu a FiLonacci algoiithm as the example. It`s a laiily simple algoiithm that can
Le implementeu easily in Loth C anu ]ava. Auuitionally, we can implement it iecuisively
as well as iteiatively.
As a guick ielieshei, the FiLonacci seiies is uelineu as:
fib(0)=0
fib(1)=1
fib(n)=fib(n-1)+fib(n-2)
So the FiLonacci seguence looks like this: 0, 1, 1, 2, 3, 5, S, 13, 21, 3+, 55, S9, 1++, anu
so on.
In this example, we aie going to:
Cieate the ]ava class iepiesenting the FiLonacci liLiaiy.
Cieate the native coue heauei lile.
Implement the native coue Ly wiiting C coue.
Compile eveiything anu Luilu a shaieu liLiaiy.
Use this native coue insiue an Anuioiu activity.
FibLib
FibLib is wheie we ueclaie oui algoiithms loi computing the FiLonacci seguence. Ve
have a total ol loui veisions ol the FiLonacci algoiithm:
]ava iecuisive veision
]ava iteiative veision
Native iecuisive veision
Native iteiative veision
Ve`ll wiite the ]ava implementation in Example 15-1 anu uo the native ones in C latei.
An NDK Example: Fibonacci | 229
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Exanp|c 15-1. IibLib.java
package com.marakana;
public class FibLib {
// Java implementation - recursive
public static long fibJ(long n) { //
if (n <= 0)
return 0;
if (n == 1)
return 1;
return fibJ(n - 1) + fibJ(n - 2);
}
// Java implementation - iterative
public static long fibJI(long n) { //
long previous = -1;
long result = 1;
for (long i = 0; i <= n; i++) {
long sum = result + previous;
previous = result;
result = sum;
}
return result;
}
// Native implementation
static {
System.loadLibrary("fib"); //
}
// Native implementation - recursive
public static native long fibN(int n); //
// Native implementation - iterative
public static native long fibNI(int n); //
}
This is the ]ava iecuisive veision ol the FiLonacci iecuisive algoiithm.
The iteiative veision ol the same ]ava iecuisive algoiithm. Eveiything that can Le
implementeu iecuisively can Le ieuuceu to an iteiative algoiithm as well.
The native veision will Le implementeu in a shaieu liLiaiy. Heie, we tell the ]ava
viitual machine to loau that liLiaiy so the lunction can Le lounu when calleu.
Ve ueclaie the native FiLonacci methou, Lut uon`t implement it. Notice the use ol
the native keywoiu heie. It tells the ]ava VM that the implementation ol this methou
is in a shaieu liLiaiy. The liLiaiy shoulu Le loaueu piioi to this methou call.
The pievious ueclaiation is loi the iecuisive native implementation. This one is loi
the iteiative veision.
230 | Chapter 15:The Native Development Kit (NDK)
At this point, oui FibLib is complete, Lut we still neeu to Lack the native methous with
theii C implementations. To uo that, liist we neeu to cieate the appiopiiate ]NI heauei
lile.
The JNI Header File
The next step is to cieate the C heauei lile Laseu on oui FiLLiL ]ava lile. To uo that,
we use ]ava`s stanuaiu javah tool. Note that you must have the ]ava Development Kit
(]DK) installeu in oiuei to linu this tool in the jDK/bin uiiectoiy.
Now, to cieate the C heauei, go to youi pioject`s bin uiiectoiy anu execute:
[Fibonacci/bin]> javah -jni com.marakana.FibLib
javah -jni takes a ]ava class as the paiametei. Not all the classes aie in the ]ava class-
path Ly uelault, so it is easiest to just change uiiectoiy to youi pioject`s bin uiiectoiy.
Heie, we assume that the cuiient woiking uiiectoiy is pait ol youi ]ava classpath anu
thus that javah -jni com.marakana.FibLib at this location will woik.
The iesult shoulu Le a new lile nameu con_nara|ana_IibLib.h. This is the C heauei
lile that we neeu to implement next.
Beloie implementing oui native liles, let`s oiganize oui pioject a little Lit. Although
Eclipse uiu a lot to set up oui Anuioiu application uiiectoiies in a meaninglul way thus
lai, it uoesn`t yet ollei that level ol suppoit anu automation loi NDK uevelopment. Ve
aie going to uo a couple ol steps manually heie.
Foi one, cieate a uiiectoiy nameu jni insiue youi Eclipse FiLonacci pioject. This will
Le the place wheie you`ll stoie all youi native coue anu ielateu liles. You can cieate this
uiiectoiy liom within Eclipse Ly selecting the FiLonacci pioject in Package Exploiei,
iight-clicking on it, anu choosing NewFoluei.
Next, move this new heauei lile into that loluei:
[Fibonacci/bin]> mv com_marakana_FibLib.h ../jni/
You can look into this lile:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_marakana_FibLib */
#ifndef _Included_com_marakana_FibLib
#define _Included_com_marakana_FibLib
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_marakana_FibLib
* Method: fibN
* Signature: (I)J
*/
An NDK Example: Fibonacci | 231
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibN
(JNIEnv *, jclass, jint);
/*
* Class: com_marakana_FibLib
* Method: fibNI
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibNI
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
As you can see, this lile is automatically geneiateu anu is not to Le mouilieu Ly the
piogiammei uiiectly. You may oLseive signatuies loi two ol oui native lunctions that
we`ie yet to implement:
...
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibN
(JNIEnv *, jclass, jlong);
...
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibNI
(JNIEnv *, jclass, jlong);
...
These aie stanuaiu ]NI signatuies. They aie geneiateu Ly a naming convention inui-
cating that the lunction contains coue uelineu in Java as pait ol the com.mara
kana.FibLib class loi the native methous fibN anu fibNI. You can also see that Loth
methous ietuin jlong, a ]NI-stanuaiuizeu integei value.
Theii input paiameteis aie also inteiesting: JNIEnv, jclass, anu jlong. The liist two aie
always pait ol a ]ava class, cieateu to inteilace with native coue. The JNIEnv points Lack
to the viitual machine enviionment, anu the next paiametei points Lack to the class oi
oLject wheie this methou is liom; the paiametei is jclass loi a class methou oi
jobject loi an instance methou. The thiiu paiametei, jlong, is just oui input into the
FiLonacci algoiithm, oi oui n.
Now that we have this heauei lile, it is time to pioviue its implementation in C.
C Implementation
Ve aie going to cieate a C lile that will implement oui native algoiithms. Foi simplic-
ity`s sake, we`ll call it jib.c. Like the heauei lile we lookeu at eailiei, this lile will iesiue
in the jni loluei. To cieate it, iight-click on the jni loluei anu choose NewFile. Save
it as jib.c.
232 | Chapter 15:The Native Development Kit (NDK)
Vhen you open the C lile, it might open up in anothei euitoi outsiue
ol Eclipse. That`s Lecause the ]ava veision ol Eclipse typically uoesn`t
have suppoit loi C uevelopment. You coulu extenu youi Eclipse with
C uevelopment tools Ly opening Eclipse anu going to HelpInstall New
Soltwaie. Alteinatively, you can just open the lile with the stanuaiu
Eclipse text euitoi Ly selecting the lile anu choosing Open VithText
Euitoi.
Next, we pioviue the implementation ol the FiLonacci algoiithm in C in this jib.c lile,
as shown in Example 15-2. The C veisions ol oui algoiithms aie almost iuentical to the
]ava veisions.
Exanp|c 15-2. jni/jib.c
#include "com_marakana_FibLib.h" /* */
/* Recursive Fibonacci Algorithm */
long fibN(long n) {
if(n<=0) return 0;
if(n==1) return 1;
return fibN(n-1) + fibN(n-2);
}
/* Iterative Fibonacci Algorithm */
long fibNI(long n) {
long previous = -1;
long result = 1;
long i=0;
int sum=0;
for (i = 0; i <= n; i++) {
sum = result + previous;
previous = result;
result = sum;
}
return result;
}
/* Signature of the JNI method as generated in header file */
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibN
(JNIEnv *env, jclass obj, jlong n) {
return fibN(n);
}
/* Signature of the JNI method as generated in header file */
JNIEXPORT jlong JNICALL Java_com_marakana_FibLib_fibNI
(JNIEnv *env, jclass obj, jlong n) {
return fibNI(n);
}
Ve impoit con_nara|ana_IibLib.h, the heauei lile that was piouuceu when we
calleu javah -jni com.marakana.FibLib.
The actual iecuisive FiLonacci algoiithm. This is laiily similai to the ]ava veision.
An NDK Example: Fibonacci | 233
An iteiative veision ol FiLonacci. Again, veiy similai to the ]ava veision.
]NI pioviues this lunction to us. Copy anu paste the piototype liom con_
nara|ana_IibLib.h, auu vaiiaLle names, anu call the appiopiiate C lunction to
piouuce the iesult.
Same loi the iteiative signatuie ol the methou.
Now that we have implementeu C veisions ol FiLonacci, we want to Luilu the shaieu
liLiaiy. To uo that, we neeu an appiopiiate makelile.
The Makefile
To Luilu the native liLiaiy, the Android.n| makelile must uesciiLe oui liles. The lile is
shown in Example 15-3.
Exanp|c 15-3. jni/Android.n|
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fib
LOCAL_SRC_FILES := fib.c
include $(BUILD_SHARED_LIBRARY)
The makelile is a pait ol the stanuaiu Anuioiu na|c system. All we aie auuing heie is
oui specilic input (jib.c) anu oui specilic output (the fib mouule). The name ol the
mouule we specily is impoitant anu will ueteimine the name ol the liLiaiy Laseu on
the opeiating system convention. Foi example, on ARM-Laseu systems, the output will
Le a |ibjib.so lile.
Once we have this makelile, we`ie ieauy to initiate the Luilu.
Building the Shared Library
Assuming you have the NDK installeu piopeily, you can now Luilu the native shaieu
liLiaiy Ly iunning ndk-build in youi pioject uiiectoiy. Heie, ndk-build is a tool in the
uiiectoiy wheie youi NDK is installeu. Ve assume you put this uiiectoiy into youi
enviionment PATH.
At this point, you shoulu have a suLuiiectoiy nameu |ib containing youi shaieu liLiaiy.
Vhen you ueploy the FiLonacci application in the next section, this liLiaiy is packageu
as pait ol the APK.
The shaieu liLiaiy is compileu to iun on the emulatoi Ly uelault, so it`s
Laseu on ARM aichitectuie.
234 | Chapter 15:The Native Development Kit (NDK)
Finally, we neeu an application to put this liLiaiy to goou use.
The Fibonacci Activity
The FiLonacci Activity asks the usei to input a numLei. Then, it iuns the loui algo-
iithms to compute the FiLonacci value ol that numLei. It also times the computation
anu piints the iesults to the scieen. This activity Lasically uses the FibLib class that in
tuin uses |ibjib.so loi its native pait. Example 15-+ shows the coue.
Exanp|c 15-1. IibActivity.java
package com.marakana;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class Fibonacci extends Activity implements OnClickListener {
TextView textResult;
Button buttonGo;
EditText editInput;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Find UI views
editInput = (EditText) findViewById(R.id.editInput);
textResult = (TextView) findViewById(R.id.textResult);
buttonGo = (Button) findViewById(R.id.buttonGo);
buttonGo.setOnClickListener(this);
}
public void onClick(View view) {
int input = Integer.parseInt(editInput.getText().toString()); //
long start, stop;
long result;
String out = "";
// Dalvik - Recursive
start = System.currentTimeMillis(); //
result = FibLib.fibJ(input); //
stop = System.currentTimeMillis(); //
out += String.format("Dalvik recur sive: %d (%d msec)", result,
stop - start);
// Dalvik - Iterative
An NDK Example: Fibonacci | 235
start = System.currentTimeMillis();
result = FibLib.fibJI(input); //
stop = System.currentTimeMillis();
out += String.format("\nDalvik iterative: %d (%d msec)", result,
stop - start);
// Native - Recursive
start = System.currentTimeMillis();
result = FibLib.fibN(input); //
stop = System.currentTimeMillis();
out += String.format("\nNative recursive: %d (%d msec)", result,
stop - start);
// Native - Iterative
start = System.currentTimeMillis();
result = FibLib.fibNI(input); //
stop = System.currentTimeMillis();
out += String.format("\nNative iterative: %d (%d msec)", result,
stop - start);
textResult.setText(out); //
}
}
Ve conveit the stiing we get liom the usei into a numLei.
Beloie we stait the calculation, we take the cuiient timestamp.
Ve peiloim the actual FiLonacci calculation Ly invoking the appiopiiate static
methou in FibLib. In this case, it`s the ]ava iecuisive implementation.
Ve take anothei timestamp anu suLtiact the pievious one. The uelta is the length
ol the computation, in milliseconus.
Ve uo the same loi the iteiative ]ava implementation ol FiLonacci.
Heie we use the native iecuisive algoiithm.
Anu linally, we use the native iteiative algoiithm.
Ve loimat the output anu piint out the iesults on the scieen.
Testing That It All Works
At this point, we can liie up the FiLonacci application anu iun some tests on it. Keep
in minu that laigei values loi n take guite a Lit longei to piocess, especially using the
iecuisive algoiithms. One suggestion woulu Le to keep n in the 2530 iange. Also keep
in minu that we aie uoing all this piocessing on Activity`s main UI thieau, anu Llocking
that thieau loi a long peiiou ol time will leau to the Application Not Responuing (ANR)
eiioi we showeu in Figuie 6-9. As an exeicise, you might want to move the actual
calculation into an AsyncTask, as uesciiLeu in AsyncTask on page 67, to pievent
Llocking the main thieau.
236 | Chapter 15:The Native Development Kit (NDK)
As you iun some tests, you might notice that the native veision ol the algoiithm iuns
aLout one oiuei ol magnituue lastei than the ]ava implementation (see Figuie 15-1).
Iigurc 15-1. Iibonacci oj 33
These iesults alone shoulu pioviue enough motivation to consiuei moving some ol youi
computationally intensive coue into native coue. NDK makes the joL ol integiating
native coue into youi app much simplei.
Summary
Staiting with the GingeiLieau veision ol Anuioiu, NDK also suppoits Native activities,
a way to cieate an entiie activity in C anu still have it auheie to the activity lile cycle
iules, as uiscusseu in Activity Lile Cycle on page 2S. This makes game uevelopment
in Anuioiu even easiei.
Summary | 237
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
Index
A
ALsoluteLayout, 50
activities, 2S, 39
auL shell, 9S
auuPieleiencesFiomResouice() methou, S7
alteiTextChangeu() methou, 73
AIDL (Anuioiu Inteilace Delinition Language),
215
Alaim seivice, 205, 20S211
Alpha channel, 77
Anuioiu components (see activities) (see
Lioaucast ieceiveis) (see content
pioviueis) (see system seivices)
Anuioiu Device DashLoaiu, 5
Anuioiu Inteilace Delinition Language (AIDL),
215
Anuioiu Pioject, 1S
Anuioiu UI (see UI (usei inteilace))
Anuioiu Viitual Device (AVD), 23, 96
Anuioiu, histoiy ol, 3
AnuioiuManilest.xml examples, 61, 163
Apache Haimony, 9
API
anu AIDL inteilace, 216
Content Pioviuei, 17S, 1S3
levels, +, 19, 51
Location, 195
ioot, S3, S5, 95, 9S
Twittei-compatiLle, 5S, 59, 113, 127
APK (Application Package) lile, 12, 22S, 23+
app iesouices, 90
Application Context, 3+
application liamewoik, 11
application initial setup, 152
application oLjects, 102105, 113, 133
application signing, 12
AppViugetPioviuei class, 1S2
ARGB coloi set, 77
asInteilace() methou, 223
AsyncTask, 67
AVD (Anuioiu Viitual Device), 23, 96
B
Lackgiounu, iunning seivices in, 31
Lase activity example, 153
Latteiy consumption, 29, 3+, 50, 167, 190, 195,
205
LinuSeivice() methou, 223
LinuView() methou, 1+6, 1+9
Bionic, 9
BootReceivei, 162, 210211
Boinstein, Dan, 9
Lioaucast ieceiveis, 3+, 39, 161173
BootReceivei, 162, 210211
netwoik ieceiveis, 167169
timeline ieceiveis, 163165, 172
Luilu taiget, 19, 51
Luiluing Llocks, oveiview, 27
Luttons, +S, 5259, 91, 10S, 15+, 207
C
C implementation, 12, 227, 22S, 231, 232
Canvas, 19+
classpaths, 60
close() methou, 133
coaise location peimissions, 199
coloi, auuing, 7+7S
Compass uemo, 1S9195
Ve`u like to heai youi suggestions loi impioving oui inuexes. Senu email to indcxorci||y.con.
239
compiling coue, 5961
compiehensive platloim, 1, 37
content pioviueis
cieating, 1751S1
oveiview, 32, 39
using thiough wiugets, 1S11S6
CRUD piinciple, 32
cuisois, 122, 1+1, 1S0
custom peimissions, 169171
D
.u() seveiity level, 62
Dalvik, 9
uataLases
constiaints on, 129
oveiview, 119
schema, cieating, 120
woiking with, 139
DLHelpei, 120
DDMS, 17, 63, 95, 9S, 127
ueLugging, +1
ueclaiative usei inteilace, +7
uelete() methou, 121, 175
uesign philosophy, 39
Destioyeu State, 30
uevelopment tools, 17
uistiiLution ol applications, 12
uoInBackgiounu() methou, 67
E
.e() seveiity level, 62
Eclipse Anuioiu Development Tools (ADT),
+7
Eclipse IDE
euiting coue in, S7, SS
installing, 16
Oiganize Impoits tool, 62
VYSIVYG Euitoi, 75
emulatois, 23
events, 7073
execSQL() methou, 122, 12+
F
letchStatusUpuates() methou, 13+, 166
FiLonacci uemo, 229237
lile system, +2, 9599
liles, saving, 59
line location peimissions, 199
loimat() methou, 1+1
FiameLayout, 50
G
gaiLage collectoi, 1+1
Geocouei, 196
getApplication() methou, 35, 105, 116
getApplicationContext() methou, 35
getColumnInuex() methou, 1+1
getDelaultShaieuPieleiences() methou, 9+
getFilesDii() methou, 9S
getFiienusTimeline() methou, 113, 116, 127,
129
getID() methou, 175, 17S
getLatestStatusCieateuAtTime() methou, 133
getReauaLleDataLase() methou, 1+0
getRelativeTimeSpanStiing() methou, 1+S,
150
getSeivice() methou, 209
getStatusTextByIu() methou, 133
getStatusUpuates() methou, 15S
getStiing() methou, 9+
getSystemSeivice() methou, 190, 195, 202,
205
getTwittei() methou, 95, 102, 105, 116, 127
getType() methou, 175, 1S0
getViiteaLleDataLase() methou, 1+0
GNU liLc, 9
Google, 3
giaphics, auuing, 7+7S
giavity piopeity, 55
H
heauei liles, cieating, 231
Hello, Voilu example, 1S22
hexauecimal, 77
Hieiaichy Viewei, S1
HTC Sense, 3+
I
.i() seveiity level, 62
iu piopeity, 55
IDE (Integiateu Development Enviionment),
16
images, auuing, 7+
inseit() methou, 121, 127, 129, 175, 177
inseitOiThiow() methou, 129
inseitVithOnConllict() methou, 133
240 | Index
Integiateu Development Enviionment (IDE),
16
intents
Lioaucasts, 161, 165
liltei, 162
anu menus, S3, 92
oveiview, 31, 215
seivices, 20620S
inteilaces, 216
Inteinet access, 167, 169
Inteinet peimissions, 61
Inteipiocess Communication (IPC), 215
inteiiupt() methou, 112
invaliuate() methou, 195
IPC (Inteipiocess Communication), 215
J
]ava, 16
(see also Eclipse IDE)
anu AIDL, 216, 21S
BaseActivity.java, 15+, 20S
BootReceivei.java, 162, 210
classes, 51
classpaths, 60
compaieu to native coue, 229, 237
Compass.java, 192
Dalvik compilei, 10, 12
DLHelpei.java, 123
eiiois, 59
FiLActivity.java, 235
FiLLiL.java, 230
lile naming conventions, 51, 53
gen/com/maiakana/R.java, 22
HelloVoilu.java, 22
inllateu liom XML, +S, 56
liLiaiies loi, 60
liLiaiies loi Anuioiu, 11
LogActivity.java, 222
LogSeivice.java, 217
loops, 116, 127
Message.java, 21S
multithieaueu execution, 66, 111
NetwoikReceivei.java, 167
notilications, 190, 196
packages, 19, 51, 97
paicels, 21S, 221
PielsActivity.java, S7
piogiammatic usei inteilace with, +S
R lile anu, 22, 90
Rose.java, 19+
souice coue, 22
StatusActivity.java, 56, 5S, 67, 71, 109,
202
StatusData.java, 130
synchionizeu methou, 10+
TimelineActivity.java, 139, 1++150, 156,
16+, 172
UpuateiSeivice.java, 106, 111, 11+, 12+,
13+, 165, 206, 212
VheieAmI.java, 197
wiuget iu's, 55
YamLaApplication.java, 102, 133, 201
YamLaViuget.java, 1S2
]ava Native Inteilace (]NI), 227
javah tool, 231
]NI (]ava Native Inteilace), 227
jtwittei.jai liLiaiy, 59
L
layout lile, 21
layouts anu views, +S
layoutgiavity, 55
layoutheight, 5+
layoutweight, 55
layoutwiuth, 5+
liLiaiies
Luiluing shaieu, 23+
native, 912, 23+
packaging, 22S
SQLite as set ol, 119
using thiiu-paity, 60
licensing, 2, 9
LineaiLayout, +9
Linux, 7
Lists anu Auapteis, +3
Location Seivice, 195205
LocationListenei, 205
Log class, 62
log() methou, 217
LogCat, 62, 113
LogClient uemo, 221
logging, 62
LogSeivice uemo, 21522+
looping in seivices, 110
M
make system, 23+
Index | 241
makeText() methou, 69
malwaie, 13
manageis, 11
manilest lile
ueclaiing peimissions in, 61, 170
LocationListenei example, 199
oveiview, 20
ielactoiing via, 10+
iegisteiing activities via, SS, 150
iegisteiing BootReceivei via, 162
iegisteiing content pioviueis via, 1S1
iegisteiing netwoik ieceiveis via, 167
iegisteiing seivices via, 107, 220
iegisteiing wiugets via, 1S6
maishaling, 215
Meuia Stoie, 33
menus
auuing items to, 10S
events, 92
loauing, 91
iesouices, S9
moveToNext() methou, 1+1
multithieaueu execution, 66
multithieauing, +1
N
name-value paiis, S3
naming conventions
CamelCase, 19
]ava classes, 19, 51
]ava packages, 51
]NI signatuies, 232
iesouices, 56, 79
wiugets, 55
Native Development Kit (NDK), 227237
native liLiaiies, 9, 12, 227
NDK (Native Development Kit), 227237
netwoik connectivity, 61, 167, 169
netwoik latency, +1
netwoik ieceiveis, 167169
notilication seivice, 212
O
OLseivei pattein, 3+, 161
onAccuiacyChangeu() methou, 190, 193
onBinu() methou, 107, 217
onClick() methou, 95
onCieate() methou, 56, S7, 93, 106, 107, 121,
123, 127, 139
onCieateOptions() methou, 156
onCieateOptionsMenu() methou, S9, 91
onDeleteu() methou, 1S2
onDestioy() methou, 106, 107, 112, 139, 1+1
onDisaLleu() methou, 1S2
onDiaw(), 19+
onEnaLleu() methou, 1S2
onHanuleIntent() methou, 206
onLocationChangeu() methou, 199, 205
onMenuOpeneu() methou, 15+, 156, 207
onOptionsItemSelecteu() methou, S9, 91, 109,
156, 207
onPause() methou, 165, 190, 193, 199
onPostExecute() methou, 67, 69
onPiogiessUpuate() methou, 67, 6S
onReceive() methou, 161, 1S2, 1S+
onResume() methou, 139, 165, 172, 190, 193
onSensoiChangeu() methou, 190, 193
onSeiviceConnecteu() methou, 223
onSeiviceDisconnecteu() methou, 223
onShaieuPieleienceChangeu() methou, 9+
onStait() methou, 190
onStaitCommanu() methou, 106, 107, 109,
112
onStop() methou, 190
onTeiminate() methou, 10+
onUpuate() methou, 1S2, 1S+
onUpgiaue() methou, 121, 123
Open Hanuset Alliance, 1, +
open souice platloim, 2
OpenGL, 9
Open]DK, 10
OpenSSL, 9
options menus, S9, 153
Oiganize Impoits tool, 62
Oveiiiue/Implement Methous, 92, 106
P
packages, 19
packaging liLiaiies, 22S
paiameteis, passing, 215
Paicel, implementing, 21S
paititions, 96
passwoiu, 9S
PATH vaiiaLle, 16
Pauseu State, 30
PenuingIntent, 209
242 | Index
peimissions
custom, 169171
ueclaiing in manilest lile, 61, 170
line anu coaise, 199
Inteinet, 61
to senu/ieceive Lioaucasts, 170
loi status upuates, 171
phishing attacks, 13
poitaLility, 2, 7
pieleiences
accessing in lile system, 9599
uiiecting usei to, 15S
initial setup, 152
location, 200
menu system, S992
oveiview, S3
piels iesouice, S+S7
PielsActivity class, S7S9
secuiity, lilesystem, 9S
shaieu, 93
piepaieu statement appioach, 127
piogiammatic usei inteilace, +S
pioject uesign, 39
PuLlish/SuLsciiLe pattein, 161
puLlisheis, 161
putExtia() methou, 166
Q
QEMU, 23
gueiy() methou, 121, 1+1, 175, 179
R
R lile, 22
ielactoiing, 39, 9+, 10+, 130135, 1S9
iegisteiing, 9+, 95, 150, 162169, 19019+,
220
RelativeLayout, 50
iemote client, 221
iemote seivices, 215
iegueiy() methou, 16+
ieguestLocationUpuates() methou, 19S
ies/layout loluei, 53
iesouices, 12, 79, 90
RGB coloi set, 77
iose wiuget, 191195
iun() methou, 113, 13+
Running State, 29, 190
S
schema, uataLase, 120
Schmiut, Eiic, 3
SDCaiu paitition, 96
SDK (Soltwaie Development Kit), 15, 19, 23,
91
secuiity, S, 61, 9S, 120, 122, 169, 227
senuBioaucast() methou, 166, 172, 209
senuTimelineNotilication() methou, 213
SensoiManagei, 190
seivices (see system seivices)
setContentView() methou, 53, 57
setDiiection() methou, 195
setInexactRepeating() methou, 211
setMyLocation() methou, 205
Settings Pioviuei, 33
setupList() methou, 15S
setViewBinuei() methou, 1+9
setViewValue() methou, 1+9
seveiity levels, log, 62
shaieu pieleiences, 93
signing, application, 12
simulatois, 23
single thieau, 65
Soltwaie Development Kit (SDK) (see SDK
(Soltwaie Development Kit))
spywaie, 13
SQL injection, 122
SQLite, 9, +2, 119
sglite3 tool, 12S
stack, 713
staitActivity() methou, 92, 152, 209
Staiting State, 29
staitManagingCuisoi() methou, 1+1, 1S0
staitSeivice() methou, 109, 209
Status activity, 202
status uata, 110, 127, 130135, 177, 1S+
status upuates
checking loi new, 110
using IntentSeivice to iun, 206
notilication ol, 163, 21221+
peimissions loi, 171
scieen, 53
senuing, 161
stoiing locally, 119
wiuget loi uisplaying, 1S11S6
status.xml, 52
StatusActivity, 52, 56, 67, 91, 105
Stoppeu State, 30
Index | 243
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>
stopSeivice() methou, 109, 16S
stiings iesouice, 55
StuL() methou, 21S, 223
suLsciiLeis, 161
system seivices
auuing anu hanuling menus, 10S
Anuioiu Seivices vs. native seivices, 32
common steps in using, 190
Compass uemo, 1S9195
cieating, 105
uelining in manilest lile, 107
intents, 20620S
location seivice, 195205
looping in, 110
notilication seivice, 212
oveiview, 101, 1S9
anu pioject uesign, 39
testing, 109, 113
T
TaLleLayout, 50
TaLleRow, 50
testing, 109, 113, 117, 22+
text piopeity, 55
TextVatchei, 70
Thieau.sleep() methou, 110, 113
thieauing, 65
timeline activity example, 1371+6, 156, 163
timeline auaptei example, 1+6150
timeline ieceiveis, 163165, 172
toggle seivice, 15+
Twittei
1+0-chaiactei countei, 7073
cieating compatiLle apps, 5661, 67, 71, 9+,
137
example ol app, 27, 3+
pulling uata liom, 105, 113116, 120, 127
anu YamLa, 37
U
UI (usei inteilace), 39
Anuioiu oLjects, 57
optimizing, S0
two ways to cieate, +7
Uniloim Resouice Iuentiliei (URI), 176
unmaishaling, 215
upuate() methou, 121, 175
upuateAppViuget() methou, 1S+
UpuateiSeivice, 105, 11+, 12+127, 162, 163,
165, 171
upuateStatus() methou, 65
URI (Uniloim Resouice Iuentiliei), 176
usei uata paitition, 96, 97
usei inteilace (see UI)
usei pieleiences (see pieleiences)
useiname, 9S
V
ViewBinuei, 1+9
views anu layouts, +S
viiuses, 13
W
.w() seveiity level, 62
wakeups, 161
VeLkit, 9
Vheie Am I? uemo, 196200
wiugets
Anuioiu UI wiugets vs. App Viugets, +9
App Viugets, 1S11S6
Compass Rose example, 191195
content pioviueis thiough, 1S11S6
impoitant piopeities ol, 5+
selection/viewing, 137, 196
anu UI sluggishness, S0
withAppenueuID() methou, 17S
wiiteToPaicel() methou, 220
.wtl() seveiity level, 62
VYSIVYG Euitoi, 75
X
XML
anuioiu: keywoiu, 90
AnuioiuManilest.xml, 21, 61, SS, 151, 163,
16S, 199
ueclaiative usei inteilace with, +7
uevelopei-liienuly view, S9
Eclipse lile naming/ienaming, 53, 79, S+
euiting options, SS
inllateu into ]ava, +S, 56
intent liltei, 151
layout coue, 21, 1+3, 1S5
main.xml, 52
manilest lile, SS, 107, 1S1, 1S6
menu iesouice, S9
menu.xml, 10S
244 | Index
loi pieleience iesouice, S6
piels.xml, 210
ies/layout/main.xml, 21, 196
ies/layout/iow.xml, 1+3
ies/layout/status.xml, 7S
ies/layout/status2.xml, 70
ies/layout/timeline.xml, 1+2
ies/layout/timelineLasic.xml, 13S
ies/layout/yamLawiuget.xml, 1S5
ies/menu/menu.xml, 91, 15+
ies/values/stiings.xml, 21, 56, 92
ies/xml/menu.xml, 207
ies/xml/piels.xml, S6, 201
ies/xml/yamLawiugetinlo.xml, 1S5
stiings, 21
stiings.xml, 152, 209
upuating uiiectly in, 76
viewing, 53, 61
Y
YamLa
application oLject, 102
opening a uataLase, 122
oveiview, 37+5
staiting, 51
upuating to use location seivice, 200202
YamLaViuget class, 1S2
Z
zeio-conliguiation uataLase, 119
Index | 245
About the Author
Marko Gargenta is the lounuei anu chiel Anuioiu expeit at Maiakana, a tiaining
company in San Fiancisco. Maiko has uevelopeu Anuioiu Bootcamp anu Anuioiu In-
teinals couises, anu has tiaineu ovei 1,000 uevelopeis on loui continents. His clients
incluue Qualcomm, Sony-Eiicsson, Motoiola, Shaip, Cisco, the US Depaitment ol
Delense, anu many moie. Maiko lieguently speaks on Anuioiu at technical conleiences
anu events, anu is the lounuei ol the San Fiancisco Anuioiu Useis Gioup.
Colophon
The animal on the covei ol Lcarning Android is a Little Owl.
The Little Owl is pait ol the taxonomic lamily Stiiguae, which is inloimally known as
typical owl oi tiue owl (the othei taxonomic lamily incluues Lain owls). Tiue to
its name, the Little Owl is small, measuiing Letween 23 anu 27.5 centimeteis in length.
It is native to the waimei aieas ol east Asia (paiticulaily Koiea), Euiope, anu Noith
Aliica anu has Leen intiouuceu anu natuializeu in Gieat Biitain anu the South Islanu
ol New Zealanu.
The Little Owl is chaiacteiizeu Ly long legs anu a iounu heau with yellow eyes anu
white eyeLiows; the eyeLiows aie saiu to give the owl a seiious expiession. The most
wiuespieau species, Athcnc noctua, is white anu speckleu Liown on top anu white-anu-
Liown stieakeu on Lottom. A species commonly lounu in the Miuule East, A. n.
|i|ith, oi the Syiian Little Owl, is a pale giayish-Liown.
The seuentaiy Little Owl typically makes its home in open countiy, such as paiklanu
anu laimlanu. It pieys on amphiLians, eaithwoims, insects, anu even smallei mammals
anu Liius; uespite its uiminutive statuie, the Little Owl is aLle to attack many game
Liius. Unlike many ol its tiue owl lamily memLeis, the Little Owl is uiuinal, oi active
uuiing the uay, uuiing which it olten peiches openly. Depenuing on the haLitat, the
Little Owl Luilus nests in clills, iocks, holes in tiees, iivei Lanks, anu Luiluings. Little
Owls that live in aieas with human activity tenu to get useu to people anu may peich
in lull view when humans aie piesent.
The covei image is liom Cassell`s Natura| History. The covei lont is AuoLe ITC Gaia-
monu. The text lont is Linotype Biika; the heauing lont is AuoLe Myiiau Conuenseu;
anu the coue lont is LucasFont`s TheSansMonoConuenseu.
D
o
w
n
l
o
a
d

f
r
o
m

W
o
w
!

e
B
o
o
k

<
w
w
w
.
w
o
w
e
b
o
o
k
.
c
o
m
>

You might also like