Android Application Development

5LFN5RJHUV-RKQ/RPEDUGR=LJXUG0HGQLHNVDQG%ODNH
0HLNH
Beijing • Cambridge • Farnham • Köln • Sebastopol • Taipei • Tokyo
Android Application Development
Ly Rick Rogeis, ]ohn LomLaiuo, Ziguiu Meunieks, anu Blake Meike
Copyiight © 2009 Rick Rogeis, ]ohn LomLaiuo, Ziguiu Meunieks, anu Blake Meike. Nll iights ieseiveu.
Piinteu in the Uniteu States ol Nmeiica.
PuLlisheu Ly O`Reilly Meuia, Inc., 1005 Giavenstein Highway Noith, SeLastopol, CN 95+72.
O`Reilly Looks may Le puichaseu loi euucational, Lusiness, oi sales piomotional use. Online euitions
aie also availaLle loi most titles (http://nysafariboo|son|inc.con). Foi moie inloimation, contact oui
coipoiate/institutional sales uepaitment: (800) 998-9938 oi corporatc¿orci||y.con.
Editor: Nnuy Oiam
Production Editor: Sumita Mukheiji
Copyeditor: Genevieve u`Entiemont
Proofreader: Saua Pieisch
Indexer: ]oe Vizua
Cover Designer: Kaien Montgomeiy
Interior Designer: Daviu Futato
Illustrator: RoLeit Romano
Printing History:
May 2009: Fiist Euition.
Nutshell HanuLook, the Nutshell HanuLook logo, anu the O`Reilly logo aie iegisteieu tiauemaiks ol
O`Reilly Meuia, Inc. Android App|ication Dcvc|opncnt, the image ol an Eastein guoll 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 authois assume
no iesponsiLility loi eiiois oi omissions, oi loi uamages iesulting liom the use ol the inloimation con-
taineu heiein.
TM
This Look uses RepKovei¹, a uuiaLle anu llexiLle lay-llat Linuing.
ISBN: 978-0-596-521+7-9
¦M¦
12+153371+
Table of Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
Part I. Development Kit Walk-Through
1. Getting to Know Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Vhy Nnuioiu? 3
The Open Hanuset Nlliance +
The Nnuioiu Execution Enviionment 5
Components ol an Nnuioiu Npplication 6
Nnuioiu Nctivity Lilecycle 8
Nnuioiu Seivice Lilecycle 10
How This Book Fits Togethei 10
2. Setting Up Your Android Development Environment . . . . . . . . . . . . . . . . . . . . . . . . . 13
Setting Up Youi Development Enviionment 13
Cieating an Nnuioiu Development Enviionment 1+
Hello, Nnuioiu 18
Vheie Ve`ie Going 18
Staiting a New Nnuioiu Npplication: HelloVoilu 18
Viiting HelloVoilu 22
Running HelloVoilu 2+
3. Using the Android Development Environment for Real Applications . . . . . . . . . . . . 27
Micio]oLs: This Book`s Main Sample Npplication 27
Nnuioiu anu Social Netwoiking 27
Downloauing the M]Nnuioiu Coue 30
N Biiel Toui ol the M]Nnuioiu Coue 30
The Pioject Root Foluei (M]Nnuioiu) 30
The Souice Foluei (sic) 31
The Resouice Foluei (ies) 32
Fiist Steps: Builuing anu Running the Micio]oLs Npplication 33
iii
N Veiy Shoit Toui ol the Nnuioiu SDK/Eclipse IDE 33
Loauing anu Staiting the Npplication 35
Digging a Little Deepei: Vhat Can Go Viong? 36
Running an Npplication on the T-MoLile Phone 39
Summaiy +1
4. Under the Covers: Startup Code and Resources in the MJAndroid Application . . . . 43
Initialization Paiameteis in NnuioiuManilest.xml ++
Initialization in Micio]oLs.java +6
Moie Initialization ol Micio]oLs.java 52
Summaiy 56
5. Debugging Android Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
The Tools 57
Eclipse ]ava Euitoi 58
]ava Eiiois 58
The DeLuggei 6+
Logcat 67
Nnuioiu DeLug Biiuge (auL) 71
DDMS: Dalvik DeLug Monitoi Seivice 7+
Tiaceview 75
Summaiy 80
6. The ApiDemos Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Npplication Setup in the Manilest File 81
Finuing the Souice to an Inteiesting Example 83
Custom Title Demo 83
Linkily Demo 8+
Nuuing Youi Own Examples to NpiDemos 8+
7. Signing and Publishing Your Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Test Youi Npplication 88
Nttach an Enu Usei License Ngieement Il Desiieu 89
Cieate anu Nttach an Icon anu LaLel 89
Clean Up loi Release 90
Veision Youi Npplication 90
OLtaining a Signing Ceitilicate anu NPI Key 90
Getting a Signing Ceitilicate loi an Npplication You Nie Going to Ship 91
Getting a Signing Ceitilicate Vhile DeLugging 93
Signing Youi Npplication 95
Retesting Youi Npplication 96
PuLlishing on Nnuioiu Maiket 96
Signing Up Ns an Nnuioiu Developei 96
iv | Table of Contents
Uploauing Youi Npplication 96
Part II. Programming Topics
8. Persistent Data Storage: SQLite Databases and Content Providers . . . . . . . . . . . . . 101
DataLases 101
Basic Stiuctuie ol the Micio]oLsDataLase Class 102
Reauing Data liom the DataLase 107
Mouilying the DataLase 110
Content Pioviueis 11+
Intiouucing NotePau 116
Content Pioviueis 118
Consuming a Content Pioviuei 129
9. Location and Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Location-Baseu Seivices 137
Mapping 139
The Google Maps Nctivity 139
The MapView anu MapNctivity 1+0
Voiking with MapViews 1+0
MapView anu MyLocationOveilay Initialization 1+1
Pausing anu Resuming a MapNctivity 1++
Contiolling the Map with Menu Buttons 1+5
Contiolling the Map with the KeyPau 1+7
Location Vithout Maps 1+8
The Manilest anu Layout Files 1+8
Connecting to a Location Pioviuei anu Getting Location Upuates 1+9
Upuating the Emulateu Location 152
10. Building a View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Nnuioiu GUI Nichitectuie 157
The Mouel 157
The View 158
The Contiollei 159
Putting It Togethei 159
NssemLling a Giaphical Inteilace 161
Viiing Up the Contiollei 166
Listening to the Mouel 168
Listening loi Touch Events 173
Listening loi Key Events 176
Nlteinative Vays to Hanule Events 177
Nuvanceu Viiing: Focus anu Thieauing 179
Table of Contents | v
The Menu 183
11. A Widget Bestiary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Nnuioiu Views 188
TextView anu EuitText 188
Button anu ImageButton 191
Nuapteis anu NuapteiViews 192
CheckBoxes, RauioButtons, anu Spinneis 193
ViewGioups 198
Galleiy anu GiiuView 198
ListView anu ListNctivity 202
SciollView 20+
TaLHost 205
Layouts 208
Fiame Layout 209
LineaiLayout 209
TaLleLayout 213
NLsoluteLayout 215
RelativeLayout 216
12. Drawing 2D and 3D Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Rolling Youi Own Viugets 221
Layout 222
Canvas Diawing 226
DiawaLles 237
Bitmaps 2+2
Bling 2+3
Shauows, Giauients, anu Filteis 2+6
Nnimation 2+7
OpenGL Giaphics 252
13. Inter-Process Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
Intents: Simple, Low-Oveiheau IPC 258
Intent OLjects Useu in Intei-Piocess Communication 258
Nctivity OLjects anu Navigating the Usei Inteilace Hieiaichy 259
Example: Nn Intent to Pick How Ve Say ¨Hello Voilu¨ 259
Getting a Result via Intei-Piocess Communication 262
Remote Methous anu NIDL 265
Nnuioiu Inteilace Delinition Language 266
Classes Unueilying NIDL-Geneiateu Inteilaces 270
PuLlishing an Inteilace 273
Nnuioiu IPC Compaieu with ]ava Native Inteilace (]NI) 27+
Vhat Binuei Doesn`t Do 275
vi | Table of Contents
Binuei anu Linux 275
14. Simple Phone Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Quick anu Easy Phone Calls 277
Cieating an Example Npplication to Run the call Methou 278
EmLeuuing the Coue Snippet in a Simple Npplication 279
Exploiing the Phone Coue Thiough the DeLuggei 280
Cieating an Instance ol an Intent 282
Nuuing Data to an Instance ol an Intent 283
Initiating a Phone Call 28+
Exception Hanuling 28+
Nnuioiu Npplication-Level Mouulaiity anu Telephony 285
15. Telephony State Information and Android Telephony Classes . . . . . . . . . . . . . . . . 287
Opeiations Olleieu Ly the anuioiu.telephony Package 287
Package Summaiy 288
Limitations on Vhat Npplications Can Do with the Phone 288
Example: Deteimining the State ol a Call 289
Nnuioiu Telephony Inteinals 291
Intei-Piocess Communication anu NIDL in the
anuioiu.inteinal.telephony Package 291
The anuioiu.inteinal.telephony Package 292
The anuioiu.inteinal.telephony.gsm Package 295
Exploiing Nnuioiu Telephony Inteinals 299
Nnuioiu anu VoIP 302
Appendix: Wireless Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
Table of Contents | vii
Preface
Vhen Google announceu the uevelopment ol Nnuioiu, the lielu ol moLile platloims
was alieauy well estaLlisheu. Even in the naiiowei categoiy ol open souice platloims,
a numLei ol viaLle alteinatives weie Leing pusheu Ly pioponents. Yet Nnuioiu has
stimulateu not only wiuespieau technical inteiest Lut iampant speculation aLout its
potential to completely tiansloim the woilu ol the peisonal uevice. Insteau ol a con-
venient piop to suppoit a set ol lamiliai lunctions, such as phone calls, email, anu
iestauiant lookups, the electionic uevice coulu Lecome an open-enueu winuow into
the whole woilu÷coulu Lecome, in shoit, anything that the usei anu the uevelopei
coulu think to make it.
How much ol the cogent analysis anu leiviu hype will come to pass can Le uiscusseu
elsewheie; this Look is loi those who want to get to know the piogiamming enviion-
ment loi Nnuioiu anu leain what they themselves can uo to make a uilleience. Ve have
spent many giueling months investigating the souice coue ovei multiple ieleases anu
tiying out the lunctions ol the liLiaiy anu uevelopment kit. Ve have Leen woiking haiu
to uncovei the tiue Nnuioiu, going Leyonu any uocumentation we coulu linu online
oi in piint.
This Look, ieau caielully, can enaLle any ]ava piogiammei to uevelop uselul anu ioLust
applications loi Nnuioiu. It also takes you into the inteinals in some places, so you
know how Nnuioiu suppoits what you`ie uoing÷anu so you can play aiounu with its
open souice coue il you like.
Audience
This Look is intenueu loi expeiienceu soltwaie uevelopeis who want to uevelop ap-
plications in the Nnuioiu moLile enviionment. It assumes you have some expeiience
with the ]ava piogiamming language, with using ]ava to implement usei inteilaces,
anu that you aie at least lamiliai with the technologies Nnuioiu uses, such as XML,
SQL, GTalk(XMPP), OpenGL-ES, anu HTTP.
ix
How This Book Is Organized
This Look is oiganizeu aiounu the coie example piogiam intiouuceu in Chaptei 2.
Latei chapteis illustiate uevelopment technigues Ly auuing to the example thiough
implementing mouulai extensions, wheie this is leasiLle. Some chapteis (anu the Np-
penuix) covei moie auvanceu topics that aie not ieguiieu loi many applications.
Pait I, Dcvc|opncnt Kit Wa||-Through, gets you staiteu with the Lasics you`ll neeu to
wiite applications.
Chaptei 1, Gctting to Know Android, explains Nnuioiu`s place in the maiket anu its
Lasic aichitectuie.
Chaptei 2, Sctting Up Your Android Dcvc|opncnt Environncnt, tells you how to uown-
loau the soltwaie you neeu, incluuing Eclipse anu the Nnuioiu plug-in, anu how to get
staiteu piogiamming.
Chaptei 3, Using thc Android Dcvc|opncnt Environncnt for Rca| App|ications, uesciiLes
the liles that make up a typical Nnuioiu piogiam.
Chaptei +, Undcr thc Covcrs: Startup Codc and Rcsourccs in thc MjAndroid App|ica-
tion, looks at the lunuamental ]ava coue anu XML iesouices that eveiy application
neeus.
Chaptei 5, Dcbugging Android App|ications, intiouuces a numLei ol tools loi ueLugging
anu peiloimance, incluuing Eclipse, logs, the Nnuioiu DeLug Biiuge (adb), DDMS, anu
Tiaceview.
Chaptei 6, Thc ApiDcnos App|ication, olleis a high-level toui ol the sample Nnuioiu
coue incluueu in the toolkit, with tips loi exploiing it youisell.
Chaptei 7, Signing and Pub|ishing Your App|ication, shows you how to make youi ap-
plication ieauy loi puLlic use.
Pait II, Progranning Topics, exploies in uepth the majoi liLiaiies you`ll neeu, anu
shows you how to use them ellectively.
Chaptei 8, Pcrsistcnt Data Storagc: SQLitc Databascs and Contcnt Providcrs, shows
how to use the two most poweilul means in Nnuioiu loi stoiing anu seiving uata.
Chaptei 9, Location and Mapping, shows how to ueteimine anu uisplay the usei`s lo-
cation, anu how to use Google Maps.
Chaptei 10, Bui|ding a \icw, intiouuces giaphical piogiamming on Nnuioiu Ly ex-
plaining how to cieate anu manipulate winuows anu views.
Chaptei 11, A Widgct Bcstiary, coveis the most populai anu uselul giaphical inteilace
elements pioviueu Ly Nnuioiu.
Chaptei 12, Drawing 2D and 3D Graphics, shows how to lay out giaphics, anu uelves
into uiawing, tiansloiming, anu animating youi own giaphics.
x | Preface
Chaptei 13, |ntcr-Proccss Connunication, coveis Intents anu Remote Methous, which
allow you to access the lunctionality ol othei applications.
Chaptei 1+, Sinp|c Phonc Ca||s, shows how to uial a numLei liom an application, anu
explains how Nnuioiu caiiies out the ieguest.
Chaptei 15, Tc|cphony Statc |nfornation and Android Tc|cphony C|asscs, shows how
to get inloimation aLout telephony seivice anu phone calls, anu olleis a toui ol tel-
ephony inteinals.
Nppenuix, Wirc|css Protoco|s, olleis some Lackgiounu anu histoiy on wiieless seivices.
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, uataLases, uata types, enviionment vaiiaLles,
statements, anu keywoius.
Constant width bold
Shows commanus oi othei text that shoulu Le typeu liteially Ly the usei.
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
Preface | xi
ieguiie peimission. Nnsweiing 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. Nn attiiLution usually incluues the title,
authoi, puLlishei, anu ISBN. Foi example: ¨Android App|ication Dcvc|opncnt Ly Rick
Rogeis, ]ohn LomLaiuo, Ziguiu Meunieks, anu Blake Meike. Copyiight 2009 Rick
Rogeis, ]ohn LomLaiuo, Ziguiu Meunieks, anu Blake Meike, 978-0-596-521+7-9.¨
Il you leel youi use ol coue examples lalls outsiue laii use oi the peimission given heie,
leel liee to contact us at pcrnissions¿orci||y.con.
Safari® Books Online
Vhen you see a Salaii® Books Online icon on the covei ol youi lavoiite
technology Look, that means the Look is availaLle online thiough the
O`Reilly Netwoik Salaii Bookshell.
Salaii olleis a solution that`s Lettei than e-Looks. It`s a viitual liLiaiy that lets you easily
seaich thousanus ol top tech Looks, cut anu paste coue samples, uownloau chapteis,
anu linu guick answeis when you neeu the most accuiate, cuiient inloimation. Tiy it
loi liee at http://ny.safariboo|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, CN 95+72
800-998-9938 (in the Uniteu States oi Canaua)
707-829-0515 (inteinational oi local)
707-829-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://www.orci||y.con/cata|og/978059ó521179
To comment oi ask technical guestions aLout this Look, senu email to:
boo|qucstions¿orci||y.con
Foi moie inloimation aLout oui Looks, conleiences, Resouice Centeis, anu the
O`Reilly Netwoik, see oui weLsite at:
http://www.orci||y.con
xii | Preface
Acknowledgments
Ve`u like to thank Bill Dimmick, Biau O`Heaine, anu Hycel Tayloi loi theii thoughtlul
anu caielul ieviews ol this Look unuei a high-piessuie timeline.
Rick Rogers
Like anything woith uoing, I suppose, this Look enueu up taking moie time anu elloit
than any ol us planneu in the Leginning. I`u like to thank my coauthois anu the gieat
lolks at O`Reilly loi sticking with it anu Liinging the woik to liuition, thiough all the
twists anu tuins. I`u also like to thank my lamily anu liienus, who encouiageu me all
thiough the piocess, anu lent an eai when I just neeueu to talk. Most especially, though,
I want to ueuicate the Look to my wile, Susie, whose patience knows no Lounus, anu
whose amazing attituue towaiu lile is an enuuiing inspiiation loi me no mattei what
I`m uoing.
John Lombardo
I woulu like to thank my wonueilul wile, Dena, who kept lile liom inteileiing when I
closeu the ollice uooi to woik on the Look. I want to ueuicate this Look to my mothei,
Maigueiite Megaiis, who uieu suuuenly in 2007. I gave hei a copy ol my liist Look,
Enbcddcd Linux (New Riueis), Lack in 2001. She ciackeu it open to a page with some
assemLly coue, lookeu at it loi aLout 10 seconus, closeu it, anu saiu, ¨That`s nice, ueai.¨
Ve hau a goou laugh ovei that. I`u also like to thank all the wonueilul people at O`Reilly
loi all theii haiu woik. I`u especially like to thank Nnuy Oiam, who couuleu anu
piouueu us in just the iight uoses to keep the Look humming along at a goou clip.
Zigurd Mednieks
Thanks to Teiiy, Maija, anu Chailes loi putting up with my scheuule while I was wiit-
ing, anu to Nnuy Oiam anu my coauthois loi letting me paiticipate, anu hopelully,
contiiLute.
Blake Meike
I am veiy giatelul to have Leen inviteu to woik with such an amazing gioup ol people.
Thanks to Ziguiu loi suggesting it; Nnuy Oiam loi piactically holuing my pen; anu
Rick, ]ohn, anu IsaLel Kunkle loi making those Thuisuay moining calls a pleasuie.
Thanks to Mike Moiton loi actually ieauing Loth the text anu the coue. Though it may
seem oLvious, thanks to the Google Nnuioiu uevelopeis. Not Lau guys. Not Lau at all.
Finally, love anu thanks to my wile, Catheiine, who nevei let me see any uisappoint-
ment when I saiu, yet again, ¨Can`t. Gotta woik on the Look this weekenu.¨ Yes, LaLe,
let`s uo the Lookcase now.
Preface | xiii
PART I
Development Kit Walk-Through
This Look gets you staiteu with Nnuioiu. Ve`ll explain what`s special aLout Nnuioiu`s
leatuies anu how its aichitectuie achieves its goals, anu show you how to get staiteu
piogiamming. You`ll leain the tools that let you wiite piogiams using Eclipse; iun them
on the Nnuioiu emulatoi; anu caiiy out ueLugging, tiacing, anu pioliling. The last
chaptei in Pait 1 shows you how to sign youi piogiam loi puLlic uistiiLution.
CHAPTER 1
Getting to Know Android
Why Android?
Google`s Nnuioiu moLile phone soltwaie platloim may Le the next Lig oppoitunity loi
application soltwaie uevelopeis.
Google announceu the Open Hanuset Nlliance anu the Nnuioiu platloim in NovemLei
ol 2007, ieleasing the liist Leta veision ol the Nnuioiu Soltwaie Development Kit (SDK)
at the same time. Vithin a mattei ol a lew months, ovei 1 million people hau uown-
loaueu veisions ol the SDK liom Google`s weLsite. In the Uniteu States, T-MoLile
announceu the G1 Nnuioiu moLile phone in OctoLei ol 2008, anu estimates aie that
seveial hunuieu thousanu G1s weie solu Leloie the enu ol that yeai. Theie aie alieauy
seveial competing moLile phone soltwaie stacks in the maiket, so why is theie such
inteiest in Nnuioiu?
Nnuioiu has the potential loi iemoving the Laiiieis to success in the uevelopment anu
sale ol a new geneiation ol moLile phone application soltwaie. ]ust as the the stanu-
aiuizeu PC anu Macintosh platloims cieateu maikets loi uesktop anu seivei soltwaie,
Nnuioiu, Ly pioviuing a stanuaiu moLile phone application enviionment, will cieate
a maiket loi moLile applications÷anu the oppoitunity loi applications uevelopeis to
piolit liom those applications.
Vhy hasn`t it Leen piolitaLle to uevelop moLile applications loi smaitphones until
now? Nnu what aie the pioLlems that Nnuioiu alleviates?
Iragncntation
NLout 70 million smaitphones weie solu in 2007, so theie aie a lot ol phones
availaLle to iun applications, Lut each Lianu has a uilleient application enviion-
ment. This is paiticulaily tiue ol Linux-Laseu phones, wheie each hanuset venuoi
has hau to assemLle scoies ol pieces ol thiiu-paity soltwaie to cieate a viaLle moLile
phone platloim. Theie is no chance that they woulu all choose the same compo-
nents to Luilu a moLile smaitphone.
3
]ava was supposeu to help this situation, with ]2ME anu the wiieless ]ava iecom-
menuations (CDC, CLDC, MIDP, ]TVI, MSN, etc.) pioviuing a common
applications enviionment acioss hanusets. Unloitunately, almost eveiy hanuset
that suppoits ]2ME also suppoit venuoi-piopiietaiy extensions that limit the poit-
aLility ol applications.
Proprictary softwarc stac|s
Most existing smaitphones use piopiietaiy, ielatively closeu soltwaie stacks, such
as Nokia`s Seiies 60 with the SymLian opeiating system, oi Miciosolt`s Vinuows
MoLile. Mouilications to these stacks (auuing a uiivei, loi example) have to Le
uone eithei Ly the stack ownei oi Ly the hanuset manulactuiei. The stacks aie not
open souice, so changing anything in the stack is uillicult at Lest. Most Linux-
Laseu phones to uate have an open souice keinel (as ieguiieu Ly the GPL license),
Lut keep othei uetails ol the soltwaie stack (application liamewoik, multimeuia
liamewoik, applications) piopiietaiy.
C|oscd nctwor|s
Seiies 60 anu Vinuows MoLile uo allow the auuition ol thiiu-paity applications,
Lut moLile opeiatois olten lock the hanusets so applications cannot Le auueu. The
opeiatois claim this is neeueu to pieseive the integiity ol theii moLile netwoiks,
making suie that viiuses anu spam aie not inauveitently installeu Ly enu useis. It
also suits the opeiatoi`s Lusiness mouel, Lecause theii moLile phone customeis
aie conlineu to the opeiatois` ¨walleu gaiuen¨ ol applications, Loth on the phone
anu in the netwoik. Nnuioiu incluues an open catalog ol applications, Nnuioiu
Maiket, that useis can uownloau ovei the aii to theii Nnuioiu phones. It also allows
uiiect loauing ol applications via USB connection.
Nnuioiu gives uevelopeis a way to uevelop unigue, cieative applications anu get those
applications in the hanus ol customeis. Hunuieus ol thousanus ol Nnuioiu moLile
phone useis aie alieauy theie, looking loi the next clevei oi uselul application, anu that
application coulu Le youis.
The Open Handset Alliance
Google anu 33 othei companies announceu the loimation ol the Open Hanuset Nlli-
ance on NovemLei 5, 2007. Nccoiuing to the joint piess ielease liom that uay:
This alliance shaies a common goal ol losteiing innovation on moLile uevices anu giving
consumeis a lai Lettei usei expeiience than much ol what is availaLle on touay`s moLile
platloims. By pioviuing uevelopeis a new level ol openness that enaLles them to woik
moie collaLoiatively, Nnuioiu will acceleiate the pace at which new anu compelling
moLile seivices aie maue availaLle to consumeis.
Foi us as moLile application uevelopeis, that means we aie liee to uevelop whatevei
cieative moLile applications we can think ol, liee to maiket them (oi give them, at oui
option) to Nnuioiu moLile phone owneis, anu liee to piolit liom that elloit any way
4 | Chapter 1:ಗGetting to Know Android
we can. Each memLei ol the Open Hanuset Nlliance has its own ieasons loi paitici-
pating anu contiiLuting its intellectual piopeity, anu we aie liee to Lenelit.
The Open Hanuset Nlliance integiates contiiLuteu soltwaie anu othei intellectual
piopeity liom its memLei companies anu makes it availaLle to uevelopeis thiough the
open souice community. Soltwaie is licenseu thiough the Npache V2 license, which
you can see at http://www.apachc.org/|iccnscs/L|CENSE-2.0.txt. Use ol the Npache li-
cense is ciitical, Lecause it allows hanuset manulactuieis to take Nnuioiu coue, mouily
it as necessaiy, anu then eithei keep it piopiietaiy oi ielease it Lack to the open souice
community, at theii option. The oiiginal Nlliance memLeis incluue hanuset manulac-
tuieis (HTC, LG, Motoiola, Samsung), moLile opeiatois (China MoLile Communica-
tions, KDDI, DoCoMo, Spiint/Nextel, T-MoLile, Telecom Italia, Telelonica),
semiconuuctoi companies (Nuuience, Bioaucom, Intel, Maivell, NViuia Qualcomm,
SiRF, Synaptics), soltwaie companies (Nscenuei, eBay, esmeitec, Google, LivingImage,
LiveViie, Nuance, Packet Viueo, SkyPop, SONiVOX), anu commeicialization com-
panies (Nplix, Nosei, TNT, Vinu Rivei). The Nlliance incluues the majoi paitneis
neeueu to uelivei a platloim loi moLile phone applications in all ol the majoi
geogiaphies.
The Nlliance ieleases soltwaie thiough Google`s uevelopei weLsite (http://dcvc|opcr
.android.con). The Nnuioiu SDK loi use Ly application soltwaie uevelopeis can Le
uownloaueu uiiectly liom that weLsite. (The Nnuioiu Platloim Poiting Kit loi use Ly
hanuset manulactuieis who want to poit the Nnuioiu platloim to a hanuset uesign is
not coveieu in this Look.)
The Android Execution Environment
Npplications in Nnuioiu aie a Lit uilleient liom what you may Le useu to in the uesktop
anu seivei enviionments. The uilleiences aie uiiven Ly a lew key concepts unigue to
the moLile phone enviionment anu unigue to Google`s intentions loi Nnuioiu. Ns you
wiite applications loi an Nnuioiu hanuset, you will use these concepts to guiue the
uesign anu implementation ol the application:
Linitcd rcsourccs
MoLile phones touay aie veiy poweilul hanuhelu computeis, Lut they aie still
limiteu. The lunuamental limitation ol a moLile uevice is Latteiy capacity. Eveiy
clock tick ol the piocessoi, eveiy ieliesh ol memoiy, eveiy Lacklit pixel on the
usei`s scieen takes eneigy liom the Latteiy. Batteiy size is limiteu, anu useis uon`t
like lieguent Latteiy chaiging. Ns a iesult, the computing iesouices aie limiteu÷
clock iates aie in the hunuieus ol MHz, memoiy is at Lest a lew gigaLytes, uata
stoiage is at Lest a lew tens ol gigaLytes. Thioughout this Look we will talk aLout
the mechanisms incluueu in Nnuioiu to optimize loi these limiteu iesouices.
The Android Execution Environment | 5
Mobi|c nashups
In the uesktop Inteinet woilu, mashups make it veiy easy to cieate new applications
Ly ieusing the uata anu usei inteilace elements pioviueu Ly existing applications.
Google Maps is a gieat example: you can easily cieate a weL-Laseu application that
incoipoiates maps, satellite imageiy, anu tiallic upuates using just a lew lines ol
]avaSciipt on youi own weL page. Nnuioiu extenus that concept to the moLile
phone. In othei moLile enviionments, applications aie sepaiate, anu with the ex-
ception ol Liowsei-Laseu applications, you aie expecteu to coue youi applications
sepaiately liom the othei applications that aie iunning on the hanuset. In Nnuioiu
you can easily cieate new applications that incoipoiate existing applications.
Chaptei 13 locuses on these moLile mashups.
|ntcrchangcab|c app|ications
In othei moLile soltwaie enviionments, applications aie coueu to access uata liom
specilic uata pioviueis. Il you neeu to senu an email liom a Vinuows MoLile ap-
plication, loi example, you coue explicit ieleiences to Pocket Outlook`s email in-
teilace, anu senu the email that way. But what il the usei wants to use anothei
email client?
Nnuioiu incoipoiates a lunuamental mechanism (Intents) that is inuepenuent ol
specilic application implementations. In an Nnuioiu application, you uon`t say you
want to senu email thiough a specilic application; insteau, you say you want to
senu an email thiough whatevei application is availaLle. The opeiating system
takes caie ol liguiing out what application can senu emails, staits that application
il neeueu, anu connects youi ieguest so the email can Le sent. The usei can suL-
stitute uilleient Liowseis, uilleient MP3 playeis, oi uilleient email clients at will,
anu Nnuioiu auapts automatically.
Components of an Android Application
Youi Nnuioiu applications will Le Luilt liom loui Lasic component types that aie ue-
lineu Ly the Nnuioiu aichitectuie:
Activitics
These aie compaiaLle to stanualone utilities on uesktop systems, such as ollice
applications. Nctivities aie pieces ol executaLle coue that come anu go in time,
instantiateu Ly eithei the usei oi the opeiating system anu iunning as long as they
aie neeueu. They can inteiact with the usei anu ieguest uata oi seivices liom othei
activities oi seivices via gueiies oi Intents (uiscusseu in a moment).
Most ol the executaLle coue you wiite loi Nnuioiu will execute in the context ol
an Nctivity. Nctivities usually coiiesponu to uisplay scieens: each Nctivity shows
one scieen to the usei. Vhen it is not actively iunning, an Nctivity can Le killeu Ly
the opeiating system to conseive memoiy.
6 | Chapter 1:ಗGetting to Know Android
Scrviccs
These aie analogous to seivices oi uaemons in uesktop anu seivei opeiating sys-
tems. They aie executaLle pieces ol coue that usually iun in the Lackgiounu liom
the time ol theii instantiation until the moLile hanuset is shut uown. They geneially
uon`t expose a usei inteilace.
The classic example ol a Seivice is an MP3 playei that neeus to keep playing gueueu
liles, even while the usei has gone on to use othei applications. Youi application
may neeu to implement Seivices to peiloim Lackgiounu tasks that peisist without
a usei inteilace.
Broadcast and |ntcnt Rcccivcrs
These iesponu to ieguests loi seivice liom anothei application. N Broadcast
Rcccivcr iesponus to a system-wiue announcement ol an event. These announce-
ments can come liom Nnuioiu itsell (e.g., Latteiy low) oi liom any piogiam iun-
ning on the system. Nn Nctivity oi Seivice pioviues othei applications with access
to its lunctionality Ly executing an |ntcnt Rcccivcr, a small piece ol executaLle coue
that iesponus to ieguests loi uata oi seivices liom othei activities. The ieguesting
(client) activity issues an Intent, leaving it up to the Nnuioiu liamewoik to liguie
out which application shoulu ieceive anu act on it.
Intents aie one ol the key aichitectuial elements in Nnuioiu that lacilitate the cie-
ation ol new applications liom existing applications (moLile mashups). You will
use Intents in youi application to inteiact with othei applications anu seivices that
pioviue inloimation neeueu Ly youi application. Intents anu Intent Receiveis aie
coveieu in moie uetail in Chaptei 13.
Contcnt providcrs
These aie cieateu to shaie uata with othei activities oi seivices. N content pioviuei
uses a stanuaiu inteilace in the loim ol a URI to lullill ieguests loi uata liom othei
applications that may not even know which content pioviuei they aie using. Foi
example, when an application issues a gueiy loi Contact uata, it auuiesses the
gueiy to a URI ol the loim:
content://contacts/people
The opeiating system looks to see which applications have iegisteieu themselves
as content pioviueis loi the given URI, anu senus the ieguest to the appiopiiate
application (staiting the application il it is not alieauy iunning). Il theie is moie
than one content pioviuei iegisteieu loi the ieguesteu URI, the opeiating system
asks the usei which one he wants to use.
Nn application uoesn`t have to use all ol the Nnuioiu components, Lut a well-wiitten
application will make use ol the mechanisms pioviueu, iathei than ieinventing lunc-
tionality oi haiucouing ieleiences to othei applications. URIs anu Intents togethei al-
low Nnuioiu to pioviue a veiy llexiLle usei enviionment. Npplications can Le easily
auueu, ueleteu, anu suLstituteu, anu the loose coupling ol intents anu URIs keeps
eveiything woiking togethei.
Components of an Android Application | 7
Android Activity Lifecycle
Nnuioiu is uesigneu aiounu the unigue ieguiiements ol moLile applications. In pai-
ticulai, Nnuioiu iecognizes that iesouices (memoiy anu Latteiy, loi example) aie limi-
teu on most moLile uevices, anu pioviues mechanisms to conseive those iesouices. The
mechanisms aie eviuent in the Nnuioiu Nctivity Lilecycle, which uelines the states oi
events that an activity goes thiough liom the time it is cieateu until it linishes iunning.
The lilecycle is shown uiagiammatically in Figuie 1-1.
Youi activity monitois anu ieacts to these events Ly instantiating methous that oveiiiue
the Nctivity class methous loi each event:
onCreate
Calleu when youi activity is liist cieateu. This is the place you noimally cieate youi
views, open any peisistent uataliles youi activity neeus to use, anu in geneial ini-
tialize youi activity. Vhen calling onCreate, the Nnuioiu liamewoik is passeu a
Bundle oLject that contains any activity state saveu liom when the activity ian
Leloie.
Start activity
User navigates
back to activity
Process is killed
Activity comes
to foreground
Activity no longer visible
NO
YES
Activity interacts
with user
Activity becomes
visible
Activity exits
onCreate()
onStart()
In foreground?
onResume()
onPause()
onStop()
onDestroy()
onRestart()
Iigurc 1-1. Android Activity |ifccyc|c
8 | Chapter 1:ಗGetting to Know Android
onStart
Calleu just Leloie youi activity Lecomes visiLle on the scieen. Once onStart com-
pletes, il youi activity can Lecome the loiegiounu activity on the scieen, contiol
will tianslei to onResume. Il the activity cannot Lecome the loiegiounu activity loi
some ieason, contiol tiansleis to the onStop methou.
onResume
Calleu iight altei onStart il youi activity is the loiegiounu activity on the scieen.
Nt this point youi activity is iunning anu inteiacting with the usei. You aie ieceiving
keyLoaiu anu touch inputs, anu the scieen is uisplaying youi usei inteilace.
onResume is also calleu il youi activity loses the loiegiounu to anothei activity, anu
that activity eventually exits, popping youi activity Lack to the loiegiounu. This is
wheie youi activity woulu stait (oi iesume) uoing things that aie neeueu to upuate
the usei inteilace (ieceiving location upuates oi iunning an animation, loi
example).
onPause
Calleu when Nnuioiu is just aLout to iesume a uilleient activity, giving that activity
the loiegiounu. Nt this point youi activity will no longei have access to the scieen,
so you shoulu stop uoing things that consume Latteiy anu CPU cycles unnecessa-
iily. Il you aie iunning an animation, no one is going to Le aLle to see it, so you
might as well suspenu it until you get the scieen Lack. Youi activity neeus to take
auvantage ol this methou to stoie any state that you will neeu in case youi activity
gains the loiegiounu again÷anu it is not guaianteeu that youi activity will iesume.
Il the moLile uevice you aie iunning on iuns out ol memoiy, theie is no viitual
memoiy on uisk to use loi expansion, so youi activity may have to make way loi
a system piocess that neeus memoiy. Once you exit this methou, Nnuioiu may kill
youi activity at any time without ietuining contiol to you.
onStop
Calleu when youi activity is no longei visiLle, eithei Lecause anothei activity has
taken the loiegiounu oi Lecause youi activity is Leing uestioyeu.
onDestroy
The last chance loi youi activity to uo any piocessing Leloie it is uestioyeu. Noi-
mally you`u get to this point Lecause the activity is uone anu the liamewoik calleu
its finish methou. But as mentioneu eailiei, the methou might Le calleu Lecause
Nnuioiu has ueciueu it neeus the iesouices youi activity is consuming.
It is impoitant to take auvantage ol these methous to pioviue the Lest usei expeiience
possiLle. This is the liist place in this Look we`ve uiscusseu how piogiamming loi
moLile uevices is uilleient liom piogiamming loi uesktop uevices, anu theie will Le
many moie such places as you go thiough latei chapteis. Youi useis will appieciate it
il you wiite youi activities with the activity lilecycle in minu, anu you will ultimately
Lenelit.
Android Activity Lifecycle | 9
Android Service Lifecycle
The lilecycle loi a seivice is similai to that loi an activity, Lut uilleient in a lew impoitant
uetails:
onCreate anu onStart uilleiences
Seivices can Le staiteu when a client calls the Context.startService(Intent)
methou. Il the seivice isn`t alieauy iunning, Nnuioiu staits it anu calls its
onCreate methou lolloweu Ly the onStart methou. Il the seivice is alieauy iunning,
its onStart methou is invokeu again with the new intent. So it`s guite possiLle anu
noimal loi a seivice`s onStart methou to Le calleu iepeateuly in a single iun ol the
seivice.
onResume, onPause, anu onStop aie not neeueu
Recall that a seivice geneially has no usei inteilace, so theie isn`t any neeu loi the
onPause, onResume, oi onStop methous. Vhenevei a seivice is iunning, it is always
in the Lackgiounu.
onBind
Il a client neeus a peisistent connection to a seivice, it can call the Context.bind
Service methou. This cieates the seivice il it is not iunning, anu calls onCreate Lut
not onStart. Insteau, the onBind methou is calleu with the client`s intent, anu it
ietuins an IBind oLject that the client can use to make luithei calls to the seivice.
It`s guite noimal loi a seivice to have clients staiting it anu clients Lounu to it at
the same time.
onDestroy
Ns with an activity, the onDestroy methou is calleu when the seivice is aLout to Le
teiminateu. Nnuioiu will teiminate a seivice when theie aie no moie clients staiting
oi Lounu to it. Ns with activities, Nnuioiu may also teiminate a seivice when
memoiy is getting low. Il that happens, Nnuioiu will attempt to iestait the seivice
when the memoiy piessuie passes, so il youi seivice neeus to stoie peisistent in-
loimation loi that iestait, it`s Lest to uo so in the onStart methou.
How This Book Fits Together
Nnuioiu is a sophisticateu platloim whose paits all woik togethei: uiawing anu layout,
intei-piocess communication anu uata stoiage, seaich anu location. Intiouucing it in
pieces is a challenge, Lut we`ve enteitaineu the conceit ol intiouucing the complexities
ol the platloim in a lineai oiuei.
The platloim is also so iich that we can`t hope to show you how to use eveiything you
want, oi even a laige suLset ol its capaLilities. Ve expect you to consult the ollicial
uocumentation while ieauing this Look anu tiying the examples. You shoulu also use
othei online iesouices÷Lut Le caielul aLout weL pages oi loium postings that have
10 | Chapter 1:ಗGetting to Know Android
Leen aiounu a while, Lecause inteilaces change. Theie is also a suLstantial amount ol
misinloimation out on the VeL; we uiscoveieu scaus ol it while wiiting the Look.
This Look is wiitten loi expeiienceu uevelopeis who want to guickly leain what they
neeu to know to Luilu Nnuioiu applications. The Look is wiitten with ieleiences to an
example application (M]Nnuioiu, uiscusseu in much moie uetail in the next chaptei)
that you can lieely uownloau anu ieuse. The majoi topics coveieu in the Look incluue:
Ncw Android conccpts
Nnuioiu Luilus upon a lot ol legacy technology (]ava, Linux, anu the Inteinet, just
to name a lew), Lut it also intiouuces some new concepts neeueu to enaLle the
application enviionment.
Android dcvc|opncnt cnvironncnt
Ve`ll show how to install the liee, open souice Nnuioiu uevelopment enviionment
on youi own system, anu how to use that enviionment to uevelop, test, anu ueLug
youi own applications. You`ll not only leain the mechanics ol using the system,
Lut also what`s going on Lehinu the scenes, so you`ll have a Lettei unueistanuing
ol how the whole system lits togethei.
Android uscr intcrfacc
The Nnuioiu usei inteilace elements aie similai to things you`ve seen Leloie, Lut
also uilleient. Ve`ll show you what the piincipal elements aie, how they`ie useu,
anu what they look like on the scieen. Ve`ll also show you the Lasic layout types
availaLle loi the Nnuioiu scieen.
|ntcnts
Nnuioiu makes it easy to leveiage existing applications thiough the use ol Intents.
Foi example, il you want to uial a phone numLei, you uon`t have to uo all the woik
in youi application, oi even know what applications aie availaLle that know how
to uial. You can just ask Nnuioiu to linu you an installeu application that knows
how to uial out, anu pass it the stiing ol numLeis.
Location-bascd scrviccs and napping
Ns you`u expect liom a Google-sponsoieu enviionment, mapping anu location aie
majoi leatuies ol Nnuioiu. You`ll see how easy it is to cieate sophisticateu mapping
anu location-Laseu applications.
Pcrsistcnt data
Nnuioiu incluues the SQLite uataLase liLiaiies anu tools, which youi application
can use to stoie peisistent uata. Content pioviueis, which we`ve alieauy intio-
uuceu, pioviue uata to othei applications. Using the liLiaiies can Le a little tiicky,
Lut in Chaptei 8 we`ll guiue you thiough the cieation ol a uataLase, anu ieauing,
wiiting, anu ueleting uata iecoius.
Graphics
Youi application has access to 2D anu 3D giaphics capaLilities in Nnuioiu. Nni-
mation anu vaiious auvanceu ellects aie also pioviueu. This Look will show you
How This Book Fits Together | 11
how to use those liLiaiies so you can Luilu a compelling usei inteilace loi youi
application.
Connunications
Nnuioiu, even moie than most smaitphone opeiating systems, places gieat em-
phasis on communication÷Ly voice, Ly text messaging, Ly instant messaging, anu
Ly Inteinet. You`ll see how youi application can take auvantage ol these capaLilities
so youi useis can Lecome pait ol a laigei community ol uata anu useis.
The next thiee chapteis, Chapteis 2 thiough +, set you up with a woiking application,
anu will give you a sense ol how the liles anu Lasic classes lit togethei. Chaptei 5
empoweis you to Lettei unueistanu what you`ie uoing anu helps you ueLug youi liist
elloits.
The Nnuioiu toolkit natuially comes with an enoimous numLei ol woiking coue ex-
amples in its NpiDemos application. Unloitunately, its veiy size anu sophistication
make it a loimiuaLle castle loi novices to entei. Chaptei 6 guiues you thiough it.
N Lit ol expeiience with NpiDemos will convince you that you neeu some moie Lack-
giounu anu tutoiial help. In Chaptei 7, we`ll show you how to sign anu puLlish youi
application, which you neeu to uo in oiuei to test it with Google Maps, even Leloie
you`ie ieauy to go puLlic.
Chaptei 8 piesents tutoiials on two uata stoiage systems.
Chaptei 9 piesents location anu mapping, which aie key leatuies that uiaw people to
moLile uevices anu which you`ll suiely want to incoipoiate into youi application.
Ve then tuin to a ciitical pait ol any enu-usei application, giaphics, in thiee
inloimation-packeu chapteis, Chapteis 10 thiough 12.
Chaptei 13 takes anothei step into the complexity anu unigue powei ol Nnuioiu, Ly
uiscussing how applications can ollei lunctionality to othei applications. This allows
loi poweilul mashups, which involve one piogiam stanuing on the shoulueis ol othei
piogiams.
Let`s not loiget that Nnuioiu iuns on telephones. Chapteis 1+ anu 15 wiap up the Look
Ly showing you how to place anu tiack phone calls.
Theie`s even moie to Nnuioiu than these leatuies, ol couise, Lut piogiammeis ol all
stiipes will linu in this Look what they neeu to cieate uselul anu ellicient piogiams loi
the Nnuioiu platloim.
12 | Chapter 1:ಗGetting to Know Android
CHAPTER 2
Setting Up Your Android
Development Environment
Setting Up Your Development Environment
Nnuioiu applications, like most moLile phone applications, aie uevelopeu in a host-
taiget uevelopment enviionment. In othei woius, you uevelop youi application on a
host computei (wheie iesouices aie aLunuant) anu uownloau it to a taiget moLile
phone loi testing anu ultimate use. Npplications can Le testeu anu ueLuggeu eithei on
a ieal Nnuioiu uevice oi on an emulatoi. Foi most uevelopeis, using an emulatoi is
easiei loi initial uevelopment anu ueLugging, lolloweu Ly linal testing on ieal uevices.
To wiite youi own Nnuioiu moLile phone applications, you`ll liist neeu to collect the
ieguiieu tools anu set up an appiopiiate uevelopment enviionment on youi PC oi Mac.
In this chaptei we`ll collect the tools you neeu, uownloau them anu install them on
youi computei, anu wiite a sample application that will let you get the leel ol wiiting
anu iunning Nnuioiu applications on an emulatoi. Linux, Vinuows, anu OS X aie all
suppoiteu uevelopment enviionments, anu we`ll show you how to install the latest set
ol tools on each. Then, we`ll show you any conliguiation you neeu to uo altei installing
the tools (setting PNTH enviionment vaiiaLles anu the like), again loi each ol the thiee
opeiating systems. Finally, we`ll wiite a shoit little ¨Hello, Nnuioiu¨ application that
uemonstiates what neeus to Le uone in oiuei to get a geneiic application iunning.
The Nnuioiu SDK suppoits seveial uilleient integiateu uevelopment enviionments
(IDEs). Foi this Look we will locus on Eclipse Lecause it is the IDE that is Lest integiateu
with the SDK, anu, hey, it`s liee. No mattei which opeiating system you aie using, you
will neeu essentially the same set ol tools:
º The Eclipse IDE
º Sun`s ]ava Development Kit (]DK)
º The Nnuioiu Soltwaie Developei`s Kit (SDK)
º The Nnuioiu Developei Tool (NDT), a special Eclipse plug-in
13
Since you`ie pioLaLly going to uevelop on only one ol the host opeiating systems, skip
to the appiopiiate section that peitains to youi selecteu opeiating system.
Creating an Android Development Environment
The Nnuioiu Soltwaie Development Kit suppoits Vinuows (XP anu Vista), Linux
(testeu on ULuntu Dappei Diake, Lut any iecent Linux uistio shoulu woik), anu Mac
OS X (10.+.8 oi latei, Intel platloim only) as host uevelopment enviionments. Instal-
lation ol the SDK is suLstantially the same loi any ol the opeiating systems, anu most
ol this uesciiption applies egually to all ol them. Vheie the pioceuuie uilleis, we will
cleaily tell you what to uo loi each enviionment:
1. InstaII JDK: The Nnuioiu SDK ieguiies ]DK veision 5 oi veision 6. Il you alieauy
have one ol those installeu, skip to the next step. In paiticulai, Mac OS X comes
with the ]DK veision 5 alieauy installeu, anu many Linux uistiiLutions incluue a
]DK. Il the ]DK is not installeu, go to http://java.sun.con/javasc/down|oads anu
you`ll see a list ol ]ava piouucts to uownloau. You want ]DK 6 Upuate n loi youi
opeiating system, wheie n is 6 at the time ol this wiiting.
Windows (XP and \ista)
º Select the uistiiLution loi ¨Vinuows Ollline Installation, Multi-language.¨
º Reau, ieview, anu accept Sun`s license loi the ]DK. (The license has Lecome
veiy peimissive, Lut il you have a pioLlem with it, alteinative liee ]DKs
exist.)
º Once the uownloau is complete, a uialog Lox will ask you whethei you want
to iun the uownloaueu executaLle. Vhen you select ¨Run,¨ the Vinuows
Installei will stait up anu leau you thiough a uialog to install the ]DK on
youi PC.
Linux
º Select the uistiiLution loi ¨Linux sell-extiacting lile.¨
º Reau, ieview, anu accept Sun`s license loi the ]DK. (The license has Lecome
veiy peimissive, Lut il you have a pioLlem with it, alteinative liee ]DKs
exist.)
º You will neeu to uownloau the sell-extiacting Linaiy to the location in
which you want to install the ]DK on youi lilesystem. Il that is a system-
wiue uiiectoiy (such as /usr/|oca|), you will neeu ioot access. Nltei the
lile is uownloaueu, make it executaLle (chmod +x jdk-6version-linux-
i586.bin), anu execute it. It will sell-extiact to cieate a tiee ol uiiectoiies.
Mac OS X
Mac OS X comes with ]DK veision 5 alieauy loaueu.
14 | Chapter 2:ಗSetting Up Your Android Development Environment
2. InstaII EcIipse: The Nnuioiu SDK ieguiies Eclipse veision 3.3 oi latei. Il you uo
not have that veision ol Eclipse installeu yet, you will neeu to go to http://www
.cc|ipsc.org/down|oads to get it, anu you might as well get veision 3.+ (also known
as Ganymeue), since that package incluues the ieguiieu plug-ins mentioneu in the
next step. You want the veision ol the Eclipse IDE laLeleu ¨Eclipse IDE loi ]ava
Developeis,¨ anu oLviously you want the veision loi youi opeiating system. Eclipse
will ask you to select a miiioi site, anu will then stait the uownloau.
Windows (XP or \ista)
The Eclipse uownloau comes as a Lig ZIP lile that you install Ly extiacting the
liles to youi lavoiite uiiectoiy. Foi this Look, we`ll assume that you extiacteu
to C:/cc|ipsc. Eclipse is now installeu, Lut it will not show up in youi Stait menu
ol applications. You may want to cieate a Vinuows shoitcut loi C:/cc|ipsc/
cc|ipsc.cxc anu place it on youi uesktop, in youi Stait menu, oi someplace else
wheie you can easily linu it.
Linux and Mac OS X
Note that, as ol this wiiting, the veision ol Eclipse installeu il you ieguest it
on ULuntu Haiuy Heion is 3.2.2, which uoes not contain all the plug-ins
neeueu loi Nnuioiu. The Eclipse uownloau comes as a Lig taiLall (.gz lile) that
you install Ly extiacting the liles to youi lavoiite uiiectoiy. Foi this Look, we`ll
assume that you extiacteu to /usr/|ib/cc|ipsc. The executaLle itsell is locateu in
that uiiectoiy anu is nameu cc|ipsc.
3. Check for required pIug-ins: You can skip this step il you just uownloaueu a
cuiient veision ol Eclipse as we iecommenueu. Il you aie using a pieinstalleu vei-
sion ol Eclipse, you neeu to make suie you have the ]ava Development Tool (]DT)
anu VeL Stanuaiu Tools (VST) plug-ins. You can easily check to see whethei they
aie installeu Ly staiting Eclipse anu selecting menu options ¨Vinuows ൺ
Pieleiences...¨. The list ol pieleiences shoulu incluue one loi ¨]ava¨ anu one loi
eithei ¨XML¨ oi ¨VeL anu XML.¨ Il they aien`t on the list, the easiest thing to uo
is ieinstall Eclipse, as uesciiLeu in the pievious step. Installing ¨Eclipse IDE loi
]ava Developeis¨ will automatically get the neeueu plug-ins.
+. InstaII Android SDK: This is wheie you shoulu stait il you alieauy have the iight
veisions ol Eclipse anu the ]DK loaueu. The Nnuioiu SDK is uistiiLuteu thiough
Google`s Nnuioiu site, http://dcvc|opcr.android.con/sd|/1.1_r1/indcx.htn|. You
will neeu to ieau, ieview, anu accept the teims ol the license to pioceeu. Vhen you
get to the list ol uownloaus, you will see a taLle ol uistiiLutions. Select the one loi
youi opeiating system (XP anu Vista use the same uistiiLution). The package (lile)
names incluue the ielease numLei. Foi example, as this is wiitten, the latest
veision ol the SDK is 1.1¸i1, so the lilename loi Vinuows is android-sd|-
windows-1.1_r1.zip.
Setting Up Your Development Environment | 15
Foi veisions 3.3 anu latei ol Eclipse, the Nnuioiu uownloau site pioviues uiiections
aLout how to install the plug-in thiough Eclipse`s soltwaie upuates utility. Il you`ie
using Eclipse 3.2 oi the soltwaie upuate technigue uoesn`t woik loi you, uownloau
the SDK liom the Nnuioiu site anu install it using instiuctions in the next
paiagiaph.
The lile you uownloau is anothei aichive lile, as with Eclipse: a ZIP lile on Vin-
uows, a tai-zippeu lile loi Linux anu MacOS X. Do the same thing as loi Eclipse:
extiact the aichive lile to a uiiectoiy wheie you want to install Nnuioiu, anu make
a note ol the uiiectoiy name (you`ll neeu it in step 6). The extiaction will cieate a
uiiectoiy tiee containing a Lunch ol suLuiiectoiies, incluuing one calleu too|s.
5. Update the environment variabIes: To make it easiei to launch the Nnuioiu
tools, auu the too|s uiiectoiy to youi path.
º On Vinuows XP, click on Stait, then iight-click on My Computei. In the pop-
up menu, click on Piopeities. In the iesulting System Piopeities uialog Lox,
select the Nuvanceu taL. Neai the Lottom ol the Nuvanceu taL is a Lutton, ¨En-
viionment VaiiaLles,¨ that takes you to an Enviionment VaiiaLles uialog. Usei
enviionment vaiiaLles aie listeu in the top hall ol the Lox, anu System enviion-
ment vaiiaLles in the Lottom hall. Scioll uown the list ol System enviionment
vaiiaLles until you linu ¨Path¨; select it, anu click the ¨Euit¨ Lutton. Now you
will Le in an Euit System VaiiaLle uialog that allows you to change the envi-
ionment vaiiaLle ¨Path.¨ Nuu the lull path ol the too|s uiiectoiy to the enu ol
the existing Path vaiiaLle anu click ¨OK.¨ You shoulu now see the new veision
ol the vaiiaLle in the uisplayeu list. Click ¨OK¨ anu then ¨OK¨ again to exit the
uialog Loxes.
º On Vinuows Vista, click on the Miciosolt ¨llag¨ in the lowei lelt ol the uesktop,
then iight-click on Computei. Nt the top ol the iesulting uisplay, just Lelow the
menu Lai, click on ¨System Piopeities.¨ In the column on the lelt ol the iesulting
Lox, click on ¨Nuvanceu system settings.¨ Vista will wain you with a uialog Lox
that says ¨Vinuows neeus youi peimission to continue¨; click ¨Continue.¨
Neai the Lottom ol the System Piopeities Lox is a Lutton laLeleu ¨Enviionment
VaiiaLles¨ that takes you to an Enviionment VaiiaLles uialog. Usei enviionment
vaiiaLles aie listeu in the top hall ol the Lox, anu System enviionment vaiiaLles
in the Lottom hall. Scioll uown the list ol System enviionment vaiiaLles until
you linu ¨Path¨; select it, anu click the ¨Euit¨ Lutton. Now you will Le in an
Euit System VaiiaLle uialog that allows you to change the enviionment vaiiaLle
¨Path.¨ Nuu the lull path ol the too|s uiiectoiy to the enu ol the existing Path
vaiiaLle, anu click ¨OK.¨ You shoulu now see the new veision ol the vaiiaLle
in the uisplayeu list. Click ¨OK¨ anu then ¨OK¨ again to exit the uialog Loxes.
º On Linux, the PNTH enviionment vaiiaLle can Le uelineu in youi -/.bashrc
-/.bash_profi|c lile. Il you have eithei ol those liles, use a text euitoi such as
gcdit, vi, oi Emacs to open the lile anu look loi a line that expoits the PNTH
16 | Chapter 2:ಗSetting Up Your Android Development Environment
vaiiaLle. Il you linu such a line, euit it to auu the lull path ol the too|s uiiectoiy
to the path. Il theie is no such line, you can auu a line like this:
export PATH=${PATH}:your_sdk_dir/tools
wheie you put the lull path in place ol your_sdk_dir.
º On Mac OS X, look loi a lile nameu .bash_profi|c in youi home uiiectoiy (note
the initial uot in the lilename). Il theie is one, use an euitoi to open the lile anu
look loi a line that expoits the PNTH vaiiaLle. Il you linu such a line, euit it to
auu the lull path ol the too|s uiiectoiy to the path. Il theie is no such line, you
can auu a line like this:
export PATH=${PATH}:your_sdk_dir/tools
wheie you put the lull path in place ol your_sdk_dir.
6. InstaII the Android pIug-in (ADT): Thioughout this Look, we will make use ol
the Nnuioiu Development Tool plug-in that Google supplies loi use in Luiluing
Nnuioiu applications. The plug-in is installeu in much the same way as any othei
Eclipse plug-in:
a. Stait Eclipse, il it`s not alieauy iunning.
L. Fiom the menu Lai, select ¨Help ൺSoltwaie Upuates ൺFinu anu Install...¨.
c. In the Install/Upuate uialog, select ¨Seaich loi new leatuies to install¨ anu
click on ¨Next.¨
u. In the Install uialog, click on ¨New Remote Site.¨ N ¨New Upuate Site¨ uialog
pops up. Entei a name loi the plug-in (¨Nnuioiu Plugin¨ will uo), anu the URL
loi upuates: https://d|-ss|.goog|c.con/android/cc|ipsc. Click ¨OK.¨
e. The new site shoulu now appeai in the list ol sites on the Install uialog. Click
¨Finish.¨
l. In the Seaich Results uialog, select the checkLox loi ¨Nnuioiu Plugin ൺ
Developei Tools¨ anu click ¨Next.¨
g. The license agieement loi the plug-in appeais. Reau it, anu il you agiee, select
¨Nccept teims ol the license agieement¨ anu click ¨Next.¨ Click ¨Finish.¨
h. You will get a waining that the plug-in is not signeu. Choose to install it anyway
Ly clicking ¨Install Nll.¨
i. Restait Eclipse.
j. Nltei Eclipse iestaits, you neeu to tell it wheie the SDK is locateu. Fiom the
menu Lai, select ¨Vinuow ൺPieleiences.¨ In the Pieleiences uialog, select
¨Nnuioiu¨ in the lelt column.
k. Use the ¨Biowse¨ Lutton to navigate to the place you installeu the Nnuioiu
SDK, anu click on ¨Npply,¨ then on ¨OK.¨
Setting Up Your Development Environment | 17
Congiatulations÷you have installeu a complete Nnuioiu uevelopment enviionment
without spenuing a penny. Ns you`ll see in this anu suLseguent chapteis, the enviion-
ment incluues a veiy sophisticateu set ol tools to make Nnuioiu piogiamming easiei,
incluuing:
º Nn Integiateu Development Enviionment Laseu on Eclipse, aiguaLly the piemiei
IDE loi ]ava uevelopment. Eclipse itsell Liings many valuaLle uevelopment lea-
tuies. Google anu OHN have taken auvantage ol Eclipse`s extensiLility to pioviue
leatuies customizeu loi Nnuioiu, incluuing ueLugging capaLilities that aie tuneu
to the neeus ol moLile application uevelopeis like you.
º N ]ava uevelopment enviionment anu Dalvik viitual machine that Luilu on Sun`s
]DK lounuation to pioviue a veiy sophisticateu piogiamming enviionment loi
youi applications.
º N complete moLile phone emulatoi that allows you to test youi applications with-
out having to uownloau them to a taiget moLile phone. The emulatoi incluues
leatuies loi testing youi application unuei uilleient moLile phone communication
conuitions (lauing, uioppeu connections, etc.).
º Test tools, such as Tiaceview, which allow you to tune youi application to take
Lest auvantage ol the limiteu iesouices availaLle on a moLile phone.
Hello, Android
So enough uownloauing; let`s wiite a piogiam. N ¨Hello Voilu!¨ piogiam is tiaui-
tional, anu we will stait with something similai to uemonstiate what you neeu to uo
to cieate, Luilu, anu test an Nnuioiu application. Ve won`t exploie much ol the Nn-
uioiu NPI loi this piogiam÷that`s lelt loi the lollowing chapteis÷Lut heie we`ll get
a taste loi the uevelopment enviionment anu the steps you go thiough to cieate an
application loi Nnuioiu.
Where We’re Going
Theie isn`t much lunctionality in this piogiam. Ve just want to uisplay some text on
the Nnuioiu emulatoi winuow that says ¨Hello Nnuioiu!¨ (see Figuie 2-1).
Starting a New Android Application: HelloWorld
Seveial components aie neeueu to Luilu an Nnuioiu application. Foitunately, the
Eclipse IDE with the Nnuioiu plug-in automates a lot ol the woik neeueu to cieate anu
maintain these components. Ve will stait Ly using the IDE to cieate a pioject loi oui
application. Stait up Eclipse anu select ¨File ൺNew ൺPioject...¨ liom the menu Lai
(Le suie to select ¨Pioject...¨, not ¨]ava Pioject¨). You`ll see a list ol pioject types,
similai to the menu in Figuie 2-2.
18 | Chapter 2:ಗSetting Up Your Android Development Environment
Select ¨Nnuioiu Pioject¨ anu click ¨Next¨ to get the ¨New Nnuioiu Pioject¨ uialog Lox
(Figuie 2-3).
Ve`ll use ¨HelloVoilu¨ as the name loi Loth the Pioject anu the Npplication. You
uon`t neeu to change the Lutton oi checkLox selections, anu we`ll use the package name
com.oreilly.helloworld as shown.
Eveiy Nnuioiu application has to have at least one Nctivity (an executaLle that usually
has a usei inteilace), so let`s say we`ie going to incluue an Nctivity calleu Hello
WorldActivity, as shown in the uialog Lox. Click ¨Finish,¨ anu the Nnuioiu Soltwaie
Development Kit uoes a numLei ol things loi you, to make youi lile easiei as a
Iigurc 2-1. ¨Hc||o Android¨ scrccnshot
Iigurc 2-2. Ec|ipsc Ncw Projcct ncnu
Hello, Android | 19
uevelopei. In Figuie 2-+, I`ve expanueu the tiee in the Package Exploiei winuow to
show some ol the liles anu uiiectoiies that the Nnuioiu SDK cieateu.
The Nnuioiu SDK cieateu a Hc||oWor|d uiiectoiy in the uelault Eclipse woikspace loi
youi pioject. It also cieateu suLuiiectoiies loi youi souice liles (.src), ieleiences to the
Nnuioiu LiLiaiy, assets, iesouices (.rcs), anu a manilest lile (AndroidManifcst.xn|). In
each ol the suLuiiectoiies it cieateu anothei level ol suLuiiectoiies as appiopiiate. Let`s
take a guick look at them:
Sourccs (undcr src)
º Contains a uiiectoiy stiuctuie that coiiesponus to the package name you gave
loi youi application: in this case, con.android.hc||owor|d.
º Contains a ]ava template loi the Nctivity you inuicateu was in the application
(HelloWorldActivity) anu may contain a uiiectoiy ol iesouice ieleiences
(R.java). R.java is actually geneiateu Ly the Nnuioiu SDK the liist time you
Iigurc 2-3. Ec|ipsc Ncw Android Projcct dia|og
20 | Chapter 2:ಗSetting Up Your Android Development Environment
compile youi application; it contains the ]ava veision ol all the iesouices you
ueline in the rcs uiiectoiy (coveieu latei). Ve`ll come Lack to R.java latei.
Iigurc 2-1. Ec|ipsc projcct |isting aftcr crcation of thc Hc||oWor|d projcct
Hello, Android | 21
Android Library
This is just what it says. Il you like, you can expanu the android.jar tiee anu see
the names ol the mouules incluueu in the liLiaiy. This is wheie youi application
will go loi Nnuioiu liLiaiy ieleiences.
asscts
Files you want to Lunule with youi application. Ve won`t have any loi
HelloVoilu.
Rcsourccs (undcr rcs)
º DiawaLle iesouices aie any images, Litmaps, etc., that you neeu loi youi ap-
plication. Foi HelloVoilu, the Nnuioiu SDK has supplieu us with the uelault
Nnuioiu icon, anu that`s all we`ll neeu.
º Layout iesouices tell Nnuioiu how to aiiange items on the scieen when the
application iuns. These iesouices aie XML liles that give you guite a Lit ol
lieeuom in laying out the scieen loi uilleient puiposes. Foi HelloVoilu, we`ll
just use the uelaults geneiateu Ly the Nnuioiu SDK.
º Values aie constants, stiings, etc., availaLle loi use Ly youi application. Keeping
them outsiue the souices makes it easiei to customize the application, such as
auapting it loi uilleient languages.
Manifcst (AndroidManifcst.xn|)
This is anothei XML lile that tells the Nnuioiu Luilu system what it neeus to know
to Luilu anu package youi application so it can Le installeu on an Nnuioiu phone
oi the emulatoi. This lile has its own specializeu euitoi, which we`ll uesciiLe when
we get to moie complicateu applications.
Writing HelloWorld
In the Eclipse Package Exploiei winuow, uouLle-click on HelloWorldActivity.java.
This opens the souice lile ol that name in the centei winuow, ieauy loi euiting:
package com.oreilly.helloworld;
import android.app.Activity;
import android.os.Bundle;
public class HelloWorldActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
22 | Chapter 2:ಗSetting Up Your Android Development Environment
Looking guickly at the template coue that the Nnuioiu SDK has pioviueu loi us, we
can note seveial things:
º The Nnuioiu SDK has incluueu the package ieleience we askeu loi, which is con-
sistent with the uiiectoiy stiuctuie it cieateu.
º It has also cieateu a (collapseu) set ol impoits loi the liLiaiy ieleiences it knows
we neeu.
º It cieateu a class uelinition loi the Nctivity we saiu we wanteu (Hello
WorldActivity), incluuing a methou calleu OnCreate.
Foi the moment, uon`t woiiy aLout the paiametei passeu into OnCreate. The
savedInstanceState Bunule is a way ol passing uata Letween activities anu stoiing
uata Letween instantiations ol the same Nctivity. Ve won`t neeu to use this loi
HelloVoilu.
º One special line ol coue has Leen incluueu in OnCreate:
setContentView (R.layout.main);
RememLei that Nnuioiu uses layouts to ueline scieen layouts on the taiget, anu
that nain.xn| was the name ol the uelault layout lile that the Nnuioiu SDK cieateu
loi us unuei .rcs/|ayout. The R.java lile is geneiateu automatically anu contains
]ava ieleiences loi each ol the iesouices unuei .rcs. You will nevei neeu to euit the
R.java lile Ly hanu; the Nnuioiu SDK takes caie ol it as you auu, change, oi uelete
iesouices.
Ngain in the Eclipse Package Exploiei winuow, uouLle-click on nain.xn| anu you will
see the uelault layout scieen in the centei winuow. Theie aie two taLs at the Lottom
ol the panel that say ¨Layout¨ anu ¨main.xml¨. Click on the one that says ¨main.xml¨
to Liing up the coue veision:
<?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>
Ngain, let`s look at the key leatuies ol this template coue:
º Like any othei XML lile, this one staits with a ieleience to the XML veision anu
encouing useu.
º LineaiLayout is one ol the scieen layout loimats pioviueu Ly the Nnuioiu SDK.
Theie aie seveial otheis, which can Le comLineu hieiaichically to cieate veiy
Hello, Android | 23
complex scieen layouts. Foi oui puiposes, a simple lineai layout is line. Moie
Layout types aie coveieu latei in the Look in Chaptei 11.
÷The LineaiLayout uelinition:
xmlns:android="http://schemas.android.com/apk/res/android"
iuentilies the XML schema Leing useu.
÷This coue:
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
uelines an oiientation, wiuth, anu height loi the entiie scope ol the layout.
º TextView uesciiLes an aiea wheie text can Le uisplayeu anu euiteu. It iesemLles
the text Loxes you may have encounteieu when piogiamming in othei giaphical
enviionments.
÷Vithin the TextView uelinition:
android:layout_width="fill_parent"
android:layout_height="wrap_content"
ueline a wiuth anu height loi the TextView Lox.
÷This coue:
android:text="@string/hello"
pioviues some text to uisplay in the TextView. The actual stiing is uelineu in a
sepaiate lile, rcs/va|ucs/strings.xn|. Il we open that lile (again Ly clicking on it
in the Package Exploiei), we see a specializeu stiing euitoi auueu Ly NDT. Il
you select ¨hello (Stiing)¨ Ly clicking on it, you`ll see the cuiient value loi that
stiing. By a stioke ol luck, the Nnuioiu SDK has alieauy incluueu text that is
close to what we wanteu to uisplay anyway. ]ust to show them who`s Loss,
change the value ol the Stiing hello to say ¨Hello Nnuioiu!¨, oi something else
egually clevei.
Save the Pioject eithei liom the Eclipse File menu (File ൺSave) oi Ly clicking on the
uisk icon in the menu Lai.
Believe it oi not, we`ie uone. Ve uon`t have to wiite a single line ol ]ava to cieate this
application.
Running HelloWorld
Fiom the Eclipse menu Lai, select Run ൺRun. N ¨Run Ns¨ uialog Lox will pop up.
Select ¨Nnuioiu Npplication¨ liom the list, which uisplays the uialog shown in Fig-
uie 2-5.
24 | Chapter 2:ಗSetting Up Your Android Development Environment
N commanu winuow will pop up, lolloweu guickly Ly an emulatoi winuow that looks
just like a moLile phone. The emulateu phone will then go thiough its Loot seguence,
which takes a lew minutes (ielax; il anything goes wiong, it will tell you). Nltei a lew
minutes you shoulu see the scieen shown in Figuie 2-6.
Iigurc 2-ó. Iirst try at Hc||oAndroid
Notice anything uilleient Letween that scieen image anu the one we showeu in Fig-
uie 2-1? The application piints out ¨Hello Nnuioiu!¨, oi whatevei you wiote into the
android:text line eailiei, Lut it also uisplays the title ol the application as ¨Hello
Voilu¨. Let`s change the title to match oui cieative change to the application text.
In the Package Exploiei in the lelt panel ol the Eclipse woikLench, ieopen the
strings.xn| lile (the one wheie we lounu the Stiing hello Leloie). This will open the lile
in the euiting winuow. The intent ol this lile is to give you a place to ueline stiings that
will Le useu Ly youi application, without actually emLeuuing them in the ]ava souice
coue. The othei stiing that`s uelineu heie is app_name. To make things consistent,
change the uelinition ol app_name to HelloAndroid, as shown in Figuie 2-7.
Iigurc 2-5. Ec|ipsc App|ication Typc sc|cction
Hello, Android | 25
Now when we iun the application, we get a scieen that looks just like what we set out
to uo, as shown pieviously in Figuie 2-1.
Congiatulations! You`ve just cieateu youi liist Nnuioiu piogiam Ly uoing nothing
moie than changing the text in one line ol coue. Theie aie much gieatei challenges
aheau.
Iigurc 2-7. Hc||oWor|d String cditing
26 | Chapter 2:ಗSetting Up Your Android Development Environment
CHAPTER 3
Using the Android Development
Environment for Real Applications
MicroJobs: This Book’s Main Sample Application
Ve want to take a look at applications that aie moie complex than ¨Hello, Nnuioiu,¨
anu that`s what we`ll uo in this chaptei. Baseu on the theoiy that it`s olten easiest to
explain things thiough an example, we`ll take an in-uepth look at a moie complex
application, calleu Micio]oLs. Some ol the application`s coue mouules aie nameu
M]Nnuioiu, so we`ll also use that name loi the coue associateu with Micio]oLs.
Ve`ll liist take a look at what we want the Micio]oLs application to uo, then we`ll
guickly get into the coue itsell. Nltei looking at the stiuctuie ol the application, we`ll
uesciiLe in uetail how to Luilu the application anu how to get it iunning on the emu-
latoi. Finally, we`ll take a look at some helplul ueLug hints in case you`ie ueveloping
a similai application anu it uoesn`t stait up. The ieasons aie not always oLvious in the
Nnuioiu enviionment.
Android and Social Networking
One ol the gieat piomises ol Nnuioiu moLile phones is theii aLility to iun applications
that enhance oppoitunities loi social netwoiking Letween useis. This piomise echoes
the ieality ol the Inteinet. The liist geneiation ol Inteinet applications weie aLout usei
access to inloimation, anu many ol those applications have Leen veiy populai. The
seconu wave ol Inteinet applications has Leen aLout connecting useis to each othei.
Npplications such as FaceLook, YouTuLe, anu many otheis enhance oui aLility to
connect with people ol similai inteiests, anu allow the application`s useis to pioviue
some oi all ol the content that makes the application what it is. Nnuioiu has the po-
tential to take that concept anu auu a new uimension: moLility. It`s expecteu that a
whole new geneiation ol applications will Le Luilt loi useis ol moLile uevices: social
netwoiking applications that aie easy to use while walking uown the stieet; applications
27
that aie awaie ol the usei`s location; applications that allow the easy shaiing ol content-
iich inloimation, such as pictuies anu viueos.
Ns mentioneu in the pievious chaptei, we aie going to stuuy just such an application
as an example ol Nnuioiu application uevelopment. The coue is availaLle loi you to
uownloau liom the Look`s weLsite (http://www.orci||y.con/cata|og/978059ó521179),
anu is Laseu on an actual entiy in the liist iounu ol the Nnuioiu Developei Challenge,
sponsoieu Ly Google. The application is an example ol a class ol applications known
as ¨liienu linueis¨ Lecause that`s the cential iuea.
In the case ol the Micio]oLs application, insteau ol linuing liienus, the usei is tiying
to locate a tempoiaiy joL in the vicinity, so she can woik loi a lew houis anu make
some money. The piemise is that employeis looking loi tempoiaiy help have enteieu
availaLle joLs, uesciiptions, houis, anu olleieu wages in a weL-Laseu uataLase that is
accessiLle liom Nnuioiu moLile phones. Nnyone looking loi a lew houis` woik can use
the Micio]oLs application to access that uataLase, look loi joLs in the immeuiate aiea,
communicate with liienus aLout potential employeis anu potential joLs, anu call the
employei uiiectly il she is inteiesteu in the position. Foi oui puiposes heie, we won`t
cieate an online seivice; we`ll just have some canneu uata on the phone. The application
has a numLei ol leatuies that extenu that cential iuea in ways that aie unigue to moLile
hanusets:
Mapping
The Nnuioiu moLile phone enviionment pioviues veiy iich suppoit loi uynamic,
inteiactive maps, anu we`ie going to take lull auvantage ol its capaLilities. You`ll
see that with veiy little coue, we`ll Le aLle to show uynamic maps ol oui local
neighLoihoou, getting location upuates liom the inteinal GPS to automatically
scioll the map as we move. Ve`ll Le aLle to scioll the map in two uiiections, zoom
in anu out, anu even switch to satellite views.
Iinding fricnds and cvcnts
N giaphic oveilay on the map will show us wheie joLs aie placeu in the aiea, anu
will allow us to get moie inloimation aLout a joL Ly just touching its symLol on
the map. Ve will access Nnuioiu`s Contact Managei application to get auuiess
inloimation loi oui liienus (telephone numLeis, instant messaging auuiesses, etc.),
anu access the MicroJobs uataLase to get moie inloimation aLout posteu joLs.
|nstant ncssaging
Vhen we linu liienus we want to chat with, we will Le aLle to contact them via
instant messages (IMs), Ly tiauing SMS messages with oui liienus` moLile phones.
Ta||ing with fricnds or cnp|oycrs
Il IMing is too slow oi cumLeisome, we`ll Le aLle to easily place a cellulai call to
oui liienus, oi call the employei olleiing a joL.
28 | Chapter 3:ಗUsing the Android Development Environment for Real Applications
Browsing thc Wcb
Most employeis have an associateu weLsite that pioviues moie uetaileu inloima-
tion. Ve`ll Le aLle to select an employei oll a list oi oll the map anu guickly zeio
in on theii weLsite to linu out, loi example, what the place looks like.
This is a lun application that coulu easily Le uevelopeu luithei into a lull-Llown seivice,
Lut oui intent in this Look is to show you just how easy it is to uevelop anu comLine
these poweilul capaLilities in youi own application. The complete souice coue loi the
application is availaLle to you on the Look`s weLsite, anu we will ielei to it lieguently
thioughout this Look. Nlthough it`s not aLsolutely ieguiieu in oiuei to unueistanu the
mateiial in the Look, you aie stiongly encouiageu to uownloau the souice to youi own
computei. That way, you`ll have it ieauily availaLle loi ieleience, anu it will Le easy to
copy sections ol coue anu paste them into youi own applications as you move on.
Figuie 3-1 shows the scieen uisplayeu Ly M]Nnuioiu when you liist iun it. It`s a map
ol youi local aiea, oveilaiu with a lew Luttons anu pins.
Iigurc 3-1. MjAndroid opcning scrccnshot
Android and Social Networking | 29
Downloading the MJAndroid Code
The M]Nnuioiu application souice coue anu pioject liles aie availaLle liom the O`Reilly
weLsite, at http://www.orci||y.con/cata|og/978059ó521179. To uownloau it to youi
uevelopment system, use a Liowsei to navigate to the link given, anu select ¨Downloau
M]Nnuioiu.¨ Youi opeiating system (Vinuows, Linux, oi OS X) will ask you to con-
liim that you want the uownloau to happen, anu ask you wheie to put the uownloaueu
liles. It uoesn`t mattei wheie you put the uownloaueu, compiesseu liles, Lut you want
to extiact the uncompiesseu liles into the uiiectoiy that Eclipse uses as youi uelault
woikspace, to make it easy to loau the pioject. The uelault place is a loluei calleu
wor|spacc unuei the cc|ipsc uiiectoiy that you cieateu when you installeu Eclipse. Il
you can`t iememLei wheie that is, stait Eclipse, go to File ൺSwitch Voikspace, anu it
will uisplay the location ol the cuiient woikspace uiiectoiy. Expanu the compiesseu
liles into that uiiectoiy, anu Le suie ¨use uiiectoiies¨ is checkeu in the uecompiession
uialog, so the coiiect lolueis will Le cieateu anu the liles wiitten to them.
To impoit the M]Nnuioiu pioject into Eclipse, go to File ൺImpoit..., anu you`ll see a
Select uialog list ol possiLle impoit types. Click on ¨Existing Piojects into Voikspace,¨
anu use the Biowse Lutton to linu the uiiectoiy wheie you just expanueu M]Nnuioiu.
Eclipse will impoit the pioject, anu it shoulu appeai in the Pioject Exploiei pane.
A Brief Tour of the MJAndroid Code
M]Nnuioiu is a ielatively simple application, uespite the capaLilities it gives its useis.
This section will give you an oveiview ol the coue anu iesouice mouules, tell you wheie
they aie locateu in the uiiectoiy stiuctuie, anu pioviue a glimpse ol what each com-
ponent uoes. You may want to ielei to this section in the lutuie when you`ie tiying to
linu example coue loi a paiticulai lunction anu want to locate it in the M]Nnuioiu coue
tiee. M]Nnuioiu uses a uiiectoiy stiuctuie that is ueiiveu uiiectly liom the stanuaiu
Nnuioiu application uiiectoiy stiuctuie, so this will also seive as a guiue to linuing coue
in othei application souice tiees.
The Project Root Folder (MJAndroid)
Il you use Eclipse`s Package Exploiei to look at the M]Nnuioiu pioject, you will see a
set ol lolueis anu liles. It tuins out all ol these weie oiiginally cieateu Ly Eclipse anu
the Nnuioiu Development Tool, anu similai lolueis anu liles aie cieateu loi any
Nnuioiu application. Let`s see what they uo:
src fo|dcr
src is shoit loi Souice, anu this is wheie Eclipse anu NDT expect to linu all ol the
]ava souice liles in youi application. Nlmost all ol the woik you uo to cieate an
Nnuioiu application is uone in this loluei anu the rcs loluei. In the next section,
we will take a moie uetaileu look at how the src loluei is stiuctuieu loi M]Nnuioiu.
30 | Chapter 3:ಗUsing the Android Development Environment for Real Applications
Android Library
This is just what it says: a pointei to the liLiaiy ol Nnuioiu class liles that Eclipse
links to in oiuei to pioviue the Nnuioiu NPIs. You uon`t neeu to uo anything with
this entiy, Lut il you evei neeu to conliim that a paiticulai Nnuioiu class is (still)
theie, this is wheie you woulu look.
asscts fo|dcr
This loluei is uselul loi holuing assets that aie useu Ly the application: lonts, ex-
teinal ]NR liles, anu so on. Foi this Look anu M]Nnuioiu, we uon`t have any assets,
so we will not Le using the asscts loluei.
doc fo|dcr
Shoit loi uocumentation, this is wheie you can put uocumentation loi a pioject.
Foi M]Nnuioiu, weL pages that uesciiLe the Loco pioject aie stoieu in this loluei.
rcs fo|dcr
rcs is shoit loi iesouices, anu this is wheie Eclipse anu NDT expect to linu the
iesouices loi youi application. Resouices incluue most ol the XML liles that ueline
the layout ol youi application, any image liles (icons, pictuies that aie useu in youi
layout, spiites, etc.)÷just aLout eveiything that isn`t pait ol a ]ava souice lile.
AndroidManifcst.xn| fi|c
This lile is cieateu Ly NDT when you cieate a new Nnuioiu pioject. Ns the extension
suggests, it is an XML lile, anu it contains a wealth ol inloimation aLout youi
application: what the activities, seivices, anu intents aie, which one staits liist,
which peimissions youi application neeus liom the opeiating system (loi iestiicteu
lunctions such as getting location oi making a phone call), anu a lot ol othei in-
loimation. This lile is so impoitant that NDT pioviues a special euitoi to maintain
it. It`s just an XML lile, so you coulu always euit it with a text euitoi, Lut you will
see latei that the specializeu euitoi makes eveiything a lot easiei.
Eclipse also cieates two othei liles anu anothei uiiectoiy at the same uiiectoiy level
(the ioot uiiectoiy ol the M]Nnuioiu pioject) that aie not shown Ly Package Exploiei.
The .c|asspath lile is useu Ly Eclipse to keep tiack ol the location ol stanuaiu ]ava classes
anu liLiaiies. Eclipse uses the .projcct lile to stoie inloimation aLout the pioject. You
will nevei neeu to touch eithei ol these liles uiiectly, so Eclipse uoesn`t Lothei you with
them in Package Exploiei. The bin uiiectoiy is wheie Eclipse puts the compileu class
liles loi each ol youi ]ava souice liles (the ones in src). You can see all ol these liles il
you list the uiiectoiy ol the ioot loluei, Lut you uon`t ieally neeu to pay any attention
to them, Lecause Eclipse will uo it all loi you.
The Source Folder (src)
The package name loi M]Nnuioiu is com.microjobsinc.mjandroid. Eclipse lays out the
eguivalent uiiectoiy stiuctuie, just as it woulu loi any ]ava pioject, anu shows you the
whole thing when you open src. In auuition to these package lolueis, theie is a loluei
nameu loi the package that contains all the ]ava liles loi the pioject. These incluue:
A Brief Tour of the MJAndroid Code | 31
Microjobs.java
The main souice lile loi the application. It uesignates the Nctivity that staits liist,
uisplays the map that is the centeipiece ol the application, anu calls othei Nctivities
oi Seivices as necessaiy to implement uilleient leatuies in the usei inteilace.
MicrojobsDatabasc.java
N uataLase helpei that pioviues easy access to the local M]Nnuioiu uataLase. This
is wheie all the employei, usei, anu joL inloimation is stoieu, using SQLite.
Addjob.java and Editjob.java
Pait ol the uataLase poition ol M]Nnuioiu. These pioviue scieens thiough which
the usei can auu oi euit joL entiies in the uataLase.
MicrojobsDctai|.java
The Nctivity that uisplays all ol the uetail inloimation aLout a paiticulai joL
oppoitunity.
MicrojobsEnpDctai|.java
The Nctivity that uisplays inloimation aLout an employei, incluuing name, au-
uiess, ieputation, email auuiess, phone numLei, etc.
MicrojobsList.java
The Nctivity that uisplays a list ol joLs (as opposeu to the map view in
Microjobs.java). It shows a simple list containing Employei anu ]oL entiies, anu
allows the usei to soit the list Ly eithei lielu anu call up specilics ol the joL oi
employei Ly touching the name on the list.
R.java
This lile is cieateu automatically Ly Eclipse anu the NDT to contain ]ava ieleiences
loi all the iesouices that aie uelineu in the rcs loluei (see the next section). You
shoulu nevei have to euit this lile Ly hanu, as it is maintaineu loi you as you auu
oi euit iesouices. Take a look, though, just to see how iesouices aie uelineu loi
latei use in the othei ]ava souice liles.
The Resource Folder (res)
The rcs loluei contains thiee lolueis, anu anothei pointei to the same Android
Manifcst.xn| lile that shows up in the ioot uiiectoiy:
drawab|c
Ns you might suspect, this contains all the uiawaLle images that M]Nnuioiu will
use: any ]PEG oi PNG oi GIF liles oi Litmaps.
|ayout
Ns with many mouein application enviionments, Nnuioiu allows you to sepaiate
what is uisplayeu Ly an Nctivity liom how it is uisplayeu. This uiiectoiy contains
XML liles that uesciiLe the ¨how¨; in othei woius, they aie the layout liles loi each
Nctivity in the application. Vhen a piogiam iuns, Nnuioiu applies the iules in
these liles to cieate the visiLle layout, a piocess known as ¨inllating.¨
32 | Chapter 3:ಗUsing the Android Development Environment for Real Applications
va|ucs
Goou piogiamming piactice calls loi the sepaiation ol uata that uoes not uiiectly
allect the opeiation ol an application, making it a lot easiei to uo things like tians-
lation to loieign languages, theming, etc. Ve aien`t going to Le supei stiict aLout
this in M]Nnuioiu, Lut we will at least put all ol the oLvious usei-visiLle text into
a lile calleu strings.xn|. You`ll see how easy it is to ietiieve these loi use in the
actual Nnuioiu Nctivity souice coue.
First Steps: Building and Running the MicroJobs Application
So now that we know a Lit aLout which liles aie locateu in which lolueis, what happens
when we ask Nnuioiu to iun the M]Nnuioiu application? Nnu loi that mattei, how uo
we ask Nnuioiu to iun the application? Let`s take a closei look at the Nnuioiu SDK
enviionment anu the views anu commanus availaLle to us loi iunning anu ueLugging
any application.
A Very Short Tour of the Android SDK/Eclipse IDE
The Nnuioiu SDK pioviues thiee ¨peispectives¨ loi woiking with Nnuioiu piojects anu
applications. Il you`ie new to Eclipse, a peispective is a collection ol Eclipse views that
pioviues a paiticulai viewpoint ol an application. Eclipse anu the Nnuioiu SDK have
pieassemLleu sets ol views that uevelopeis have lounu uselul, anu you can switch Le-
tween those views, eithei Ly selecting one liom the Vinuow menu oi Ly using the icons
in the uppei-iight coinei ol the Eclipse winuow. You aie also liee to customize the
peispectives, Lut in this Look we will assume you use the stanuaiu ones pioviueu:
java
This is the uelault peispective, launcheu Ly Eclipse when you liist say that you
want to view the woikspace. It incluues:
Pac|agc Exp|orcr
Useu loi viewing lolueis anu selecting liles
Sourcc Editor
Useu loi euiting ]ava anu XML souice liles
Tabbcd \icws
Contains a set ol uselul views, accesseu Ly taLs:
º PioLlems, which lists eiiois that Eclipse anu the Nnuioiu SDK linu in the
application
º ]avauoc, which extiacts anu uisplays ]avauoc uocumentation liom the
application
º Declaiation, which makes it easy to linu the ueclaiation loi any vaiiaLle in
the coue
First Steps: Building and Running the MicroJobs Application | 33
º Console, which shows the console teiminal output liom eithei the emulatoi
oi the Nnuioiu phone
º Seaich, which is useu to seaich loi iesults
º Piogiess, which uisplays piogiess as an application is launcheu anu iuns
Dcbug
This peispective is piimaiily loi ueLugging the application, oLviously. Il you select
DeLug liom the Run menu, Eclipse switches automatically to this peispective,
pioviuing you with views that aie uselul loi ueLugging:
Dcbug
N view ol the application call stack, showing you how you got to the cuiient
ueLug point
Sourcc \icw
This shows you the cuiient souice location in the iunning (oi stoppeu)
application
Conso|c and Tas|s \icws
This contains the console teiminal (as in the ]ava peispective), anu a winuow
wheie uevelopment tasks can Le iecoiueu anu tiackeu
\ariab|cs, Brca|points, and Exprcssions
This is wheie you can view cuiient vaiiaLle values, view Lieakpoints, anu
evaluate expiessions while ueLugging
Out|inc
This shows you an outline ol the cuiient activity Leing executeu: the classes
ueclaieu, anu the instances anu methous uelineu
DDMS
This peispective, which stanus loi Dalvik DeLug Monitoi Seivice, is unigue to
Nnuioiu. It pioviues Nnuioiu-specilic ueLug inloimation, incluuing:
Dcviccs
This shows you what uevices (emulateu oi haiuwaie) aie availaLle to iun youi
applications.
Enu|ator Contro|
This is wheie you can aujust paiameteis that ueline how the telephony anu
location emulatois woik. Vhen iunning on the emulatoi, we`ll use this to
manually senu location upuates to the location pioviuei.
LogCat
This is a view ol the veiy poweilul logging lacility availaLle unuei Nnuioiu,
which allows you to see eveiything going on in the taiget system, anu to liltei
out the inloimation you ieally caie aLout.
34 | Chapter 3:ಗUsing the Android Development Environment for Real Applications
Thrcads, Hcap, and Ii|c Exp|orcr
This is a taLLeu set ol views wheie you can lollow the iunning thieaus in the
application, see how the heap is Leing useu, anu select liles liom the loluei
hieiaichy.
Loading and Starting the Application
Running M]Nnuioiu liom the SDK is complicateu Ly the lact that the application uses
a MapView. Nnuioiu ieguiies a special Map NPI Keywhenevei you use a MapView,
anu the key is tieu to youi paiticulai uevelopment machine. You`ll leain all aLout this
in Chaptei 7, Lut iight now the easiest way loi you to iun M]Nnuioiu is simply to install
the .ap| lile in the emulatoi.
Running the MJAndroid Code
Il you uownloaueu the M]Nnuioiu coue anu tiieu to use the Nnuioiu SDK to compile
it anu iun it, it pioLaLly uiun`t woik. The most likely ieason is that you uiun`t change
the Map NPI Key to match the key neeueu Ly youi installation ol the SDK. To iun an
application such as M]Nnuioiu that uses the MapView, you neeu a Map NPI Key. The
easiest way to iun the application is to install the Linaiy we pioviueu liom the .ap| lile
in the Look`s examples: MjAndroid-1.0.0.ap|. You can install the lile into the emulatoi
Ly simply staiting the emulatoi (il it`s not alieauy iunning) liom a teiminal winuow:
$ emulator
You`ll then neeu to open anothei teiminal winuow to entei the installation commanu:
$ adb install MJAndroid-1.0.0.apk
Once M]Nnuioiu is installeu on youi emulatoi, you can launch it liom the Npplication
Launchei, just like any othei application.
Il you want to Le aLle to make mouilications to the coue anu Luilu anu iun unuei the
SDK, ieau Chaptei 7 to leain how to get the Map NPI Key you neeu.
You aie pioLaLly alieauy in the ]ava peispective, Lut il not, select it now. Il you loaueu
the M]Nnuioiu application into youi Eclipse woikspace loluei as uesciiLeu eailiei, you
shoulu see it in the Package Exploiei. Il you now iight-click on the M]Nnuioiu entiy,
you get a long menu ol options. Select Open Pioject, a little ovei hallway uown the list,
anu Eclipse will open the M]Nnuioiu pioject anu allow you to see its contents.
Il we uiun`t have to ueal with the Map NPI Key issue, staiting the application woulu
Le as easy as selecting Run liom the menu ol the same name. Eclipse shows a uialog
Lox (laLeleu ¨Run Ns¨) that asks how you want to iun the application. You will always
select Nnuioiu Npplication liom the top ol the list.
First Steps: Building and Running the MicroJobs Application | 35
Nt this point, the Nnuioiu SDK will eithei select the taiget haiuwaie you iuentilieu oi
stait the emulatoi as the taiget. It will automatically loau youi application on the taiget
anu attempt to stait it. In the case ol M]Nnuioiu, you shoulu see the opening scieen,
shown eailiei in Figuie 3-1.
Digging a Little Deeper: What Can Go Wrong?
Ns you aie ueveloping youi application, at some point you will tiy to iun it, as just
uesciiLeu, anu it won`t woik. You`ll eithei get an unexpecteu iesult oi you`ll get an
eiioi on the taiget scieen that may Le less than inloimative. Let`s spenu a little time
looking at what the Nnuioiu SDK uoes to get an application iunning, anu what might
go wiong.
Ns you know, Nnuioiu applications iun unuei a viitual machine calleu Dalvik. Vhen
you selecteu ¨Run¨ in the pievious section, tools in the Nnuioiu SDK saw that theie
was not a compileu veision ol M]Nnuioiu availaLle to iun. They liist took all the layout
anu vaiiaLle inloimation that was coueu into XML liles anu conveiteu it into ]ava
souice coue (in the R.java loluei), anu then compileu all the ]ava souice coue into ]ava
Lytecoue liles (.c|ass liles). N tianslatoi conveiteu the ]ava Lytecoues into Dalvik Lyte-
coue liles (.dcx liles). The Dalvik mouules weie comLineu with othei inloimation aLout
the application, incluuing the manilest lile AndroidManifcst.xn|, anu packageu into an
Nnuioiu package (oi .ap|) lile. In the case ol the M]Nnuioiu application, this lile is
MjAndroid.ap|, locateu in .../MjAndroid/bin. Nn Nnuioiu package is what the taiget
ieceives to loau anu stait the application iunning. N lot ol the staitup inloimation is in
the AndroidManifcst.xn| lile, so let`s take a closei look at it.
Vhen you uouLle-click the AndroidManifcst.xn| listing in the Package Exploiei, the
Nnuioiu SDK staits the Nnuioiu Manilest euitoi in the miuule pane ol the ]ava pei-
spective, anu loaus the lile, as shown in Figuie 3-2.
Ns you see, theie aie live taLs at the Lottom ol the euitoi pane, which give you live
uilleient views ol the manilest lile:
Ovcrvicw
This is the view piesenteu Ly uelault (il the lile hasn`t Leen openeu Leloie). It shows
the package name loi the application anu shaieu usei ID inloimation (loi use when
multiple applications have to shaie a common usei ID), piesents some options loi
expoiting anu signing youi application, anu pioviues links to each ol the taLs ue-
sciiLeu next.
App|ication
This view pioviues access to a lot ol the paiameteis that can Le set loi an applica-
tion. Most ol these aie eithei sell-explanatoiy oi aie not useu in an application like
M]Nnuioiu. Two aieas ol inteiest aie:
º Icon, which tells Nnuioiu wheie to linu a uiawaLle icon to use loi the application
on the taiget.
36 | Chapter 3:ಗUsing the Android Development Environment for Real Applications
º Npplication Noues, which iuentilies the activities, seivices, anu pioviueis in the
application. Theie aie a numLei ol things woith noting in this section.
Uscs Library
Foi M]Nnuioiu, we will use the MapNctivity to uisplay maps. That class is
not pait ol the coie Nnuioiu liLiaiies, so we call out heie that we neeu access
to the auuitional liLiaiy com.google.android.maps.
Activity Attributcs
Click on the little tiiangle to the lelt ol Micio]oLs (Nctivity) to see the intent
lilteis attacheu to that activity. Il you iecall, activities in Nnuioiu aie iun
when theii intent lilteis satisly an intent that was expiesseu Ly some alieauy
iunning application. In this case we see two lilteis loi Micio]oLs:
<action android:name="android.intent.action.MAIN" />
This tells the Nnuioiu application launchei that this activity is the one
to Le staiteu liist loi M]Nnuioiu.
<category android:name="android.intent.category.LAUNCHER" />
This tells Nnuioiu that the icon loi this activity anu application is to Le
uisplayeu on the menu ol launchaLle applications.
Iigurc 3-2. Android Manifcst cditor
First Steps: Building and Running the MicroJobs Application | 37
Ve`ll talk aLout the intent lilteis assigneu to the othei activities as we get
to theii use in the coue.
Pcrnissions
Nnuioiu contiols what applications aie alloweu to uo Ly ieguiiing that they ask
loi peimission to peiloim ciitical actions. Vhen the application is installeu on a
ieal uevice, the usei can choose whethei to allow the ieguesteu peimissions anu
pioceeu with installation, oi to ieject installation (in the emulatoi enviionment, it
is assumeu all peimission ieguests aie gianteu). It is impoitant to incluue only the
peimissions neeueu Ly youi application; you uon`t want to ask the usei loi pei-
missions that you uon`t neeu. Foi M]Nnuioiu, we`ll neeu the peimissions shown
in this taL:
º <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
/> allows us to use line-giaineu location pioviueis, such as GPS.
º <uses-permission android:name="android.permission.ACCESS_LOCA
TION_EXTRA_COMMANDS" /> allows us to access auuitional location commanus.
º <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
/> allows the cieation ol mock location pioviueis.
º <uses-permission android:name="android.permission.INTERNET" /> allows us
to access the Inteinet.
º <uses-permission android:name="android.permission.CALL_PHONE" /> allows
the application to place telephone calls.
|nstruncntation
Nnuioiu allows uevelopeis to ieplace Dalvik classes with suLstitute classes when
iunning in the emulatoi enviionment. The intent is to allow one to Lettei instiu-
ment paiticulaily tiicky coue. Ve won`t Le using this leatuie in this Look, Lut you
can seaich loi ¨Instiumentation¨ in the Nnuioiu uocumentation to linu out moie.
AndroidManifcst.xn|
This view shows the actual XML lile that iesults liom all the choices maue in the
othei views. Il you aie alieauy comloitaLle with XML, you may pielei to euit the
lile uiiectly in this view, iathei than using the otheis. Be caielul, though, Lecause
Nnuioiu is veiy choosy aLout seeing the iight tags in the iight places, anu uoesn`t
always give you an eiioi message inuicating what, exactly, is wiong. The euitoi
useu in this view uoes XML syntax checking loi you, Lut it uoesn`t know anything
aLout the semantics ol the vaiious XML tags uelineu Ly Nnuioiu. It`s inteiesting
to make changes in the othei views anu see theii ellect on the actual XML lile Ly
looking at this view.
So theie is a lot ol inloimation in the AndroidManifcst.xn| lile, anu the system uses that
inloimation when launching the application. In the next chaptei, we`ll see what actually
goes on insiue the application as it staits up.
38 | Chapter 3:ಗUsing the Android Development Environment for Real Applications
Running an Application on the T-Mobile Phone
Emulatois aie gieat uevelopment timesaveis, anu the QEMU emulatoi useu Ly Nnuioiu
iuns paiticulaily well. You can pioLaLly ueLug 95º ol youi application just using the
emulatoi. But an Nnuioiu application uoesn`t have much raison d`ctrc until it gets the
chance to iun on ieal phones. Luckily, Nnuioiu makes it easy loi you to tiy youi ap-
plication on one. Ns this is wiitten, the T-MoLile G1 phone is the only Nnuioiu phone
on the maiket, so we`ll give instiuctions loi using it with the Nnuioiu SDK. Futuie
Nnuioiu phones shoulu Le similai.
Enable USB debugging on your phone
Beloie you connect youi T-MoLile G1 to the host, go to the Desktop scieen on the
phone, anu push the Menu Lutton. One ol the menu options is Settings. Touch it to
select, anu you will Le taken to the Settings uialog loi the phone, which consists ol a
list ol things you can set. The list is Liggei than the scieen, so scioll up anu uown until
you linu Npplications, anu touch that entiy. You`ie taken to a suLlist ielateu to appli-
cations, anu one ol the entiies is Development. Touch that, anu you`ie shown two
options:
USB Dcbugging
You want to enaLle this option Ly touching it. N gieen checkmaik shoulu appeai
in the aujacent checkLox.
Stay awa|c
This option will keep the scieen on as long as the USB caLle is connecteu. It can
Le annoying when the scieen goes oll, taking you Lack to the opening scieen, so
you might as well enaLle this too.
Youi T-MoLile G1 now expects to ieceive ueLug inloimation thiough the USB poit,
Lut uon`t plug it in just yet, Lecause we may neeu to loau a special uiivei on the host.
Load the USB driver for ADB
Depenuing on which host opeiating system you aie using, you will neeu to install a
uiivei loi the USB poit, oi conliguie the existing uiivei:
Windows (cithcr \ista or XP)
You will neeu to install a USB uiivei that is incluueu with the Nnuioiu SDK. The
uiivei is locateu in <SDK>/usb_drivcr, wheie <SDK> is the location in which you
installeu the Nnuioiu SDK.
Once you`ve extiacteu the uiivei, plug in the USB caLle connecting the phone to
the host. N Founu New Haiuwaie uialog will pop up that gives you a chance to
loau the new uiivei. The uetails will vaiy slightly, Lut in geneial:
First Steps: Building and Running the MicroJobs Application | 39
1. Vinuows will ask il you want to seaich loi a uiivei, which you uon`t. Insteau,
you want to tell it wheie you put the uiivei uiiectoiy, so select the option that
is something like ¨Install liom a list oi specilieu location.¨
2. Ignoie any uiie wainings liom Vinuows aLout the uiivei not Leing ceitilieu.
This just means that no one paiu Miciosolt to peiloim the ceitilication tests.
3. Vhen askeu loi the uiivei`s location, Liowse to the USB uiivei uiiectoiy,
<SDK>usb_drivcr. The extiaction shoulu have cieateu a suLuiiectoiy calleu
android_usb_windows. Select that suLuiiectoiy anu click OK.
Vinuows will loau the uiivei anu tell you that the haiuwaie is ieauy to use.
Mac OS X
You`ie all set without uoing anything.
Ubuntu Linux
Foi ULuntu, you neeu to conliguie the USB connection with a iules lile, locateu
at /ctc/udcv/ru|cs.d/50-android.ru|cs. The contents ol the iules lile aie slightly uil-
leient uepenuing on which veision ol ULuntu you aie using. Il you aie using a
uilleient Linux uistiiLution, you`ll neeu to look at its uocumentation to unueistanu
how USB iules liles aie conliguieu.
Ubuntu Dappcr Dra|c
Cieate a lile at /ctc/udcv/ru|cs.d/50-android.ru|cs with one line in it:
SUBSYSTEM=="usb_device", SYSFS{idVendor}=="0bb4", MODE="0666"
Ubuntu Gutsy Gibbon or Hardy Hcron
Cieate a lile at /ctc/udcv/ru|cs.d/50-android.ru|cs with one line it it:
SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"
|n a|| cascs (Dappcr, Gutsy, or Hardy), na|c thc ru|cs fi|c rcadab|c and cxccutab|c
by cxccuting fron thc shc|| as root:
chmod a+rx /etc/udev/rules.d/50-android.rules
Connecting the phone
Now that you have the uiivei loaueu, you aie ieauy to plug in the USB caLle that
connects the T-MoLile G1 to the host. The phone will Leep, anu Eclipse will upuate
itsell as it leains ol the new taiget. Il you go to a teiminal (Linux oi OS X) oi Commanu
winuow (Vinuows) anu type adb devices, you shoulu see something like this:
>adb devices
List of devices attached
emulator-5554 device
HT840GZ12968 device
40 | Chapter 3:ಗUsing the Android Development Environment for Real Applications
Running MicroJobs on the phone
Now when you select Run liom the Eclipse menu, you will still get the uialog that asks
what kinu ol application you want to iun (Nnuioiu Npplication, ]ava Npplet, ]ava
Npplication, etc.), Lut now you will get a seconu uialog that asks which taiget you want
to iun on. The availaLle taigets will Le listeu, anu you can click on eithei the emulatoi
oi the phone, uepenuing on which you`u pielei. Select the phone, anu the application
is uownloaueu (using the ueLug signatuie; moie aLout application signatuies in Chap-
tei 7), anu staiteu on the phone. Most ol the ueLug leatuies availaLle on the emulatoi
(coveieu in uetail in Chaptei 5) aie also availaLle when iunning in ueLug moue on the
phone.
Summary
Ve`ve lookeu at this moie iealistic application in some uetail to unueistanu the pio-
ceuuies you`ll neeu to lollow when ueveloping youi own application. Youi application
is likely to uillei in the uetails, Lut it will inheiit a similai stiuctuie, anu you will use
similai pioceuuies to Luilu anu iun youi application, Loth on the emulatoi anu on a
live phone. You now know all the Lasics you neeu to stait Luiluing youi application,
Lut as you`ll see, theie is a lot moie to leain aLout Nnuioiu anu the leatuies you can
Luilu into youi application.
Summary | 41
CHAPTER 4
Under the Covers: Startup Code and
Resources in the MJAndroid
Application
Chaptei 3 intiouuceu the majoi application we use in this Look to illustiate Lasic Nn-
uioiu concepts. That chaptei explaineu which liles make up the souice coue, Lut it
uiun`t actually covei any souice coue in the application. Ve`ll stait looking at souice
coue in this chaptei. Nnu to allow you to get staiteu ueveloping an application guickly,
we`ll Legin with the liist task eveiy stanualone application has to peiloim: initialization.
The events coveieu in this chaptei occui Letween youi selecting ¨Run Ns Nnuioiu
Npplication¨ liom the Eclipse menu anu seeing the map that M]Nnuioiu uisplays at
staitup. This chaptei shows how Nnuioiu makes it easy to cieate ielatively complex
applications. In just 80 lines ol coue anu some associateu XML iesouice liles,
M]Nnuioiu manages to:
º Display an inteiactive map
º Tiack the cuiient location ol the Nnuioiu phone anu upuate the map
º Cieate a local uataLase ol inloimation anu loau usei pieleiences into it
º Pioviue a uynamically changing menu
º Display usei inteilace elements such as laLels, Luttons, anu spinneis
º Run a new Nctivity to uisplay a suppoiting scieen
The ]ava coue in an Nnuioiu application inteiacts tightly with XML iesouice liles, so
we`ll Lounce Lack anu loith Letween them in this chaptei. Ns we point out iepeateuly,
XML liles aie easiei to tweak uuiing uevelopment anu maintain ovei the lile ol an
application. The uesign ol Nnuioiu encouiages you to specily the look anu Lehavioi ol
the application in the iesouice liles.
43
Initialization Parameters in AndroidManifest.xml
Ns Chaptei 3 explaineu, we tolu Nnuioiu to launch Microjobs.java as the liist Nctivity
loi M]Nnuioiu. Ve uelineu that on the Npplication taL ol the AndroidManifcst.xn|
euitoi. The liist pait ol the XML coue that iesults liom that choice is shown heie:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.microjobsinc.mjandroid" android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name=
"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:icon="@drawable/icon2">
<uses-library android:name="com.google.android.maps" />
<activity android:name=".MicroJobs" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
This section ol the chaptei locuses on the XML in this lile. The Micio]oLs Nctivity is
iuentilieu in the manilest at the Leginning ol the lile. This pait ol the lile is noimally
cieateu in Eclipse when you liist cieate the Pioject that you use to wiite youi
application.
Like all goou XML liles, line 1 has the stanuaiu ueclaiation ol the XML veision anu the
chaiactei encouing useu. Beloie we get into the Nctivities that make up the M]Nnuioiu
application, we ueline a lew paiameteis anu ueclaie neeueu peimissions loi the whole
application:
package="com.microjobsinc.mjandroid"
This is just the package name we gave when we cieateu the application in Eclipse.
It`s also the uelault package loi all the mouules in the application.
android:versionCode
This is an integei that shoulu always inciement with each new veision ol the ap-
plication. Eveiy application shoulu incluue a veision coue, anu it shoulu always
Le a monotonically incieasing integei liom veision to veision. This lets othei pio-
giams (such as Nnuioiu Maiket, installeis, anu launcheis) easily liguie out which
is the latest veision ol an application. The lilename ol youi .ap| lile shoulu incluue
this same veision numLei, so it is oLvious which veision it contains.
android:versionName
This veision iuentiliei is a stiing, anu it is intenueu to Le moie like the veision
numLeis you usually see loi applications. The naming convention is up to you, Lut
44 | Chapter 4:ಗUnder the Covers: Startup Code and Resources in the MJAndroid Application
geneially the iuea is to use a scheme like m.n.o (loi as many numLeis as you want
to use), to iuentily successive levels ol change to the application. The iuea is that
this is the veision iuentiliei that woulu Le uisplayeu to a usei (eithei Ly youi ap-
plication oi anothei application).
<uses-permission android:name=...
Theie aie loui ol these in M]Nnuioiu, anu they ueclaie that the application intenus
to use leatuies ol Nnuioiu that ieguiie explicit peimission liom the usei ol the
moLile uevice iunning the application. The peimission is ieguesteu when the ap-
plication is installeu, anu liom then on Nnuioiu iememLeis that the usei saiu it
was OK (oi not) to iun this application anu access the secuie leatuies. Theie aie
many peimissions alieauy uelineu in Nnuioiu, all uesciiLeu in the Nnuioiu uocu-
mentation (seaich loi android.Manifest.permission). You can also ueline youi
own peimissions anu use them to iestiict othei applications` access to lunctions
in youi application, unless the usei giants the othei application that peimission.
The peimissions ieguesteu heie aie:
º ACCESS_FINE_LOCATION, which is ieguiieu to oLtain location inloimation liom a
GPS sensoi.
º ACCESS_LOCATION_EXTRA_COMMANDS. The Nnuioiu uocumentation uoesn`t tell us
which location commanus aie ¨extia,¨ so we`ll ask loi all ol them.
º CALL_PHONE. This allows M]Nnuioiu to ieguest that the Dialei place a moLile
phone call on its Lehall.
º ACCESS_MOCK_LOCATION, so we can get lake location inloimation when we`ie iun-
ning unuei the emulatoi.
º INTERNET, so we can ietiieve map tiles ovei an Inteinet connection.
android:icon="@drawable/icon2"
This is the lilename loi a PNG lile that contains the icon you`u like to use loi youi
application. In this case we`ie telling the Nnuioiu SDK to look loi the icon lile in
the drawab|c suLuiiectoiy ol the rcs (iesouices) uiiectoiy unuei M]Nnuioiu.
Nnuioiu will use this icon loi youi application in the Nnuioiu Desktop.
Tuining oui attention to the uelinition loi the liist (anu main) Nctivity, Micio]oLs, we
liist ueline a lew attiiLutes loi the Nctivity:
android:name
The name ol the Nctivity. The lull name ol the Nctivity incluues the package name
(which in oui application is ¨com.miciojoLsinc.mjanuioiu.Micio]oLs¨), Lut since
this lile is always useu in the package`s namespace, we uon`t neeu to incluue the
leauing package names. The Nnuioiu SDK stiips the package name uown to
¨.Micio]oLs¨ when it cieates this pait ol AndroidManifcst.xn|, anu even the leau-
ing peiiou is optional.
Initialization Parameters in AndroidManifest.xml | 45
android:label
The laLel that we want to appeai at the top ol the Nnuioiu scieen when the Nctivity
is on the scieen. Ve saw this Leloie in HelloVoilu, wheie we changeu the stiing
in strings.xn| to match oui application.
Ve then ueclaie an intent liltei that tells Nnuioiu when this Nctivity shoulu Le iun.
Ve talkeu Liielly aLout Intents in Chaptei 1, anu now we see them in use. Ns you`ll
iecall, when Nnuioiu encounteis an Intent to lullill, it looks among the availaLle Nc-
tivities anu Seivices to linu something that can seivice the Intent. Ve set two attiiLutes:
action
Right now Nnuioiu is tiying to launch this application, so it`s looking loi an Nctivity
that ueclaies itsell ieauy to iesolve the MNIN action. Nny application that is going
to Le launcheu Ly the Launchei neeus to have exactly one Nctivity oi Seivice that
makes this asseition.
category
The Intent iesolvei in Nnuioiu uses this attiiLute to luithei gualily the Intent that
it`s looking loi. In this case, the gualilication is that we`u like loi this Nctivity to
Le uisplayeu in the Usei Menu so the usei can select it to stait this application.
Specilying the LNUNCHER categoiy accomplishes this. You can have a peilectly
valiu application without this attiiLute÷you just won`t Le aLle to launch it liom
the Nnuioiu usei inteilace. Noimally, again, you`ll have exactly one LNUNCHER
pei application, anu it will appeai in the same intent liltei as the opening Nctivity
ol youi application.
Initialization in MicroJobs.java
Having seen the XML iesouices that Nnuioiu uses to launch the application, we can
tuin to some ]ava coue that initializes the application. Use Eclipse to open
Microjobs.java in the ]ava euitoi.
Nltei the package ueclaiation anu the impoit statements, the MicroJobs class is uelineu.
Most Nctivities (anu the othei activities in this application) extenu the Nctivity class.
Because we want to uisplay a map in this application, anu we want to take auvantage
ol the poweilul mapping leatuies Luilt into Nnuioiu, we ueclaie that Micio]oLs will
extenu MapNctivity, as shown in the lollowing coue segment. Il you look in the Nnuioiu
uocumentation loi MapNctivity, you will see that it is a suLclass ol Nctivity, anu so
inheiits all the Nctivity methous anu vaiiaLles:
/**
* MicroJobs
*/
public class MicroJobs extends MapActivity {
Skip ovei the liist lew vaiiaLles anu the uelinition ol the MJOverlay class loi the moment,
to get to the uelinition ol the onCreate methou, as shown in the coue Llock that lollows.
46 | Chapter 4:ಗUnder the Covers: Startup Code and Resources in the MJAndroid Application
This is the methou calleu Ly Nnuioiu when it liist launches an application, so that`s
wheie we`ll put oui initialization coue. Let`s take a look at it, section Ly section:
MapView mvMap;
MicroJobsDatabase db;
MyLocationOverlay mMyLocationOverlay;
double latitude, longitude;
/**
* Called when the activity is first created.
*
* @see com.google.android.maps.MapActivity#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
The liist thing to note is that onCreate ieceives an aigument when it iuns: a Bund|c
that will Le ieleiieu to as savedInstanceStte. Note also that the liist thing onCreate
uoes is call the onCreate methou ol its supeiclass. That makes sense Lecause we want
the chain ol supeiclasses to initialize themselves appiopiiately. But what is this Bunule
thing?
N Bunule is one ol the mechanisms useu Ly Nnuioiu to pass stiuctuieu uata Letween
Nctivities. It`s just a paicel ol key/oLject paiis, anu you`ll see latei when we stait anothei
Nctivity that we have the option ol passing that Nctivity a Bunule. In the case
ol Micio]oLs, we aien`t going to make use ol any ol the iesouices in the
savedInstanceState Bunule, Lut we laithlully pass it on to the onCreate methou ol oui
supeiclass.
The veiy last line in this section ol coue sets oui Content View. N view, as we explaineu
in Chaptei 1, uesciiLes how an application winuow appeais anu inteiacts with the usei.
So the setContentView call tells Nnuioiu that we want to use the layout inloimation in
R.|ayout.nain.java to lay out the scieen loi the Nctivity. Ns Chaptei 2 explaineu, the
R.´ iesouice liles aie geneiateu Ly the Nnuioiu SDK liom youi own XML iesouice liles
when you compile youi application (as a iesult ol selecting Run); in this case, the pa-
iameteis come liom oui rcs/|ayout/nain.xn| lile. Nnuioiu ¨inllates¨ these paiameteis
when layouts aie cieateu, using them to ueteimine how the layout looks.
So let`s uigiess loi a minute anu take a look at the liist pait ol the XML veision ol that
lile:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffc5d1d4"
>
<com.google.android.maps.MapView
Initialization in MicroJobs.java | 47
android:id="@+id/mapmain"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="0P18K0TAE0dO2GifdtbuScgEGLWe3p4CYUQngMg"
/>
<TextView
android:id="@+id/lblMicroJobsToday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MicroJobs for You Today Near:"
android:textSize="20dp"
android:textColor="#FF000000"
android:layout_centerHorizontal="true"
android:gravity="top"
/>
<Spinner
android:id="@+id/spnLocations"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="2dp"
android:layout_below="@+id/lblMicroJobsToday"
/>
<Button
android:id="@+id/btnShowList"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="List Jobs"
android:textSize="20sp"
android:gravity="center_vertical"
android:layout_centerInParent="true"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
Fiist, we say that we aie going to use a Relative Layout loi this scieen. Nnuioiu olleis
a vaiiety ol Layout types, anu though it`s Leyonu the scope ol this Look, you can even
ueline youi own Layout types. N Relative Layout says that we aie going to ueline the
positions ol the uilleient usei inteilace elements Ly ielating theii positions to each othei
anu to the oveiall scieen. That may sounu a little vague iight now, Lut it will Le cleai
when we go into some ol the attiiLutes in uetail. Ve go into much moie uepth on the
piocess ol scieen layout latei in this Look in Chaptei 12.
The liist lew lines ol coue ueline oveiall attiiLutes loi the scieen layout:
android:orientation
This tells Nnuioiu which way we want ¨giavity¨ to woik in ueteimining the scieen
layout.
android:layout_width and android:layout_height
These tell Nnuioiu that we want to make use ol the whole scieen; we aien`t tiying
to leave ioom loi othei Nctivities to Le paitially visiLle.
48 | Chapter 4:ಗUnder the Covers: Startup Code and Resources in the MJAndroid Application
android:background
This uelines the coloi ol the Lackgiounu loi the application (which isn`t ieally
visiLle in oui case, since the map coveis the whole scieen).
Colors in Android
This is a goou time to talk Liielly aLout uelining colois in Nnuioiu; we`ll uiscuss it
luithei when we talk aLout giaphics in Chaptei 12. The coloi specilication will Le
lamiliai to you il you`ve woikeu with weL pages (although on a weL page, the Nlpha
value is the last item insteau ol the liist). Colois in Nnuioiu aie uelineu Ly a pounu sign
(#) lolloweu Ly loui 8-Lit integeis in hexauecimal:
A|pha
The tianspaiency ol the iesulting coloi, FF Leing completely opague anu 0 Leing
completely tianspaient.
Rcd
Reu`s contiiLution to the iesulting coloi, FF Leing lully on anu 0 meaning no ieu.
Grccn
Gieen`s contiiLution to the iesulting coloi, FF Leing lully on anu 0 meaning no
gieen.
B|uc
Blue`s contiiLution to the iesulting coloi, FF Leing lully on anu 0 meaning no Llue.
Common colois aie also uelineu as gloLal constants loi use in ]ava.
The iest ol the lile uelines each ol the visual elements ol the scieen, anu tells Nnuioiu
wheie we`u like it placeu.
The lollowing elements ol the application aie uelineu in the lile:
Scction starting <com.google.android.maps.MapView
This is the main View loi this Nctivity:a Map that consumes most ol the scieen anu
shows the locations ol joLs that might Le ol inteiest to the usei. You`ll see that
most Views can Le uesciiLeu in a layout lile Ly just wiiting the name ol the View,
Lut this holus only loi Views that aie pait ol Nnuioiu`s uelault liLiaiies. MapViews
aie not incluueu, so we cieate an XML element loi it. The MapView View is uelineu
in the maps liLiaiy, so the lull pathname is com.google.android.maps.MapView. Ve
assign it the lollowing attiiLutes:
android:id
This uelines an iuentiliei that we can use to ielei to this View, eithei liom othei
places in this XML lile oi liom oui ]ava coue. You`ll see latei in the ]ava ini-
tialization coue that we connect the ]ava souice coue with this XML souice
thiough these IDs.
android:layout_width and android:layout_height
These aie the same attiiLutes uelineu eailiei loi the application, Lut heie they
apply to the MapView alone, not the whole application. The fill_parent
Initialization in MicroJobs.java | 49
value, as its name suggests, asks loi peimission to lill all the space within the
paient. In this case the paient happens to Le the whole scieen, Lut it is
impoitant to keep in minu that this attiiLute allects only the ielationship Le-
tween the MapView anu its paient.
android:clickable
This tells Nnuioiu that we want an inteiactive MapView that the usei can click
on using the touchscieen on the Nnuioiu phone (simulateu Ly mouse clicks
on the emulateu Nnuioiu phone).
android:apiKey
This is an attiiLute unigue to MapViews. You neeu an NPI Key liom Google
to use a Map View, just as you uo when you auu a Google map to youi weL
page. You`ll see how to oLtain anu use Map NPI Keys in Chapteis 7 anu 9.
Scction starting <TextView
This will uisplay a LaLel telling the usei what he`s looking at. The attiiLutes uelineu
heie aie typical ol what neeus to Le uelineu loi a TextView. In auuition to attiiLutes
we alieauy saw unuei MapView, this element has:
android:text
This contains the text we`u like to uisplay in the TextView.
android:textSize
This says how Lig Nnuioiu shoulu uisplay the text÷in this case, 20 scaleu
pixels high (see the upcoming siueLai loi a uesciiption ol Nnuioiu
uimensions).
android:textColor
This uelines the coloi ol the text.
android:layout_centerHorizontal
This tells Nnuioiu that we want it to centei the uisplayeu text hoiizontally.
android:gravity
This tells the Nnuioiu layout managei wheie to position the element veitically
ielative to its containei, when the element is smallei. Giavity can Le uelineu
as top, center_vertical, oi bottom. Note that giavity anu attiiLutes like
layout_centerHorizontal aie layout hints that the layout managei uses to lay
out the chiluien ol a containei. Theie is no guaiantee that the hints will Le
lolloweu, Lut the layout managei attempts to satisly the comLineu ieguests
liom the containei, the chiluien it contains, anu any gloLal layout hints liom
the usei inteilace.
Theie aie many othei attiiLutes we coulu ueline loi oui TextView, anu they aie all
uesciiLeu in the Nnuioiu uocumentation that accompanies the SDK.
Scction starting <Spinner
This is a stanuaiu Nnuioiu contiol that allows the usei to select liom the cuiient
location oi any ol seveial ¨lavoiite¨ locations that aie iecoiueu in the usei`s piolile.
In auuition to the attiiLutes we`ve seen alieauy, the android:layout_below attiiLute
50 | Chapter 4:ಗUnder the Covers: Startup Code and Resources in the MJAndroid Application
contiols the placement ol the Spinnei. This is the liist attiiLute we`ve seen that
applies specilically to the Relative Layout we chose at the top ol the lile. It tells
Nnuioiu that it shoulu position this Spinnei just Lelow the inteilace element whose
id is lblMicroJobsToday.
Scction starting <Button
The linal segment ol nain.xn| uelines a Button wiuget, which is just what it sounus
like÷a Lutton that the usei can piess to initiate some action. In this case, we want
a Lutton that takes us to the listing ol joLs.
android:layout_width and android:layout_height
These aie the same attiiLutes useu loi the othei views, Lut we uon`t want the
Button to take up the whole wiuth ol the scieen, so we give it a uelineu wiuth.
Veitically, we just tell it to wiap the text that it is uisplaying.
android:text
This places a laLel on the Button.
android:textSize
This tells Nnuioiu how laige we`u like that text uiawn÷in this case, 20 scaleu
pixels.
android:layout_centerInParent
Since the Lutton is not as wiue as the paient (the scieen), we neeu to tell the
layout managei wheie to put the Button hoiizontally. This says ¨put it in the
miuule.¨
android:layout_alignParentBottom
The Button is only tall enough to wiap the laLel that it uisplays, so we also
neeu to tell the layout managei wheie to place it veitically on the scieen. This
says ¨put it at the Lottom.¨ Note that we coulu also have saiu
android:gravity=bottom. Nnuioiu pioviues multiple ways ol expiessing oui
layout ieguests.
Dimensions in Android
Olten you will neeu to specily a uimension loi some element ol the usei inteilace. In
the example heie we geneially useu scaleu pixels (aLLieviateu ¨sp¨), Lut Nnuioiu ac-
tually olleis a iich set ol uimensions to choose liom:
px (pixc|s)
Il a uimension is set at 10px, it will Le exactly 10 pixels long, no mattei what the
physical size (anu physical uensity) ol the pixels on the uisplay. 10px will theieloie
Le uilleient sizes on hanuset uisplays with uilleient pixel uensities. On a QVGN
uisplay, loi example (320×2+0 pixels), it will Le 1/2+th ol the height ol the uisplay.
The same 10px iunning on a VGN uisplay (6+0×+80 pixels) will Le 1/6+th ol the
height ol the uisplay.
dip or dp (dcvicc-indcpcndcnt pixc|s)
In an elloit to make it easiei to auapt applications to uilleient pixel uensities,
uimensions can Le expiesseu in uevice-inuepenuent pixels (sometimes also calleu
Initialization in MicroJobs.java | 51
¨uensity-inuepenuent pixels¨). Vhen you specily a uimension ol 10upi, Nnuioiu
will scale the iesulting oLject so it appeais the same size it woulu appeai on a
160upi scieen. Foi example, il a 6+0×+80 uisplay is +"×3", its pixel uensity is 160
uots pei inch (6+0/+, oi +80/3). On that scieen, up`s aie the same as px`s. But il
we iun the same application on a taLlet-size VGN scieen÷say, 8"×6"÷the pixel
uensity is 80upi, anu a uimension given as 10up will Le twice as laige as a uimension
given as 10px. The scaling lactoi loi up`s is appioximate÷Nnuioiu uoesn`t tiy to
make up`s come out exactly iight.
sp (sca|cd pixc|s)
Scaleu pixels aie a lot like up`s, Lut they aie intenueu loi elements that neeu linei
contiol ovei the uensity scaling lactoi, such as text.
pts (points)
This is useu to expiess text size in points, just as you woulu in any text euitoi.
Points aie a lixeu uimension (ioughly 1/72nu ol an inch), so the text will appeai
the same size on any uisplay.
in (inchcs)
This is just what it says: the uimension in inches.
nn (ni||inctcrs)
This is also just what it says, only metiic this time.
More Initialization of MicroJobs.java
The pievious section was a iathei long uigiession into XML Layout liles, Lut as you
can see, that is wheie a lot ol the initialization ol the application`s usei inteilace takes
place: wheie views aie uelineu, nameu, anu given attiiLutes; wheie the scieen is layeu
out; anu wheie hints aie given to the layout managei uesciiLing the way we woulu like
the scieen to look. Let`s get Lack to the ]ava coue that Liings up the application, staiting
wheie we lelt oll in Microjobs.java:
db = new MicroJobsDatabase(this);
// Get current position
final Location myLocation
= getCurrentLocation((LocationManager) getSystemService(Context.LOCATION_SERVICE));
Spinner spnLocations = (Spinner) findViewById(R.id.spnLocations);
mvMap = (MapView) findViewById(R.id.mapmain);
// get the map controller
final MapController mc = mvMap.getController();
mMyLocationOverlay = new MyLocationOverlay(this, mvMap);
mMyLocationOverlay.runOnFirstFix(
new Runnable() {
public void run() {
mc.animateTo(mMyLocationOverlay.getMyLocation());
mc.setZoom(16);
52 | Chapter 4:ಗUnder the Covers: Startup Code and Resources in the MJAndroid Application
}
});
Crcatc thc databasc objcct
Ve saiu Leloie that we aie going to use a small SQLite uataLase to holu the joL,
woikei, anu employei inloimation. The liist line initializes that uataLase Ly asking
Nnuioiu to cieate a new MicroJobsDatabase oLject (anu initialize it). The ]ava coue
loi this is in the lile MicrojobsDatabasc.java, anu we`ll look at it in uetail latei in
Chaptei 8.
Gct our |ocation
Ve`ll neeu to know oui cuiient location to uo things like linuing joLs that aie close
Ly, so we get it heie Ly calling getCurrentLocation, which is a methou uelineu latei
anu that accepts the name ol oui LocationManager as its aigument. The Location
Manager is a special class that Nnuioiu instantiates loi you, anu you can ietiieve the
instance loi youi application thiough the call to getSystemService.
|nitia|izc thc Spinncr
Ns explaineu in the pievious section, we place a Spinnei wiuget at the top ol the
scieen to help useis guickly go to one ol theii lavoiite locations anu look loi joLs.
This is the liist time we encountei the findViewById methou, which is the way we
access the IDs we uelineu in the XML layout lile. Il you iecall, we iuentilieu the
Spinnei in nain.xn| as spnLocations. Vhen we Luilt the application, Nnuioiu
compileu that XML into a ]ava iuentiliei that it placeu in R.|ayout.nain.java anu
linkeu it into the application. So now we can use findViewById to connect oui ]ava
Spinnei to the XML attiiLutes we uelineu.
|nitia|izc thc MapView and MapController
Similaily,we connect the ]ava MapView to the attiiLutes uelineu loi it in
nain.xn|, anu then attach a MapContiollei to it. You`ll see much moie aLout the
contiollei in Chaptei 9, Lut loi now think ol it as a hanule to get to all the methous
you neeu to contiol the MapView.
|nitia|izc thc LocationOverlay
Ve want to cieate a LocationOverlay that will Luilu anu uiaw the Map in oui
MapView when we want to view a map ol oui local aiea. Ngain, Maps aie coveieu
in much moie uetail latei, Lut you can see heie that we use the constiuctoi to cieate
a new oveilay anu tell it to iun when it gets its liist lix liom the LocationManagei,
so that it uisplays oui cuiient location. Ve also set the zoom level so it`s aLout
iight loi a metiopolitan aiea.
Ve`ll skip ovei the map oveilay initialization, Lecause that will Le coveieu in moie
uetail in Chaptei 9, wheie we talk aLout mapping. Ve still neeu to initialize the ie-
maining Views on this scieen: the Button anu the Spinner. The coue loi these lollows:
// Create a button click listener for the List Jobs button.
Button btnList = (Button) findViewById(R.id.btnShowList);
btnList.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Initialization in MicroJobs.java | 53
Intent intent = new Intent(MicroJobs.this.getApplication(),
MicroJobsList.class);
startActivity(intent);
}
});
// Load a HashMap with locations and positions
List<String> lsLocations = new ArrayList<String>();
final HashMap<String, GeoPoint> hmLocations = new HashMap<String, GeoPoint>();
hmLocations.put("Current Location", new GeoPoint((int) latitude, (int) longitude));
lsLocations.add("Current Location");
// Add favorite locations from this user's record in workers table
worker = db.getWorker();
hmLocations.put(worker.getColLoc1Name(), new GeoPoint((int)worker.getColLoc1Lat(),
(int)worker.getColLoc1Long()));
lsLocations.add(worker.getColLoc1Name());
hmLocations.put(worker.getColLoc2Name(), new GeoPoint((int)worker.getColLoc2Lat(),
(int)worker.getColLoc2Long()));
lsLocations.add(worker.getColLoc2Name());
hmLocations.put(worker.getColLoc3Name(), new GeoPoint((int)worker.getColLoc3Lat(),
(int)worker.getColLoc3Long()));
lsLocations.add(worker.getColLoc3Name());

ArrayAdapter<String> aspnLocations
= new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,
lsLocations);
aspnLocations.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnLocations.setAdapter(aspnLocations);
Crcatc a ca||bac| for thc btnList Button \icw
Ve liist get a hanule on the Button View Ly uoing a lookup on its ID, just as we
uiu Leloie loi the Spinner anu MapView. Ve then set the Lehavioi ol the Button,
which uses a constiuct known as a |istcncr to iesponu to exteinal events.
Vhen a usei clicks a Lutton, Nnuioiu senus an event to its OnClickListener lis-
tenei. In this coue, we set the Button`s Lehavioi Ly setting its OnClickListener to
the methou that we immeuiately ueline, onClick.
Vhen the usei clicks on btnList, we want to uisplay a list ol availaLle Micio]oLs.
To uo that, we have to launch a new Nctivity, Micio]oLsList.java, which contains
the scieen that uisplays the list. Ve can uo that Ly calling the startActivity methou
with an Intent that uesciiLes the new Nctivity. The liist statement in onClick()
cieates the Intent, using the constiuctoi loi Intents that allows us to explicitly name
the Nctivity. This constiuctoi takes two aiguments: a pointei to the context ol the
cuiient application, anu the name ol the Class to stait. The next statement in
onClick() then uses that Intent to stait an instantiation ol Micio]oLsList.
|nitia|izc thc |ist of cntrics in thc Spinncr \icw
Ve neeu two uata stiuctuies to pass to oui Spinnei: a list ol lavoiite locations
that the Spinnei will uisplay (anu the usei can select), anu a hash map connecting
54 | Chapter 4:ಗUnder the Covers: Startup Code and Resources in the MJAndroid Application
location names to geogiaphical locations (latituue anu longituue). Don`t conluse
the HashMap with a geogiaphical Map; the HashMap uses the teim ¨map¨ in the
way many piogiammeis use it, to mean an associative aiiay.
Ve liist cieate the list ol location names (lsLocations), anu then the HashMap
that we`ll use to map names to GeoPoints (hmLocations). Ve then put the liist
entiy, Current Location, into the list anu the HashMap. This entiy will always
ietuin the usei to the cuiient location. This item is special Lecause it can Le a
moving taiget. Foi example, the usei may Le consulting oui application on a last-
moving tiain oi an aiiplane, so we have to uynamically ietiieve the location ol the
uevice whenevei the cuiient location is selecteu.
Ve then auu thiee entiies loi the usei`s ¨lavoiite locations,¨ iecoiueu in the usei`s
iecoiu in the woikeis taLle in the M]Nnuioiu uataLase. Ve`ll uive into the uetails
ol how the uataLase woiks anu how it`s set up latei. Foi now, we`ll just say that
the coue immeuiately lollowing worker = db.getWorker(); loaus the location
names anu positions (latituues anu longituues) into the lsLocations anu
hmLocations lists.
Spinnei Views ieguiie an NiiayNuaptei to leeu them the list, so we cieate
one nameu aspnLocations, attaching it to the list ol location names in its constiuc-
toi. Then, we attach the auaptei to the Spinnei Ly calling setAdapter. The state-
ment "aspnLocations.setDropDownViewResource(android.R.layout.simple_spin
ner_dropdown_item);" pioviues the Spinnei with the uiop-uown layout necessaiy
loi the usei to uisplay the whole list ol locations.
Now that we have initializeu the lists, we can auu the lollowing coue, which enaLles
the appiopiiate action when the usei clicks on an item with the Spinnei:
// Set up a callback for the spinner
spnLocations.setOnItemSelectedListener(
new OnItemSelectedListener() {
public void onNothingSelected(AdapterView<?> arg0) { }
public void onItemSelected(AdapterView<?> parent, View v, int position,
long id) {
TextView vt = (TextView) v;
if ("Current Location".equals(vt.getText())) {
latitude = myLocation.getLatitude();
longitude = myLocation.getLongitude();
mc.animateTo(new GeoPoint((int) latitude, (int) longitude));
} else {
mc.animateTo(hmLocations.get(vt.getText()));
}
mvMap.invalidate();
}
});
}
Initialization in MicroJobs.java | 55
|nitia|izc thc Spinncr ca||bac|
]ust as we uiu with the Button View, we cieate a methou nameu onItemSelected
anu set it to Le calleu when the usei selects an item using the Spinnei. The
onNothingSelected methou is also ieguiieu, Lut we leave it empty (not useu).
Ns mentioneu eailiei, Current Location is a special case Lecause we ietiieve the
uevice`s location uynamically when the usei selects that item. The if Llock hanules
that case: we look to see whethei the selection is Current Location anu il it is, we
get the cuiient location anu go theie. Otheiwise, we go to the selecteu location.
Then, in the linal statement, we invaliuate the map so it will ieuiaw itsell.
Summary
Vith these explanations (skipping ovei a lew auvanceu leatuies coveieu latei in the
Look), we`ve linisheu initializing the application÷at least as lai as the main Nctivity,
Micio]oLs, is conceineu. Ve`ve seen how the Nctivity gets staiteu, how it gets its layout
inloimation liom its associateu layout XML lile (nain.xn|), how it initializes the Views
it contains, anu how it causes the initialization ol othei Nctivities oi Seivices (eithei Ly
invoking a constiuctoi, as when cieating the SQL uataLase instance, oi Ly asking Nn-
uioiu to stait anothei Nctivity, as with Micio]oLsList).
56 | Chapter 4:ಗUnder the Covers: Startup Code and Resources in the MJAndroid Application
CHAPTER 5
Debugging Android Applications
Unless you`ie ieally goou oi ieally lucky, the applications you wiite loi Nnuioiu will
not Le peilect the liist time you iun them. Foitunately, Eclipse anu the Nnuioiu Solt-
waie Development Kit pioviue a iich set ol tools loi ueLugging, anu even some leatuies
that make it easiei to wiite coiiect coue. Ve`ll take a look at the set ol availaLle tools
in this chaptei, anu pioviue some pointeis to othei places you can look loi even moie
inloimation on some ol the tools.
The Tools
Thioughout the uevelopment lilecycle ol wiiting, Luiluing, anu iunning the applica-
tion, the piimaiy tools Nnuioiu uevelopeis use aie:
Ec|ipsc java Editor
N specilic text euitoi loi ]ava that Nnuioiu SDK has inloimeu aLout the Nnuioiu
piogiamming enviionment. The euitoi not only wains you aLout coue the compilei
can`t paise, Lut also gives you a wealth ol inloimation aLout what it can.
java and Da|vi| Bui|d Systcn
Recall that Nnuioiu conveits youi ]ava application to iun on the Dalvik viitual
machine unuei Nnuioiu. The ]ava compilei anu the Dalvik tianslatoi Loth pioviue
eiioi inloimation il they can`t Luilu youi application.
Ec|ipsc Dcbuggcr
Eclipse pioviues a souice-level ueLuggei that the Nnuioiu SDK connects with the
iunning Dalvik Lytecoue, so you have all the ueLug capaLility you`u noimally ex-
pect liom a ]ava piogiam iunning unuei Eclipse.
Logcat
Nnuioiu also pioviues a geneial-puipose logging package that you can take au-
vantage ol to log inloimational oi eiioi messages liom youi iunning application.
Peihaps ol moie impoitance, Nnuioiu uses this lacility extensively to tell you what
is going on as it staits up, initiates youi application, anu tiies to iun it. Theie is
also a special logcat log loi telephony-ielateu messages.
57
Nnuioiu DeLug Biiuge (adb)
This pioviues a commanu-line ueLugging inteilace to a iunning Nnuioiu phone oi
emulatoi.
DDMS
Nnuioiu also pioviues a special winuow-oiienteu ueLugging enviionment custom
tailoieu loi Nnuioiu anu the Dalvik VM.
Traccvicw
Nn Nnuioiu-specilic utility that tiacks all the methou calls youi application exe-
cuteu anu the time spent in each methou.
Eclipse Java Editor
The Nnuioiu SDK takes lull auvantage ol the leatuies Luilt into the Eclipse IDE,
incluuing those in the Eclipse text euitoi, which is customizeu loi ]ava souice coue
uevelopment. Let`s use a simple application as an example ol some ol that euitoi`s
leatuies. Il you`ie alieauy an expeit on using Eclipse loi ]ava uevelopment, you can
skip this section. Il you`ie new to Eclipse (oi new to ]ava), theie aie some hints heie
that will speeu up youi uevelopment ol Nnuioiu applications.
Java Errors
Ve`ve cieateu a new Nnuioiu pioject calleu DeLugTest, using Eclipse anu the Nnuioiu
SDK (File ൺNew ൺPioject ൺNnuioiu Pioject). Vhen you uo that, anu open the ]ava
souice lile the SDK cieateu loi you, you get a cential pane that looks like Figuie 5-1.
This is the Eclipse ]ava text euitoi, anu it is alieauy uoing its joL to point out eiiois in
the nascent application.
In this case, the eiioi inuication is in the lelt maigin: the little lightLulL anu ieu X on
line 11. Vithin that line, the euitoi has unueilineu the R in R.layout.main to tell you
specilically wheie theie`s a pioLlem. Euitois in Eclipse aie smait enough to unueistanu
Iigurc 5-1. Ec|ipsc dcbug window upon startup
58 | Chapter 5:ಗDebugging Android Applications
the syntax ol the language they aie euiting, anu in this case, the eiioi llag is telling us
theie`s a pioLlem with this pait ol the coue. Il we use the mouse to hovei ovei the R,
we get a pop up that gives us moie inloimation, as shown in Figuie 5-2. Il you hovei
youi mouse ovei the symLols in the lelt maigin, you get the same pop up.
Notice also that theie`s a little ieu inuicatoi in the uppei-iight aiea ol the pane, inui-
cating theie is an eiioi somewheie in this lile, anu a little ieu open iectangle in the iight
maigin. Il this lile weie Lig enough to neeu the veitical scioll Lai, you coulu easily see
the locations ol the eiiois in the lile, anu you coulu scioll to them Ly uiagging the scioll
segment to the ieu iectangle. Eclipse makes it veiy easy to see wheie it has lounu eiiois
in youi coue.
N guick check ol the Package Exploiei pane shows that theie`s no R.java lile. Ol couise
not! It uoesn`t exist, Lecause we haven`t Luilt the pioject yet, anu that`s why iesouices
unuei R can`t Le iesolveu. Nltei we Luilu DeLugTest (Pioject ൺBuilu Nll), the eiioi
goes away (Loth the ieu unueiline anu the symLols in the maigin).
So let`s auu some coue loi a simple application anu see some ol Eclipse`s ueLug leatuies.
Ve`ll euit DcbugTcst.java anu nain.xn| to auu a laLel, a text Lox, a VeLView (we want
some Inteinet action to give us moie to look at), anu a Lutton. The application will Le
a tiivial Liowsei, with the Lox Leing the URL anu the Lutton Leing the tiiggei to go
loau the URL into the VeLView. Ve`ll thiow in some intentional eiiois to see how
Eclipse hanules them.
Oui alteieu nain.xn| lile now looks like this:
<?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"
Iigurc 5-2. Ec|ipsc crror dctai|
Eclipse Java Editor | 59
android:text="Enter URL:"
/>
<EditText
android:id="@+id/URL"
android:layout_width="fill_parent"
android:layout_height="60.0dip"
android:maxLines="1"
<Button
android:id="@+id/btnGo"
android:layout_width="wrap_content"
android:layout_height="60.0dip"
android:text="Go"
/>
<WebView
android:id="@+id/wvBrowser"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<LinearLayout>
anu DcbugTcst.java looks like this:
package com.oreilly.debug;
import android.app.Activity;
import android.os.Bundle;
public class DebugTest extends Activity {
private EditText txtURL;
private Button btnGo;
private WebView wvBrowser;
// Set up an onClick routine to gather URLs entered by the user
private final Button.OnClickListener btnGoOnClick = new Button.OnClickListener() {
public void onClick(View v) {
try {
wvBrowser.loadURL();
}
catch (Exception e) {}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Find the Views in the layout file
txtURL = (EditText) findViewById(R.id.txtURL);
btnGo = (Button) findViewById(R.id.btnGo);
btnGo.setOnClickListener(btnGoOnClick);
wvBrowser = (WebView) findViewById(R.id.wvBrowser);
}
}
60 | Chapter 5:ಗDebugging Android Applications
Il you type in these lines (insteau ol copying anu pasting), you`ll see that the euitoi tiies
to anticipate what you might type given the context ol wheie you aie in the coue. Ns
you type ¨wvBiowsei.¨, loi example (incluuing the linal uot), the euitoi knows that
wvBrowser is a VeLView, so it gives you a list ol methous anu vaiiaLles that VeLViews
have. This is a gieat leatuie that ieally helps cut uown on mistypeu methou anu vaiiaLle
names. Once you`ve typeu oi selecteu the methou, the euitoi shows you the paiameteis
loi that methou, so you uon`t have to look those up eithei.
Since we neeu to access the Inteinet to get weL pages, we ask loi that peimission in
AndroidManifcst.xn|:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.oreilly.debug"
android:versionCode="1"
android:versionName="1.0.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".DebugTest"
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-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>
Looking at nain.xn| in the Eclipse euitoi pane (now an XML euitoi, Lut with many ol
the same leatuies we saw in the ]ava euitoi), we see some eiiois (Figuie 5-3).
Iigurc 5-3. nain.xn| in Ec|ipsc
Eclipse Java Editor | 61
N guick inspection conliims what the euitoi is telling us÷that theie`s no close tag loi
the EditText. Ve type /> into line 17, anu the ieu unueilines immeuiately go away.
Now that the EditText tag is lixeu, we`ie lelt with one moie eiioi, shown in Figuie 5-+.
It says we`ie missing the enu tag loi LineaiLayout, Lut we`ie ieally missing the slash
that shoulu stait the enu tag </LinearLayout>. Fiom the euitoi`s syntactical point ol
view, it knows only that it expecteu to linu a </LinearLayout> Leloie the next <Linear
Layout> tag oi the enu ol the lile, anu it uiun`t linu one. The eiioi message is enough
to cause us to look in the iight place anu liguie out what is ieally wiong.
Now that we have nain.xn| lixeu up, let`s look at the liist pait ol DcbugTcst.java as it
appeais in Eclipse (Figuie 5-5). Ve can see liom the iight scioll maigin that theie aie
a total ol seven eiiois, anu oui mouse is hoveiing ovei the eiioi in the ueclaiation ol
btnGo.
Now loi one ol my lavoiite leatuies ol Eclipse. The souice ol the eiioi uisplayeu in
Figuie 5-5, it tuins out, is that EuitText can`t Le iesolveu in the example, Lecause we
haven`t impoiteu the package that uelines EuitTexts. You coulu go look in the Nnuioiu
uocumentation anu linu the iight name loi the liLiaiy, Lut Eclipse has a laLoi-saving
Iigurc 5-1. Additiona| nain.xn| crror
Iigurc 5-5. DcbugTcst.java with crrors, scrccn 1
62 | Chapter 5:ಗDebugging Android Applications
leatuie that will linu it loi you. ]ust type Ctil-Shilt-O (that`s the lettei O) while the
euitoi has locus, anu Eclipse will attempt to iesolve all the uniesolveu ieleiences in the
lile Ly linuing appiopiiate liLiaiies. Vith that one stioke, the appiopiiate packages get
impoiteu loi EuitText, Button, anu VeLView (you can`t see them in Figuie 5-5, Lecause
they`ie hiuuen Ly the pop up), anu those eiiois uisappeai liom the euiting pane as well.
That leaves us with live moie eiiois, so we scioll uown as shown in the Eclipse scieen-
shot in Figuie 5-6.
The loui eiiois in lines 29, 32, 33, anu 35 have the same souice as the one in Fig-
uie 5-2 anu will go away the liist time we Luilu the pioject with the new nain.xn|.
Let`s lix the iemaining eiioi using Eclipse`s help.
Ve cuiiently have the mouse hoveiing ovei the eiioi in line 19, anu the pop up says
we`ie tiying to pass an EuitaLle insteau ol a Stiing to the loadURL(String) methou.
That`s easy to lix: EuitaLles have a toString methou, like most oLjects, so we can change
onClick to look like this:
public void onClick(View v) {
try {
wvBrowser.loadUrl(txtURL.getText().toString());
}
catch (Exception e) {}
}
Now we tiy to Luilu anu iun the pioject (Run ൺ Run ൺ Nnuioiu Npplication), Lut
Eclipse tells us we still have eiiois. It helplully lists all the pioLlems lounu in the PioL-
lems taL, locateu in the pane at the Lottom ol the Eclipse winuow. Figuie 5-7 shows
that taL.
Clicking on an eiioi in the PioLlems taL takes us uiiectly to the coiiesponuing line ol
souice coue in the Euiting pane loi DcbugTcst.java. N guick look at nain.xn| ieveals
Iigurc 5-ó. DcbugTcst.java with crrors, scrccn 2
Eclipse Java Editor | 63
the pioLlem: we ieleiieu to the text Lox as URL in nain.xn|, anu tiieu to linu it as
txtURL in the ]ava coue. N guick lix to nain.xn|, anu the compile completes.
Eclipse staits the Nnuioiu emulatoi loi us anu loaus oui application so it appeais on
the scieen. The application iuns÷now to see whethei it piouuces coiiect iesults.
Il you type in a URL like www.oreilly.com anu click the Go Lutton, you get...an eiioi.
Insteau ol the weL page you askeu loi, you see a page that says ¨VeL Page not Nvail-
aLle.¨ Let`s tiy http://www.oreilly.com...ah, that woiks. So let`s auu coue that checks
whethei the URL staits with http://, anu il not, auus it:
public void onClick(View v) {
try {
String sURL = txtURL.getText().toString();
if(sURL.substring(0,6).equals("http://")) {
wvBrowser.loadUrl(sURL);
}else{
sURL = "http://" + sURL;
wvBrowser.loadUrl(sURL);
}
}
catch (Exception e) {}
}
Now when we iun the piogiam using www.oreilly.com as the URL, it woiks÷Lut
http://www.oreilly.com uoesn`t! Let`s use the ueLuggei to liguie out why.
The Debugger
The Nnuioiu SDK makes the use ol the Eclipse ueLuggei completely tianspaient, so
let`s use it to see what`s going wiong with oui piogiam. Ve`ll put a Lieakpoint at the
line we just enteieu, so the ueLuggei will Lieak theie when we iun the piogiam. Eclipse
gives us thiee ways to toggle a Lieakpoint:
º Use the menus. Select the line you want to toggle anu choose Run ൺ Toggle
Bieakpoint.
º Use the keyLoaiu. Select the line you want to toggle anu key Ctil-Shilt-B.
º DouLle-click in the lelt maigin ol the euitoi winuow at the line you want to toggle
(my lavoiite methou).
Iigurc 5-7. DcbugTcst conpi|c prob|cns
64 | Chapter 5:ಗDebugging Android Applications
Vhatevei way you choose, you enu up with a Lieakpoint maik in the lelt maigin ol
the euitoi winuow, as shown in Figuie 5-8.
To invoke the DeLuggei, choose Run ൺDeLug ൺNnuioiu Npplication liom the Eclipse
menu. Eclipse anu the Nnuioiu SDK uo what they uiu Leloie (Luilu the piogiam il
necessaiy, conveit to Dalvik, invoke the emulatoi, loau youi piogiam, anu stait it iun-
ning). You may get a winuow in the Emulatoi that says ¨Vaiting loi DeLuggei: Np-
plication DeLugTest is waiting loi the DeLuggei to connect.¨ Il you uo, just wait a lew
seconus anu the DeLuggei shoulu linish initializing, the winuow will uisappeai, anu
you`ll see the DeLugTest scieen.
Now entei http://www.oreilly.com anu click the Go Lutton. DeLugTest staits execut-
ing anu Lieaks at the Lieakpoint. Eclipse automatically changes to the DeLug Peispec-
tive, showing you panes that apply to ueLugging youi application. Staiting liom the
uppei lelt anu moving uown the winuow, lelt to iight, these aie:
Dcbug
The DeLug pane has a single taL (DeLug) that shows a tiace ol iecent execution.
It shoulu show that you aie at a Lieakpoint in a Dalvik thieau iunning DeLugTest,
at ]ava line 19. In its toolLai, this pane also contains the Luttons loi Resume,
Suspenu, Teiminate, Step Into, Step Ovei, Step Retuin, etc.
\ariab|cs and Brca|points
This pane has two taLs, the most uselul ol which is VaiiaLles, wheie you can see
the cuiient value ol vaiiaLles that aie in scope. So lai it`s showing values loi this
anu v.
Editor
This contains a taL loi each ol the souice liles that you hau open in the ]ava Pei-
spective. The cuiiently uisplayeu taL shoulu show DcbugTcst.java, highlighting
the cuiient Lieakpoint (line 19).
Out|inc
This shows the stiuctuie ol youi application. DeLugTest is simple, so it shows only
one methou, OnCreate.
Iigurc 5-8. Editor panc showing brca|point
Eclipse Java Editor | 65
Conso|c/Tas|s/Propcrtics
This pane has taLs loi each ol these views, which uon`t contain much that`s intei-
esting at the moment. The Console is the most uselul, anu in some ueLug situations
can have impoitant inloimation telling you what is (oi isn`t) happening.
Logcat
This is the suLject ol the next section: the contents ol the Nnuioiu logcat log, with
Luttons to liltei the content.
Focusing on the Euitoi pane, which shows us stoppeu at line 19, let`s use the Step Ovei
Lutton (in the DeLug toolLai in the pane aLove) to step the piogiam one line, to line
20. Now sURL appeais in the VaiiaLles Pane, anu it has the iight value, http://
www.oreilly.com. Step once moie anu you can tell something`s wiong: we expecteu the
piogiam to take the liist Lianch ol the if, anu it took the seconu insteau. That`s why
http:// is appeaiing twice in the URL stiing. Il we step once moie we can see that, as
the value ol sURL changes in the VaiiaLles Pane.
To linu out why, let`s use anothei ueLug leatuie ol Eclipse. Fiom the menu, choose
Vinuow ൺShow View ൺDisplay. N new Display taL is auueu to the lowei-lelt pane,
anu comes to the liont. Ns long as the DeLuggei is iunning, you can type any vaiiaLle
oi expiession that`s in scope into this winuow to uisplay the vaiiaLle`s value oi execute
the expiession. Ve shoulu Le cuiious aLout the expiession we`ie compaiing the usei`s
URL to, sURL.substring(0,6). So cut anu paste this methou call liom the Euitoi pane
into the Display taL, select the expiession, iight-click, anu choose Display liom the
pop-up menu. Eclipse evaluates the expiession anu uisplays the iesult in the pane÷
anu what uo you know, it`s http:/, with the last / missing, as shown in Figuie 5-9. This
pioLlem may Le typical ol eiiois that piogiammeis encountei with the use ol ]ava`s
substring methou, Lecause its seconu paiametei iepiesents the location ol the last
chaiactei, not the count ol chaiacteis, as in some othei languages. Ve change the 6 to
7, anu the piogiam woiks line.
Iigurc 5-9. Ec|ipsc dcbuggcr disp|ay panc
66 | Chapter 5:ಗDebugging Android Applications
Logcat
Gianteu, the eiiois we ueLuggeu in the last section weie pietty stiaightloiwaiu÷no
uilleient liom ueLugging in any othei enviionment. But most applications aie not as
simple as DeLugTest, anu many pioLlems aie much haiuei to isolate anu solve. Nnuioiu
pioviues a geneial-puipose logging lacility that can help with many ol those moie uil-
licult pioLlems.
Ns mentioneu Leloie, theie`s a logcat pane on the DeLug peispective (it`s also in the
DDMS peispective, which we`ll talk aLout in the next section anu in ¨DDMS: Dalvik
DeLug Monitoi Seivice¨ on page 7+). The log loi DeLugTest isn`t veiy inteiesting,
so insteau stait M]Nnuioiu in DeLug moue anu we`ll take a look at its log.
Nltei the application comes up in the emulatoi, Eclipse switches to the DeLug Pei-
spective anu shows the logcat pane on the lowei iight, as it looks in Figuie 5-10.
To make the pane laige enough to Le uselul loi ieauing the log, click on the ¨lull scieen¨
symLol at the uppei iight ol the pane, anu it will expanu to lill the Eclipse winuow.
You will then see that theie aie hunuieus ol log messages in the lile, going Lack to when
Eclipse liist staiteu the instantiation ol the emulatoi that you aie using, continuing
thiough the Loot piocess loi Nnuioiu, loauing all the applications, anu linally loauing
anu executing M]Nnuioiu. How aie you supposeu to linu anything uselul in all ol that?
Luckily, Nnuioiu pioviues you with some hanuy lilteis to apply to the loglile. See the
V, D, I, V, anu E symLols in the toolLai? These lilteis successively naiiow the scope
ol messages uisplayeu, as lollows:
\ (\crbosc)
Show eveiything
D (Dcbug)
Show DeLug, Inloimation, Vaining, anu Eiioi messages (eguivalent to V loi now)
| (|nfornation)
Show Inloimation, Vaining, anu Eiioi messages
Iigurc 5-10. Logcat panc, nininizcd
Eclipse Java Editor | 67
W (Warning)
Show Vaining anu Eiioi messages
E (Error)
Show only Eiioi messages
The columns uisplayeu loi the log aie:
Tinc
The time the log entiy was maue
Priority (thc co|unn is not actua||y |abc|cd)
One ol the log entiy types liom the pievious list (D, I, V, oi E)
pid
The Linux piocess ID ol the piocess making the entiy
tag
N shoit tag uesciiLing the souice ol the entiy
Mcssagc
The log entiy itsell
NLout two-thiius ol the way thiough the log (il you staiteu a new emulatoi when you
Liought up M]Nnuioiu), you`ll see a message entiy something like:
11-28 12:10:31.475: INFO/ActivityManager(52): Start proc com.microjobsinc.mjandroid
for activity com.microjobsinc.mjandroid/.MicroJobs:
pid=163 uid=10017 gids={3003}
which actually appeais all on one line; we`ve Lioken it heie so it will lit on a piinteu
page.
This is a log message liom the Nctivity Managei telling us that it staiteu Micio]oLs with
piocess ID 163 (it will pioLaLly Le uilleient as you iun it). Il you click on the gieen
cioss at the top ol the logcat pane, it will let you ueline a custom liltei. Fill in a ianuom
name anu the piu numLei that you saw in the log. Now the log is lilteieu to show only
the messages that apply to this instance ol Micio]oLs. Theie aie likely still a lot ol
messages, which you can liltei luithei (using the D, I, V, anu E Luttons) oi just scan.
Il you ask othei people loi help ueLugging an eiioi in youi own pio-
giam, one ol the liist things you`ll likely Le askeu loi is a copy ol the
logcat output. You can easily extiact the content ol the loglile to a text
lile Ly selecting what you`u like to pieseive anu clicking on the little
uown aiiow at the uppei iight ol the logcat pane, which Liings uown a
pull-uown menu. One ol the selections on the menu is ¨Expoit Selection
as Text...¨, which takes you to a uialog wheie you can name an output
lile loi the log text.
68 | Chapter 5:ಗDebugging Android Applications
Looking at logcat to solve runtime errors
Logcat gives you a lot ol inloimation aLout what happeneu as Nnuioiu tiieu to iun
youi piogiam. It is veiy uselul when you get a geneiic eiioi message liom Nnuioiu that
uoesn`t tell you much. Let`s uemonstiate one ol my (least) lavoiites.
In Eclipse, go to nain.xn| loi M]Nnuioiu anu iemove the apiKcy line unuei the
MapView ueclaiation (save it in a text lile oi somewheie, so you can iestoie it; we`ie
uoing this just to geneiate an eiioi). The apiKcy is neeueu to access mapping inloima-
tion, so iemoving it Liings the piogiam to a scieeching halt. Vhen you iun the piogiam,
the emulatoi scieen looks like Figuie 5-11.
Nlthough it`s goou to know that the application stoppeu, the message tells us veiy little
aLout why. Il you now look at the logcat output in the DeLug peispective (oi the DDMS
peispective), you`ll linu something like this altei Micio]oLs staits up, all in ieu type
(we`ve lelt oll the liist lew columns so it will lit):
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.microjobsinc.mjandroid/com.microjobsinc.mjandroid.MicroJobs}:
android.view.InflateException: Binary XML file line #8: Error
inflating class java.lang.reflect.Constructor
Iigurc 5-11. ¨Stoppcd uncxpcctcd|y¨ ncssagc
Eclipse Java Editor | 69
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2156)
at android.app.ActivityThread.access$1800(ActivityThread.java:112)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1580)
at android.os.Handler.dispatchMessage(Handler.java:88)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3742)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #8: Error
inflating class
java.lang.reflect.Constructor
at android.view.LayoutInflater.createView(LayoutInflater.java:512)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:564)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:617)
at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
at
com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:227)
at android.app.Activity.setContentView(Activity.java:1569)
at com.microjobsinc.mjandroid.MicroJobs.onCreate(MicroJobs.java:132)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1122)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2103)
... 11 norc
Caused by: java.lang.reflect.InvocationTargetException
at com.google.android.maps.MapView.<init>(MapView.java:227)
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:424)
at android.view.LayoutInflater.createView(LayoutInflater.java:499)
... 21 norc
Caused by: java.lang.IllegalArgumentException: You need to specify an API Key for
each MapView.
See the MapView documentation
for details.
at com.google.android.maps.MapView.<init>(MapView.java:263)
at com.google.android.maps.MapView.<init>(MapView.java:244)
... 25 norc
The liist thiee eiiois Lasically tell us that Nnuioiu coulu not stait oui application Le-
cause it coulu not inllate the Views it lounu in oui layout lile. The last eiioi Llock we
showeu in the output cleaily tells us we neeu an NPI Key loi each MapView. Logcat is
olten the Lest way to get insight into eiiois wheie theie isn`t specilic inloimation
otheiwise.
Writing your own logcat entries
To wiite youi own entiies liom youi application into logcat, Nnuioiu pioviues methous
coiiesponuing to the uilleient entiy piioiities. The methous aie all ol the loim:
Log.x(String tag, String message, [Throwable exception])
70 | Chapter 5:ಗDebugging Android Applications
wheie x can Le v, d, i, w, oi e, anu the optional exception makes it easy to iepoit
exceptions that you uiun`t anticipate in youi coue Lut encountei within a tiy/catch
Llock. Foi example, look at the onItemSelected methou loi the Spinner in Micro
jobs.java:
try {
mc.animateTo(mMyLocationOverlay.getMyLocation());
}
catch (Exception e) {
Log.i("MicroJobs", "Unable to animate map", e);
}
mvMap.invalidate();
Android Debug Bridge (adb)
Nnuioiu comes with a specializeu commanu-line ueLug utility calleu adb. It lets you
contiol a uevice oi emulatoi liom youi host, olleiing the kinu ol iemote teiminal oi
iemote shell seivice that emLeuueu piogiammeis have come to expect when woiking
with theii taiget systems. Invoke the adb client liom a commanu piompt on the host
(Stait ൺRun ൺcmu.exe on Vinuows, oi open a teiminal winuow on Linux oi OS X).
The client talks to an adb seivei that iuns in Lackgiounu on the host anu piocesses
ieguests. Il the seivei isn`t iunning when you stait the client, it staits the seivei loi you.
The seivei in tuin communicates with adb uaemons that iun on eithei a uevice oi an
emulatoi. Nll ol this communication is thiough TCP/IP poits. N single client/seivei
can ueal with multiple uevices anu emulatois, Lut to simplily things loi oui uiscussion,
we`ll assume theie`s only one.
Il you just type adb at the commanu piompt, you get the help inloimation loi adb:
Android Debug Bridge version 1.0.20
-d - directs command to the only connected USB device
returns an error if more than one USB device
is present.
-e - directs command to the only running emulator.
returns an error if more than one emulator
is running.
-s <serial number> - directs command to the USB device or emulator with
the given serial number
-p <product name or path> - simple product name like 'sooner', or
a relative/absolute path to a product
out directory like 'out/target/product/sooner'.
If -p is not specified, the ANDROID_PRODUCT_OUT
environment variable is used, which must
be an absolute path.
devices - list all connected devices
device commands:
adb push <local> <remote> - copy file/dir to device
adb pull <remote> <local> - copy file/dir from device
adb sync [ <directory> ] - copy host -> device only if changed
(see 'adb help all')
Eclipse Java Editor | 71
adb shell - run remote shell interactively
adb shell <command> - run remote shell command
adb emu <command> - run emulator console command
adb logcat [ <filter-spec> ] - View device log
adb forward <local> <remote> - forward socket connections
forward specs are one of:
tcp:<port>
localabstract:<unix domain socket name>
localreserved:<unix domain socket name>
localfilesystem:<unix domain socket name>
dev:<character device name>
jdwp:<process pid> (remote only)
adb jdwp - list PIDs of processes hosting a JDWP transport
adb install [-l] [-r] <file> - push this package file to the device and install it
('-l' means forward-lock the app)
('-r' means reinstall the app, keeping its data)
adb uninstall [-k] <package> - remove this app package from the device
('-k' means keep the data and cache directories)
adb bugreport - return all information from the device
that should be included in a bug report.
adb help - show this help message
adb version - show version num
DATAOPTS:
(no option) - don't touch the data partition
-w - wipe the data partition
-d - flash the data partition
scripting:
adb wait-for-device - block until device is online
adb start-server - ensure that there is a server running
adb kill-server - kill the server if it is running
adb get-state - prints: offline | bootloader | device
adb get-product - prints: <product-id>
adb get-serialno - prints: <serial-number>
adb status-window - continuously print device status for a specified
device
adb remount - remounts the /system partition on the device
read-write
networking:
adb ppp <tty> [parameters] - Run PPP over USB.
Note: you should not automatically start a PDP connection.
<tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1
[parameters] - Eg. defaultroute debug dump local notty usepeerdns
adb sync notes: adb sync [ <directory> ]
<localdir> can be interpreted in several ways:
- If <directory> is not specified, both /system and /data partitions will be
updated.
- If it is "system" or "data", only the corresponding partition
is updated.
72 | Chapter 5:ಗDebugging Android Applications
Heie aie a lew ol the moie uselul adb commanus. Theie is much moie inloimation
aLout these anu othei adb commanus in the Nnuioiu uocumentation anu online.
adb devices
Displays a list ol uevices anu emulatois that the adb seivei knows aLout. This is a
goou way to linu the TCP/IP poit loi an emulatoi oi uevice il you uon`t alieauy
know it. The poit numLei is also uisplayeu in the title ol each emulatoi at the top
ol its winuow. Il theie`s only one uevice oi emulatoi iunning (the noimal case,
unless you`ie ueLugging a multiuevice application), any adb commanus you issue
automatically go to that taiget. The -s anu -e options aie pioviueu loi multiuevice
applications to let you specily a uevice oi emulatoi.
adb shell
This connects you with a shell iunning on the taiget anu gives you a # piompt. The
shell is a simplilieu Unix-like shell, so you can use the usual shell commanus (ls,
cat, rm, ps, etc.) to exploie the taiget anu make changes as appiopiiate. Ctil-D oi
exit will get you out ol the shell anu Lack to youi enviionment on the host.
sqlite3 jpath_to_databasej
N paiticulaily uselul shell commanu (you have to get into the shell with
adb shell liist) loi manipulating SQLite uataLase liles. The sq|itc3 piogiam is lui-
thei uesciiLeu in Chaptei 8, anu on the SQLite weLsite (http://www.sq|itc.org). You
can optionally incluue the path to the uataLase lile you want to manipulate
(the M]Nnuioiu uataLase, loi example, woulu Le in data/data/com.micro
jobsinc.mjandroid/databases/MJAndroid).
adb logcat jfilter_specj
This is anothei way ol looking at the logcat log on the taiget. Vhen you iun it, it
uumps the existing log to youi viitual teiminal anu continues to senu auuitional
log entiies as they aie geneiateu in the iunning system. The commanu is noimally
enteieu with a tiailing &, the Unix paiametei loi ¨iun this in a sepaiate piocess,¨
so that you can go on anu use the teiminal loi othei commanus (incluuing, even-
tually, to kill the logcat piocess). The liltei specs aie ol the loim tag:priority,
wheie tag anu priority weie uesciiLeu in ¨Logcat¨ on page 67. So the commanu
to see all AndroidRuntime log entiies ol piioiity E woulu Le:
adb logcat AndroidRuntime:E &
This is also uselul loi ieauing the ¨othei¨ logs, ol which theie aie two: iauio anu
events. The iauio log is accesseu thiough a commanu like:
adb -b radio &
Similaily, to ieau the events log, entei:
adb -b events &
adb install j-lj j-rj file_spec
This can Le useu to install oi ieinstall an application. The -l option loiwaiu-locks
the installation (pieventing the application liom Leing copieu latei to anothei
Eclipse Java Editor | 73
uevice), anu the -r option ieinstalls the application without oveiwiiting the
existing application uata. The file_spec must Le a valiu, signeu .ap| lile loi the
application to Le installeu.
adb uninstall j-kj package
This uninstalls the application with the given package name. The package paiam-
etei neeus to Le the lull name ol the package, without the ¨.ap|¨ extension. So to
uninstall Micio]oLs, loi example, you`u type:
adb uninstall com.microjobsinc.mjandroid
Il you want to keep the application`s associateu uata, you incluue the -k option.
adb push local remote
This commanu copies a lile liom the local name on the host to the remote name
on the taiget.
adb pull remote local
This is the counteipait to the pievious commanu, anu copies a lile liom the taiget
to the host.
DDMS: Dalvik Debug Monitor Service
Installing the Nnuioiu Soltwaie Development Kit auus DDMS to the Eclipse integiateu
uevelopment enviionment, pioviuing a winuow-oiienteu inteilace to Nnuioiu-specilic
ueLug inloimation on the taiget. The most lieguently useu peispectives aie uisplayeu
in the uppei-iight coinei ol the Eclipse winuow. Il theie`s a DDMS Lutton theie, you
can just click on it to switch to DDMS. Il not, in that same aiea theie is a little winuow
symLol with a - sign in its uppei-iight coinei. Clicking on this winuow will open a
menu ol Peispectives, incluuing DDMS.
The DDMS peispective has loui panes Ly uelault. Staiting liom the uppei lelt anu going
lelt to iight uown the scieen, these aie:
Dcviccs
This lists the availaLle taiget uevices connecteu to Eclipse, anu the piocesses iun-
ning on each uevice. The uelault emulatoi uevice is laLeleu with its poit numLei
(555+). Theie aie also some toolLai Luttons in this pane, uesciiLeu latei in this
section.
Thrcads/Hcap/Ii|c Exp|orcr
This pioviues thiee uilleient views ol what is going on in the taiget. The Thieaus
taL shows the cuiiently active thieaus in the selecteu ¨client,¨ which is the appli-
cation selecteu in the Devices pane. To see the Thieaus inloimation, you have to
click the ¨Upuate Thieaus¨ Lutton at the top ol the Devices pane. The Heap taL
shows the state ol the VM`s heap memoiy, anu is upuateu at each gaiLage collect.
Ngain, in oiuei to see the Heap inloimation, you neeu to enaLle it Ly clicking the
¨Upuate Heap¨ Lutton at the top ol the Devices pane, anu you may neeu to exeicise
the application loi a while until the VM ueciues a gaiLage collect is ieguiieu Leloie
74 | Chapter 5:ಗDebugging Android Applications
the inloimation will Le upuateu. You can also loice a gaiLage collect Ly clicking
on the ¨Cause GC¨ Lutton in the Heap view.
Enu|ator Contro|
This gives you contiol ol the Telephony anu Location emulation lunctions:
Tc|cphony Enu|ator
You can simulate voice anu uata opeiation in a vaiiety ol netwoik states (un-
iegisteieu, home, ioaming, seaiching, uenieu) anu at a vaiiety ol netwoik
speeus anu latencies. It`s uselul to vaiy these paiameteis uuiing application
testing to Le suie that youi application iesponus appiopiiately in all typical
situations. You can also simulate incoming voice anu SMS calls liom a specilic
numLei (to test Callei ID), anu cieate the SMS message to Le ieceiveu.
Location Enu|ator
Heie you can senu a specilic location lix to the Location Pioviuei Ly enteiing
a latituue anu longituue. You can alteinatively loau a GPX oi KML lile ol
locations to Le playeu Lack to the Location Pioviuei in a continuous seguence,
as though the taiget was moving aiounu.
Logcat/Conso|c/Out|inc/Propcrtics
This is similai to the ¨catchall¨ pane in the DeLug peispective, pioviuing a collec-
tion ol uselul taLs that uisplay the inuicateu inloimation.
Scrccn Capturc
This isn`t a pane, Lut one ol the toolLai Luttons in the Display pane. It looks like
a veiy small Nnuioiu scieen, anu when you click it, it captuies anu uisplays what
is cuiiently showing on the taiget scieen. It gives you the oppoitunity to save the
captuie to a PNG lile, which you can then use as you woulu any othei image.
Traceview
MayLe the pioLlem you`ie tiying to ueLug isn`t aLout lunctionality. MayLe youi ap-
plication uoes exactly what it`s supposeu to uo, Lut takes too long to uo it. Voulun`t
it Le nice to have a way ol seeing how the methous within youi classes aie inteiacting,
anu even to keep tiack ol the ielative time spent executing in each methou? Tiaceview
is a utility that allow you just that kinu ol visiLility. It consists ol two paits, one that
you enaLle Leloie iunning youi piogiam anu one that you woik with altei the iun in
oiuei to uiagnose youi linuings:
Runtinc data co||cction
You can enaLle anu uisaLle logging loi youi application. Vhile enaLleu, ioutines
aie linkeu into youi application that cieate a Linaiy tiace lile on the taiget. The
tiace lile iecoius eveiy methou instantiation anu the time spent in each methou.
Tracc ana|ysis
Il you then copy the Linaiy tiace lile liom the taiget to youi host, you can iun a
tiace analysis piogiam that uisplays all the inloimation liom the lile in giaphical
Eclipse Java Editor | 75
loim. You can easily oLseive which methous aie consuming most ol the iuntime,
anu uiill uown into those methous to linu out which methous they in tuin call anu
which ol them consume the most time.
Trace data collection
The ioutines to peiloim tiace uata collection aie pioviueu in the Nnuioiu Soltwaie
Development Kit. Nll you have to uo is:
1. Impoit the DeLug package (android.os.Dcbug) into youi application.
2. Call startMethodTracing when you want to stait collecting tiace inloimation.
3. Call stopMethodTracing when you`ie uone.
The tiacing ioutines always wiite theii tiace inloimation to a lile on the taiget`s SD
caiu. Il you`ie iunning on a ieal uevice, you neeu to plug in an SD caiu. Il you`ie
ueLugging on the emulatoi, you neeu to cieate a viitual SD caiu anu tell the emulatoi
to use it:
1. Cieate a viitual SD caiu with mksdcard.
Fiom the host commanu piompt, use the mksdcard utility to cieate a lile that the
emulatoi can use as a viitual SD caiu:
$ mksdcard -l ANDROID 1024M filename
You can cieate the lile anywheie you like, Lut the ioot uiiectoiy loi youi pioject
is a goou place. The utility will allocate a lile as Lig as the size you`ve given in the
mksdcard commanu (1 GB in the example shown).
2. Tell the emulatoi to use the viitual SD caiu.
In Eclipse, choose Vinuow ൺPieleiences ൺNnuioiu ൺLaunch. You`ll see a Lox
theie loi emulatoi options. Nuu the lollowing option:
-sdcard filename
Use the complete path to the lile, so the emulatoi can always linu it, no mattei
wheie it`s iunning liom.
Ns an example ol the coue neeueu, let`s auu tiacing to Micio]oLs anu collect some uata.
Ve auu tiacing to Microjobs.java as lollows:
...
import android.os.Debug;
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// start trace
Debug.startMethodTracing("x");
76 | Chapter 5:ಗDebugging Android Applications
...
// stop tracing when application ends
@Override
public void onDestroy() {
super.onDestroy();
Debug.stopMethodTracing();
}
Iigurc 5-12. Traccvicw Tinc|inc Panc|
Running M]Nnuioiu now cieates a lile nameu x.tracc on the viitual SD caiu on the
taiget. Vhen tiacing is enaLleu, the Dalvik viitual machine is noticeaLly slowei to stait
up anu slowei to iun, Lecause it is mapping the viitual SD caiu into memoiy, anu
collecting all the methou call anu timing uata loi you as it iuns. Foi this example we
went thiough a lew UI opeiations anu then closeu the application.
To analyze x.tracc, move it Lack to the host:
$ adb pull sdcard/x.trace x.trace
anu stait the Tiaceview piogiam:
$ traceview pathnamex.trace
Foi the moment at least, Tiaceview expects the lull pathname ol the tiace lile.
You aie iewaiueu with a uisplay ol all the methous that weie calleu Letween the time
you staiteu anu stoppeu the tiace÷not just the methous in youi application, Lut a||
the methous that weie calleu. The top pait ol the uisplay is the Timeline Panel, which
looks something like Figuie 5-12. The numLeieu line acioss the top is a timeline (in
milliseconus), with each application thieau listeu as a sepaiate iow. Vithin each iow,
each methou invocation is shown as a little coloieu Llock (a little haiu to see at the
staitup iesolution). The colois map to a list ol methous shown in Figuie 5-12.
You can zoom in on a iegion ol inteiest Ly moving the mouse into the timeline aiea,
clicking the lelt mouse Lutton at the stait time ol inteiest, uiagging to the stop time,
anu ieleasing the Lutton. The timeline then zooms in, as shown in Figuie 5-13. Ns you
Eclipse Java Editor | 77
move the mouse liom lelt to iight, the timeline cuisoi shows the seguence ol methou
calls, anu the methou names aie calleu out in the uppei iight.
The Lottom pait ol the Tiaceview uisplay lists each methou, in ueclining oiuei Ly the
amount ol time spent in it. The liist pait ol that list is shown in Figuie 5-1+.
The columns in this uisplay have the lollowing meanings:
Nanc
You can`t see colois heie, Lut on the scieen, the coloi in the coloi-coueu Lox to
the lelt ol each name tiacks to the timeline shown in Figuie 5-12. The 15 colois
get ieuseu in oiuei Ly inclusive time, as you go uown the list.
Iigurc 5-13. Traccvicw zoon into Tinc|inc Panc|
Iigurc 5-11. Traccvicw |ist of ncthods
78 | Chapter 5:ಗDebugging Android Applications
|nc|° and |nc|usivc
The time (anu peicentage ol total time) spent in this methou, incluuing all the
methous that it calleu. The times aie in milliseconus, Lut they shoulu Le inteipieteu
with caie. Because tiacing slows uown execution consiueiaLly, these times uo not
iepiesent the tiue iuntimes unuei noimal execution. They uo pioviue accuiate
ielative timing inloimation when compaiing the iuntimes ol two methous.
Exc|° and Exc|usivc
The time (anu peicentage ol total time) spent actually executing in this methou.
In othei woius, any time spent in nesteu lunctions is iemoveu liom these two lielus.
The same timing caveats apply to Exclusive times as to Inclusive.
Ca||s-Rccursivc ca||s
Two values: the numLei ol times this methou was calleu exteinally anu the numLei
ol times it calleu itsell.
Tinc/Ca||
Simply the guotient ol the seconu column uiviueu Ly the sum ol the numLeis in
the sixth column.
Vhen you select a methou Ly clicking on its name in the Piolile Panel, Tiaceview
aujusts the pane to Liing that methou to the top ol the view, anu opens a list ol Paient
anu Chilu methous, as shown in Figuie 5-15. ¨Paients¨ aie methous that call this
methou. ¨Chiluien¨ aie methous calleu Ly this methou.
Iigurc 5-15. Traccvicw zoon into Profi|c Panc|
Cleaily, theie is a lot ol inloimation availaLle in the Tiaceview iecoius, anu a lull ex-
ploiation is Leyonu the scope ol this Look. Ve`ll leave othei leatuies ol Tiaceview loi
you to exploie, such as the use ol Native Tiacing to tiace the QEMU emulatoi itsell,
the use ol the othei DeLug methous to get timing inloimation, anu the use ol the
dmtracedump utility to geneiate call giaphs.
Eclipse Java Editor | 79
Summary
DeLugging anu pioliling aie laige topics within themselves, anu we have only sciatcheu
the suilace ol the tools anu methous availaLle to you to uevelop Nnuioiu applications.
Some ieleiences lollow to othei souices ol inloimation that might piove uselul:
º DeLugging with the Eclipse Platloim, http://www.ibn.con/dcvc|opcrwor|s/|ibrary/
os-ccbug/
º Foi inloimation aLout using the platloim, http://www.cc|ipsc.org
º DeLugging Tasks (pait ol the Nnuioiu SDK uocumentation), http://d.android.con/
guidc/dcvc|oping/dcbug-tas|s.htn|
º Developing on a Device (pait ol the Nnuioiu SDK uocumentation), http://d.android
.con/guidc/dcvc|oping/dcvicc.htn|
º Using Dalvik DeLug Monitoiing Seivice (DDMS) (pait ol the Nnuioiu SDK uoc-
umentation), http://d.android.con/guidc/dcvc|oping/too|s/ddns.htn|
º Tiaceview: N Giaphical Log Viewei (pait ol the Nnuioiu SDK uocumentation),
http://d.android.con/guidc/dcvc|oping/too|s/traccvicw.htn|
80 | Chapter 5:ಗDebugging Android Applications
CHAPTER 6
The ApiDemos Application
The NpiDemos application comes with the Nnuioiu SDK, anu can Le lounu in the
sanp|cs/ApiDcnos suLuiiectoiy. It`s a tieasuie tiove ol coue that shows an application
uevelopei how to use a lot ol the Nnuioiu NPI. Unloitunately, it`s lelt up to the stuuent
to liguie out how it woiks. That`s wheie this chaptei comes in. Heie, we`ll show you
the iopes ol the NpiDemos application, anu how to linu the coue that implements a
leatuie that you see. Once you get the hang ol it, it`s a veiy uselul place to linu out how
to use Nnuioiu.
Foi the iemainuei ol this chaptei, we`ll make a couple ol assumptions when talking
aLout liles anu uiiectoiies:
º Non-]ava souice liles anu suLuiiectoiies can Le lounu in the sanp|cs/ApiDcnos
suLuiiectoiy ol the uiiectoiy wheie you install the Nnuioiu SDK.
º ]ava liles aie in the src/con/cxanp|c/android/apis uiiectoiy unuei the
sanp|cs/ApiDcnos uiiectoiy.
Application Setup in the Manifest File
Like eveiy othei Nnuioiu application, the Lest place to get a sense ol how the application
is stiung togethei is the application`s AndroidManifcst.xn| lile. Let`s take a look at pait
ol the AndroidManifcst.xn| lile loi NpiDemos, neai the Leginning ol the lile:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.apis">
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:name="ApiDemosApplication"
android:label="@string/activity_sample_code"
android:icon="@drawable/app_sample_code" >
81
<uses-library android:name="com.google.android.maps" />
<activity android:name="ApiDemos">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Heie aie some ol the highlights ol the coue:
Inuicates that this XML lile is an Nnuioiu manilest.
Delines the uelault package loi the application. This allows the uevelopei to ielei
to classes without expiessing the lully gualilieu class each time. In teims ol uiiec-
toiies, it tells Nnuioiu that classes loi this application will Le in sanp|cs/ApiDcnos/
src/con/cxanp|c/android/apis oi some suLuiiectoiy theieol.
Sets up the vaiious peimissions ieguiieu Ly this application. On a ieal phone, when
the usei attempts to install the applications, she is askeu whethei she wants the
application to have the peimissions listeu. This way she knows that the application
has the potential to ieau anu wiite contacts, use the cameia, make the phone viLiate,
linu the geneial aiea wheie the phone is at any given time, anu use the Inteinet. Il
the usei uoes not tiust the uevelopei, she may ueciue not to install the application
altei viewing the ieguesteu peimissions.
Delines the application-wiue paiameteis. The most inteiesting ol these is
ApiDemosApplication, uiscusseu in the lollowing text.
Delines the staitup Nctivity loi the application, ApiDemos. This activity can Le lounu
in the ApiDcnos.java lile. Its joL is to uiscovei all ol the othei uemos in the appli-
cation anu uisplay them on a menu loi the usei to select. The ApiDemos class uses
inloimation liom rcs/strings.xn| anu AndroidManifcst.xn| to aiu in this uiscoveiy
(look at the call to queryIntentActivities).
The ApiDemosApplication class, lounu in the top-level uiiectoiy ol the souice coue,
extenus the Application class anu has two methous: onCreate anu onTerminate. The
onCreate methou executes Leloie any activities stait. Npplication-level gloLal vaiiaLles
shoulu Le uelineu anu initializeu Ly the onCreate methou. It`s also a goou place to set
up any application-level uelault values.
Theie aie seveial suLuiiectoiies unuei sanp|cs/ApiDcnos/src/con/cxanp|c/android/
apis, each coiiesponuing to a high-level lunctional aiea ol the Nnuioiu NPI:
App
Examples ol application-level constiucts such as Nctivities, Nlaims, Dialogs, anu
Seivices.
82 | Chapter 6:ಗThe ApiDemos Application
Contcnt
DesciiLes how to ieau assets liom a lile, liom iesouices, anu liom an XML lile.
Graphics
Many types ol giaphics examples, such as aics Litmap manipulation, clipping,
layeis, anu OpenGL.
Mcdia
Examples ol the MeuiaPlayei anu the ViueoView.
OS
Examples ol how to invoke opeiating system seivices. Ns ol this wiiting, it shows
how to use the VIBRATOR_SERVICE anu SENSOR_SERVICE.
Tcxt
Cool text tiicks. The ¨Linkily¨ uemo shows how to use the autoLink attiiLute ol
the TextView to automatically set up links in text: the usei clicks on a URL anu the
Liowsei comes up, oi clicks on a phone numLei anu the uialei appeais. The ¨Log-
TextBox¨ uemo shows how to cieate a simple scieen log with a LogTextBox View.
\icws
Nll ol the vaiious Nnuioiu views: Luttons, text Loxes, autocompletion, uate wiug-
ets, etc. You can linu the uozens ol uilleient Nnuioiu GUI elements heie, along
with theii many options.
Finding the Source to an Interesting Example
The NpiDemos application has a lot ol inteiesting examples that will help you leain
how to piogiam an Nnuioiu application. Howevei, it`s not entiiely oLvious how to linu
the souice to any paiticulai scieen. The lollowing pioceuuie will help you linu the
souice to any NpiDemo you`ie inteiesteu in. To unueistanu the piocess, we`ll tiace a
couple ol uemos: the ¨Npp/Nctivity/Custom Title¨ anu the ¨Text/Linkily¨ examples.
Custom Title Demo
This technigue woiks when the NpiDemos application stoies inloimation aLout the
uemo in the rcs/strings.xn| iesouice lile:
1. Nltei staiting the NpiDemos application, linu the paiticulai uemo Ly clicking on
the menu, anu iememLei the path you took thiough the menu system. In this case,
you click on App, then Activity, anu linally Custon Tit|c.
2. Open the rcs/va|ucs/strings.xn| lile in a text euitoi such as Eclipse (actually, any
text euitoi that can uo iegulai expiession seaiches shoulu woik line). Caiiy out a
iegulai expiession seaich (Ctil-F Ctil-X in Eclipse) loi each ol the menu woius
liom step 1. Use the iegulai expiession ¨.'¨ to sepaiate the woius. Thus, the seaich
teim in oui example is App.*Activity.*Custom.*Title. The seaich shoulu ietuin
zeio oi one iesult.
Finding the Source to an Interesting Example | 83
Il you uon`t linu any iesults, use the pioceuuie in the lollowing section ol this
chaptei. Otheiwise, the single iesult shoulu Le the contents ol a stiing element.
The value ol the name attiiLute ol that stiing element is oui seaich teim loi the next
step. Foi oui example, this is activity_custom_title.
3. Open the AndroidManifcst.xn| lile anu seaich it loi the stiing you lounu in the
pievious step: activity_custom_title. The seaich shoulu ietuin only one iesult,
which shoulu Le pait ol the the value ol the android:label attiiLute within an
activity element. That activity element shoulu also contain an android:name at-
tiiLute. The value ol this attiiLute contains the path to the Activity class that
implements the uemo. In oui example it`s .app.CustomTitle. This tianslates to the
CustonTit|c.java liles in the app suLuiiectoiy ol the souice tiee.
In the enu, theieloie, the souice loi the Npp ൺNctivity ൺCustom Title menu item can
Le lounu in sanp|cs/ApiDcnos/src/con/cxanp|c/android/apis/app/CustonTit|c.java.
Linkify Demo
This technigue shoulu woik loi uemos that you can`t linu with the pievious methou.
Il the NpiDemos application uoesn`t stoie inloimation aLout the uemo in rcs/
strings.xn|, it gets its inloimation uiiectly liom AndroidManifcst.xn|÷anu so will we.
1. Nltei staiting the NpiDemos application, linu the paiticulai uemo thiough clicking
on the menu, anu iememLei the path you took thiough the menu system. In this
case, you click on Text anu then Linkily.
2. Open the AndroidManifcst.xn| lile anu seaich loi the menu elements as in the
pievious example. But this time the menu elements must Le sepaiateu Ly slashes
insteau ol ¨.'¨ iegulai expiessions. So in this case, seaich loi the
text Text/Linkify (it uoesn`t have to Le a iegulai expiession seaich).
The seaich shoulu ietuin only one iesult, which shoulu Le pait ol the the value ol
the android:label attiiLute within an activity element. That element shoulu also
contain an android:name attiiLute. The value ol this attiiLute contains the path to
the Activity class that implements the uemo. In oui example, the path
is .text.Link. This tianslates to the Lin|.java lile within the tcxt suLuiiectoiy ol
the souice tiee.
So in this example, the souice loi the Text ൺLinkily menu item can Le lounu in sanp|cs/
ApiDcnos/src/con/cxanp|c/android/apis/tcxt/Lin|ify.java.
Adding Your Own Examples to ApiDemos
The NpiDemos application is a hanuy sanuLox loi youi own testing, anu auuing a new
menu entiy anu Nctivity to it is guite easy. But iememLei that whenevei you upgiaue
youi NPI, all ol youi changes will Le lost. Don`t auu coue to the NpiDemo that you
might want to save altei an upgiaue. It ieally is just a sanuLox loi guick tests.
84 | Chapter 6:ಗThe ApiDemos Application
Vith that caveat in minu, this section shows you how to auu a new menu anu scieen
to the NpiDemos application. Ve`ll uo that Ly auuing a new ToastTest Nctivity with
a matching toast_test layout. Ve`ll then hook them into the NpiDemos application
Ly auuing them to the AndroidManifcst.xn| lile.
Fiist, cieate a lile nameu toast_tcst.xn| in the rcs/|ayouts uiiectoiy anu auu the lollowing
content to lay out the wiugets:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/RelativeLayout01"
android:layout_width="wrap_content "
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Guess my favorite color:" />
<RadioGroup android:id="@+id/RadioGroup01"
android:layout_below="@id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton android:id="@+id/redButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Red" />
<RadioButton android:id="@+id/greenButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Green" />
<RadioButton android:id="@+id/blueButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Blue" />
</RadioGroup>
</RelativeLayout>
This layout cieates a RelativeLayout layout managei nameu RelativeLayout01, speci-
lying up a TextView anu a RadioGroup. The TextView piesents the usei with the text
¨Guess My Favoiite Coloi¨ while the RadioGroup, nameu RadioGroup01, contains thiee
RadioButton wiugets: redButton, greenButton, anu blueButton. They have the text
¨Reu¨, ¨Gieen¨, anu ¨Blue¨, iespectively.
Next, cieate the vicw/ToastTcst.java lile. It simply iesponus to clicks liom the layout:
package com.example.android.apis.view;
//Need the following import to get access to the app resources, since this
//class is in a sub-package.
import com.example.android.apis.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.RadioButton;
import android.widget.Toast;
public class ToastTest extends Activity{
Adding Your Own Examples to ApiDemos | 85
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.toast_test);
final RadioButton redButton = (RadioButton) findViewById(R.id.redButton);
redButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Toast.makeText(ToastTest.this, "Ooooh, red", Toast.LENGTH_SHORT).show();
}
});
}
}
Heie aie some ol the highlights ol the coue:
Calls the methou liom the supeiclass, which is the Activity class itsell.
Sets the ContentView to use the toast_test layout, uelineu in the layout lile you
cieateu eailiei.
Cieates one ol the RadioButton wiugets, also going to the layout lile.
Sets up the OnClickListener ol the redButton to show a piece ol ¨Toast¨ that says
¨Ooooh, ieu¨ loi a shoit peiiou ol time. Chaptei 12 coveis giaphics piogiamming
on Nnuioiu.
Like toast in a toastei, this text pops up when activateu. This technigue can Le guite
hanuy loi ueLug coue.
Finally, auu a new activity element to the AndroidManifcst.xn| lile:
<activity android:name=".view.ToastTest" android:label="Views/ToastTest" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
This activity element shoulu Le auueu iight altei the TextSwitchei1 uemo.
86 | Chapter 6:ಗThe ApiDemos Application
CHAPTER 7
Signing and Publishing
Your Application
Viiting anu iunning Nnuioiu applications loi youi own amusement is all well anu
goou, Lut the point ol cieating new applications is to shaie them with otheis, whethei
you chaige money loi them oi give them away loi liee. Google has cieateu Nnuioiu
Maiket just loi that puipose. Nnyone with a connecteu Nnuioiu phone can open the
Nnuioiu Maiket application anu immeuiately uownloau any ol hunuieus (soon to Le
thousanus) ol applications expiessly uesigneu loi Nnuioiu. These applications iange
liom the veiy piactical (Navigation, Timesheets, File Manageis, etc.) to the uowniight
silly (applications that make iuue noises loi the lun ol it). Theie aie a numLei ol steps
any application uevelopei will go thiough in piepaiing anu suLmitting an application
to Nnuioiu Maiket:
1. Thoioughly test the application÷at least with the Nnuioiu emulatoi, Lut also with
as many actual Nnuioiu uevices as you can lay youi hanus on. Theie is no suLstitute
loi testing applications on ieal phones unuei ieal moLile netwoik conuitions to
piove that they woik as you intenu. The last thing you want is thousanus ol people
upset with you Lecause youi application uoesn`t woik the way they expect it to.
2. Deciue whethei you`u like to auu an Enu Usei License Ngieement (EULN) to youi
application. This is noimal piactice in the inuustiy (it`s the ¨click to accept¨ license
that you see when you uownloau an application, even on uesktops), anu is stiongly
auviseu. You can cieate youi own license using one you`ve seen that you like, oi
you can have a lawyei cieate a new one loi you. Ngain, you uon`t have to have a
EULN to suLmit youi application, Lut it is stiongly auviseu.
3. Cieate the icon anu laLel you want uisplayeu loi youi application in the Npplication
Launchei, anu attach them to youi application.
+. Clean up the application loi ielease: tuin oll ueLugging, get iiu ol any extianeous
piint oi logging statements that you hau in loi ueLug, anu take a linal look at the
coue to clean it up.
87
5. Make suie you`ve incluueu a veision numLei anu a veision name in youi manilest
lile, anu ol couise, Lump the veision numLei il this is a new veision ol a pieviously
ieleaseu application.
6. Cieate a signing ceitilicate, anu, il neeueu, a Map NPI Key, as uesciiLeu in this
chaptei.
7. Recompile youi application loi ielease using Nnuioiu Tools.
8. Sign youi application using jarsigner anu youi signing ceitilicate.
9. Retest youi signeu application to Le suie no eiiois weie enteieu uuiing the piocess.
Test Your Application
You`ve pioLaLly Leen ueveloping youi application using the Nnuioiu Emulatoi that is
pait ol the Nnuioiu Developeis Kit. Il you haven`t alieauy uone so, take the time to
loau youi application on a ieal Nnuioiu uevice (such as the T-MoLile G1 phone), anu
test the application again. The emulatoi is veiy goou, Lut theie aie a numLei ol things
that can Le uilleient Letween the uesktop emulation anu a ieal uevice:
Scrccn rcso|ution
The Nnuioiu SDK emulates a uevice like the T-MoLile G1, with a hall VGN scieen
(320×+80), ioughly 3.2 inches in uiagonal measuie. Real Nnuioiu uevices will have
a vaiiety ol scieen shapes, sizes, anu iesolutions, so you neeu to know how youi
application will lunction on those uilleient uevices.
Scrccn oricntation
The SDK emulates only poitiait moue, with the scieen tallei than it is wiue. Many
Nnuioiu uevices (incluuing the T-MoLile G1) suppoit switching scieen oiienta-
tion, anu you neeu to Le suie youi application Lehaves appiopiiately in all
oiientations.
Touchscrccn opcration
The emulatoi uses mouse clicks anu movements to mimic the touchscieen on a
ieal uevice, Lut theie`s nothing like a ieal touchscieen. On a ieal uevice you can
get a much Lettei sense ol what it will Le like loi useis to inteiact with youi
application.
CPU and nctwor| pcrfornancc
On the emulatoi, you aie using youi PC oi Mac to emulate an NRM piocessoi.
The application`s speeu is tieu to the speeu ol youi unueilying host piocessoi,
which typically consists ol multiple multigigaheitz multipiocessois. Il youi appli-
cation is at all peiloimance sensitive, you`ll want to see how it lunctions on ieal
uevices. Similaily, the emulatoi is using youi host`s netwoik connection, which
may Le LioauLanu, to access the Inteinet. On a ieal uevice youi netwoik connec-
tion will eithei Le ViFi oi a moLile netwoik (GPRS, EDGE, HSPN, oi 3G, ue-
penuing on youi location), anu the connection`s speeu anu latency will Le changing
88 | Chapter 7:ಗSigning and Publishing Your Application
as the phone moves aiounu. You want to know how these lactois allect the opei-
ation ol youi application, anu how it appeais to the usei.
The emulatoi is guite llexiLle, anu some ol these things can Le testeu to some uegiee
Ly manipulating the emulatoi setup in DDMS (see ¨DDMS: Dalvik DeLug Monitoi
Seivice¨ on page 7+ loi moie aLout DDMS). But again, it is impoitant to stiess that
nothing can ieplace testing on ieal Nnuioiu uevices.
Attach an End User License Agreement If Desired
Viitually eveiy application that you uownloau onto a uesktop oi noteLook computei
will contain an Enu Usei License Ngieement. You shoulu seiiously consiuei whethei
you want to attach such a license to youi application anu have useis agiee to it Leloie
they install the application on theii phone. Typically it limits what useis aie alloweu
to uo with the application, uelines whethei it can Le useu loi commeicial puiposes,
specilically uoes not allow ieveise engineeiing, anu tiies to piotect you, the authoi,
shoulu something go wiong anu someone has ieason to Liing a lawsuit against you.
Theie aie many such EULNs availaLle on the Inteinet. You can eithei auopt one ol
those as youi own oi hiie a lawyei to cieate a unigue one loi you, Lut the use ol a EULN
is stiongly auviseu.
Create and Attach an Icon and Label
Vhen youi application is installeu (on eithei the emulatoi oi a ieal uevice), an icon
anu a laLel aie placeu on the Npplication Launchei that is pait ol youi Nnuioiu Desktop.
This is how most useis will launch youi application, so you neeu a small giaphic (in
the loim ol a PNG lile) loi the icon, anu a shoit laLel loi youi piogiam. Icons aie small
sguaie (6+×6+ pixel) pictuies. Figuie 7-1 shows the one we useu loi M]Nnuioiu.
Iigurc 7-1. MjAndroid icon
The icon anu the laLel aie Loth assigneu in the AndroidManifcst.xn| lile. Heie is the
section ol the lile loi M]Nnuioiu that uelines the icon (in the lile icon2.png, locateu
unuei the rcs/drawab|c uiiectoiy) anu the laLel (liom the strings.xn| lile unuei rcs/
va|ucs):
<application android:icon="@drawable/icon2" android:debuggable="true">
<uses-library android:name="com.google.android.maps" />
<activity android:name=".MicroJobs" android:label="@string/app_name">
<intent-filter>
...
Create and Attach an Icon and Label | 89
Clean Up for Release
Il you`ie like most uevelopeis, youi path to completing youi application was not lineai.
You tiieu some things, kept some, stoppeu using otheis, put in uiagnostics when things
uiun`t woik guite iight, nameu some things that you latei wisheu you`u nameu uillei-
ently, anu so loith. Now is the time to clean all that up. Once youi application is out
in the ieal woilu, you`ll have to suppoit this veision, anu it woulu Le goou loi you il
the coue weie as clean as possiLle:
º Tuin oll ueLug anu logging coue. You uon`t ieally want youi ueployeu application
eating up piecious moLile phone stoiage Ly geneiating logliles, anu the usei
won`t Le aLle to unueistanu youi ueLug messages anyway. Il you haven`t alieauy,
cieate a Loolean to switch them oll anu leave them oll loi now. Nnu iemove
android:debuggable=true liom the AndroidManifcst.xn| lile (see the eailiei exam-
ple) to make suie ueLug is tuineu oll.
º Clean up youi coue wheievei possiLle. Make the naming consistent, ieoiuei meth-
ous in some ieasonaLle way, anu tiy to impiove ieauaLility. Even il you`ie the next
peison to look at it, you won`t iememLei what you uiu six months liom now.
º Remove any test uata that you incluueu÷paiticulaily anything that`s piivate oi
piopiietaiy (like youi name anu auuiess in a Contacts uataLase).
º Delete any extianeous liles liom the pioject: olu logliles, souice liles that you no
longei incluue in the application, etc.
Version Your Application
Nll applications suLmitteu to Nnuioiu Maiket must Le veisioneu anu nameu. You uo
that with simple statements in AndroidManifcst.xn|, as shown in the lollowing segment
ol M]Nnuioiu`s manilest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.microjobsinc.mjandroid" android:versionCode="1"
android:versionName="1.0">
OLviously you want the veision numLeiing anu naming to make sense. Nnuioiu Maiket
ieally only caies aLout the versionCode, which neeus to Le monotonically incieasing
loi each ielease ol youi application, so a uownloauing uevice will know when to up-
giaue to new veisions.
Obtaining a Signing Certificate and API Key
Beloie you can puLlish youi application to Nnuioiu Maiket anu have eveiy Nnuioiu
usei in the woilu uownloau it, you liist must sign youi application. In lact, you`ve Leen
signing youi application all along, Lecause the Nnuioiu Soltwaie Development Kit
90 | Chapter 7:ಗSigning and Publishing Your Application
geneiates a ueLug signatuie that is useu eveiy time you iun youi application liom
Eclipse. The catch is that you cannot use the ueLug signatuie to puLlish youi applica-
tion to the woilu at laige; you must geneiate a new signatuie.
Il you`ie lamiliai with othei moLile uevelopment enviionments (]2ME, SymLian,
BREV, etc.), you`ie pioLaLly an olu hanu at signing applications. But il you`ie new to
ueveloping moLile applications, you may Le asking youisell what all this signing stull
is loi, anyway. Nnuioiu uses application signing loi only one puipose: to ensuie that
applications that claim to Le liom the same uevelopei actually aie. Npplications liom
the same uevelopei have special capaLilities, uiscusseu in the next section.
Google has stateu that one ol its intentions with Nnuioiu was to minimize the hassle
ol getting applications signeu. You uon`t have to go to a cential signing authoiity to
get a signing ceitilicate; you can cieate the ceitilicate youisell. Once you geneiate the
ceitilicate, you can sign youi application using the jarsigner tool that comes with the
]ava ]DK. Once again, you uon`t neeu to apply loi oi get anyone`s appioval. Ns you`ll
see, it`s aLout as stiaightloiwaiu as signing can Le.
Getting a Signing Certificate for an Application You Are Going to Ship
To sign youi application, you aie going to cieate an enciypteu signing ceitilicate anu
use it to sign youi application. You can sign eveiy Nnuioiu application you uevelop
with the same signing ceitilicate. You can cieate as many signing ceitilicates as you
want, Lut you ieally neeu only one loi all youi applications. Nnu using one ceitilicate
loi all youi applications lets you uo some things that you coulun`t uo otheiwise:
Sinp|ify upgradcs
Signing ceitilicates aie tieu to the application package name, so il you change the
signing ceitilicate you use with suLseguent veisions ol youi application, you`ll have
to change the package name, too. Changing ceitilicates is manageaLle, Lut messy.
Mu|tip|c app|ications pcr proccss
Vhen all youi applications shaie the same signing ceitilicate, they can iun in the
same Linux piocess. You can use this to sepaiate youi application into smallei
mouules (each one an Nnuioiu application) that togethei make up the laigei ap-
plication. Il you weie to uo that, you coulu upuate the mouules sepaiately anu they
coulu still communicate lieely.
Codc/data sharing
Nnuioiu lets you enaLle oi iestiict access to paits ol youi application Laseu on the
ieguestei`s signing ceitilicate. Il all youi applications shaie the same ceitilicate, it`s
easy loi you to ieuse paits ol one application in anothei.
One ol the things you`ll Le askeu when you geneiate a key paii anu ceitilicate is the
valiuity peiiou you uesiie loi the ceitilicate. Google iecommenus that you set it loi at
least 25 yeais, anu in lact, il you`ie going to use Nnuioiu Maiket to uistiiLute youi
Obtaining a Signing Certificate and API Key | 91
application, it ieguiies a valiuity uate at least until OctoLei 22, 2033 (25 yeais to the
uay liom when they openeu Nnuioiu Maiket) loi youi ceitilicate.
Generating a key pair (public and private keys) and a signing certificate
To geneiate a paii ol puLlic/piivate keys, use a tool calleu keytool, which came with
the Sun ]DK when you installeu it onto youi uevelopment computei. keytool asks you
loi some inloimation anu uses that to geneiate the paii ol keys:
º N piivate key that will Le kept in a keystoie on youi computei, secuieu with pass-
woius. You will use the piivate key to sign youi application, anu il you neeu a Map
NPI Key loi youi application, you will use the MD5 lingeipiint ol the signing cei-
tilicate to geneiate the Map NPI Key.
'
º N puLlic key that Nnuioiu can use to ueciypt youi signing ceitilicate. You will senu
the puLlic key along with youi puLlisheu application so that it can Le maue avail-
aLle in the iuntime enviionment. Signing ceitilicates aie actually checkeu only at
install time, so once installeu, youi application is goou to iun, even il the ceitilicate
oi keys expiie.
keytool is pietty stiaightloiwaiu. Fiom youi opeiating system`s commanu line, entei
something like:
$ keytool -genkey -v -keystore microjobs.keystore -alias mjkey -keyalg RSA
-validity 10000
This asks keytool to geneiate a key paii anu sell-signeu ceitilicate (-genkey) in veiLose
moue (-v), so you get all the inloimation, anu put it in a keystoie calleu
nicrojobs.|cystorc (-keystore). It also says that in the lutuie you want to ielei to that
key Ly the name mjkey (-alias), anu that keytool shoulu use the RSN algoiithm loi
geneiating puLlic/piivate key paiis (-keyalg). Finally, we say that we`u like the key to
Le valiu loi 10,000 uays (-validity), oi aLout 27 yeais.
keytool will piompt you loi some things it uses to Luilu the key paii anu ceitilicate:
º N passwoiu to Le useu in the lutuie when you want to access the keystoie
º Youi liist anu last names
º Youi oiganizational unit (the name loi youi uivision ol youi company, oi some-
thing like ¨sell¨ il you aien`t ueveloping loi a company)
º Youi oiganization name (the name ol youi company, oi anything else you want to
use)
º The name ol youi city oi locality
'
Il you`ie not lamiliai with MD5, you can linu many ieleiences on the Inteinet. Foi oui puiposes, you can
think ol it as a hash algoiithm that cieates a 128-Lit lingeipiint ol an aiLitiaiily long stiing. It is olten useu
to valiuate uownloaueu liles on the Inteinet, anu heie it is a way ol conveniently valiuating anu conuensing
a signing ceitilicate so it can Le easily veiilieu anu compaieu Ly Google Maps.
92 | Chapter 7:ಗSigning and Publishing Your Application
º The name ol youi state oi piovince
º The two-lettei countiy coue wheie you aie locateu
keytool will then echo all this inloimation Lack to you to make suie it`s accuiate, anu
il you conliim the inloimation, will geneiate the key paii anu ceitilicate. It will then
ask you loi anothei passwoiu to use loi the key itsell (anu give you the option ol using
the same passwoiu you useu loi the keystoie). Using that passwoiu, keytool will stoie
the key paii anu ceitilicate in the keystoie.
You can get moie inloimation aLout secuiity, key paiis, anu the keytool utility on Sun`s
weLsite at http://java.sun.con/j2sc/1.5.0/docs/too|docs/=sccurity.
Getting a Signing Certificate While Debugging
Vhen you`ie cieating anu ueLugging youi application that uses a MapView, oi when
you`ie iunning a uemo application like M]Nnuioiu, you still neeu a valiu Map NPI Key
to get map tiles liom Google Maps, anu you neeu the lingeipiint ol youi ueLug signing
ceitilicate to oLtain a Map NPI Key. You can`t just use the apiKey that we have coueu
into the M]Nnuioiu souice liles, Lecause it is tieu to the signing ceitilicate that was
geneiateu Ly oui ueLug enviionment. Youi ueLug enviionment will geneiate its own,
uilleient signing ceitilicate loi you to use, so you neeu to oLtain a Map NPI Key to
match.
Theie aie two steps to getting the key:
1. Get a copy ol the MD5 lingeipiint loi youi DeLug signing ceitilicate.
2. Use that lingeipiint to oLtain a valiu Map NPI Key liom Google anu entei it into
AndroidManifcst.xn|.
Getting the MD5 fingerprint of your Debug signing certificate
Vhen the Nnuioiu SDK automatically geneiates a DeLug signing ceitilicate loi you, it
places it in a keystoie calleu dcbug.|cystorc. The tiick is to linu this keystoie. Nt least
loi the cuiient veision ol the SDK, as this is Leing wiitten, the location is opeiating
system uepenuent:
º Unuei Linux anu Mac OS X, it is in the .android suLuiiectoiy unuei youi home
uiiectoiy: -/.android/dcbug.|cystorc.
º Unuei Vinuows Vista, it`s a little haiuei to linu; it`s unuei youi peisonal
Npplication Data uiiectoiy: C:\Uscrs\your_username\AppData\Loca|\Android
\dcbug.|cystorc.
º Vinuows XP is similai to Vista: C:\Docuncnts and Scttings\your_username\Loca|
Scttings\App|ication Data\Android\dcbug.|cystorc (unlike Vista, you will neeu to
use a guoteu stiing loi the XP shell).
Obtaining a Signing Certificate and API Key | 93
Once you`ve lounu dcbug.|cystorc, keytool can give you the MD5 lingeipiint ol youi
DeLug signing ceitilicate. Unuei Linux oi OS X you`u type:
$ keytool -list -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass
android -keypass android
Foi Vista oi XP, just suLstitute the coiiect location in the -keystore option. keytool
piints the uate the DeLug signing ceitilicate was cieateu anu the MD5 lingeipiint. Ns
an inteiesting note, DeLug signing ceitilicates aie goou loi 365 uays altei cieation.
What Happens When My Debug Signing Certificate Expires?
Nltei youi ceitilicate expiies, you`ll get a Luilu eiioi whenevei you tiy to Luilu youi
application. The eiioi will Le uisplayeu on the Nnuioiu console (one ol the taLs in the
Lottom pane ol the ]ava anu DDMS Peispectives), anu it will say something like:
debug:
[echo] Packaging bin/samples-debug.apk, and signing it with a debug key...
[exec] Debug Certificate expired on 8/4/08 3:43 PM
To lix it, just uelete youi dcbug.|cystorc lile (see the eailiei list loi its location in uilleient
host opeiating systems). The next time you Luilu, the Nnuioiu SDK will geneiate a new
dcbug.|cystorc with a new DeLug signing ceitilicate, anu youi application can Luilu
anu iun.
Now that you have the MD5 lingeipiint ol youi DeLug Signing Ceitilicate, you can use
it to get a valiu Map NPI Key loi youi system.
Getting a Map API Key from Google
Now that you have a signing ceitilicate to use loi youi application, you can apply to
Google loi a Map NPI Key. Map NPI Keys aie tieu to a signing ceitilicate, so oLviously
the Map NPI Key you get will woik only with applications signeu with the same cei-
tilicate (anothei goou ieason loi sticking with the same ceitilicate loi all youi applica-
tions). Getting the key is pietty easy, anu it`s liee.
Vhen an application that contains a MapView iuns, it ieguests map ¨tiles¨ liom Goo-
gle Maps via the Inteinet. Ns pait ol that ieguest, it senus the Map NPI Key that was
oLtaineu when the uevelopei signeu up with Google, as well as the MD5 lingeipiint ol
the application`s signing ceitilicate. Google Maps checks to see that the key is iegisteieu
to a uevelopei, anu then checks to see that the Map NPI Key matches the one on lile
loi applications with that signing ceitilicate lingeipiint. Il they match, it senus the
ieguesteu tiles. Il they uon`t match, no tiles aie sent.
So we`ie going to neeu the MD5 lingeipiint ol the signing ceitilicate that we just cieateu.
Foitunately, keytool can get that loi us:
$ keytool -list -alias mjkey -keystore microjobs.keystore
94 | Chapter 7:ಗSigning and Publishing Your Application
keytool asks loi the passwoius to the keystoie (anu key, il they`ie uilleient), anu piints
out the MD5 lingeipiint in hexauecimal. Use youi mouse to copy the lingeipiint so
you can paste it into the Google page latei.
Now you can go to the Google Map NPI Key weLsite at http://codc.goog|c.con/android/
naps-api-signup.htn| to actually get the Map NPI Key. The Teims ol Seivice aie shown
in a text Lox. Reau them, anu il appiopiiate, click on the checkLox that inuicates you
accept. Paste the MD5 lingeipiint into the loim, click the ¨Geneiate NPI key¨ Lutton,
anu the weLsite will ask you to log into youi Google account. Il you uon`t have a Google
account, you can guickly cieate one on the spot.
Once you log in, the weLsite ietuins the Map NPI Key, which can Le useu with any
application that uses the signing ceitilicate whose lingeipiint you enteieu. It`s a long
alphanumeiic stiing, so you will want to copy it into youi clipLoaiu anu paste it into
the XML layout lile loi youi Map Nctivity.
Ns an example, the XML layout lile loi M]Nnuioiu`s Map Nctivity (calleu Micio]oLs)
has the lollowing section uelining the MapView anu the NPI Key that matches oui
ueLug enviionment:
<com.google.android.maps.MapView
android:id="@+id/mapmain"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="0P18K0TAE0dO2GifdtbuScgEGLWe3p4CYUQngMg"
/>
Ol couise, you will have to suLstitute youi own apiKey loi ouis.
Signing Your Application
Ve`ie almost ieauy to sign youi application, Lut liist you neeu to cieate an unsigncd
veision that you can sign with youi signatuie ceitilicate. To uo that, in the Package
Exploiei winuow ol Eclipse, iight-click on youi pioject name. You`ll get a long pop-
up menu; towaiu the Lottom, click on Android Tools. You shoulu see anothei menu
that incluues the item you want: ¨Expoit Unsigneu Npplication Package...¨. This item
takes you to a File Save uialog Lox, wheie you can pick the place to save the unsigneu
veision ol youi ap| lile. It uoesn`t mattei wheie you put it÷just pick a place you can
iememLei.
Now that you have an unsigneu veision ol youi ap| lile, we can go aheau anu sign it
using jarsigner. Open a teiminal oi commanu winuow in the uiiectoiy wheie you
stoieu the unsigneu ap| lile. Heie`s the line we useu to sign M]Nnuioiu, using the key
we geneiateu eailiei in the keystoie microjobs.keystore:
$ jarsigner -verbose -keystore microjobs.keystore MJAndroid.apk mjkey
Signing Your Application | 95
Congiatulations! You now have a signeu veision ol youi application that can Le loaueu
anu iun on any Nnuioiu uevice. But Leloie you senu it in to Nnuioiu Maiket, theie`s
one moie inteivening step....
Retesting Your Application
Il eveiything went smoothly, youi application is now signeu anu will lunction just as
well as it uiu Leloie you went thiough this piocess. But to Le suie things went smoothly,
it is wise to ietest youi application, again testing on ieal Nnuioiu uevices wheie possiLle.
You ieally uon`t want thousanus ol people uownloauing a Lioken application attiiL-
uteu to you, so just to Le sale, ietest on as many Nnuioiu uevices as you can get youi
hanus on.
Publishing on Android Market
Nltei you`ie satislieu that youi application iuns as expecteu on ieal Nnuioiu uevices,
you`ie ieauy to uploau to Nnuioiu Maiket, Google`s seivice loi puLlishing anu uown-
loauing Nnuioiu applications. The pioceuuie is pietty stiaightloiwaiu:
1. Sign up as an Nnuioiu Developei (il you`ie not alieauy signeu up).
2. Uploau youi signeu application.
Signing Up As an Android Developer
Go to Google`s weLsite at http://nar|ct.android.con/pub|ish, anu lill out the loims
pioviueu. Ns this is wiitten, Nnuioiu Maiket is still in Leta, anu you will Le askeu to:
º Use youi Google account to log in (il you uon`t have a Google account, you can
get one loi liee Ly lollowing the Cieate Nccount link on the login page).
º Ngiee to the Nnuioiu Maiket Teims ol Seivice.
º Pay a one-time lee ol $25 (payaLle Ly cieuit caiu via Google Checkout; again, il
you uon`t have an account set up, you can uo so guickly).
The loims ask loi a minimal amount ol inloimation÷youi name, phone numLei,
etc.÷anu you aie signeu up.
Uploading Your Application
Now you can go to http://nar|ct.android.con/pub|ish/Honc to uploau youi applica-
tion. To iuentily anu categoiize youi application, you will Le askeu loi the lollowing:
App|ication ap| fi|c Nanc and Location
The ap| lile ol youi application, signeu with youi piivate signatuie ceitilicate.
96 | Chapter 7:ಗSigning and Publishing Your Application
Tit|c and Dcscription
These aie veiy impoitant, Lecause they aie the coie ol youi maiketing message to
potential useis. Tiy to make the title uesciiptive anu catchy at the same time, anu
uesciiLe the application in a way that will make youi taiget maiket want to uown-
loau it.
App|ication Typc
Theie aie cuiiently two choices: Npplications oi Games.
Catcgory
The allowaLle list ol categoiies vaiies uepenuing on Npplication Type. The
cuiiently availaLle categoiies loi Npplications aie: Communications, Demo, En-
teitainment, Finance, Lilestyle, Multimeuia, News e Veathei, Piouuctivity, Rel-
eience, Shopping, Social, Soltwaie LiLiaiies, Tools, anu Tiavel. Foi Games, the
cuiiently availaLle categoiies incluue: Nicaue e Nction, Biain e Puzzle, Caius e
Casino, anu Casual.
Pricc
This must Le ¨Fiee¨ unuei the Leta veision ol Nnuioiu Maiket. Google has saiu
they will enaLle chaiging loi applications in the neai lutuie (mayLe Ly the time
you ieau this).
Gcography
You can limit wheie youi application is availaLle, oi choose to make it availaLle
eveiywheie.
Finally, you aie askeu to conliim that youi application meets the Nnuioiu Content
Guiuelines anu that it uoes not knowingly violate any expoit laws. Nltei that, you can
uploau youi ap| lile, anu within a lew uays youi application will appeai on the Nnuioiu
Maiket online catalog, accessiLle liom any connecteu Nnuioiu uevice. Theie is cui-
iently no way to access Nnuioiu Maiket uiiectly liom youi PC oi Mac, so you`ll have
to use youi Nnuioiu phone to linu out when youi application is availaLle loi uownloau.
Publishing on Android Market | 97
PART II
Programming Topics
Nltei getting ieauy to wiite youi own piogiams Ly ieauing Pait I, you can leain how
to make the most ol Nnuioiu`s liLiaiies in this pait ol the Look. Ve covei uataLases,
giaphics, intei-piocess communication, anu telephony.
CHAPTER 8
Persistent Data Storage: SQLite
Databases and Content Providers
To accomplish many ol the activities olleieu Ly mouein moLile phones, such as tiack-
ing contacts, events, anu tasks, the opeiating system anu applications must Le auept
at stoiing anu keeping tiack ol laige guantities ol uata. Most ol this uata is stiuctuieu
like a spieausheet, in the loim ol iows anu columns. Each Nnuioiu application is like
an islanu unto itsell, in that each application is only alloweu to ieau anu wiite uata that
it has cieateu, Lut shaiing uata acioss application Lounuaiies is necessaiy. Nnuioiu
suppoits the content pioviuei leatuie mentioneu in Chaptei 1 so that applications can
shaie uata.
In this chaptei we examine two uistinct uata access NPIs that the Nnuioiu liamewoik
olleis:
SQLitcDatabasc
Nnuioiu`s ]ava inteilace to its ielational uataLase, SQLite. It suppoits an SQL im-
plementation iich enough loi anything you`ie likely to neeu in a moLile applica-
tion, incluuing a cuisoi lacility.
ContcntProvidcr
Nn inteilace useu Letween applications. The seivei application that hosts the uata
manages it thiough Lasic cieate, ieau, upuate, anu uelete (CRUD) opeiations. The
client application uses a similai NPI, Lut the Nnuioiu liamewoik tiansmits the
client`s ieguests to the seivei. Ve`ll show Loth the seivei NPI anu the client NPI
in this chaptei.
Databases
Data is Lest stoieu in a ielational uataLase loimat il it can incluue many instances ol
the same type ol thing. Take a contact list, loi instance. Theie aie many contacts, all
ol whom potentially have the same types ol inloimation (auuiess, phone numLei, etc.).
Each ¨iow¨ ol uata stoies inloimation aLout a uilleient peison, while each ¨column¨
101
stoies a specilic attiiLute ol each peison: names in one column, auuiesses in anothei
column, anu home phone numLeis in a thiiu.
Nnuioiu uses the SQLite uataLase engine, a sell-containeu, tiansactional uataLase
engine that ieguiies no sepaiate seivei piocess. It is useu Ly many applications anu
enviionments Leyonu Nnuioiu, anu is Leing actively uevelopeu Ly a laige community.
The piocess that initiates a uataLase opeiation, such as a SELECT oi UPDATE, uoes the
actual woik ol ieauing oi wiiting the uisk lile that contains the uataLase in oiuei to
lullill the ieguest. Vith SQLite, the uataLase is a simple uisk lile. Nll ol the uata stiuc-
tuies making up a ielational uataLase÷taLles, views, inuexes, etc.÷aie within this lile.
SQLite is not a Google pioject, although Google has contiiLuteu to it. SQLite has an
inteinational team ol soltwaie uevelopeis who aie ueuicateu to enhancing the solt-
waie`s capaLilities anu ieliaLility. Some ol those uevelopeis woik lull time on the
pioject.
ReliaLility is a key leatuie ol SQLite. Moie than hall ol the coue in the pioject is uevoteu
to testing the liLiaiy. The liLiaiy is uesigneu to hanule many kinus ol system lailuies,
such as low memoiy, uisk eiiois, anu powei lailuies. In no case shoulu the uataLase
Le lelt in an uniecoveiaLle state: this woulu Le a showstoppei on a moLile phone, wheie
ciitical uata is olten stoieu in a uataLase. Il that uataLase weie susceptiLle to easy
coiiuption, the moLile phone coulu Lecome an expensive papeiweight il the Latteiy
weie to lail at an inoppoitune time.
This is not a Look on SQL, so we will not go into much uetail aLout the uataLase
commanus themselves. Nmple uocumentation aLout SQL in geneial anu SQLite in
paiticulai can Le lounu on the VeL. But the SQL we use in oui examples shoulu Le a
goou staiting point loi youi own applications.
Ve`ll use the MicrojobsDatabasc.java lile liom oui Micio]oLs example application to
uiscuss how to cieate anu use a SQLite uataLase using Nnuioiu. This is the suLject ol
the next section.
Basic Structure of the MicroJobsDatabase Class
In oui example, the MicrojobsDatabasc.java lile completely encapsulates all ol the SQL
logic necessaiy to woik with the uataLase. Nll ol the othei ]ava classes in the Micio]oLs
application woik with stanuaiu ]ava classes oi Cuisois anu aie unawaie ol how the
uata is actually stoieu. This is goou piogiamming piactice anu shoulu Le emulateu in
all ol youi Nnuioiu applications that use uataLases.
Beloie we uelve too ueeply into the guts ol cieating a uataLase anu selecting uata liom
it, it`s impoitant to unueistanu the geneial layout ol the MicroJobsDatabase class.
MicroJobsDatabase inheiits liom the aLstiact SQLiteOpenHelper class, anu theieloie
must oveiiiue the onCreate anu onUpgrade methous. The onCreate methou is automat-
ically calleu when the application staits loi the liist time; its joL is to cieate the uataLase.
102 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
Ns newei veisions ol the application aie shippeu, the uataLase on the phone tenus to
Le upuateu, a task that lalls to the onUpgrade methou. Vhen you ship a new veision ol
a uataLase, you must also inciement the veision numLei, as we`ll explain.
The geneial elements in MicroJobsDatabase coue aie:
Constants
The MicroJobsDatabase class uelines two impoitant constants:
DATABASE_NAME
This holus the lilename ol the uataLase, "MicroJobs" in this case.
Heie is the lull path to the Micio]oLs lile: /data/data/
con.nicrojobsinc.njandroid/databascs/Microjobs. You can
use the adb pull commanu line on youi uesktop (see the uis-
cussion ol adb in ¨The Tools¨ on page 57) to pull the uataLase
liom the emulatoi oi uevelopei uevice anu then ueLug it using
the SQLitc3 executaLle on the uesktop.
DATABASE_VERSION
This uelines the uataLase veision unueistoou Ly the soltwaie that uelines
the constant. Il the veision ol the uataLase on the machine is less than
DATABASE_VERSION, the application shoulu iun onUpgrade to upgiaue the uata-
Lase to the cuiient level.
Constructor
The constiuctoi loi the uataLase in this piogiam, MicroJobsDatabase, uses the
super lunction to call its paient`s constiuctoi. The paient uoes most ol the woik
ol cieating the uataLase oLject. One thing oui MicroJobsDatabase constiuctoi has
to uo is stoie the Context oLject. This step is not ieguiieu in applications whose
uataLase coue is encapsulateu within an enclosing content pioviuei class, Lecause
the ContentProvider class has a getContext call that will pioviue the Context oLject
when necessaiy. Since Micio]oLs is a stanualone uataLase class, it has to keep the
Context oLject aiounu in its own piivate vaiiaLle. In the case ol Micio]oLs, the
Context oLject is ieally the Activity oLject that opens the uataLase. Nn Nctivity is
a Context. The Context oLject is the inteilace to application-gloLal iesouices anu
classes as well as application-level opeiations, such as Lioaucasting Intents anu
launching activities.
onCreate
Vhen an Nnuioiu application attempts to ieau oi wiite uata to a uataLase that
uoes not exist, the liamewoik executes the onCreate methou. The onCreate methou
in the MicroJobsDatabase class shows one way to cieate the uataLase. Because so
much SQL coue is ieguiieu to cieate the uataLase anu populate it with sample uata,
we`ve chosen to segiegate all ol the SQL coue invokeu Ly onCreate into the
strings.xn| iesouice lile; this makes the ]ava coue much moie ieauaLle Lut loices
Databases | 103
the uevelopei to look in two sepaiate liles to see what`s ieally going on. Vhen we
look at the custom Cuisoi classes latei in this chaptei, we`ll see that SQL can Le
emLeuueu into the application souice coue as well. It`s ieally a mattei ol style.
To actually cieate the uataLase, the liist line ol the onCreate methou loaus the
SQL stiing ieleienceu Ly the MicroJobsDatabase_onCreate iesouice iuentiliei
into a String aiiay nameu sql. Note the lollowing coue snippets liom
MicrojobsDatabasc.java:
String[] sql =
mContext.getString(R.string.MicroJobsDatabase_onCreate).split("\n");
anu liom strings.xn|:
<string name="MicroJobsDatabase_onCreate">"
CREATE TABLE jobs (_id INTEGER PRIMARY KEY AUTOINCREMENT, employer_id INTEGER,
title TEXT, description TEXT, start_time INTEGER, end_time INTEGER,
status INTEGER);
CREATE TABLE employers( _id INTEGER, employer_name TEXT, ...
CREATE TABLE workers( _id INTEGER PRIMARY KEY AUTOINCREMENT, ...
CREATE TABLE status( _id INTEGER PRIMARY KEY AUTOINCREMENT, ...
INSERT INTO status (_id , status) VALUES (NULL, 'Filled');
INSERT INTO status (_id , status) VALUES (NULL, 'Applied For');
INSERT INTO status (_id , status) VALUES (NULL, 'Open');
...
"</string>
The single getString line ol ]ava coue loaus the SQL ieguiieu to cieate the uata-
Lase, along with a ieasonaLle amount ol test uata.
One ciucial piece ol inloimation mentioneu only Liielly in the Nn-
uioiu uocumentation is that you must eithei escape all single
guotes anu uouLle guotes with a Lackslash (###BOT_TEXT###quot; oi

) within a ie-
souices stiing oi enclose the entiie stiing in eithei single oi uouLle
guotes. Il single anu uouLle guotes aie mixeu in a iesouice
stiing, they must Le escapeu. In the case ol the MicroJobs
Database_onCreate stiing just shown, notice that the entiie thing is
suiiounueu with uouLle guotes.
The iest ol the onCreate methou iuns each line ol SQL. The entiie piocess iuns unuei
a tiansaction so that it will eithei execute completely oi Le iolleu Lack anu have
no ellect at all on the uataLase.
onUpdate
In the Micio]oLs application, the onUpdate methou is veiy similai in stiuctuie to
the onCreate methou. Howevei, the contents ol the strings.xn| iesouice lile aie
guite uilleient:
<string name="MicroJobsDatabase_onUpgrade">"
DROP TABLE IF EXISTS jobs
DROP TABLE IF EXISTS employers
104 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
DROP TABLE IF EXISTS workers
DROP TABLE IF EXISTS status
"</string>
The opening <string> tag is lolloweu Ly a uouLle guotation maik to stait a stiing,
anu a closing guotation maik enus the stiings Leloie the </string> tag. Vithin the
stiing aie loui iathei uiastic SQL commanus. To suppoit the uemonstiation coue
in this Look, we cheat a little. The ¨upgiaue¨ coue iemoves the olu uataLase anu
ie-cieates it with whatevei is in the cuiient veision ol the coue. Nlthough this is
nice loi a Look, it won`t woik veiy well in ieal lile. Youi customeis won`t Le veiy
happy il they have to ie-key theii inloimation each time they upgiaue soltwaie
veisions! N ieal application woulu have seveial upgiaue sciipts, one loi each vei-
sion that might Le out in the wilu. Ve woulu execute each upgiaue sciipt, one at
a time, until the phone`s uataLase is completely up-to-uate.
The stiuctuial paits ol MicroJobsDatabase.java lollow. The custom Cuisois anu the
puLlic lunctions that ietuin them aie uiscusseu next.
MicroJobsDatabase.java (structure):
package com.microjobsinc.mjandroid;
import ...
/**
* Provides access to the MicroJobs database. Since this is not a Content Provider,
* no other applications will have access to the database.
*/
public class MicroJobsDatabase extends SQLiteOpenHelper {
/** The name of the database file on the file system */
private static final String DATABASE_NAME = "MicroJobs";
/** The version of the database that this class understands. */
private static final int DATABASE_VERSION = 1;
/** Keep track of context so that we can load SQL from string resources */
private final Context mContext;
/** Constructor */
public MicroJobsDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.mContext = context;
}
/** Called when it is time to create the database */
@Override
public void onCreate(SQLiteDatabase db) {
String[] sql =
mContext.getString(R.string.MicroJobsDatabase_onCreate).split("\n");
db.beginTransaction();
try {
// Create tables and test data
execMultipleSQL(db, sql);
db.setTransactionSuccessful();
} catch (SQLException e) {
Log.e("Error creating tables and debug data", e.toString());
Databases | 105
throw e;
} finally {
db.endTransaction();
}
}
/** Called when the database must be upgraded */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(MicroJobs.LOG_TAG, "Upgrading database from version " + oldVersion +
" to " +
newVersion + ", which will destroy all old data");
String[] sql =
mContext.getString(R.string.MicroJobsDatabase_onUpgrade).split("\n");
db.beginTransaction();
try {
execMultipleSQL(db, sql);
db.setTransactionSuccessful();
} catch (SQLException e) {
Log.e("Error upgrading tables and debug data", e.toString());
throw e;
} finally {
db.endTransaction();
}
// This is cheating. In the real world, you'll need to add columns, not
rebuild from scratch.
onCreate(db);
}
/**
* Execute all of the SQL statements in the String[] array
* @param db The database on which to execute the statements
* @param sql An array of SQL statements to execute
*/
private void execMultipleSQL(SQLiteDatabase db, String[] sql){
for( String s : sql )
if (s.trim().length()>0)
db.execSQL(s);
}
}
Heie aie some ol the highlights ol the coue:
Constiucts the MicroJobsDatabase oLject. Ve pass the paient class the uataLase
name anu veision, anu it keeps tiack ol when to simply open the uataLase anu when
to upgiaue the veision. The uataLase itsell is not openeu heie÷that happens in
iesponse to a getReadableDatabase oi getWritableDatabase call. Ve also keep a pii-
vate ieleience to the Context oLject in the constiuctoi.
Retiieves stiings containing SQL coue, which we have chosen to stoie in a iesouice
lile loi easiei ieauaLility anu maintenance.
106 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
Begins the tiansaction within which all the SQL statements will execute to cieate
the uataLase.
Enus the tiansaction, cieating the uataLase.
Function to call in oiuei to upgiaue the uataLase.
Function that executes each SQL statement ietiieveu Ly item 2.
Reading Data from the Database
Theie aie many ways to ieau uata liom an SQL uataLase, Lut they all come uown to a
Lasic seguence ol opeiations:
1. Cieate an SQL statement that uesciiLes the uata that you neeu to ietiieve.
2. Execute that statement against the uataLase.
3. Map the iesulting SQL uata into uata stiuctuies that the language you`ie woiking
in can unueistanu.
This piocess can Le veiy complex in the case ol oLject-ielational mapping soltwaie, oi
ielatively simple when wiiting the gueiies uiiectly into youi application. The uilleience
is liagility. Complex ORM tools shielu youi coue liom the complexities ol uataLase
piogiamming anu oLject mapping Ly moving that complexity elsewheie. The iesult is
that youi coue is moie ioLust in the lace ol uataLase changes, Lut at the cost ol complex
ORM setup anu maintenance.
The simple appioach ol wiiting gueiies uiiectly into youi application woiks well only
loi veiy small piojects that will not change much ovei time. Npplications with uataLase
coue in them aie veiy liagile Lecause as the uataLase changes, any coue that ieleiences
those changes must Le examineu anu potentially changeu.
N common miuule-giounu appioach is to seguestei all ol the uataLase logic into a set
ol oLjects whose sole puipose is to tianslate application ieguests into uataLase ieguests
anu uelivei the iesults Lack to the application. This is the appioach we have taken with
the Micio]oLs application; all ol the uataLase coue is containeu in a single class in the
lile MicrojobsDatabasc.java.
Nnuioiu gives us the aLility to customize Cuisois, anu we use that aLility to luithei
ieuuce coue uepenuencies Ly hiuing all ol the inloimation aLout each specilic uataLase
opeiation insiue a custom cuisoi. Each custom cuisoi is a class within the
MicroJobsDatabase class; the one that we`ll look at in this chaptei is the JobsCursor.
The inteilace to the callei in the getJobs methou ol MicroJobsDatabase appeais liist in
the coue that lollows. The methou`s joL is to ietuin a JobsCursor lilleu with joLs liom
the uataLase. The usei can choose (thiough the single paiametei passeu to getJobs) to
soit joLs Ly eithei the title column oi the employer_name column:
public class MicroJobsDatabase extends SQLiteOpenHelper {
...
Databases | 107
/** Return a sorted JobsCursor
* @param sortBy the sort criteria
*/
public JobsCursor getJobs(JobsCursor.SortBy sortBy) {
String sql = JobsCursor.QUERY + sortBy.toString();
SQLiteDatabase d = getReadableDatabase();
JobsCursor c = (JobsCursor) d.rawQueryWithFactory(
new JobsCursor.Factory(),
sql,
null,
null);
c.moveToFirst();
return c;
}
...
public static class JobsCursor extends SQLiteCursor{
public static enum SortBy{
title,
employer_name
}
private static final String QUERY =
"SELECT jobs._id, title, employer_name, latitude, longitude, status "+
"FROM jobs, employers "+
"WHERE jobs.employer_id = employers._id "+
"ORDER BY ";
private JobsCursor(SQLiteDatabase db, SQLiteCursorDriver driver,
String editTable, SQLiteQuery query) {
super(db, driver, editTable, query);
}
private static class Factory implements SQLiteDatabase.CursorFactory{
@Override
public Cursor newCursor(SQLiteDatabase db,
SQLiteCursorDriver driver, String editTable,
SQLiteQuery query) {
return new JobsCursor(db, driver, editTable, query);
}
}
public long getColJobsId()
{return getLong(getColumnIndexOrThrow("jobs._id"));}
public String getColTitle()
{return getString(getColumnIndexOrThrow("title"));}
public String
getColEmployerName()
{return getString(getColumnIndexOrThrow("employer_name"));}
public long getColLatitude()
{return getLong(getColumnIndexOrThrow("latitude"));}
public long getColLongitude()
{return getLong(getColumnIndexOrThrow("longitude"));}
public long getColStatus(){return getLong(getColumnIndexOrThrow("status"));}
}
Heie aie some ol the highlights ol the coue:
Function that lashions a gueiy Laseu on the usei`s ieguesteu soit column (the
sortBy paiametei) anu ietuins iesults as a cuisoi.
108 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
Cieates the gueiy stiing. Most ol the stiing is static (the QUERY vaiiaLle), Lut this line
tacks on the soit column. Even though QUERY is piivate, it is still availaLle to the
enclosing class. This is Lecause the getJobs methou anu the the JobsCursor class aie
Loth within the MicroJobsDatabase class, which makes JobsCursor`s piivate uata
memLeis availaLle to the getJobs methou.
To get the text loi the soit column, we just iun toString on the enumeiateu value
passeu Ly the usei. The enumeiation is uelineu at item 8. Ve coulu have uelineu an
associative aiiay, which woulu give us moie llexiLility in naming vaiiaLles, Lut this
solution is simplei. Nuuitionally, the names ol the columns pop up guite nicely in
Eclipse`s autocompletion.
Retiieves a hanule to the uataLase.
Cieates the JobsCursor cuisoi using the SQLiteDatabase oLject`s rawQueryWith
Factory methou. This methou lets us pass a lactoiy methou that Nnuioiu will use
to cieate the exact type ol cuisoi we neeu. Il we hau useu the simplei rawQuery
methou, we woulu get Lack a geneiic Cursor that lackeu the special leatuies ol
JobsCursor.
Ns a convenience to the callei, moves to the liist iow in the iesult. This way, the
cuisoi is ietuineu ieauy to use. N common mistake is loigetting the moveToFirst call
anu then pulling youi haii out tiying to liguie out why the Cursor oLject is thiowing
exceptions.
The cuisoi is the ietuin value.
Class that cieates the cuisoi ietuineu Ly getJobs.
Simple way to pioviue alteinate soit ciiteiia: stoie the names ol columns in an
enum. This vaiiaLle is useu in item 2.
Constiuctoi loi the customizeu cuisoi. The linal aigument is the gueiy passeu Ly
the callei.
Factory class to cieate the cuisoi, emLeuueu in the JobsCursor class.
Cieates the cuisoi liom the gueiy passeu Ly the callei.
Retuins the cuisoi to the enclosing JobsCursor class.
Convenience lunctions that extiact paiticulai columns liom the iow unuei the cui-
soi. Foi instance, getColTitle ietuins the value ol the title column in the iow
cuiiently ieleienceu Ly the cuisoi. This sepaiates the uataLase implementation liom
the calling coue anu makes that coue easiei to ieau.
N sample use ol the uataLase lollows. The coue gets a cuisoi, soiteu Ly title, thiough
a call to getJobs. It then iteiates thiough the joLs.
MicroJobsDatabase db = new MicroJobsDatabase(this);
JobsCursor cursor = db.getJobs(JobsCursor.SortBy.title);
Databases | 109
for( int rowNum=0; rowNum<cursor.getCount(); rowNum++){
cursor.moveToPosition(rowNum);
doSomethingWith(cursor.getColTitle());
}
Heie aie some ol the highlights ol the coue:
Cieates a MicroJobsDatabase oLject. The aigument, this, iepiesents the context, as
uiscusseu pieviously.
Cieates the JobsCursor cuisoi, ieleiiing to the SortBy enumeiation uiscusseu eailiei.
Uses geneiic Cuisoi methous to iteiate thiough the cuisoi.
Still within the loop, invokes one ol the custom accessoi methous pioviueu Ly
JobsCursor to ¨uo something¨ chosen Ly the usei with the value ol each iow`s title
column.
Modifying the Database
Nnuioiu Cuisois aie gieat when you want to ieau uata liom the uataLase, Lut the
Cuisois NPI uoes not pioviue methous loi cieating, upuating, oi ueleting uata. The
SQLiteDatabase class pioviues two Lasic inteilaces that you can use loi Loth ieauing
anu wiiting:
º N set ol loui methous calleu simply insert, query, update, anu delete
º N moie geneial execSQL methou that takes any SQL statement anu iuns it against
the uataLase
Ve iecommenu using the liist methou when youi opeiations lit its capaLilities. Ve`ll
show you Loth ways using the M]Nnuioiu opeiations.
Inserting data into the database
The SQL INSERT statement is useu whenevei you want to inseit uata into an SQL
uataLase. The INSERT statement maps to the ¨cieate¨ opeiation ol the CRUD
methouology.
In the M]Nnuioiu application, the usei can auu joLs to the list Ly clicking on the Nuu
]oL menu item when looking at the ]oLs list. The usei can then lill out a loim to input
the employei, joL title, anu uesciiption. Nltei the usei clicks on the Nuu ]oL Lutton on
the loim, the lollowing line ol coue is executeu:
db.addJob(employer.id, txtTitle.getText().toString(),
txtDescription.getText().toString());
This coue calls the addJob lunction, passing in the employei ID, the joL title, anu the
joL uesciiption. The addJob lunction uoes the actual woik ol wiiting the joL out to the
uataLase.
Example 8-1 shows you how to use the insert methou.
110 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
Exanp|c 8-1. Using thc inscrt ncthod
/**
* Add a new job to the database. The job will have a status of open.
* @param employer_id The employer offering the job
* @param title The job title
* @param description The job description
*/
public void addJob(long employer_id, String title, String description){
ContentValues map = new ContentValues();
map.put("employer_id", employer_id);
map.put("title", title);
map.put("description", description);
try{
getWritableDatabase().insert("jobs", null, map);
} catch (SQLException e) {
Log.e("Error writing new job", e.toString());
}
}
Heie aie some ol the highlights ol the coue in Example 8-1:
The ContentValues oLject is a map ol column names to column values. Inteinally,
it`s implementeu as a HashMap<String,Object>. Howevei, unlike a simple HashMap,
ContentValues is stiongly typeu. You can specily the uata type ol each value stoieu
in a ContentValues containei. Vhen tiying to pull values Lack out, ContentValues
will automatically conveit values to the ieguesteu type il possiLle.
The seconu paiametei to the insert methou is nullColumnHack. It`s useu only when
the thiiu paiametei, the map, is null anu theieloie the iow woulu otheiwise Le
completely empty.
Example 8-2 shows you how to use the execSQL methou.
Exanp|c 8-2. Using thc cxccSQL ncthod
/**
* Add a new job to the database. The job will have a status of open.
* @param employer_id The employer offering the job
* @param title The job title
* @param description The job description
*/
public void addJob(long employer_id, String title, String description){
String sql =
"INSERT INTO jobs (_id, employer_id, title, description, start_time, end_time,
status) " +
"VALUES ( NULL, ?, ?, ?, 0, 0, 3)";
Object[] bindArgs = new Object[]{employer_id, title, description};
try{
getWritableDatabase().execSQL(sql, bindArgs);
} catch (SQLException e) {
Log.e("Error writing new job", e.toString());
}
}
Databases | 111
Heie aie some ol the highlights ol the coue in Example 8-2:
Fiist, we Luilu a SQL stiing template nameu sql that contains LinuaLle paiameteis
that will Le lilleu in with usei uata. The LinuaLle paiameteis aie maikeu Ly a gues-
tion maik in the stiing. Next, we Luilu an oLject aiiay nameu bindArgs that contains
one oLject pei element in oui SQL template. Theie aie thiee guestion maiks in the
template, anu theieloie theie must Le thiee elements in the oLject aiiay.
Executes the SQL commanu Ly passing the SQL template stiing anu the Linu aigu-
ments to execSQL. Using a SQL template anu Linu aiguments is much pieleiieu ovei
Luiluing up the SQL statement, complete with paiameteis, into a String oi
StringBuilder. By using a template with paiameteis, you piotect youi application
liom SQL injection attacks. These attacks occui when a malicious usei enteis in-
loimation into a loim that is ueliLeiately meant to mouily the uataLase in a way that
was not intenueu Ly the uevelopei. This is noimally uone Ly enuing the cuiient SQL
commanu piematuiely, using SQL syntax chaiacteis, anu then auuing new SQL
commanus uiiectly in the loim lielu. The template-plus-paiameteis appioach also
piotects you liom moie iun-ol-the-mill eiiois, such as invaliu chaiacteis in the
paiameteis.
Updating data already in the database
The Micio]oLs application enaLles the usei to euit a joL Ly clicking on the joL in the
]oLs list anu choosing the Euit ]oL menu item. The usei can then mouily the stiings
loi employei, joL title, anu uesciiption in the editJob loim. Nltei the usei clicks on the
Upuate Lutton on the loim, the lollowing line ol coue is executeu:
db.editJob((long)job_id, employer.id, txtTitle.getText().toString(),
txtDescription.getText().toString());
This coue calls the editJob methou, passing the joL ID anu the thiee items the usei can
change: employei ID, joL title, anu joL uesciiption. The editJob methou uoes the actual
woik ol mouilying the joL in the uataLase.
Example 8-3 shows you how to use the update methou.
Exanp|c 8-3. Using thc updatc ncthod
/**
* Update a job in the database.
* @param job_id The job id of the existing job
* @param employer_id The employer offering the job
* @param title The job title
* @param description The job description
*/
public void editJob(long job_id, long employer_id, String title, String description) {
ContentValues map = new ContentValues();
map.put("employer_id", employer_id);
map.put("title", title);
map.put("description", description);
String[] whereArgs = new String[]{Long.toString(job_id)};
112 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
try{
getWritableDatabase().update("jobs", map, "_id=?", whereArgs);
} catch (SQLException e) {
Log.e("Error writing new job", e.toString());
}
}
Heie aie some ol the highlights ol the coue in Example 8-3:
The liist paiametei to update is the name ol the taLle to manipulate. The seconu is
the map ol column names to new values. The thiiu is a small snippet ol SQL; in this
case, it`s a SQL template with one paiametei. The paiametei is maikeu with a gues-
tion maik, anu is lilleu out with the contents ol the louith aigument.
Example 8-+ shows you how to use the execSQL methou.
Exanp|c 8-1. Using thc cxccSQL ncthod
/**
* Update a job in the database.
* @param job_id The job id of the existing job
* @param employer_id The employer offering the job
* @param title The job title
* @param description The job description
*/
public void editJob(long job_id, long employer_id, String title, String description) {
String sql =
"UPDATE jobs " +
"SET employer_id = ?, "+
" title = ?, "+
" description = ? "+
"WHERE _id = ? ";
Object[] bindArgs = new Object[]{employer_id, title, description, job_id};
try{
getWritableDatabase().execSQL(sql, bindArgs);
} catch (SQLException e) {
Log.e("Error writing new job", e.toString());
}
}
Foi the application in Example 8-+, we show the simplest possiLle lunction. This makes
it easy to unueistanu in a Look, Lut is not enough loi a ieal application. In a ieal
application, you woulu want to check input stiings loi invaliu chaiacteis, veiily that
the joL exists Leloie tiying to upuate it, veiily that the employer_id value is valiu Leloie
using it, uo a Lettei joL ol catching eiiois, etc. You woulu also pioLaLly authenticate
the usei loi any application that is shaieu Ly multiple people.
Deleting data in the database
The Micio]oLs application enaLles the usei to uelete a joL as well as cieate anu change
it. Fiom the main application inteilace, the usei clicks on the List ]oLs Lutton to get a
list ol joLs, anu then clicks on a paiticulai joL to see the joL uetail. Nt this level, the
Databases | 113
usei can click on the ¨Delete this joL¨ menu item to uelete the joL. The application
asks the usei il he ieally wants to uelete the joL. Vhen the usei hits the ¨Delete¨ Lutton
in iesponse, the lollowing line ol coue in the MicrojobsDctai|.java lile is executeu:
db.deleteJob(job_id);
This coue calls the deleteJob methou ol the MicroJobsDatabase class, passing it the joL
ID to uelete. The coue is similai to the lunctions we`ve alieauy seen anu lacks the same
ieal-woilu leatuies.
Example 8-5 shows you how to use the delete methou.
Exanp|c 8-5. Using thc dc|ctc ncthod
/**
* Delete a job from the database.
* @param job_id The job id of the job to delete
*/
public void deleteJob(long job_id) {
String[] whereArgs = new String[]{Long.toString(job_id)};
try{
getWritableDatabase().delete("jobs", "_id=?", whereArgs);
} catch (SQLException e) {
Log.e("Error deleteing job", e.toString());
}
}
Example 8-6 shows you how to use the execSQL methou.
Exanp|c 8-ó. Using thc cxccSQL ncthod
/**
* Delete a job from the database.
* @param job_id The job id of the job to delete
*/
public void deleteJob(long job_id) {
String sql = String.format(
"DELETE FROM jobs " +
"WHERE _id = '%d' ",
job_id);
try{
getWritableDatabase().execSQL(sql);
} catch (SQLException e) {
Log.e("Error deleteing job", e.toString());
}
}
Content Providers
Much ol the time, an application`s uata is tightly Lounu to that application. Foi in-
stance, a Look ieauei application will typically have one uatalile pei Look. Othei
applications on the moLile phone will have no inteiest in the liles that the Look ieauei
114 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
uses to stoie Looks, so those liles aie tightly Lounu to the application, anu theie is no
neeu to make any elloit to shaie the Look uata. In lact, the Nnuioiu OS enloices this
tight Linuing so that applications can`t ieau oi wiite uata acioss packages at all.
Howevei, some applications want to shaie theii uata; that is, they want othei applica-
tions to Le aLle to ieau anu wiite uata within theii uataLase. Peihaps the most oLvious
example is contact uata. Il each application that ieguiieu contacts loiceu the usei to
maintain a sepaiate uataLase loi that specilic application, the phone woulu Le all Lut
useless.
Nnuioiu enaLles applications to shaie uata using the content pioviuei NPI. This NPI
enaLles each client application to gueiy the OS loi uata it`s inteiesteu in, using a uni-
loim iesouice iuentiliei (URI) mechanism, similai to the way a Liowsei ieguests in-
loimation liom the Inteinet.
The client uoes not know which application will pioviue the uata; it simply piesents
the OS with a URI anu leaves it to the OS to stait the appiopiiate application to pioviue
the iesult.
The content pioviuei NPI enaLles lull CRUD access to the content. This means the
application can:
º Cieate new iecoius
º Retiieve one, all, oi a limiteu set ol iecoius
º Upuate iecoius
º Delete iecoius il peimitteu
This section shows how to use the content pioviuei NPI Ly examining the innei woik-
ings ol the NotePau application pioviueu with the Nnuioiu SDK. Nssuming the SDK
was installeu in the /sd| uiiectoiy, all lile ieleiences within the NotePau pioject aie
ielative to /sd|/sanp|cs/NotcPad; thus, when the AndroidManifcst.xn| lile is ieleienceu
in this section, the /sd|/sanp|cs/NotcPad/AndroidManifcst.xn| lile is assumeu. By
stuuying NotePau`s implementation, you`ll Le aLle to cieate anu manage content pio-
viueis ol youi own.
Thioughout this chaptei we make the assumption that the Lackenu ol
a content pioviuei is a SQLite uataLase. This will almost always Le the
case, anu the NPI uses stanuaiu uataLase opeiations, such as create,
read, update, anu delete. Howevei, it is possiLle to use the NPI to stoie
anu ietiieve uata using any Lackenu that will suppoit the ieguiieu op-
eiations. Foi instance, a llat lile that just uoes inseits anu gueiies that
ietuin some suLset ol the lile is possiLle. Howevei, in most cases an
SQLite uataLase will Le on the Lackenu ol a content pioviuei, so we use
those teims anu concepts in this chaptei.
Content Providers | 115
Introducing NotePad
The Nnuioiu NotePau application is a veiy simple noteLook. It allows the usei to type
textual notes on lineu note papei anu stoie them unuei a textual title ol any length. N
usei can cieate notes, view a list ol notes, anu upuate anu uelete notes. Ns an applica-
tion, NotePau is usaLle, Lut just Laiely; its main puipose is to show piogiammeis how
to Luilu anu use content pioviueis.
Activities
The NotePau application has thiee uistinct Nctivities: NoteList, NoteEuitoi, anu
TitleEuitoi. Insteau ol communicating uiiectly to the NotePau uataLase, each ol these
Nctivities use the content pioviuei NPI, so the NotePau application is Loth a content
pioviuei client anu a seivei. This makes it peilect loi exploiing content pioviueis.
The puipose ol each activity is ieasonaLly oLvious liom its name. The NoteList activity
piesents the usei with a list ol notes, anu allows hei to auu a new note oi euit the title
oi Louy ol an existing note.
The NoteEuitoi allows a usei to cieate a new note oi mouily the Louy ol an existing
note. Finally, the TitleEuitoi is a uialog Lox that allows a usei to mouily the title ol an
existing note.
Database
The NotePad uataLase is cieateu with the lollowing SQL statement:
CREATE TABLE notes (
_id INTEGER PRIMARY KEY,
title TEXT,
note TEXT,
created INTEGER,
modified INTEGER
);
The _id column is not ieguiieu, Lut iecommenueu Ly the Nnuioiu SDK uocumenta-
tion. The uocumentation suggests that the column shoulu Le uelineu with the SQL
attiiLutes INTEGER PRIMARY KEY AUTOINCREMENT. Unless you have an application-specilic
iuentiliei that you can guaiantee to Le unigue, you might as well make use ol the
AUTOINCREMENT leatuie to assign aiLitiaiy integeis ioLustly.
The title anu note columns stoie the note title anu note Louy uata, iespectively. The
main raison d`ctrc loi the NotePau application is to manipulate the contents ol these
columns.
Finally, the created anu modified columns keep tiack ol when the note was cieateu anu
when it was last mouilieu. In the NotePau application itsell, these columns aie nevei
seen Ly the usei. Howevei, othei applications can ieau them using the content pioviuei
NPI.
116 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
Structure of the source code
This section Liielly examines each ielevant lile within the NotePau application:
AndroidManifcst.xn|
Chaptei 3 uesciiLeu the puipose ol the AndroidManifcst.xn| lile that is
pait ol eveiy Nnuioiu application. It uesciiLes impoitant attiiLutes ol the appli-
cation, such as the Nctivities anu Intents that the application implements. The
AndroidManifcst.xn| lile loi the NotePau application ieveals the thiee activities÷
NotesList, NoteEuitoi, anu TitleEuitoi÷along with the vaiious Intents that these
activities consume. Finally, the <provider> element shows that the application is a
content pioviuei. Ve`ll uiscuss the <provider> element in uetail latei in this section.
rcs/drawab|c/app_notcs.png
This lile is the icon loi the application. The <application> element within the
AndroidManifcst.xn| lile sets the icon using the android:icon attiiLute.
rcs/|ayout/´.xn|
These thiee layout liles use XML to uesciiLe how each activity scieen is laiu out.
Chaptei 2 coveis these concepts.
rcs/va|ucs/strings.xn|
Nll ol the usei-visiLle stiings in the NotePau application appeai in this lile. Ovei
time, as the application gains acceptance in the usei community, useis liom
non-English-speaking countiies will want the application auapteu to theii lan-
guages. This joL is much easiei il all usei-lacing stiings stait out in strings.xn|.
src/con/cxanp|c/android/notcpad/NotcEditor.java
The NoteEditor class extenus the Activity class anu allows the usei to euit a note
in the notes uataLase. This class nevei manipulates the notes uataLase uiiectly, Lut
insteau uses the NotePadProvider content pioviuei.
src/con/cxanp|c/android/notcpad/NotcPad.java
The NotePad class contains the AUTHORITY attiiLute (uiscusseu latei) anu the Notes
class, which uelines the names ol the content pioviuei columns. Because the ua-
taLase columns aie nameu the same as the content pioviuei columns, the Note class
also is also useu to ueline the names ol the uataLase columns. Neithei the
NotePad class noi the Notes class contain any executaLle coue. The ielevant poition
ol the NotcPad.java lile lollows:
public final class NotePad {
public static final String AUTHORITY = "com.google.provider.NotePad";
private NotePad() {}// This class cannot be instantiated
/** Notes table */
public static final class Notes implements BaseColumns {
// This class cannot be instantiated
private Notes() {} // This class cannot be instantiated
public static final Uri CONTENT_URI =
Uri.parse("content://" + AUTHORITY + "/notes");
public static final String CONTENT_TYPE =
"vnd.android.cursor.dir/vnd.google.note";
Content Providers | 117
public static final String CONTENT_ITEM_TYPE=
"vnd.android.cursor.item/vnd.google.note";
public static final String TITLE = "title";
public static final String NOTE = "note";
public static final String CREATED_DATE = "created";
public static final String MODIFIED_DATE = "modified";
}
}
src/con/cxanp|c/android/notcpad/NotcPadProvidcr.java
The NotePadProvider class is the content pioviuei loi the notes uataLase. It intei-
cepts URIs loi each ol the CRUD actions anu ietuins uata appiopiiate to the action
ieguesteu. This lile is examineu in uetail latei in this chaptei.
src/con/cxanp|c/android/notcpad/NotcsList.java
The NotesList class is an Nctivity that allows the usei to view a list ol notes. The
usei can auu a new note oi euit the title oi Louy ol an existing note
src/con/cxanp|c/android/notcpad/Tit|cEditor.java
The TitleEditor class is an Nctivity that implements a uialog Lox that allows a usei
to mouily the title ol an existing note. Since this is a veiy simple class, it is guite
helplul to examine it closely, to unueistanu how to gueiy anu mouily uata in a
content pioviuei.
Content Providers
Now that we`ve examineu the geneial stiuctuie ol the NotePau application, it`s time
to look at how the application Loth implements anu consumes the NotePadProvider
content pioviuei.
Implementing a content provider
The Nnuioiu SDK contains a uocument that uesciiLes nine steps to cieating a content
pioviuei. In summaiy, they aie:
1. Extenu the ContentProvider class.
2. Deline the CONTENT_URI loi youi content pioviuei.
3. Cieate the uata stoiage loi youi content.
+. Cieate the column names loi communication with clients.
5. Deline the piocess Ly which Linaiy uata is ietuineu to the client.
6. Declaie puLlic static Stiings that clients use to specily columns.
7. Implement the CRUD methous ol a Cuisoi to ietuin to the client.
8. Upuate the AndroidManifcst.xn| lile to ueclaie youi <provider>.
9. Deline MIME types loi any new uata types.
118 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
In the lollowing sections, we`ll examine each step in uetail using the NotePau applica-
tion as oui guiue.
Vithin NotcPadProvidcr.java, the NotePadProvider class extenus
ContentProvider, as shown heie:
public class NotePadProvider extends ContentProvider
Classes that extenu ContentProvider must pioviue implementations loi the lollowing
methous:
onCreate
This methou is calleu uuiing the content pioviuei`s staitup. Nny coue you want to
iun just once, such as making a uataLase connection, shoulu iesiue in this methou.
getType
This methou, when given a URI, ietuins the MIME type ol the uata that this content
pioviuei pioviues at that URI. The URI comes liom the client application inteiesteu
in accessing the uata.
insert
This methou is calleu when the client coue wishes to inseit uata into the uataLase
youi content pioviuei is seiving. Noimally, the implementation loi this methou
will eithei uiiectly oi inuiiectly iesult in a uataLase inseit opeiation.
query
This methou is calleu whenevei a client wishes to ieau uata liom the content
pioviuei`s uataLase. It is noimally calleu thiough ContentProvider`s
managedQuery methou. Noimally, heie you ietiieve uata using a SQL SELECT
statement anu ietuin a cuisoi containing the ieguesteu uata.
update
This methou is calleu when a client wishes to upuate one oi moie iows in the
ContentProvider`s uataLase. It tianslates to a SQL UPDNTE statement.
delete
This methou is calleu when a client wishes to uelete one oi moie iows in the
ContentProvider`s uataLase. It tianslates to a SQL DELETE statement.
Ns usual, it`s Lest to unueistanu the majoi class
anu instance vaiiaLles useu Ly a methou Leloie examining how the methou woiks. The
vaiiaLles we neeu to unueistanu loi the NotePau`s ContentProvider class aie:
private static final String DATABASE_NAME = "note_pad.db";
private static final int DATABASE_VERSION = 2;
private static final String NOTES_TABLE_NAME = "notes";
private DatabaseHelper mOpenHelper;
DATABASE_NAME
The name ol the uataLase lile on the uevice. Foi the NotePau pioject, the lull path
to the lile is /data/data/con.cxanp|c.android.notcpad/databascs/notc_pad.db.
Extend ContentProvider.
NotePadProvider class and instance variables.
Content Providers | 119
DATABASE_VERSION
The veision ol the uataLase this coue woiks with. Il this numLei is highei than the
veision ol the uataLase itsell, the application calls the DatabaseHelper.onUpdate
methou. See ¨Cieate the uata stoiage¨ on page 122 loi moie inloimation.
NOTES_TABLE_NAME
The name ol the notes taLle within the notes uataLase.
mOpenHelper
This instance vaiiaLle is initializeu uuiing onCreate. It pioviues access to the ua-
taLase loi the insert, query, update, anu delete methous.
In auuition to these class anu instance vaiiaLles, the NotePadContentProvider class also
has a static initialization Llock that peiloims complex initializations ol static vaiiaLles
that can`t Le peiloimeu as simple one-lineis:
private static HashMap<String, String> sNotesProjectionMap;
private static final UriMatcher sUriMatcher;
private static final int NOTES = 1;
private static final int NOTE_ID = 2;
...
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);
sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);
sNotesProjectionMap = new HashMap<String, String>();
sNotesProjectionMap.put(Notes._ID, Notes._ID);
sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE);
sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE);
sNotesProjectionMap.put(Notes.CREATED_DATE, Notes.CREATED_DATE);
sNotesProjectionMap.put(Notes.MODIFIED_DATE, Notes.MODIFIED_DATE);
}
The meanings ol these vaiiaLles lollow:
sNotesProjectionMap
The piojection map useu Ly the gueiy methou. This HashMap maps the content
pioviuei`s column names to uataLase column names. N piojection map is not ie-
guiieu, Lut when useu it must list all column names that might Le ietuineu Ly the
gueiy. In NotePadContentProvider, the content pioviuei column names anu the
uataLase column names aie iuentical, so the sNotesProjectionMap is not ieguiieu.
sUriMatcher
This uata stiuctuie is loaueu with seveial URI templates that match URIs clients
can senu the content pioviuei. Each URI template is paiieu with an integei that
the sUriMatcher ietuins when it`s passeu a matching URI. The integeis aie useu as
cases ol a switch in othei paits ol the class. NotePadContentProvider has two types
ol URIs, iepiesenteu Ly the NOTES anu NOTES_ID integeis.
NOTES
sUriMatcher ietuins this value loi note URIs that uo not incluue a note ID.
120 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
NOTES_ID
sUriMatcher ietuins this value when the notes URI incluues a note ID.
Vhen a client application uses a content iesolvei to ieguest uata, a
URI that iuentilies the uesiieu uata is passeu to the content iesolvei. Nnuioiu tiies to
match the URI with the CONTENT_URI ol each content pioviuei it knows aLout to linu
the iight pioviuei loi the client. Thus, the CONTENT_URI uelines the type ol URIs youi
content pioviuei can piocess.
N CONTENT_URI consists ol these paits:
content://
This initial stiing tells the Nnuioiu liamewoik that it must linu a content pioviuei
to iesolve the URI.
Thc authority
This stiing uniguely iuentilies the content pioviuei anu consists ol up to two sec-
tions: the oiganizational section anu the pioviuei iuentiliei section. The oiganiza-
tional section uniguely iuentilies the oiganization that cieateu the content pio-
viuei. The pioviuei iuentiliei section iuentilies a paiticulai content pioviuei that
the oiganization cieateu. Foi content pioviueis that aie Luilt into Nnuioiu, the
oiganizational section is omitteu. Foi instance, the Luilt-in ¨meuia¨ authoiity that
ietuins one oi moie images uoes not have the oiganizational section ol the au-
thoiity. Howevei any content pioviueis that aie cieateu Ly uevelopeis outsiue ol
Google`s Nnuioiu team must ueline Loth sections ol the content pioviuei. Thus,
the Notepau example application`s authoiity is com.google.provider.NotePad. The
oiganizational section is com.google.provider, anu the pioviuei iuentiliei section
is NotePad. The Google uocumentation suggests that the Lest solution loi picking
the authoiity section ol youi CONTENT_URI is to use the lully gualilieu class name ol
the class implementing the content pioviuei.
The authoiity section uniguely iuentilies the paiticulai content pioviuei that Nn-
uioiu will call to iesponu to gueiies that it hanules.
Thc path
The content pioviuei can inteipiet the iest ol the URI howevei it wants, Lut it must
auheie to some ieguiiements:
º Il the content pioviuei can ietuin multiple uata types, the URI must Le con-
stiucteu so that some pait ol the path specilies the type ol uata to ietuin.
Foi instance, the Luilt-in ¨Contacts¨ content pioviuei pioviues many uilleient
types ol uata: People, Phones, ContactMethous, etc. The Contacts content pio-
viuei uses stiings in the URI to uilleientiate which type ol uata the usei is ie-
guesting. Thus, to ieguest a specilic peison, the URI will Le something like this:
content://contacts/people/1
To ieguest a specilic phone numLei, the URI coulu Le something like this:
content://contacts/people/1/phone/3
Define CONTENT_URI.
Content Providers | 121
In the liist case, the MIME uata type ietuineu will Le vnd.android.cursor.item/
person, wheieas in the seconu case, it will Le vnd.android.cursor.item/phone.
º The content pioviuei must Le capaLle ol ietuining eithei one item oi a set ol
item iuentilieis. The content pioviuei will ietuin a single item when an item
iuentiliei appeais in the linal poition ol the URI. Looking Lack at oui pievious
example, the URI contcnt://contacts/pcop|c/1/phonc/3 ietuineu a single phone
numLei ol type vnd.android.cursor.item/phone. Il the URI hau insteau Leen
contcnt://contacts/pcop|c/1/phonc, the application woulu have ietuineu a list ol
all ol the phone numLeis loi the peison having the peison iuentiliei numLei 1,
anu the MIME type ol the uata ietuineu woulu Le vnd.android.cursor.dir/
phone.
Ns mentioneu eailiei, the content pioviuei can inteipiet the path poition ol the
URI howevei it wants. This means that it can use items in the path to liltei uata to
ietuin to the callei. Foi instance, the Luilt-in ¨meuia¨ content pioviuei can ietuin
eithei inteinal oi exteinal uata, uepenuing on whethei the URI contains the woiu
¨inteinal¨ oi ¨exteinal¨ in the path.
The lull CONTENT_URI loi NotePau is contcnt://con.goog|c.providcr.NotcPad/notcs.
The CONTENT_URI must Le ol type public static final Uri. It is uelineu in the
NotePad class ol the NotePau application. Fiist, a stiing nameu AUTHORITY is uelineu:
public final class NotePad {
public static final String AUTHORITY = "com.google.provider.NotePad";
Then, the CONTENT_URI itsell is uelineu:
public static final class Notes implements BaseColumns {
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY +
"/notes");
N content pioviuei can stoie uata in any way it chooses. Because
content pioviueis use uataLase semantics, the SQLite uataLase is most commonly useu.
The onCreate methou ol the ContentProvider class (NotePadProvider in the NotePau
application) cieates this uata stoie. The methou is calleu uuiing the content pioviuei`s
initialization. In the NotePau application, the onCreate methou cieates a connection to
the uataLase, cieating the uataLase liist il it uoes not exist.
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
return true;
}
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
Create the data storage.
122 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " ("
+ Notes._ID + " INTEGER PRIMARY KEY,"
+ Notes.TITLE + " TEXT,"
+ Notes.NOTE + " TEXT,"
+ Notes.CREATED_DATE + " INTEGER,"
+ Notes.MODIFIED_DATE + " INTEGER"
+ ");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldver, int newver) {
// destroy the old version -- not nice to do in a real app!
db.execSQL("DROP TABLE IF EXISTS notes");
onCreate(db);
}
}
Heie aie some ol the highlights ol the coue:
Cieates a new oLject ol the DatabaseHelper class, which is ueiiveu liom SQLiteOpen
Helper. The constiuctoi loi DatabaseHelper knows to call onCreate oi onUpgrade il it
has to cieate oi upgiaue the uataLase.
This is stanuaiu uataLase coue loi Nnuioiu, veiy similai to the uataLase cieation coue
liom the M]Nnuioiu pioject. N hanule loi the new DatabaseHelper class is assigneu to
the mOpenHelper class vaiiaLle, which is useu Ly the iest ol the content pioviuei to
manipulate the uataLase.
This methou emLeus iaw SQL into a call to execSQL. Ns we`ll see, luithei calls uon`t
neeu to use SQL; insteau, theii simple CRUD opeiations use calls pioviueu Ly the
liamewoik.
Data Store for Binary Data
The Nnuioiu SDK uocumentation suggests that when youi content pioviuei stoies
Linaiy uata, such as a Litmap oi music clip, the uata shoulu Le stoieu outsiue ol the
uataLase in a lile, anu the content pioviuei shoulu stoie a content:// URI in the uata-
Lase that points to the lile. Client applications will gueiy youi content pioviuei to
ietiieve that content:// URI anu then ietiieve the actual Lyte stieam liom the lile it
specilies.
The ieason loi this ciicuitous ioute is easy to unueistanu altei some examination. Be-
cause lilesystem I/O is much lastei anu moie veisatile than uealing with SQLite LloLs,
it`s Lettei to use the Unix lilesystem insteau ol SQL LloLs. But since an Nnuioiu ap-
plication cannot ieau oi wiite liles that anothei application has cieateu, a content pio-
viuei must Le useu to access the LloLs. Theieloie, when the liist content pioviuei
ietuins a pointei to a lile containing a LloL, that pointei must Le in the loim ol a
content:// URI insteau ol a Unix lilename. The use ol a content:// URI causes the lile
to Le openeu anu ieau unuei the peimissions ol the content pioviuei that owns the lile,
not the client application (which uoes not have access iights to the lile).
Content Providers | 123
To implement the lile appioach, insteau ol cieating a hypothetical usei taLle like this:
CREATE TABLE user (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
password TEXT,
picture BLOB
);
the uocumentation suggests two taLles that look like this:
CREATE TABLE user (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
password TEXT,
picture TEXT
);
CREATE TABLE userPicture (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
_data TEXT
);
The picture column ol the user taLle will stoie a content:// URI that points to a iow
in the userPicture taLle. The _data column ol the userPicture taLle will point to a ieal
lile on the Nnuioiu lilesystem.
Il the path to the lile weie stoieu uiiectly in the user taLle, clients woulu get a path Lut
Le unaLle to open the lile, Lecause it`s owneu Ly the application seiving up the content
pioviuei anu the clients uon`t have peimission to ieau it. In the solution shown heie,
howevei, access is contiolleu Ly a ContentResolver class, which we`ll examine latei.
The ContentResolver class looks loi a column nameu _data when piocessing ieguests.
Il the lile specilieu in that column is lounu, the class`s openOutputStream methou opens
the lile anu ietuins a java.io.OutputStream to the client. This is the same oLject
that woulu Le ietuineu il the client weie aLle to open the lile uiiectly. The
ContentResolver class is pait ol the same application as the content pioviuei, anu
theieloie is aLle to open the lile when the client cannot.
Content pioviueis exchange uata with theii clients in much the
same way an SQL uataLase exchanges uata with uataLase applications: using Cuisois
lull ol iows anu columns ol uata. N content pioviuei must ueline the column names it
suppoits, just as a uataLase application must ueline the columns it suppoits. Vhen the
content pioviuei uses an SQLite uataLase as its uata stoie, the oLvious solution is to
give the content pioviuei columns the same name as the uataLase columns, anu that`s
just what NotePadProvider uoes. Because ol this, theie is no mapping necessaiy Letween
the NotePadProvider columns anu the unueilying uataLase columns.
Not all applications make all ol theii uata availaLle to content pioviuei clients, anu
some moie complex applications may want to make ueiivative views availaLle to con-
tent pioviuei clients. The piojection map uesciiLeu in ¨NotePauPioviuei class anu
instance vaiiaLles¨ on page 119 is availaLle to hanule these complexities.
Create the column names.
124 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
Ve alieauy explaineu the iecommenueu uata stiuctuie loi seiving
Linaiy uata in the siueLai ¨Data Stoie loi Binaiy Data¨ on page 123. The othei piece
ol the solution lies in the ContentResolver class, uiscusseu latei.
The NotePadProvider columns aie uelineu in the
NotePad.Notes class, as mentioneu in ¨NotePauPioviuei class anu instance vaiia-
Lles¨ on page 119. Eveiy content pioviuei must ueline an _id column to holu the iecoiu
numLei ol each iow. The value ol each _id must Le unigue within the
content pioviuei; it is the numLei that a client will appenu to the content
pioviuei`s vnd.android.cursor.itcn URI when attempting to gueiy loi a single iecoiu.
Vhen the content pioviuei is Lackeu Ly an SQLite uataLase, as is the case loi
NotePadProvider, the _id shoulu have the type INTEGER PRIMARY KEY AUTOINCREMENT.
This way, the iows will have a unigue _id numLei anu _id numLeis will not Le ieuseu,
even when iows aie ueleteu. This helps suppoit ieleiential integiity Ly ensuiing that
each new iow has an _id that has nevei Leen useu Leloie. Il iow _ids aie ieuseu, theie
is a chance that cacheu URIs coulu point to the wiong uata.
N content pioviuei implementation must oveiiiue the CRUD meth-
ous ol the ContentProvider Lase class: insert, query, update, anu delete. Foi the Note-
Pau application, these methous aie uelineu in the NotePadProvider class.
Classes that extenu ContentProvider must oveiiiue its insert methou.
This methou ieceives values liom a client, valiuates them, anu then auus a new iow to
the uataLase containing those values. The values aie passeu to the ContentProvider
class in a ContentValues oLject:
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
// Validate the requested uri
if (sUriMatcher.match(uri) != NOTES) {
throw new IllegalArgumentException("Unknown URI " + uri);
}
ContentValues values;
if (initialValues != null)
values = new ContentValues(initialValues);
else
values = new ContentValues();
Long now = Long.valueOf(System.currentTimeMillis());
// Make sure that the fields are all set
if (values.containsKey(NotePad.Notes.CREATED_DATE) == false)
values.put(NotePad.Notes.CREATED_DATE, now);
if (values.containsKey(NotePad.Notes.MODIFIED_DATE) == false)
values.put(NotePad.Notes.MODIFIED_DATE, now);
if (values.containsKey(NotePad.Notes.TITLE) == false) {
Resources r = Resources.getSystem();
values.put(NotePad.Notes.TITLE,r.getString(android.R.string.untitled));
}
Supporting binary data.
Declare column specification strings.
Implement the Cursor.
Create data (insert).
Content Providers | 125
if (values.containsKey(NotePad.Notes.NOTE) == false) {
values.put(NotePad.Notes.NOTE, "");
}
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, values);
if (rowId > 0) {
Uri noteUri=ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI,rowId);
getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
NotePadProvider must oveiiiue the gueiy methou anu ietuin a
Cuisoi containing the uata ieguesteu. It staits Ly cieating an instance ol the SQLite
QueryBuilder class, using Loth static inloimation liom the class anu uynamic inloima-
tion liom the URI. It then cieates the Cuisoi uiiectly liom the uataLase using the
SQLiteQueryBuilder gueiy. Finally, it ietuins the Cuisoi that the uataLase cieateu.
Vhen the URI contains a note iuentilication numLei, the NOTE_ID case is useu. In this
case, text is auueu to the WHERE clause so that only the note iuentilieu Ly the URI is
incluueu in the Cuisoi ietuineu to the NotePadProvider client:
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)
{
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (sUriMatcher.match(uri)) {
case NOTES:
qb.setTables(NOTES_TABLE_NAME);
qb.setProjectionMap(sNotesProjectionMap);
break;
case NOTE_ID:
qb.setTables(NOTES_TABLE_NAME);
qb.setProjectionMap(sNotesProjectionMap);
qb.appendWhere(Notes._ID + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
// If no sort order is specified use the default
String orderBy;
if (TextUtils.isEmpty(sortOrder)) {
orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;
} else {
orderBy = sortOrder;
}
Read/select data (query).
126 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
// Get the database and run the query
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c=qb.query(db,projection,selection,selectionArgs,null,null,orderBy);
// Tell cursor what uri to watch, so it knows when its source data changes
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
NotePadProvider`s upuate methou ieceives values liom a client, valiuates
them, anu mouilies ielevant iows in the uataLase given those values. It all Loils uown
to the SQLiteDatabase`s update methou. The liist value passeu to upuate is the taLle
name. This constant is uelineu elsewheie in the class. The seconu paiametei, values,
is a ContentValues oLject loimeu Ly the client ol the ContentProvider. The linal two
aiguments, where anu whereArgs, aie useu to loim the VHERE clause ol the SQL UP-
DNTE commanu.
The ContentValues oLject is cieateu Ly the ContentProvider`s client. It contains a map
ol uataLase column names to new column values that is passeu thiough to the
SQLiteDatabase`s update methou.
The where stiing anu the whereArgs stiing aiiay woik togethei to Luilu the VHERE
clause ol the SQLite UPDNTE commanu. This VHERE clause limits the scope ol the
UPDNTE commanu to the iows that match its ciiteiia. The where stiing can Le Luilt
eithei to contain all ol the inloimation necessaiy to Luilu the VHERE clause, oi to
contain a template that is lilleu out at iuntime Ly inseiting stiings liom the whereArgs
stiing. The easiest way to unueistanu this is with a couple ol examples.
Let`s suppose that you want to upuate only those iows wheie the dogName column is
egual to 'Jackson'. Ns the content pioviuei`s client, you coulu cieate a single where
stiing consisting ol "dogName='Jackson'" anu pass it along to the update methou. This
woiks well anu is what many applications uo. But unless you check youi input veiy
well, this methou is suLject to an SQL injection attack, as uesciiLeu eailiei in the
chaptei.
The Lettei appioach is to pass a template as the where clause, something like
"dogName=?". The guestion maik maiks the location loi the value ol dogName, anu the
actual value is lounu in the whereArgs stiing aiiay. The liist guestion maik is ieplaceu
Ly the liist value in the whereArgs stiing aiiay. Il theie weie a seconu guestion maik, it
woulu Le ieplaceu with the seconu value, anu so loith:
@Override
public int update(Uri uri,ContentValues values,String where,String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
switch (sUriMatcher.match(uri)) {
case NOTES:
count = db.update(NOTES_TABLE_NAME, values, where, whereArgs);
break;
Update data.
Content Providers | 127
case NOTE_ID:
String noteId = uri.getPathSegments().get(1);
count = db.update(NOTES_TABLE_NAME, values, Notes._ID + "=" + noteId
+ (!TextUtils.isEmpty(where)?" AND ("+where+')':""), whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
NotePadProvider`s delete methou is veiy similai to the update methou, Lut
insteau ol upuating the iows with new uata, it simply ueletes them:
@Override
public int delete(Uri uri, String where, String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
switch (sUriMatcher.match(uri)) {
case NOTES:
count = db.delete(NOTES_TABLE_NAME, where, whereArgs);
break;
case NOTE_ID:
String noteId = uri.getPathSegments().get(1);
count = db.delete(NOTES_TABLE_NAME, Notes._ID + "=" + noteId
+ (!TextUtils.isEmpty(where)?" AND ("+where+')':""), whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
The AndroidManifcst.xn| lile uelines all exteinal access to
the application, incluuing any content pioviueis. Vithin the lile, the <provider> tag
ueclaies the content pioviuei.
The AndroidManifcst.xn| lile within the NotePau pioject has the lollowing
<provider> tag:
<provider android:name="NotePadProvider"
android:authorities="com.google.provider.NotePad"
/>
Nn android:authorities attiiLute must Le uelineu within the <provider> tag. Nnuioiu
uses this attiiLute to iuentily the URIs that this content pioviuei will lullill.
Delete data.
Updating AndroidManifest.xml.
128 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
The android:name tag is also ieguiieu, anu iuentilies the name ol the content pioviuei
class. Note that this stiing matches the AUTHORITY stiing in the NotePad class, uiscusseu
eailiei.
In sum, this section ol the AndroidManifcst.xn| lile can Le tianslateu to the lollowing
English statement: ¨This content pioviuei accepts URIs that stait with contcnt://
con.goog|c.providcr.notcpad/ anu passes them to the NotePadProvider class.¨
Youi content pioviuei must oveiiiue the getType methou. This
methou accepts a URI anu ietuins the MIME type that coiiesponus to that URI. Foi
the NotePadProvider, two types ol URIs aie accepteu, so two types ol URIs aie ietuineu:
º The contcnt://con.goog|c.providcr.NotcPad/notcs URI will ietuin a uiiectoiy ol zeio
oi moie notes, using the vnd.android.cursor.dir/vnd.google.note MIME type.
º N URI with an appenueu ID, ol the loim contcnt://con.goog|c.providcr.NotcPad/
notcs/N, will ietuin a single note, using the vnd.android.cursor.item/
vnd.google.note MIME type.
The client passes a URI to the Nnuioiu liamewoik to inuicate the uataLase it wants to
access, anu the Nnuioiu liamewoik calls youi getType methou inteinally to get the
MIME type ol the uata. That helps Nnuioiu ueciue what to uo with the uata ietuineu
Ly the content pioviuei.
Youi getType methou must ietuin the MIME type ol the uata at the given URI. In
NotePau, the MIME types aie stoieu as simple stiing vaiiaLles, shown eailiei
in ¨Stiuctuie ol the souice coue¨ on page 117. The ietuin value staits with
vnd.android.cursor.item loi a single iecoiu anu vnd.android.cursor.dir loi multiple
items:
@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case NOTES:
return Notes.CONTENT_TYPE; // vnd.android.cursor.dir/vnd.google.note
case NOTE_ID:
return Notes.CONTENT_ITEM_TYPE; // vnd.android.cursor.item/vnd.google.note
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
Consuming a Content Provider
The NotePau application Loth implements anu consumes the NotePadProvider content
pioviuei. The pievious sections uesciiLeu how the NotePadProvider allows any appli-
cation on the Nnuioiu uevice to access the notes uataLase. This section explains how
the vaiious Nctivities use the NotePadProvider to manipulate the uataLase. Since these
Define MIME types.
Content Providers | 129
activities aie pait ol the same application as the NotePadProvider, they coulu simply
manipulate the uataLase uiiectly, Lut insteau they use the ContentProvider. This uoes
not impose any peiloimance penalty, so not only uoes it woik well as an example loi
oui puiposes, Lut it is also goou piogiamming piactice loi all applications implement-
ing a content pioviuei.
The lollowing sections lollow the CRUD lunctions in oiuei. Fiist, uata is cieateu using
the SQL INSERT statement. That uata is then typically ieau using an SQL SELECT
gueiy. Sometimes the uata must Le upuateu using the SQL UPDNTE statement oi
ueleteu using the SQL DELETE statement.
Create data (insert)
The lollowing coue is liom the NoteEditor class in the NotePau application. Coue that
was not ielevant to the uiscussion was iemoveu in the listing:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
// Do some setup based on the action being performed.
final String action = intent.getAction();
if (Intent.ACTION_EDIT.equals(action)) {
...
} else if (Intent.ACTION_INSERT.equals(action)) {
// Requested to insert: set that state, and create a new entry
// in the container.
mUri = getContentResolver().insert(intent.getData(), null);
if (mUri == null) {
// Creating the new note failed
finish();
return;
}
// Do something with the new note here.
...
}
...
}
The NotePau application staits out in the NotesList Nctivity. NotesList has an ¨Nuu
Note¨ menu entiy, shown in Figuie 8-1.
Vhen the usei piesses the Nuu Note Lutton, the NoteEuitoi Nctivity is staiteu with
the ACTION_INSERT Intent. NoteEuitoi`s onCreate methou examines the Intent to uetei-
mine why it was staiteu. Vhen the Intent is ACTION_INSERT, a new note is cieateu Ly
calling the insert methou ol the content iesolvei:
mUri = getContentResolver().insert(intent.getData(), null);
130 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
In Liiel, this line`s joL is to cieate a new Llank note anu ietuin its URI to the mUri
vaiiaLle. The value ol the mUri vaiiaLle is the URI ol the note Leing euiteu.
So how uoes this seguence ol calls woik? Fiist, note that NotesList`s paient class is
ListActivity. Nll Activity classes aie uescenueu liom ContextWrapper. So, the liist
thing the line uoes is call ContextWrapper.getContentResolver to ietuin a
ContentResolver instance. The insert methou ol that ContentResolver is then imme-
uiately calleu with two paiameteis:
UR| of thc contcnt providcr in which to inscrt thc row
Oui aigument, intent.getData, iesolves to the URI ol the Intent that got us heie
in the liist place, contcnt://con.goog|c.providcr.NotcPad/notcs.
Data to inscrt
Heie, Ly passing null, we`ie inseiting a iecoiu with no uata. The uata is auueu
latei with a call to the update methou when the usei types something in.
ContentResolver`s joL is to manipulate oLjects that URIs point to. Nlmost all ol its
methous aie veiLs that take a URI as theii liist aigument. ContentResolver`s methous
incluue all ol the CRUD methous, stieam methous loi lile I/O, anu otheis.
Iigurc 8-1. NotcsList Activity
Content Providers | 131
Read/query data
To ieau uata, use the managedQuery methou. This is an Activity methou that calls
query inteinally. It manages the gueiy loi the uevelopei, closing the Cuisoi anu ie-
gueiying it when necessaiy. The paiameteis passeu to managedQuery aie:
uri
The URI to gueiy. This will map to a specilic content pioviuei, anu in NotePau`s
case, to the NotePau content pioviuei.
projection
N String aiiay with one element loi each column you want ietuineu in the gueiy.
Columns aie numLeieu anu coiiesponu to the oiuei ol the columns in the unuei-
lying uataLase.
selection
Inuicates which iows to ietiieve thiough an SQL VHERE clause; it is passeu as a
single String vaiiaLle. Can Le NULL il you want all iows.
selectionArgs
N String aiiay containing one aigument loi each paiametei oi placeholuei (a
guestion maik in the SQL SELECT statement). Pass NULL il theie aie no aiguments.
sortOrder
N String vaiiaLle containing a lull ORDER BY aigument, il soiting is uesiieu. Can Le
NULL.
The NotePau application gueiies the NotePadProvider to lill in the list ol notes to uisplay
to the usei:
public class NotesList extends ListActivity {
...
private static final String[] PROJECTION = new String[] {
Notes._ID, // 0
Notes.TITLE, // 1
};
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
// If no data was given in the Intent (because we were started
// as a MAIN activity), then use our default content provider.
Intent intent = getIntent();
if (intent.getData() == null) {
intent.setData(Notes.CONTENT_URI);
}
132 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
// Inform the list we provide context menus for items
getListView().setOnCreateContextMenuListener(this);
// Perform a managed query. The Activity will handle closing
// and requerying the cursor when needed.
Cursor cursor = managedQuery(getIntent().getData(),
PROJECTION, null, null, Notes.DEFAULT_SORT_ORDER);
// Used to map notes entries from the database to views
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this,
R.layout.noteslist_item,
cursor,
new String[] { Notes.TITLE },
new int[] { android.R.id.text1 });
setListAdapter(adapter);
}
Heie aie some ol the highlights ol the coue:
Cieates the piojection, the liist paiametei to managedQuery. In this case, the aiiay
contains the note ID anu title.
Sets the Nctivity`s uelault key hanuling moue to DEFAULT_KEYS_SHORTCUTS. This lets
the usei execute shoitcut commanus liom the options menu without having to piess
the menu key liist.
Gets the client`s ieguest, passeu in the Intent. This shoulu contain the content pio-
viuei URI, Lut il it uoesn`t, the next line sets it to the NotePau URI.
The managedQuery call, which ietuins a cuisoi.
To use the uata in the Cuisoi as the input loi a ListNctivity, an Nuaptei is ieguiieu.
In this case, a SimpleCuisoiNuaptei has all the lunctionality that is necessaiy.
Nltei you have cieateu the Nuaptei, issue the ListNctivity`s setListAdapter methou
to uisplay the uata liom the Cuisoi on the scieen.
Update data
To unueistanu how to upuate uata, we`ll take a look at the TitleEditor class. Because
it`s small, looking at it in its entiiety is instiuctive. Relatively lew lines aie neeueu to
manipulate the content pioviuei, anu most ol the lunction connects the usei`s clicks
to changes in the content pioviuei. The usei inteiaction uses Lasic manipulations ol
giaphic elements, which weie Liielly intiouuceu in Chaptei + anu will Le lully uiscusseu
in Chaptei 10 anu suLseguent chapteis. The iest ol this section piints the
TitleEditor class in Llocks, lollowing each Llock with explanations.
public class TitleEditor extends Activity implements View.OnClickListener {
/** An array of the columns we are interested in. */
private static final String[] PROJECTION = new String[] {
NotePad.Notes._ID, // 0
Content Providers | 133
NotePad.Notes.TITLE, // 1
};
/** Index of the title column */
private static final int COLUMN_INDEX_TITLE = 1;
/** Cursor providing access to the note whose title we are editing. */
private Cursor mCursor;
/** The EditText field from our UI. Used to extract the text when done. */
private EditText mText;
/** The content URI to the note that's being edited. */
private Uri mUri;
This liist section ol the TitleEditor Nctivity class sets up all ol its piivate uata. The
lollowing piivate vaiiaLles aie ueclaieu:
PROJECTION
Useu Ly the managedQuery lunction to uesciiLe the columns to ietuin in the gueiy,
as shown in the pievious section.
COLUMN_INDEX_TITLE
Delines the numLei ol the column, in the oiuei ietuineu Ly the gueiy, liom which
the title must Le pulleu. The numLeis stait at 0, so the value ol 1 shown is the inuex
ol the TITLE within the PROJECTION stiing.
mUri
Holus the URI ol the note whose title we`ie going to euit. Nn example URI might
Le contcnt://con.goog|c.providcr.NotcPad/notcs/2.
mCursor
The cuisoi that holus the iesults ol the gueiy.
mText
The EditText lielu on the loim.
Next, the Nctivity`s onCreate methou sets up the Nctivity:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.title_editor);
// Get the uri of the note whose title we want to edit
mUri = getIntent().getData();
// Get a cursor to access the note
mCursor = managedQuery(mUri, PROJECTION, null, null, null);
// Set up click handlers for the text field and button
mText = (EditText) this.findViewById(R.id.title);
mText.setOnClickListener(this);
134 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
Button b = (Button) findViewById(R.id.ok);
b.setOnClickListener(this);
}
Heie aie some ol the highlights ol the coue:
Finus the ContentView in the rcs/|ayout/tit|c_cditor.xn| layout lile, using the
setContentView methou.
Runs the managedQuery methou to loau iesults into a Cuisoi.
Sets click hanuleis loi Loth the Lutton anu the text Lox. This will uiiect any clicks
on the Lutton oi the text Lox to the onClick methou, which we`ll see shoitly.
Vhen onCreate linishes, the onResume methou is calleu. This methou pulls the cuiient
value ol the note title liom the cuisoi anu assigns it to the value ol the text Lox:
@Override
protected void onResume() {
super.onResume();
// Initialize the text with the title column from the cursor
if (mCursor != null) {
mCursor.moveToFirst();
mText.setText(mCursor.getString(COLUMN_INDEX_TITLE));
}
}
The onPause methou is wheie the application wiites the uata Lack to the uataLase. In
othei woius, NotePau lollows the typical Nnuioiu piactice ol saving up wiites until the
application is suspenueu. Ve`ll see soon wheie this methou is calleu:
@Override
protected void onPause() {
super.onPause();
if (mCursor != null) {
// Write the title back to the note
ContentValues values = new ContentValues();
values.put(Notes.TITLE, mText.getText().toString());
getContentResolver().update(mUri, values, null, null);
}
}
Heie aie some ol the highlights ol the coue:
Cieates a new ContentValues oLject to holu the set ol values to pass to the
ContentResolver.
Puts the column name anu the new value ol the column in the values oLject.
Stoies the upuateu value Ly cieating a ContentResolver anu passing the URI anu new
vales to its upuate methou.
Content Providers | 135
The last methou in TitleEditor is the common callLack loi hanuling usei clicks, nameu
onClick:
public void onClick(View v) {
// When the user clicks, just finish this activity.
// onPause will be called, and we save our data there.
finish();
}
The comment uesciiLes what is going on pietty well. Once the usei clicks eithei the
OK Lutton oi the text Lox within the uialog Lox, the Nctivity calls the finish methou.
That methou calls onPause, which wiites the contents ol the uialog Lox Lack to the
uataLase, as we showeu eailiei.
Delete data
N usei who pulls up a list ol notes liom the NotesList class can choose the Delete option
on the context menu to iun the lollowing methou:
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info;
info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo() ;
switch (item.getItemId()) {
case MENU_ITEM_DELETE: {
// Delete the note that the context menu is for
Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
getContentResolver().delete(noteUri, null, null);
return true;
}
}
return false;
}
Heie aie some ol the highlights ol the coue:
Vhen the menu loi the joL was cieateu, the joL ID was stulleu into the extia inloi-
mation vaiiaLle loi the menu. That extia inloimation section is ietiieveu liom the
MenuItem on this line anu useu in the next pait ol the highlighteu coue.
Builus a URI Ly extiacting the URI liom the usei`s Intent, as usual, anu appenuing
the numLei ol the item to uelete, taken liom the menu.
Cieates a ContentResolver anu pass the URI to its delete methou.
136 | Chapter 8:ಗPersistent Data Storage: SQLite Databases and Content Providers
CHAPTER 9
Location and Mapping
Evei since moLile phones staiteu incoipoiating uevices that maue them awaie ol theii
geogiaphic locations, uevelopeis have loieseen a new eia ol location-Laseu applica-
tions. Location awaieness impioves many applications anu makes possiLle totally new
applications. Il youi application is looking up iestauiants, it`s cleaily Lettei il you can
iestiict youi seaich to the aiea aiounu you. It`s even Lettei il you can see a map ol the
iestauiants` locations, anu peihaps Le aLle to look up uiiving oi walking uiiections. Il
you`ie looking loi a tempoiaiy joL, as in the M]Nnuioiu application highlighteu in this
Look, it`s cleaily an auvantage to Le aLle to see wheie the oppoitunities aie.
Nnu navigation is ieally just the liist geneiation ol Location-Baseu Seivices (LBS). De-
velopeis loiesee the uay you`ll Le aLle to opt-in to ieceive auveitisements liom neaiLy
ietaileis as you walk uown a stieet, anu youi music playei will suggest songs Laseu on
youi cuiient location. The woilu ol LBS is just Leginning to take oll, anu as we`ll see,
Google`s Nnuioiu olleis poweilul leatuies that make the uevelopment ol these appli-
cations veiy easy.
In economic teims, location-Laseu applications aie a majoi lactoi in moLile telephony,
constituting hall the ievenue liom moLile applications, anu giowing last. Because they
aie Laseu on the aLility ol the moLile netwoik to locate uevices anu the ielationship ol
moLility anu location, location-Laseu applications aie as lunuamental to moLile tel-
ephony as communication.
Location is usually comLineu with seaich: Vheie aie my contacts? Vheie aie seivices
oi piouucts I`m looking loi? Vheie aie people with common inteiests?
Location-Based Services
MoLile phones use seveial ielateu methous, alone anu in comLination, to ueteimine
wheie they aie:
Cc|| |D
Regaiuless ol whethei you`ie actually talking on the phone, as long as it`s poweieu
up, youi moLile phone caiiies on a constant conveisation with neaiLy cell toweis.
137
It has to uo this in oiuei to Le aLle to iesponu when someone calls you, so eveiy
lew seconus it ¨pings¨ the cell towei it was using last to tell it that it`s still in iange
anu to note netwoik paiameteis such as the cuiient time, the cuiient signal
stiength (uplink anu uownlink), etc.
Il you happen to Le moving, youi phone may uo a hanuovei to anothei cell towei,
all in the Lackgiounu without a neeu loi you to inteivene. Each cell towei woilu-
wiue has a unigue iuentiliei, calleu (appiopiiately enough) its Cell ID, anu each
towei knows its latituue anu longituue, so it`s easy enough loi a moLile phone to
know ¨appioximately¨ wheie you aie locateu Ly taking note ol the cuiient Cell
ID`s geogiaphic location. Cell sizes vaiy uepenuing on the expecteu tiallic in an
aiea, Lut in the U.S., theii iauius ianges liom a hall mile (cities) to live miles oi
moie (wiue-open spaces).
Triangu|ation
Most ol the time youi moLile phone is in iange ol moie than one cell towei. In 2G
anu latei moLile technologies, the cell towei has the aLility to tell what uiiection
youi signal is coming liom. Il theie aie two oi thiee toweis that can see youi phone,
togethei they can tiiangulate on youi phone`s location. Vith some opeiatois, youi
phone then has the aLility to gueiy the netwoik to linu out wheie it`s Leen locateu.
This sounus a little Lackwaiu, Lut it can Le veiy accuiate, anu uoesn`t uepenu on
any extia haiuwaie on the moLile phone.
GPS
The satellite-Laseu GloLal Positioning System (GPS) is uLiguitous these uays,
lounu in cai navigation units, hanuhelu navigatois, anu moLile phones. The goou
news is that, using GPS, youi moLile phone can ueteimine its location veiy accu-
iately, incluuing its altituue il that`s impoitant loi some paiticulai application.
Theie aie seveial uownsiues to GPS, Lut it is gaining populaiity nonetheless. The
uownsiues:
|ncrcascd cost
GPS iauios anu piocessois aie laiily inexpensive, Lut still, an inciease ol even
$10 in the Lill-ol-mateiials cost ol a moLile phone is consiueiaLle.
Rcduccd battcry |ifc
Theie have Leen gieat stiiues in ieuucing the powei ieguiieu Ly GPS iauios
anu piocessois, Lut they still suck Latteiy powei. Most phones that incluue
GPS also have a leatuie that lets the usei tuin it on anu oll. Il youi application
uepenus on GPS accuiacy, it`s goou to iememLei that youi application might
have to check whethei the GPS uevice is tuineu on anu notily the usei il it isn`t.
Unrc|iab|c avai|abi|ity
Nothing ¨always woiks,¨ Lut GPS in paiticulai uepenus on youi moLile uevice
Leing aLle to see the satellites cuiiently oveiheau. Il you`ie in the Lasement ol
a high-iise Luiluing, suiiounueu Ly steel-ieinloiceu conciete, you pioLaLly
aien`t going to Le aLle to use GPS.
138 | Chapter 9:ಗLocation and Mapping
It`s ieasonaLle to expect that all Nnuioiu phones will incluue one oi all ol these location-
linuing methous. The T-MoLile G1 in paiticulai can use them all. So now we`ll pioceeu
to technigues loi using the location capaLilities.
Mapping
Google is most lamous loi theii seaich engine, Lut not lai Lehinu that comes the lame
ol Google Maps. Vhen cieating Nnuioiu, the lolks at Google coulu easily see the po-
tential in LBS anu how well that lit with theii mapping expeitise. Most LBS applications
enu up uisplaying a map. Meanwhile, Google alieauy hau the technology to uisplay
anu upuate inteiactive maps, anu the Lusiness piocesses in place to allow otheis to use
those maps anu auu leatuies loi theii own weLsites. It still ieguiieu a leap to make that
mapping technology availaLle to application uevelopeis loi moLile phones, Lut thank-
lully Google accomplisheu just that.
The Google Maps Activity
One ol the applications that comes with Nnuioiu is Google Maps itsell. Il it`s appio-
piiate, you can stait Google Maps liom youi application the same way you stait any
othei Nctivity:
1. Cieate an Intent (new Intent(String action, Uri uri)) that says you neeu to uis-
play a Map. The paiameteis aie:
º Nn action, loi which you must specily ACTION_VIEW.
º N Uri, loi which you shoulu specily one ol the lollowing URI Schemes, suLsti-
tuting youi uata:
÷geo:latitude,longitude
÷geo:latitude,longitude?z=zoom
÷geo:0,0?qmy_street_address
÷geo:0,0?qbusiness_near_city
2. Call startActivity(Intent intent), using the Intent you just cieateu.
Nn example that cieates a map is:
Intent intent = new Intent(ACTION_VIEW, "geo:37.422006,-122.084095");
startActivity(intent);
This is ceitainly easy, anu gets you all the powei ol Google Maps, Lut you can`t ieally
integiate the map into youi application this way. Google Maps is an application unto
itsell, anu theie`s no way loi you to change anything aLout the usei inteilace oi auu
oveilay giaphics to the map to point out whatevei is ol inteiest to youi useis. Nnuioiu
pioviues moie llexiLle packages to auu that powei.
The Google Maps Activity | 139
The MapView and MapActivity
This Look`s M]Nnuioiu application neeus to Le aLle to auu oveilays that show the
locations loi joLs in the aiea. So insteau ol using the Google Maps application, we will
use a MapView, which we can oveilay with as many giaphics as we want. You can have
only one MapView pei Nctivity, howevei, anu youi activity has to extenu MapNctivity.
Ns you`ll see, that`s a small piice to pay loi all the lunctionality that comes loi liee.
Theie aie a couple ol unigue pieieguisites loi using MapViews in youi application, anu
we toucheu on Loth ol them when we lookeu at the initialization ol M]Nnuioiu in
Chaptei +.
|nc|udc thc Map\icws |ibrary
The MapView is not incluueu in the uelault Nnuioiu liLiaiies, so you neeu to
specily in AndroidManifcst.xn| that we aie using this auuitional liLiaiy:
<application android:icon="@drawable/icon2">
<uses-library android:name="com.google.android.maps" />
You can`t put the uses-library line just anywheie in AndroidManifcst.xn|; it
neeus to Le within the <application> tag anu outsiue ol the <activity> tag
uelinitions.
Sign your app|ication and obtain a Map apiKcy fron Goog|c
Vhen you use a MapView in youi application, you aie using actual Google Maps
uata to uiaw the map. Foi legal ieasons, Google neeus to tiack who is using theii
map uata. They uon`t caie what youi application uoes with it, Lut they neeu to
have you iegistei with them loi an NPI key anu agiee to appiopiiate Teims ol
Seivice. This tells them youi application is using mapping uata, anu whethei you
aie also using the iouting uata that is availaLle liom Google Maps. Chaptei 7 cov-
eieu the piocesses ol signing youi application anu getting an apiKey.
RememLei that piogiams using a MapView must Le signeu. To make it
easy loi you to tiy out the M]Nnuioiu example liom this Look, we`ve
incluueu an .ap| lile as uesciiLeu in the siueLai ¨Running the M]Nn-
uioiu Coue¨ on page 35 in Chaptei 3. Il you change the coue oi uo any
couing ol youi own, you neeu to get youi own key, as uesciiLeu in
Chaptei 7.
Working with MapViews
The MapView encapsulates a lot ol veiy complex mapping soltwaie anu is availaLle
loi you in youi Nnuioiu applications÷loi liee. Heie aie some ol the things you can uo
with a MapView, with only a little piogiamming on youi pait:
º Show a stieet map ol any aiea in the woilu, with up-to-uate mapping inloimation
couitesy ol Google
140 | Chapter 9:ಗLocation and Mapping
º Change the MapView to show:
Strcct vicw
Photogiaphs taken at stieet level loi many aieas in Noith Nmeiica
Satc||itc vicw
Nn aeiial, photogiaphic view ol the aiea
Traffic vicw
Real-time tiallic inloimation supeiimposeu on the map oi satellite views
º Move the map unuei piogiam contiol
º Plot youi own giaphics in oveilays on top ol the map
º Responu to usei touch events on the map
MapView and MyLocationOverlay Initialization
The map in Micio]oLs has two moues:
º Nt staitup, anu when we select ¨Cuiient Location¨ liom the Spinnei, we want to
uisplay a map ol oui cuiient location, anu we want that map to tiack us as we move
aiounu. Foi this map we will use the MyLocationOverlay class.
º Vhen we select a specilic location liom the Spinnei, we want to uisplay a map ol
that location, tuin oll location upuates, anu not tiack movement.
Let`s look again at the coue in Microjobs.java that initializes the MapView anu the
MyLocationOveilay that tiacks oui cuiient location:
@Override
public void onCreate(Bundle savedInstanceState) {
...
mvMap = (MapView) findViewById(R.id.mapmain);
// get the map controller
final MapController mc = mvMap.getController();
mMyLocationOverlay = new MyLocationOverlay(this, mvMap);
mMyLocationOverlay.runOnFirstFix(
new Runnable() {
public void run() {
mc.animateTo(mMyLocationOverlay.getMyLocation());
mc.setZoom(16);
}
});
Drawable marker = getResources().getDrawable(R.drawable.android_tiny_image);
marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
mvMap.getOverlays().add(new MJJobsOverlay(marker));
mvMap.setClickable(true);
mvMap.setEnabled(true);
Working with MapViews | 141
mvMap.setSatellite(false);
mvMap.setTraffic(false);
mvMap.setStreetView(false);
// start out with a general zoom
mc.setZoom(16);
...
/**
* Required method to indicate whether we display routes
*/
@Override
protected boolean isRouteDisplayed() { return false; }
Heie aie some ol the highlights ol the coue:
Ve liist linu the MapView in the nain.xn| layout lile, the same way we linu any
othei view, anu assign it to the vaiiaLle mvMap ol type MapView, so we can ielei to it
when we neeu to.
Ve also get a hanule on the MapContiollei associateu with MapView. Ve`ll use
that to pan (animate) the map, zoom in, zoom out, change views, etc.
To use MyLocationOveilay, we cieate a new instantiation, giving it the highly cie-
ative name mMyLocationOverlay.
The liist thing we uo with mMyLocationOverlay is ueline a methou that Nnuioiu will
call when we ieceive oui liist location lix liom the location pioviuei.
This runOnFirstFix methou moves the map to the cuiient location (given Ly
mMyLocationOverlay.getMyLocation()) anu zooms to a ieasonaLle level loi us to see
neaiLy joL piospects.
Next, we iuentily a maikei that we`ve ueciueu to use on mMyLocationOverlay to maik
availaLle joLs. Ve use an image that`s stoieu in oui rcs/drawab|c uiiectoiy, calleu
android_tiny_inagc. It`s a pictuie ol a little Nnuioiu ioLot. Ve ueline the Lounus
ol the DiawaLle maikei, as uesciiLeu in Chaptei 12, anu auu the maikei oveilay to
the list ol oveilays loi the MapView mvMap.
Now we`u like to set some initial attiiLutes loi mvMap, uesciiLeu latei in this section.
Ve`ll allow the usei to change most ol these thiough menu Luttons.
Then, lollowing a Lelt-anu-suspenueis philosophy, just in case theie isn`t a location
pioviuei to tiiggei runOnFirstFix, we`ll set the zoom level again heie.
Finally, MapView ieguiies us to oveiiiue the isRouteDisplayed() methou to inuicate
whethei we aie uisplaying ioute inloimation on oui map. Ve aie not, so we ietuin
false.
MyLocationOveilay encapsulates a wealth ol location anu mapping coue. In oui single
call to the constiuctoi we:
º Nsk Nnuioiu to liguie out what location pioviueis aie availaLle in oui enviionment
(GPS, Cell ID, tiiangulation).
142 | Chapter 9:ಗLocation and Mapping
º Connect to the ¨Lest¨ ol those location pioviueis.
º Nsk the location pioviuei to senu us peiiouic location upuates as oui hanuset
moves.
º Link to ioutines that will automatically move oui map as neeueu to tiack any
changes in location.
MyLocationOveilay also allows us to place a compass iose on the MapView anu have
that upuateu as well, Lut we won`t Le using that in M]Nnuioiu.
The map attiiLutes set Ly the coue aie:
setClickable
Ve want useis to Le aLle to click (tap) on a joL to cause M]Nnuioiu to uisplay
moie uetail aLout that joL, so we set this to true.
setEnabled
This methou is actually inheiiteu liom android.view.View. Google uoesn`t tell us
exactly what this means in the case ol a MapView, Lut piesumaLly it enaLles the
stanuaiu map lunctions (zooming, panning, etc.).
setSatellite
Setting this llag auus a satellite view liom the composite map, wheieas cleaiing the
llag iemoves the view. To stait with, we uon`t want the satellite inloimation on
the map.
setTraffic
Similaily, setting oi cleaiing this llag auus oi iemoves cuiient tiallic inloimation
liom the map, iespectively. Ngain, we uon`t want to stait with tiallic inloimation
on the map.
setStreetView
Ve uon`t want stieet views iight now eithei, although we`ll let the usei enaLle
them latei.
Zooming in Android Maps
Nnuioiu maps come alieauy eguippeu with suppoit loi zooming in anu out. The ¨i¨
key zooms in on the map, anu the ¨o¨ key zooms out. Maps can also zoom in anu out
unuei piogiam contiol, thiough the MapContiollei.
Theie aie seveial methous uelineu loi zooming, all via the MapContiollei. Nnuioiu
uelines 21 zoom levels loi maps. Nt zoom level 1, the eguatoi ol the eaith is 256 pixels
long. Eveiy step up in zoom level multiplies that Ly 2. Google wains that the highei-
iesolution maps aie not availaLle woiluwiue. Nll ol the zoom methous clamp the zoom
level to the iange 1 thiough 21 il you ask MapContiollei to go Leyonu those limits.
The methous that contiol zoom, along with theii paiameteis, aie:
zoomIn
Zooms in one level.
Working with MapViews | 143
zoomOut
Zooms out one level.
setZoom(int zoomlevel)
Zooms to the given level, iestiicting it to the iange 1 to 21.
zoomInFixing(int xpixel, int ypixel), zoomOutFixing(int xpixel, int ypixel)
Zoom in one level, Lut keep the given point lixeu on the scieen. Noimally when
you zoom in anu out, the centei ol the scieen is the only point that stays lixeu.
These ioutines let you pick any point on the map to Le the lixeu point.
zoomToSpan(int latSpanE6, int longSpanE6)
Nttempts to zoom so the given span is uisplayeu on the map. Vhat it actually uoes
is select the zoom level that is the closest match loi the span ieguesteu. The latituue
anu longituue span paiameteis aie expiesseu as integeis with a value 10
6
times the
actual value in uegiees. Foi instance, a latituue/longituue span ol 2.5 uegiees Ly
1.0 uegiees woulu Le expiesseu as zoomToSpan(2500000, 1000000).
Pausing and Resuming a MapActivity
MoLile applications have unigue ieguiiements, uue mostly to the constiaineu iesouices
availaLle to execute applications. Foi now let`s locus on MapNctivities anu talk aLout
a way we can help save Latteiy powei. The goou news is that Nnuioiu makes it pietty
easy.
In a moLile enviionment, Latteiy lile is eveiything, anu il we`ie not the application that
is cuiiently Leing uisplayeu, we want to uo eveiything we can to minimize the powei
we consume. You iecall liom the uiscussion ol the Nnuioiu lilecycle (Chaptei 1) that
when an Nctivity (such as Micio]oLs) staits anothei Nctivity (such as Micio]oLsList)
the new Nctivity takes ovei the scieen, anu the calling Nctivity gets pusheu onto a stack
ol Nctivities that aie waiting to iun. Nt that time, Nnuioiu calls the onPause() ioutine
in the calling Nctivity so it can piepaie itsell to go into hiLeination. Nt this point in
Microjobs.java (oi just aLout any MapNctivity that uses location upuates), we want to
tuin oll location upuates. Doing so will at least save the cycles uevoteu to uoing the
upuate, anu may allow the hanuset to save even moie powei Ly putting the location
pioviuei in a guiescent state.
Vhen the calleu Nctivity (in oui case, Micio]oLsList) exits anu the calling Nctivity is
poppeu oll the stack anu takes contiol ol the scieen, the liamewoik calls the
onResume methou in the calling Nctivity. In a MapNctivity, we want to tuin on location
upuates again when this methou is invokeu.
In Micio]oLs, the onPause anu onResume methous aie stiaightloiwaiu:
/**
* @see com.google.android.maps.MapActivity#onPause()
*/
@Override
public void onPause() {
144 | Chapter 9:ಗLocation and Mapping
super.onPause();
mMyLocationOverlay.disableMyLocation();
}
/**
* @see com.google.android.maps.MapActivity#onResume()
*/
@Override
public void onResume() {
super.onResume();
mMyLocationOverlay.enableMyLocation();
}
Note that il we`u hau a compass iose as pait ol oui MyLocationOveilay, we woulu
have to uisaLle anu enaLle it as well. Otheiwise, the system woulu Le upuating the
uiiection ol the compass iose even when it wasn`t Leing uisplayeu, theieLy wasting
cycles anu Latteiy powei.
Controlling the Map with Menu Buttons
Ve want to give the usei the aLility to tuin on satellite, tiallic, anu stieet views ol the
map. In auuition, we`ll thiow in a lew menu Luttons to enaLle zooming anu anothei
way ol getting to the ]oLs List.
Nnuioiu has a sophisticateu set ol menu capaLilities that incluues thiee types ol menus
(options, context, anu suLmenus), each with its own capaLilities, icon menu Luttons,
anu othei auvanceu leatuies. Ve just use text-Laseu menu Luttons, anu so we neeu to
uo two things:
1. Cieate the menu ol Luttons that will Le uisplayeu.
2. Catch the menu events anu invoke appiopiiate actions.
The lollowing coue cieates the menu in Microjobs.java:
/**
* Set up menus for this page
*
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean supRetVal = super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE, 0, Menu.NONE, getString(R.string.map_menu_zoom_in));
menu.add(Menu.NONE, 1, Menu.NONE, getString(R.string.map_menu_zoom_out));
menu.add(Menu.NONE, 2, Menu.NONE, getString(R.string.map_menu_set_satellite));
menu.add(Menu.NONE, 3, Menu.NONE, getString(R.string.map_menu_set_map));
menu.add(Menu.NONE, 4, Menu.NONE, getString(R.string.map_menu_set_traffic));
menu.add(Menu.NONE, 5, Menu.NONE, getString(R.string.map_menu_show_list));
return supRetVal;
}
Working with MapViews | 145
Ve cieate menu Luttons Ly oveiiiuing the onCreateOptionsMenu methou, wheie we aie
passeu a menu paiametei loi the Nctivity`s menu. Nltei uutilully allowing the supeiclass
a chance to uo what it neeus to uo, we simply auu items (Luttons) to the menu using
menu.add. The veision ol menu.add that we`ve chosen takes loui paiameteis:
int groupid
Nnuioiu allows you to gioup menu items so you can guickly change the whole
menu at once. Ve uon`t have a neeu loi that in Micio]oLs, so Menu.NONE says we
uon`t neeu it.
int itemid
Ve neeu a unigue iuentiliei loi this menu item so we can tell latei whethei it was
pickeu.
int order
The itemid we uelineu in the seconu paiametei uoes not imply oiuei. Il we caieu
aLout the oiuei in which the items weie piesenteu, we`u uo that with this paiam-
etei. Since we uon`t caie, we use Menu.NONE again.
int titleRes
The ID ol the stiing iesouice we want to use loi the Lutton title. Note that this is
an integei, not a stiing, so the menu stiings neeu to Le pieuelineu in string.xn|,
unuei the rcs uiiectoiy. You iecall that Nnuioiu takes caie ol compiling the stiings
in rcs/strings.xn| into a .java lile (R.java) that assigns an integei to each stiing. The
getString methou ietiieves that integei loi you (uespite the name, the methou
ietuins an integei, not a stiing).
To catch the menu events, we oveiiiue the onOptionsItemSelected methou:
/**
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
// Zoom in
zoomIn();
return true;
case 1:
// Zoom out
zoomOut();
return true;
case 2:
// Toggle satellite views
mvMap.setSatellite(!mvMap.isSatellite());
return true;
case 3:
// Toggle street views
mvMap.setStreetView(!mvMap.isStreetView());
return true;
case 4:
146 | Chapter 9:ಗLocation and Mapping
// Toggle traffic views
mvMap.setTraffic(!mvMap.isTraffic());
return true;
case 5:
// Show the job list activity
startActivity(new Intent(MicroJobs.this, MicroJobsList.class));
return true;
}
return false;
}
Ve aie passeu the selecteu MenuItem, anu the switch has a case loi each Lutton that we
uelineu loi the menu. The coue loi each case is similai to coue that we`ve seen Leloie.
Controlling the Map with the KeyPad
Some useis might pielei to contiol the map thiough the keypau (geneially one ¨click,¨
veisus two ¨clicks¨ to cause a Menu event). EnaLling this Lehavioi also uemonstiates
how to iesponu to KeyPau events in geneial, so we`ve auueu some coue to zoom in,
zoom out, anu Lack out ol the cuiient Nctivity:
/**
* @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP: // zoom in
zoomIn();
return true;
case KeyEvent.KEYCODE_DPAD_DOWN: // zoom out
zoomOut();
return true;
case KeyEvent.KEYCODE_BACK: // go back (meaning exit the app)
finish();
return true;
default:
return false;
}
}
To catch key uown events, we simply oveiiiue onKeyDown anu pioviue a switch loi
the uilleient keys that aie ol inteiest. In auuition to the keycoues you woulu expect
(KEYCODE_A, ...KEYCODE_Z anu things like KEYCODE_SPACE, KEYCODE_SHIFT_LEFT, anu
KEYCODE_SHIFT_RIGHT), Nnuioiu incluues keycoues that may oi may not appeai
on any paiticulai uevice (e.g., KEYCODE_CAMERA anu KEYCODE_VOLUME_UP). N complete set
ol keycoues can Le lounu at http://codc.goog|c.con/android/rcfcrcncc/android/vicw/Kcy
Evcnt.htn|.
Working with MapViews | 147
Location Without Maps
Vhat il youi Nctivity neeus to access location inloimation, Lut it uoesn`t incluue a
MapView? Vhen you use a MapView, Nnuioiu makes eveiything veiy easy with
MyLocationOveilay, Lut even il you uon`t neeu a map, it isn`t uillicult to get location
inloimation. The coue in this section is not pait ol M]Nnuioiu, Lut it shows how you
woulu go aLout getting location inloimation without a map.
Let`s look at a veiy simple, one-Nctivity application that uisplays the cuiient location
in a TextView.
The Manifest and Layout Files
Nn appiopiiate AndroidManifcst.xn| lile lollows. Ve cieateu this lile using the Nnuioiu
SDK anu the Nnuioiu Manilest Euitoi that comes as pait ol the SDK. The only change
we neeueu to make with the euitoi was to auu the uses-permission tag loi
android.permission.ACCESS_FINE_LOCATION (in the next-to-last line ol the lile). Ve al-
ways neeu this peimission in oiuei to get location inloimation liom a GPS location
pioviuei:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.microjobsinc.dloc"
android:versionCode="1"
android:versionName="1.0.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main"
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-permission android:name="android.permission.ACCESS_FINE_LOCATION">
</uses-permission>
</manifest>
Ve`ll use a veiy simple layout lile with loui TextViews: one laLel anu one text Lox each
loi latituue anu longituue:
<?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:id="@+id/lblLatitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
148 | Chapter 9:ಗLocation and Mapping
android:text="Latitude:"
/>
<TextView
android:id="@+id/tvLatitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/lblLongitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Longitude:"
/>
<TextView
android:id="@+id/tvLongitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
Connecting to a Location Provider and Getting Location Updates
Let`s stait with an Nctivity that just connects with the GPS LocationProvider anu gets
anu uisplays oui cuiient location (no upuates). The pioceuuie is pietty stiaightloiwaiu:
package com.microjobsinc.dloc;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// find the TextViews
TextView tvLatitude = (TextView)findViewById(R.id.tvLatitude);
TextView tvLongitude = (TextView)findViewById(R.id.tvLongitude);
// get handle for LocationManager
LocationManager lm = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
// connect to the GPS location service
Location loc = lm.getLastKnownLocation("gps");
// fill in the TextViews
tvLatitude.setText(Double.toString(loc.getLatitude()));
tvLongitude.setText(Double.toString(loc.getLongitude()));
Location Without Maps | 149
}
}
Heie aie some ol the highlights ol the coue:
Connect to the LocationManager using getSystemService(Context.LOCATION_SERV
ICE).
Nsk the LocationManager wheie we aie using getLastKnownLocation("provider").
Get the latituue anu longituue liom the location ietuineu anu use it as neeueu.
But we also want to get peiiouic location upuates liom the LocationManager so we can
tiack oui location as we move aLout. Foi that we neeu to auu a listenei ioutine anu
ask the LocationManager to call it when it has an upuate.
Location upuates liom the LocationManager aie accessiLle to an application thiough a
DispLocListener class, so we will cieate an instance ol this class in the onCreate methou
ol oui main Nctivity. Ve aie ieguiieu to oveiiiue a numLei ol methous in
DispLocListener to meet the LocationListener inteilace uelinition, Lut we uon`t neeu
them loi this application, so we`ll leave the uelinitions empty.
The lull implementation lollows:
package com.microjobsinc.dloc;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
public class Main extends Activity {
private LocationManager lm;
private LocationListener locListenD;
public TextView tvLatitude;
public TextView tvLongitude;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// find the TextViews
tvLatitude = (TextView)findViewById(R.id.tvLatitude);
tvLongitude = (TextView)findViewById(R.id.tvLongitude);
// get handle for LocationManager
LocationManager lm = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
// connect to the GPS location service
150 | Chapter 9:ಗLocation and Mapping
Location loc = lm.getLastKnownLocation("gps");
// fill in the TextViews
tvLatitude.setText(Double.toString(loc.getLatitude()));
tvLongitude.setText(Double.toString(loc.getLongitude()));
// ask the Location Manager to send us location updates
locListenD = new DispLocListener();
lm.requestLocationUpdates("gps", 30000L, 10.0f, locListenD);
}
private class DispLocListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
// update TextViews
tvLatitude.setText(Double.toString(location.getLatitude()));
tvLongitude.setText(Double.toString(location.getLongitude()));
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
}
Oui onCreate methou cieates an instance ol DispLocListener anu ieguests that the
LocationManager upuate it as neeueu using requestLocationUpdates. This methou takes
loui paiameteis:
String provider
Vhich location pioviuei to use. Ve assume GPS is availaLle in this case.
long minTime
Minimum upuate time, in milliseconus. The LocationManager will wait at least this
long Letween upuates. Heie`s an oppoitunity to tune youi application loi Latteiy
lile: moie lieguent upuates means moie Latteiy usage.
float minDistance
Minimum uistance, in meteis, ieguiieu to tiiggei an upuate. The Location
Manager will upuate us only il we`ve moveu at least this lai since the last upuate.
LocationListener listener
The name ol the listenei methou to call when theie is an upuate. This is the
DispLocListener instance we just cieateu.
Location Without Maps | 151
Finally, we want to auu the onPause anu onResume coue to tuin oll location upuates
when we`ie not actually uisplaying on the usei`s scieen, anu then tuin them Lack on
when we aie:
/**
* Turn off location updates if we're paused
*/
@Override
public void onPause() {
super.onPause();
lm.removeUpdates(locListenD);
}
/**
* Resume location updates when we're resumed
*/
@Override
public void onResume() {
super.onResume();
lm.requestLocationUpdates("gps", 30000L, 10.0f, locListenD);
}
Updating the Emulated Location
Vhile you aie ueveloping anu ueLugging an application like the one just shown, you`ie
noimally iunning on the emulatoi. It woulu Le nice (mayLe even essential) to Le aLle
to upuate the cuiient location that the emulatoi uses as it`s iunning youi coue. Such a
Mock Location Pioviuei can get veiy lancy, Lut Nnuioiu pioviues some Luilt-in ways
ol upuating the emulateu location:
º The geo piogiam Luilt into the Nnuioiu shell
º One-time upuates via DDMS
º Tiacks that aie seguentially upuateu via DDMS
Ve`ll look at each ol these.
Using geo to update location
The geo utility is Luilt into the Nnuioiu image that iuns on the emulatoi. It has a numLei
ol capaLilities, the most impoitant ol which is geo lix:
geo fix
You can use the geo fix commanu to senu a location to Nnuioiu Ly telnetting to
the console ol the emulateu Nnuioiu. The LocationProvider will then use this as
the cuiient location:
telnet localhost 5554
Android Console: type 'help' for a list of commands
OK
geo fix -122.842232 38.411908 0
OK
152 | Chapter 9:ಗLocation and Mapping
geo fix takes thiee paiameteis:
longitude
Specilieu in uecimal
latitude
Nlso specilieu in uecimal
altitude
Specilieu in meteis
Using DDMS to update location
Ve talkeu a lot aLout DDMS (the Dalvik DeLug Monitoi Seivice) in Chaptei 5, Lut
two leatuies aie ielateu to location upuates. The Emulatoi Contiol pane ol the DDMS
scieen pioviues seveial ways ol contiolling the iunning emulatoi. Nltei switching to
the DDMS peispective (click on DDMS in the uppei iight ol the Eclipse winuow), you
shoulu see the Emulatoi Contiol pane in the miuule lelt ol the DDMS winuow (Fig-
uie 9-1). You will pioLaLly have to scioll uown in that pane to see the contiols ielateu
to Location Contiols.
Iigurc 9-1. DDMS Enu|ator Contro| panc
To senu a one-time upuate ol a location to the emulatoi, just entei the longituue anu
latituue in the appiopiiate Loxes anu click Senu.
Il you click on the GPX oi KML taLs, you will Le aLle to loau a GPX oi KML lile that
uesciiLes a path, as shown in Figuie 9-2. Heie we`ve alieauy loaueu the lile OR.|n|,
which is incluueu on the weLsite loi this Look. It tiaces a path neai O`Reilly heau-
guaiteis in SeLastopol, Caliloinia.
You can cieate GPX tiacks with many GPS navigation soltwaie tools, anu KML tiacks
with Google Eaith oi many othei navigation piogiams. The OR.|n| lile was geneiateu
Location Without Maps | 153
Ly plotting a seiies ol Google Eaith Placemaiks anu concatenating them togethei into
a single lile. Heie`s an exceipt liom OR.|n|:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<name>OR1.kml</name>
<StyleMap id="msn_ylw-pushpin">
<Pair>
<key>normal</key>
<styleUrl>#sn_ylw-pushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#sh_ylw-pushpin</styleUrl>
</Pair>
</StyleMap>
<Style id="sh_ylw-pushpin">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
<ListStyle>
</ListStyle>
</Style>
<Style id="sn_ylw-pushpin">
<IconStyle>
<scale>1.1</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
Iigurc 9-2. DDMS Enu|ator with KML |ocation updatcs
154 | Chapter 9:ಗLocation and Mapping
<ListStyle>
</ListStyle>
</Style>
<Placemark>
<name>OR1</name>
<LookAt>
<longitude>-122.7583711698369</longitude>
<latitude>38.38922415809942</latitude>
<altitude>0</altitude>
<range>14591.7166300043</range>
<tilt>0</tilt>
<heading>0.04087372005871314</heading>
<altitudeMode>relativeToGround</altitudeMode>
</LookAt>
<styleUrl>#msn_ylw-pushpin</styleUrl>
<Point>
<coordinates>-122.8239277647483,38.40273084940345,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>OR2</name>
<LookAt>
<longitude>-122.7677364592949</longitude>
<latitude>38.3819544049429</latitude>
<altitude>0</altitude>
<range>11881.3330990845</range>
<tilt>0</tilt>
<heading>-8.006283077460853e-010</heading>
<altitudeMode>relativeToGround</altitudeMode>
</LookAt>
<styleUrl>#msn_ylw-pushpin</styleUrl>
<Point>
<coordinates>-122.8064486052584,38.40786910573772,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>OR3</name>
<LookAt>
<longitude>-122.7677364592949</longitude>
<latitude>38.3819544049429</latitude>
<altitude>0</altitude>
<range>11881.3330990845</range>
<tilt>0</tilt>
<heading>-8.006283077460853e-010</heading>
<altitudeMode>relativeToGround</altitudeMode>
</LookAt>
<styleUrl>#msn_ylw-pushpin</styleUrl>
<Point>
<coordinates>-122.7911077944045,38.41500788727795,0</coordinates>
</Point>
</Placemark>
...
Location Without Maps | 155
CHAPTER 10
Building a View
Nnuioiu comes with many ieguiiements that heialu complexity in the usei inteilace:
it`s a multipiocessing system that suppoits multiple concuiient applications, accepts
multiple loims ol input, is highly inteiactive, anu must Le llexiLle enough to suppoit
a wiue iange ol uevices now anu in the lutuie. The usei inteilace is impiessively iich
anu easy to use, given all that it has to uo. But you neeu to unueistanu how it woiks in
oiuei to use it without ciashing youi application, making it look awlul on some uevices,
oi imposing a peiloimance penalty on the system.
This chaptei gives you Lasic technigues loi wiiting a giaphical inteilace on Nnuioiu.
It explains the aichitectuie ol the Nnuioiu UI toolkit, while showing you in piactical
teims how to enaLle anu lay out Lasic inteilace elements such as Luttons anu text Loxes.
It also coveis event hanuling anu othei ciitical topics, such as using multiple thieaus
to ollloau long tasks so that the UI uoesn`t lieeze.
Android GUI Architecture
The Nnuioiu enviionment auus yet anothei Giaphical Usei Inteilace (GUI) toolkit to
the ]ava ecospheie, joining NVT, Swing, SVT, anu ]2ME (leaving asiue the weL UI
toolkits). Il you`ve woikeu with any ol these, the Nnuioiu liamewoik will look lamiliai.
Like them, it is single-thieaueu, event-uiiven, anu Luilt on a liLiaiy ol nestaLle
components.
The Nnuioiu UI liamewoik is, like the othei UI liamewoiks, oiganizeu aiounu the
common Mouel-View-Contiollei pattein illustiateu in Figuie 10-1. It pioviues stiuc-
tuie anu tools loi Luiluing a Contiollei that hanules usei input (like key piesses anu
scieen taps) anu a View that ienueis giaphical inloimation to the scieen.
The Model
The Mouel is the guts ol youi application: what it actually uoes. It might Le, loi in-
stance, the uataLase ol tunes on youi uevice anu the coue loi playing them. It might Le
youi list ol contacts anu the coue that places phone calls oi senus IMs to them.
157
Vhile a paiticulai application`s View anu Contiollei will necessaiily iellect the Mouel
they manipulate, a single Mouel might Le useu Ly seveial uilleient applications. Think,
loi instance, ol an MP3 playei anu an application that conveits MP3 liles into VNV
liles. Foi Loth applications, the Mouel incluues the MP3 lile loimat anu couecs loi it.
The loimei application, howevei, has the lamiliai Stop, Stait, anu Pause contiols, anu
plays the tiack. The lattei may not piouuce any sounu at all; insteau, it will have contiols
loi setting Litiate, etc. The Mouel is all aLout the uata. It is the suLject ol most ol the
iest ol this Look.
The View
The View is the application`s leeuLack to the usei. It is the poition ol the application
iesponsiLle loi ienueiing the uisplay, senuing auuio to speakeis, geneiating tactile
leeuLack, anu so on. The giaphical poition ol the Nnuioiu UI liamewoik`s View, ue-
sciiLeu in uetail in Chaptei 12, is implementeu as a tiee ol suLclasses ol the View class.
Giaphically, each ol these oLjects iepiesents a iectangulai aiea on the scieen that is
completely within the iectangulai aiea iepiesenteu Ly its paient in the tiee. The ioot
ol this tiee is the application winuow.
Ns an example, the uisplay in a hypothetical MP3 playei might contain a component
that shows the alLum covei loi the cuiiently playing tune. Nnothei component might
uisplay the name ol the cuiiently playing song, while a thiiu contains suLcomponents
such as the Play, Pause, anu Stop Luttons.
redraw key press, taps, etc.
update invalidate
View
Controller
Model
Iigurc 10-1. Modc|-\icw-Contro||cr conccpt
158 | Chapter 10:ಗBuilding a View
The UI liamewoik paints the scieen Ly walking the View tiee, asking each component
to uiaw itsell in a prcordcr travcrsa|. In othei woius, each component uiaws itsell anu
then asks each ol its chiluien to uo the same. Vhen the whole tiee has Leen ienueieu,
the smallei, nesteu components that aie the leaves ol the tiee÷anu that weie, theieloie,
painteu latei÷appeai to Le painteu on top ol the components that aie neaiei to the
ioot anu that weie painteu liist.
The Nnuioiu UI liamewoik is actually guite a Lit moie ellicient than this oveisimplilieu
uesciiption suggests. It uoes not paint an aiea ol a paient view il it can Le ceitain that
some chilu will latei paint the same aiea, Lecause it woulu Le a waste ol time to paint
Lackgiounu unueineath an opague oLject! It woulu also Le a waste ol time to iepaint
poitions ol a view that have not changeu.
The Controller
The Contiollei is the poition ol an application that iesponus to exteinal actions: a
keystioke, a scieen tap, an incoming call, etc. It is implementeu as an event gueue. Each
exteinal action is iepiesenteu as a unigue event in the gueue. The liamewoik iemoves
each event liom the gueue in oiuei anu uispatches it.
Foi example, when a usei piesses a key on his phone, the Nnuioiu system geneiates a
KeyEvent anu auus it to an cvcnt qucuc. Eventually, altei pieviously engueueu events
have Leen piocesseu, the KeyEvent is iemoveu liom the gueue anu passeu as the pa-
iametei ol a call to the dispatchKeyEvent methou ol the View that is cuiiently selecteu.
Once an event is uispatcheu to the in-locus component, that component may take
appiopiiate action to change the inteinal state ol the piogiam. In an MP3 playei ap-
plication, loi instance, when the usei taps a Play/Pause Lutton on the scieen anu the
event is uispatcheu to that Lutton`s oLject, the hanulei methou might upuate the Mouel
to iesume playing some pieviously selecteu tune.
This chaptei uesciiLes the constiuction ol a Contiollei loi an Nnuioiu application.
Putting It Together
Ve now have all the concepts necessaiy to uesciiLe the complete UI system. Vhen an
exteinal action occuis (loi example, when the usei sciolls, uiags, oi piesses a Lutton;
a call comes in; oi an MP3 playei aiiives at the enu ol its playlist), the Nnuioiu system
engueues an event iepiesenting the action on the event gueue. Eventually the event is
uegueueu÷liist in, liist out÷anu uispatcheu to an appiopiiate event hanulei. The
hanulei, pioLaLly coue you wiite as pait ol youi application, iesponus to the event Ly
notilying the Mouel that theie has Leen a change in state. The Mouel takes the appio-
piiate action.
Android GUI Architecture | 159
Neaily any change in Mouel state will ieguiie a coiiesponuing change in the View. In
iesponse to a key piess, loi instance, an EditText component must show the newly
typeu chaiactei at the inseition point. Similaily, in a phone Look application, clicking
on a contact will cause that contact to Le highlighteu anu the pieviously highlighteu
contact to have its highlighting iemoveu.
In oiuei to upuate the uisplay, the Mouel must notily the UI Fiamewoik that some
poition ol the uisplay is now stale anu has to Le ieuiawn. The ieuiaw ieguest is, ac-
tually, nothing moie than anothei event engueueu in the same liamewoik event gueue
that helu the Contiollei event a moment ago. The ieuiaw event is piocesseu, in oiuei,
like any othei UI event.
Eventually, the ieuiaw event is iemoveu liom the gueue anu uispatcheu. The event
hanulei loi a ieuiaw event is the View. The View tiee is ieuiawn, anu each View oLject
is iesponsiLle loi ienueiing its cuiient state at the time it is uiawn.
To make this conciete, we can tiace the cycle thiough a hypothetical MP3 playei
application:
1. Vhen the usei taps the scieen image ol the Play/Pause Lutton, the liamewoik
cieates a new MotionEvent containing, among othei things, the scieen cooiuinates
ol the tap. The liamewoik engueues the new event at the enu ol the event gueue.
2. Ns uesciiLeu in ¨The Contiollei¨ on page 159, when the event peicolates thiough
the gueue, the liamewoik iemoves it anu passes it uown the View tiee to the leal
wiuget within whose Lounuing iectangle the tap occuiieu.
3. Because the Lutton wiuget iepiesents the Play/Pause Lutton, the application Lut-
ton hanuling coue tells the coie (the Mouel) that it shoulu iesume playing a tune.
+. The application Mouel coue staits playing the selecteu tune. In auuition, it senus
a ieuiaw ieguest to the UI liamewoik.
5. The ieuiaw ieguest is auueu to the event gueue anu eventually piocesseu as ue-
sciiLeu in ¨The View¨ on page 158.
6. The scieen gets ieuiawn with the Play Lutton in its playing state, anu eveiything
is again in sync.
UI component oLjects such as Luttons anu text Loxes actually implement Loth View
anu Contiollei methous. This only makes sense. Vhen you auu a Button to youi ap-
plication`s UI, you want it to appeai on the scieen as well as uo something when the
usei pushes it. Even though the two logical elements ol the UI÷the View anu the
Contiollei÷aie implementeu in the same oLject, you shoulu take caie that they uo not
uiiectly inteiact. Contiollei methous, loi instance, shoulu nevei uiiectly change the
uisplay. Leave it to the coue that actually changes state to ieguest a ieuiaw, anu tiust
that latei calls to ienueiing methous will allow the component to iellect its new state.
Couing in this way minimizes synchionization pioLlems anu helps to keep youi pio-
giam ioLust anu Lug-liee.
160 | Chapter 10:ಗBuilding a View
Theie is one moie aspect ol the Nnuioiu UI liamewoik that it is impoitant to unuei-
stanu: it is single-thieaueu. Theie is a single thieau iemoving events liom the event
gueue to make Contiollei callLacks anu to ienuei the View. This is signilicant loi sev-
eial ieasons.
The simplest conseguence ol a single-thieaueu UI is that it is not necessaiy to use
synchronized Llocks to cooiuinate state Letween the View anu the Contiollei. This is
a valuaLle optimization.
Nnothei auvantage ol a single-thieaueu UI is the guaiantee that each event on the event
gueue is piocesseu completely anu in the oiuei in which it was engueueu. That may
seem laiily oLvious, Lut its implications make couing the UI much easiei. Vhen a UI
component is calleu to hanule an event, it is guaianteeu that no auuitional UI piocessing
will take place until it ietuins. That means, loi instance, that when a component ie-
guests multiple changes in the piogiam state÷each ol which causes a coiiesponuing
ieguest that the scieen Le iepainteu÷it is guaianteeu that the iepaint will not stait
until it has completeu piocessing, peiloimeu all ol its upuates, anu ietuineu. In shoit,
UI callLacks aie atomic.
Theie is a thiiu ieason to iememLei that theie is only a single thieau uegueuing anu
uispatching events liom the UI event gueue: il youi coue stalls that thieau, loi any
ieason, youi UI will lieeze! Il a component`s iesponse to an event is simple (changing
the state ol vaiiaLles, cieating new oLjects, etc.), it is peilectly coiiect to uo that pio-
cessing on the main event thieau. Il, on the othei hanu, the hanulei must ietiieve a
iesponse liom some uistant netwoik seivice oi iun a complex uataLase gueiy, the entiie
UI will Lecome uniesponsive until the ieguest completes. That uelinitely uoes not make
loi a gieat usei expeiience! Long-iunning tasks must Le uelegateu to anothei thieau,
as uesciiLeu in ¨Nuvanceu Viiing: Focus anu Thieauing¨ on page 179.
Assembling a Graphical Interface
The Nnuioiu UI liamewoik pioviues Loth a complete set ol uiawing tools with which
to Luilu a UI anu a iich collection ol pieLuilt components Laseu on these tools. Ns we
will see in Chaptei 12, the liamewoik giaphics tools pioviue plenty ol suppoit loi
applications that neeu to cieate theii own contiols oi ienuei special views. On the othei
hanu, many applications may woik veiy well using only canneu wiugets liom the tool-
kit. In lact, as we saw in Chaptei 9, the MapActivity anu MyLocationOverlay classes
make it possiLle to cieate extiemely sophisticateu applications without uoing any cus-
tom uiawing at all.
Ve`ve alieauy useu the teim ¨wiuget¨ once oi twice, without explicitly uelining it.
Recall that the scieen is a ienueieu Ly a tiee ol components. In the Nnuioiu UI liame-
woik, these components aie all suLclasses ol android.view.View. The components that
aie leaves oi neaily leaves uo most ol the actual uiawing anu aie, in the context ol an
application UI, commonly calleu wiugets.
Assembling a Graphical Interface | 161
The inteinal noues, sometimes calleu Containcr \icws, aie special components that can
have othei components as chiluien. In the Nnuioiu UI liamewoik, Containei Views
aie suLclasses ol android.view.ViewGroup, which, ol couise, is in tuin a suLclass ol
View. Typically, they uo veiy little uiawing. Insteau, they aie iesponsiLle loi aiianging
theii chilu components on the scieen anu keeping them aiiangeu as the uisplay changes
shape, oiientation, anu so on. Doing this can Le guite complex.
You have alieauy seen a veiy simple View coueu up in ¨Viiting Hello-
Voilu¨ on page 22. That application cieateu a tiivial TextView anu uisplayeu it. Theie
is no way to auu anything to that application, Lecause the ioot View is a TextView, which
cannot Le a containei loi othei components. To cieate moie complex uisplays, it is
necessaiy to assemLle a tiee ol containeis. Example 10-1 shows an application with a
view tiee that is thiee layeis ueep. N veitical lineai layout contains two hoiizontal lineai
layouts. Each ol the hoiizontal layouts, in tuin, contains two wiugets.
Exanp|c 10-1. A conp|cx vicw trcc
package com.oreilly.android.intro;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
public class AndroidDemo extends Activity {
private LinearLayout root;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
LinearLayout.LayoutParams containerParams
= new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0.0F);
LinearLayout.LayoutParams widgetParams
= new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT,
1.0F);
root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(Color.LTGRAY);
root.setLayoutParams(containerParams);
162 | Chapter 10:ಗBuilding a View
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setBackgroundColor(Color.GRAY);
ll.setLayoutParams(containerParams);
root.addView(ll);
EditText tb = new EditText(this);
tb.setText(R.string.defaultLeftText);
tb.setFocusable(false);
tb.setLayoutParams(widgetParams);
ll.addView(tb);
tb = new EditText(this);
tb.setText(R.string.defaultRightText);
tb.setFocusable(false);
tb.setLayoutParams(widgetParams);
ll.addView(tb);
ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setBackgroundColor(Color.DKGRAY);
ll.setLayoutParams(containerParams);
root.addView(ll);
Button b = new Button(this);
b.setText(R.string.labelRed);
b.setTextColor(Color.RED);
b.setLayoutParams(widgetParams);
ll.addView(b);
b = new Button(this);
b.setText(R.string.labelGreen);
b.setTextColor(Color.GREEN);
b.setLayoutParams(widgetParams);
ll.addView(b);
setContentView(root);
}
}
Note that the coue pieseives a ieleience to the ioot ol the View tiee loi latei use.
This example uses thiee LinearLayout wiugets. N LinearLayout, just as its name implies,
is a View that uisplays its chiluien in a iow oi column, as ueteimineu Ly its oiientation
piopeity. The chilu views aie uisplayeu in the oiuei in which they aie addcd to the
LinearLayout (iegaiuless ol the oiuei in which they weie crcatcd), in the uiiections
lamiliai to Vestein ieaueis: lelt to iight anu top to Lottom. The Lutton laLeleu
¨Gieen¨, loi instance, is in the lowei iighthanu coinei ol this layout, Lecause it is the
seconu thing auueu to the hoiizontal LinearLayout View, which was, in tuin, the seconu
thing auueu to the veitical LinearLayout (the ioot).
Assembling a Graphical Interface | 163
Figuie 10-2 shows what the iesults might look like to the usei. The seven Views in the
tiee aie stiuctuieu as shown in Figuie 10-3.
Iigurc 10-2. Thc \icw as it appcars on thc scrccn
LinearLayout (vertical)
LinearLayout
(horizontal)
Text Text
Red
button
Green
button
LinearLayout
(horizontal)
Iigurc 10-3. Hicrarchy of objccts in thc \icw
Chaptei 8 explaineu that the Nnuioiu liamewoik pioviues a convenient capaLility loi
sepaiating uata iesouices liom coue. This is paiticulaily uselul in Luiluing view com-
ponent layouts. The pievious example can Le ieplaceu with the uiamatically simplei
coue in Example 10-2 anu the XML uelinition ol the layout in Example 10-3.
Exanp|c 10-2. Conp|cx \icw using a |ayout rcsourcc
package com.oreilly.android.intro;
import android.app.Activity;
import android.os.Bundle;
/**
* Android UI demo program
164 | Chapter 10:ಗBuilding a View
*/
public class AndroidDemo extends Activity {
private LinearLayout root;
@Override public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
root = (LinearLayout) findViewById(R.id.root);
}
}
Exanp|c 10-3. Conp|cx \icw |ayout rcsourcc
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:orientation="vertical"
android:background="@drawable/lt_gray"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:background="@drawable/gray"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/text1"
android:text="@string/defaultLeftText"
android:focusable="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<EditText
android:id="@+id/text2"
android:text="@string/defaultRightText"
android:focusable="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:background="@drawable/dk_gray"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/button1"
android:text="@string/labelRed"
android:textColor="@drawable/red"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
Assembling a Graphical Interface | 165
<Button
android:id="@+id/button2"
android:text="@string/labelGreen"
android:textColor="@drawable/green"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
This veision ol the coue, like the liist one, also pieseives a ieleience to the ioot ol the
View tiee. It uoes this Ly tagging a wiuget in the XML layout (the ioot LinearLayout,
in this case) with an android:id tag, anu then using the findViewById methou liom the
Activity class to iecovei the ieleience.
It is a veiy goou iuea to get into the haLit ol using a iesouice to ueline youi View tiee
layout. Doing so allows you to sepaiate the visual layout liom the coue that Liings it
to lile. This way, you can tinkei with the layout ol a scieen without iecompiling. Fui-
thei, il the histoiy ol othei UI liamewoiks is any inuication, theie will eventually Le
tools loi Nnuioiu that allow you to compose scieens, cieating theii XML uelinitions,
using a visual UI euitoi.
Wiring Up the Controller
¨NssemLling a Giaphical Inteilace¨ on page 161 uemonstiateu a view with two Luttons.
Nlthough the Luttons look nice÷they even highlight when clickeu÷they aien`t veiy
uselul. Clicking them uoesn`t actually uo anything.
The uiscussion ol ¨The Contiollei¨ on page 159 uesciiLeu how the Nnuioiu liamewoik
tianslates exteinal actions (scieen taps, key piesses, etc.) into events that aie engueueu
anu then passeu into the application. Example 10-+ shows how to auu an cvcnt
hand|cr to one ol the Luttons in the uemo, so that it uoes something when it is clickeu.
Exanp|c 10-1. Wiring up a button
@Override public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
final EditText tb1 = (EditText) findViewById(R.id.text1);
final EditText tb2 = (EditText) findViewById(R.id.text2);
((Button) findViewById(R.id.button2)).setOnClickListener(
new Button.OnClickListener() {
@Override public void onClick(View arg0) {
tb1.setText(String.valueOf(rand.nextInt(200)));
tb2.setText(String.valueOf(rand.nextInt(200)));
}
}
166 | Chapter 10:ಗBuilding a View
);
}
Vhen iun, this veision ol the application still looks a lot like Figuie 10-2. Unlike the
eailiei example, though, in this veision eveiy time a usei clicks the Lutton laLeleu
¨Gieen¨, the numLeis in the EditText Loxes change. This is illustiateu in Figuie 10-+.
Iigurc 10-1. Wor|ing button
Simply changing numLeis isn`t veiy inteiesting, Lut this small example uemonstiates
the stanuaiu mechanism that an application uses to iesponu to UI events. It is impoitant
to note that, appeaiances notwithstanuing, this example uoes not violate the MVC
sepaiation ol conceins. In iesponse to the call to setText, in this implementation ol an
OnClickListener, the EditText oLject upuates an inteinal iepiesentation ol the text it
shoulu uisplay, anu then calls its own invalidate methou. It uoes not immeuiately uiaw
on the scieen. Theie aie veiy lew iules in piogiamming that aie aLsolute, Lut the au-
monition to sepaiate the Mouel, the View, anu the Contiollei comes pietty close.
In the example, the instance ol the Button class is wiieu to its Lehavioi using its
setOnClickListener methou. Button is a suLclass ol View, which uelines an inteilace
nameu OnClickListener anu a methou nameu setOnClickListener, which iegisteis the
listenei. The OnClickListener inteilace uelines a single methou, onClick. Vhen a
Button ieceives an event liom the liamewoik, in auuition to any othei piocessing it
might uo, it examines the event to see whethei it gualilies as a ¨click.¨ (The Lutton in
Example 10-1 woulu highlight when piesseu, even Leloie the listenei was auueu.) Il
the event uoes gualily as a click anu il a click listenei has Leen installeu, that listenei`s
onClick methou is invokeu.
The click listenei is liee to implement any custom Lehavioi that`s neeueu. In the ex-
ample, the custom Lehavioi cieates two ianuom numLeis Letween 0 anu 200 anu puts
one into each ol the two text Loxes. Insteau ol suLclassing Button anu oveiiiuing its
event piocessing methous, all that is necessaiy to extenu its Lehavioi is to iegistei a
click listenei that implements the Lehavioi. Ceitainly a lot easiei!
The click hanulei is especially inteiesting Lecause at the heait ol the Nnuioiu system÷
the liamewoik event gueue÷theie is no such thing as a click event. Insteau, View event
piocessing synthesizes the concept ol a ¨click¨ liom othei events. Il the uevice has a
Wiring Up the Controller | 167
touch-sensitive scieen, loi instance, a single tap is consiueieu a click. Il the uevice has
a centei key in its D-pau oi an ¨Entei¨ key, piessing anu ieleasing eithei will also iegistei
as a click. View clients neeu not concein themselves with what a click is oi how it is
geneiateu on a paiticulai uevice. They neeu only hanule the highei-level concept, leav-
ing the uetails to the liamewoik.
N View can have only one OnClickListener. Calling setOnClickListener a seconu time
on a given View will iemove the olu listenei anu install the new one. On the othei hanu,
a single listenei can listen to moie than one View. The coue in Example 10-5, loi in-
stance, is pait ol anothei application that looks exactly like Example 10-2. In this
veision, though, pushing cithcr ol the Luttons will upuate the text Lox.
This capaLility can Le veiy convenient in an application in which seveial actions pio-
uuce the same Lehavioi. Do not Le tempteu, though, to cieate a single enoimous listenei
to hanule all youi wiugets. Youi coue will Le easiei to maintain anu mouily il it contains
multiple smallei listeneis, each ol which implements a single, cleai Lehavioi.
Exanp|c 10-5. Listcning to nu|tip|c buttons
@Override public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
final EditText tb1 = (EditText) findViewById(R.id.text1);
final EditText tb2 = (EditText) findViewById(R.id.text2);
Button.OnClickListener listener = new Button.OnClickListener() {
@Override public void onClick(View arg0) {
tb1.setText(String.valueOf(rand.nextInt(200)));
tb2.setText(String.valueOf(rand.nextInt(200)));
} };
((Button) findViewById(R.id.button1)).setOnClickListener(listener);
((Button) findViewById(R.id.button2)).setOnClickListener(listener);
}
Listening to the Model
The Nnuioiu UI liamewoik uses the hanulei installation pattein peivasively. Nlthough
oui eailiei examples weie all Buttons, many othei Nnuioiu wiugets ueline listeneis. The
View class uelines seveial events anu listeneis that aie uLiguitous, anu which we will
exploie in luithei uetail latei in this chaptei. Othei classes, howevei, ueline othei spe-
cializeu types ol events anu pioviue hanuleis loi those events that aie meaninglul only
loi those classes. This is a stanuaiu iuiom that allows clients to customize the Lehavioi
ol a wiuget without having to suLclass it.
This pattein (calleu the Ca||bac| Pattcrn) is also an excellent way loi youi piogiam to
hanule its own exteinal, asynchionous actions. Vhethei iesponuing to a change in
168 | Chapter 10:ಗBuilding a View
state on a iemote seivei oi an upuate liom a location-Laseu seivice, youi application
can ueline its own events anu listeneis to allow its clients to ieact.
The examples so lai have Leen elementaiy anu have cut seveial coineis. Nlthough they
uemonstiate connecting a View anu a Contiollei, they have not hau ieal Mouels.
(Example 10-+ actually useu a String owneu Ly the implementation ol EditText as a
Mouel.) In oiuei to pioceeu, we`ie going to have to take a Liiel uetoui to Luilu a ieal,
usaLle Mouel.
The two classes in Example 10-6 compiise a Mouel that will suppoit extensions to the
uemo application loi this chaptei. They pioviue a lacility loi stoiing a list ol oLjects,
each ol which has X anu Y cooiuinates, a coloi, anu a size. They also pioviue a way to
iegistei a listenei, anu an inteilace that the listenei must implement.
Exanp|c 10-ó. Thc Dots Modc|
package com.oreilly.android.intro.model;
/** A dot: the coordinates, color and size. */
public final class Dot {
private final float x, y;
private final int color;
private final int diameter;
/**
* @param x horizontal coordinate.
* @param y vertical coordinate.
* @param color the color.
* @param diameter dot diameter.
*/
public Dot(float x, float y, int color, int diameter) {
this.x = x;
this.y = y;
this.color = color;
this.diameter = diameter;
}
/** @return the horizontal coordinate. */
public float getX() { return x; }
/** @return the vertical coordinate. */
public float getY() { return y; }
/** @return the color. */
public int getColor() { return color; }
/** @return the dot diameter. */
public int getDiameter() { return diameter; }
}
package com.oreilly.android.intro.model;
Wiring Up the Controller | 169
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/** A list of dots. */
public class Dots {
/** DotChangeListener. */
public interface DotsChangeListener {
/** @param dots the dots that changed. */
void onDotsChange(Dots dots);
}
private final LinkedList<Dot> dots = new LinkedList<Dot>();
private final List<Dot> safeDots = Collections.unmodifiableList(dots);

private DotsChangeListener dotsChangeListener;

/** @param l the new change listener. */
public void setDotsChangeListener(DotsChangeListener l) {
dotsChangeListener = l;
}
/** @return the most recently added dot, or null. */
public Dot getLastDot() {
return (dots.size() <= 0) ? null : dots.getLast();
}

/** @return the list of dots. */
public List<Dot> getDots() { return safeDots; }
/**
* @param x dot horizontal coordinate.
* @param y dot vertical coordinate.
* @param color dot color.
* @param diameter dot size.
*/
public void addDot(float x, float y, int color, int diameter) {
dots.add(new Dot(x, y, color, diameter));
notifyListener();
}
/** Delete all the dots. */
public void clearDots() {
dots.clear();
notifyListener();
}
private void notifyListener() {
if (null != dotsChangeListener) {
dotsChangeListener.onDotsChange(this);
}
}
}
170 | Chapter 10:ಗBuilding a View
In auuition to using this mouel, the next example also intiouuces a wiuget useu to view
it, the DotView: it will Le uiscusseu latei, in Example 12-3. Foi now we intiouuce it as
a liLiaiy wiuget. Its joL is to uiaw the uots iepiesenteu in the Mouel, in the coiiect
coloi anu at the coiiect cooiuinates. The complete souice loi the application is on the
weLsite loi this Look.
Example 10-7 shows the new uemo application, altei auuing the new Mouel anu View.
Exanp|c 10-7. Dots dcno
package com.oreilly.android.intro;
import java.util.Random;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
10 import android.widget.EditText;
import android.widget.LinearLayout;
import com.oreilly.android.intro.model.Dot;
import com.oreilly.android.intro.model.Dots;
import com.oreilly.android.intro.view.DotView;
/** Android UI demo program */
public class TouchMe extends Activity {
public static final int DOT_DIAMETER = 6;
private final Random rand = new Random();
final Dots dotModel = new Dots();

DotView dotView;
/** Called when the activity is first created. */
@Override public void onCreate(Bundle state) {
super.onCreate(state);
dotView = new DotView(this, dotModel);

// install the view
setContentView(R.layout.main);
((LinearLayout) findViewById(R.id.root)).addView(dotView, 0);

// wire up the controller
((Button) findViewById(R.id.button1)).setOnClickListener(
new Button.OnClickListener() {
@Override public void onClick(View v) {
makeDot(dots, dotView, Color.RED);
} });
((Button) findViewById(R.id.button2)).setOnClickListener(
Wiring Up the Controller | 171
new Button.OnClickListener() {
@Override public void onClick(View v) {
makeDot(dots, dotView, Color.GREEN);
} });
final EditText tb1 = (EditText) findViewById(R.id.text1);
final EditText tb2 = (EditText) findViewById(R.id.text2);
dots.setDotsChangeListener(new Dots.DotsChangeListener() {
@Override public void onDotsChange(Dots d) {
Dot d = dots.getLastDot();
tb1.setText((null == d) ? "" : String.valueOf(d.getX()));
tb2.setText((null == d) ? "" : String.valueOf(d.getY()));
dotView.invalidate();
} });
}

/**
* @param dots the dots we're drawing
* @param view the view in which we're drawing dots
* @param color the color of the dot
*/
void makeDot(Dots dots, DotView view, int color) {
int pad = (DOT_DIAMETER + 2) * 2;
dots.addDot(
DOT_DIAMETER + (rand.nextFloat() * (view.getWidth() - pad)),
DOT_DIAMETER + (rand.nextFloat() * (view.getHeight() - pad)),
color,
DOT_DIAMETER);
}
}
Heie aie some ol the highlights ol the coue:
These two calls to setOnClickListener auu new listeneis to the layout oLtaineu liom
the XML uelinition.
Nnonymous classes hanule click event callLacks to the ¨Reu¨ anu ¨Gieen¨ Luttons.
These event hanuleis uillei liom those in the pievious example only in that heie
theii Lehavioi has Leen lactoieu out into the local methou makeDot, uesciiLeu in item
5.
Calls to makeDot within onClick (to take place when a Lutton is clickeu).
The most suLstantial change to the example. This is wheie the Mouel is wiieu to
the View, using the CallLack pattein, Ly installing a dotsChangedListener. Vhen the
Mouel changes, this new listenei is calleu. It installs the X anu Y cooiuinates ol the
last uot into the lelt anu iight text Loxes, iespectively, anu ieguests that the Dot
View ieuiaw itsell (the invalidate call).
Delinition ol makeDot. This new methou cieates a uot, checking to make suie it is
within the DotView`s Loiueis, anu auus it to the Mouel. It also allows the uot`s coloi
to Le specilieu as a paiametei.
172 | Chapter 10:ಗBuilding a View
Figuie 10-5 shows what the application looks like when iun.
Iigurc 10-5. Running thc Dots dcno
Pushing the Lutton laLeleu ¨Reu¨ auus a new ieu uot to the DotView. Pushing the
¨Gieen¨ Lutton auus a gieen one. The text lielus contain the cooiuinates ol the last uot
auueu.
The Lasic stiuctuie ol Example 10-2 is still iecognizaLle, with some extensions. Foi
example, heie is the chain ol events that iesults liom clicking the ¨Gieen¨ Lutton:
1. Vhen the Lutton is clickeu, its clickHandler is calleu.
2. This causes a call to the anonymous class installeu as an OnClickHandler. It, in tuin,
calls makeDot with the coloi aigument Color.GREEN. The makeDot methou geneiates
ianuom cooiuinates anu auus a new gieen Dot to the Mouel at those cooiuinates.
3. Vhen the Mouel is upuateu, it calls its DotsChangedListener.
+. The listenei upuates the values in the text views anu ieguests that the DotView Le
ieuiawn.
Listening for Touch Events
Mouilying the uemo application to hanule taps is just a mattei ol auuing a tap hanulei.
The coue in Example 10-8 extenus the uemo application to place a cyan uot in the
DotView at the point at which the scieen is tappeu. In the pievious example, the coue
Wiring Up the Controller | 173
woulu Le auueu at the Leginning ol the onCreate lunction iight altei the call to its paient
methou. Notice that, Lecause the coue that uisplays the X anu Y cooiuinates ol the
most iecently auueu uot is wiieu only to the Mouel, it continues to woik coiiectly, no
mattei how uots aie auueu.
Exanp|c 10-8. Touchab|c Dots
dotView.setOnTouchListener(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN != event.getAction()) {
return false;
}
dots.addDot(event.getX(), event.getY(), Color.CYAN, DOT_DIAMETER);
return true;
} });
The MotionEvent passeu to the hanulei has seveial othei piopeities in auuition to the
location ol the tap that causeu it. Ns the example inuicates, it also contains the event
type, one ol DOWN, UP, MOVE, oi CANCEL. N simple tap actually geneiates one DOWN anu one
UP event. Touching anu uiagging geneiates a DOWN event, a seiies ol MOVE events, anu a
linal UP event.
The lacilities pioviueu Ly the MotionEvent loi hanuling gestuies aie veiy inteiesting.
The event contains the size ol the toucheu aiea anu the amount ol piessuie applieu.
That means that, on uevices that suppoit it, an application might Le aLle to uistinguish
Letween a tap with one lingei anu a tap with two lingeis, oi Letween a veiy light Liush
anu a liim push.
Elliciency is still impoitant in the moLile woilu. N UI liamewoik conlionts the hoins
ol a uilemma when tiacking anu iepoiting touchscieen events. Repoiting too lew events
might make it impossiLle to lollow motion with sullicient accuiacy to uo, loi instance,
hanuwiiting iecognition. On the othei hanu, iepoiting too many touch samples, each
in its own event, coulu loau the system unacceptaLly. The Nnuioiu UI liamewoik au-
uiesses this pioLlem Ly Lunuling gioups ol samples togethei, ieuucing the loau anu
still maintaining accuiacy. To see all ol the samples associateu with an event, use the
histoiy lacility implementeu with the methous getHistoricalX, getHistoricalY, etc.
Example 10-9 shows how to use the histoiy lacility. It extenus the uemo piogiam to
tiack a usei`s gestuies when she touches the scieen. The liamewoik ueliveis
sampleu X anu Y cooiuinates to the onTouch methou ol an oLject installeu as the
OnTouchListener loi the DotView. The methou uisplays a cyan uot loi each sample.
Exanp|c 10-9. Trac|ing notion
private static final class TrackingTouchListener
implements View.OnTouchListener
{
private final Dots mDots;
TrackingTouchListener(Dots dots) { mDots = dots; }
174 | Chapter 10:ಗBuilding a View
@Override public boolean onTouch(View v, MotionEvent evt) {
switch (evt.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
for (int i = 0, n = evt.getHistorySize(); i < n; i++) {
addDot(
mDots,
evt.getHistoricalX(i),
evt.getHistoricalY(i),
evt.getHistoricalPressure(i),
evt.getHistoricalSize(i));
}
break;
default:
return false;
}
addDot(
mDots,
evt.getX(),
evt.getY(),
evt.getPressure(),
evt.getSize());
return true;
}
private void addDot(Dots dots, float x, float y, float p, float s) {
dots.addDot(
x,
y,
Color.CYAN,
(int) ((p * s * Dot.DIAMETER) + 1));
}
}
Heie aie some highlights ol the coue:
This loop hanules Latcheu histoiical events. Vhen touch samples change moie
guickly than the liamewoik can uelivei them, it Lunules them into a single event.
The MotionEvent methou getHistorySize ietuins the numLei ol samples in the Latch,
anu the vaiious getHistory methous get the suLevent specilics.
Figuie 10-6 shows what the extenueu veision ol the application might look like altei a
lew clicks anu uiags.
The implementation uses the size anu piessuie at a given location`s sample to ueteimine
the uiametei ol the uot uiawn theie. Unloitunately, the Nnuioiu emulatoi uoes not
emulate touch piessuie anu size, so all ol the uots have the same uiametei. Size anu
piessuie values aie noimalizeu acioss uevices, as lloating-point values Letween 0.0 anu
Wiring Up the Controller | 175
1.0, uepenuing on the caliLiation ol the scieen. It is possiLle, howevei, that eithei value
may actually Le laigei than 1.0. Nt the othei enu ol the iange, the emulatoi always
iepoits the event size as zeio.
Devices with tiackLalls also geneiate MotionEvents when the tiackLall is moveu. These
events aie similai to those geneiateu Ly taps on a touch-sensitive scieen, Lut they aie
hanuleu uilleiently. TiackLall MotionEvents aie passeu into the View thiough a call to
dispatchTrackballEvent, not to dispatchTouchEvent, which ueliveieu taps. Nlthough
dispatchTrackballEvent uoes pass the event to onTrackballEvent, it uoes not liist pass
the event to a listenei! Not only aie tiackLall-geneiateu MotionEvents not visiLle
thiough the noimal tap-hanuling machineiy, Lut, in oiuei to iesponu to them, a wiuget
must suLclass View anu oveiiiue the onTrackballEvent methou.
MotionEvents geneiateu Ly the tiackLall aie hanuleu uilleiently in yet anothei way. Il
they aie not consuncd (to Le uelineu shoitly) they aie conveiteu into D-pau key events
(like those that woulu Le geneiateu Ly lelt, iight, up anu uown aiiow keys). This makes
sense when you consiuei that most uevices have eithei a D-pau oi a tiackLall, Lut not
Loth. Vithout this conveision, it woulun`t Le possiLle to geneiate D-pau events on a
uevice with only a tiackLall. Ol couise, it also implies that an application that hanules
tiackLall events must uo so caielully, lest it Lieak the tianslation.
Listening for Key Events
Hanuling keystioke input acioss multiple platloims can Le veiy tiicky. Some uevices
have many moie keys than otheis, some ieguiie tiiple-tapping loi chaiactei input, anu
Iigurc 10-ó. Running thc Dots dcno aftcr adding thc touch trac|ing fcaturc
176 | Chapter 10:ಗBuilding a View
so on. This is a gieat example ol something that shoulu Le lelt to the liamewoik
(EditText oi one ol its suLclasses) whenevei possiLle.
To extenu a wiuget`s KeyEvent hanuling, use the View methou setOnKeyListener to in-
stall an OnKeyListener. The listenei will Le calleu with multiple KeyEvents loi each usei
keystioke, one loi each action type: DOWN, UP, anu MULTIPLE. The action types DOWN anu
UP inuicate a key was piesseu oi ieleaseu, just as they uiu loi the MotionEvent class. N
key action ol MULTIPLE inuicates that a key is Leing helu uown (autoiepeating). The
KeyEvent methou getRepeatCount gives the numLei ol keystiokes that a MULTIPLE event
iepiesents.
Example 10-10 shows a sample key hanulei. Vhen auueu to the uemo piogiam, it
causes uots to Le auueu to the uisplay at ianuomly chosen cooiuinates when keys aie
piesseu anu ieleaseu: a magenta uot when the Space key is piesseu anu ieleaseu, a
yellow uot when the Entei key is piesseu anu ieleaseu, anu a Llue uot when any othei
key is piesseu anu ieleaseu.
Exanp|c 10-10. Hand|ing |cys
dotView.setFocusable(true);
dotView.setOnKeyListener(new OnKeyListener() {
@Override public boolean onKey(View v, int keyCode, KeyEvent event) {
if (KeyEvent.ACTION_UP != event.getAction()) {
int color = Color.BLUE;
switch (keyCode) {
case KeyEvent.KEYCODE_SPACE:
color = Color.MAGENTA;
break;
case KeyEvent.KEYCODE_ENTER:
color = Color.YELLOW;
break;
default: ;
}
makeDot(dots, dotView, color);
}
return true;
} });
Alternative Ways to Handle Events
You`ve pioLaLly noticeu that the on... methous ol all ol the listeneis intiouuceu thus
lai÷incluuing onKey÷ietuin a boolean value. This is a pattein loi listeneis that allows
them to contiol suLseguent event piocessing Ly theii callei.
Vhen a Contiollei event is hanueu to a wiuget, the liamewoik coue in the
wiuget uispatches it to an appiopiiate methou, uepenuing on its type: onKeyDown,
onTouchEvent, etc. These methous, eithei in View oi one its suLclasses, implement the
wiuget`s Lehavioi. Ns uesciiLeu eailiei, though, the liamewoik liist olleis the event to
Wiring Up the Controller | 177
an appiopiiate listenei (OnTouchListener, OnKeyListener, etc.) il one exists. The lis-
tenei`s ietuin value ueteimines whethei the event is then uispatcheu to the View
methous.
Il the listenei ietuins false, the event is uispatcheu to the View methous as il the hanulei
uiu not exist. Il, on the othei hanu, a listenei ietuins true, the event is saiu to have Leen
consuncd. The View aLoits any luithei piocessing loi it. The View methous aie nevei
calleu anu have no oppoitunity to piocess oi iesponu to the event. Ns lai as the View
methous aie conceineu, it is as il the event uiu not exist.
Theie aie thiee ways that an event might Le piocesseu:
No |istcncr
The event is uispatcheu to the View methous loi noimal hanuling. N wiuget im-
plementation may, ol couise, oveiiiue these methous.
A |istcncr cxists and rcturns truc
Listenei event hanuling completely ieplaces noimal wiuget event hanuling. The
event is nevei uispatcheu to the View.
A |istcncr cxists and rcturns fa|sc
The event is piocesseu Ly the listenei anu then Ly the View. Nltei listenei event
hanuling is completeu, the event is uispatcheu to the View loi noimal hanuling.
Consiuei, loi instance, what woulu happen il the key listenei liom Example 10-10 weie
auueu to an EditText wiuget. Since the onKey methou always ietuins true, the liame-
woik will aLoit any luithei KeyEvent piocessing as soon as the methou ietuins. That
woulu pievent the EditText key-hanuling mechanism liom evei seeing the key events,
anu no text woulu evei appeai in the text Lox. That is pioLaLly not the intenueu
Lehavioi!
Il the onKey methou insteau ietuins false loi some key events, the liamewoik will
uispatch those events to the EditText wiuget loi continueu piocessing. The EditText
mechanism will see the events, anu the associateu chaiacteis will Le appenueu to the
EditText Lox, as expecteu. Example 10-11 shows an extension ol Example 10-10 that,
Lesiues auuing new uots to the Mouel, also lilteis the chaiacteis passeu to the hypo-
thetical EditText Lox. It allows numeiic chaiacteis to Le piocesseu noimally Lut hiues
eveiything else.
Exanp|c 10-11. Hand|ing |cys
new OnKeyListener() {
@Override public boolean onKey(View v, int keyCode, KeyEvent event) {
if (KeyEvent.ACTION_UP != event.getAction()) {
int color = Color.BLUE;
switch (keyCode) {
case KeyEvent.KEYCODE_SPACE:
color = Color.MAGENTA;
break;
case KeyEvent.KEYCODE_ENTER:
color = Color.YELLOW;
178 | Chapter 10:ಗBuilding a View
break;
default: ;
}
makeDot(dotModel, dotView, color);
}
return (keyCode < KeyEvent.KEYCODE_0)
||(keyCode > KeyEvent.KEYCODE_9);
}
}
Il youi application neeus to implement entiiely new ways ol hanuling events (in othei
woius, il it is something that cannot Le implementeu ieasonaLly Ly augmenting Le-
havioi anu lilteiing, using an OnKeyHandler), you will have to unueistanu anu oveiiiue
View key event hanuling. To summaiize the piocess, events aie uispatcheu to the View
thiough the DispatchKeyEvent methou. DispatchKeyEvent implements the Lehavioi ue-
sciiLeu pieviously, olleiing the event to the onKeyHandler liist. Il the hanulei ietuins
false, it olleis the event to the View methous implementing the KeyEvent.Callback
inteilace: onKeyDown, onKeyUp, anu onKeyMultiple.
Advanced Wiring: Focus and Threading
Ns uemonstiateu in Example 10-9 anu ¨Listening loi Touch Events¨ on page 173,
MotionEvents aie ueliveieu to the wiuget whose Lounuing iectangle contains the cooi-
uinates ol the touch that geneiateu them. It isn`t guite so oLvious how to ueteimine
which wiuget shoulu ieceive a KeyEvent. In oiuei to uo this, the Nnuioiu UI liamewoik,
like most othei UI liamewoiks, suppoits the concept ol selection, oi focus.
In oiuei to accept locus, a wiuget`s focusab|c attiiLute must Le set to tiue. This can Le
uone using eithei an XML layout attiiLute (the EditText Views in Example 10-3 have
theii locusaLle attiiLute set to lalse) oi the setFocusable methou, as shown in the liist
line ol Example 10-10. N usei changes which View has locus using D-pau keys oi Ly
tapping the scieen when touch is suppoiteu.
Vhen a wiuget is in locus, it usually ienueis itsell with some kinu ol highlighting to
pioviue leeuLack that it is the cuiient taiget ol keystiokes. Foi instance, when an
EditText wiuget is in locus, it is uiawn Loth highlighteu anu with a cuisoi at the text
inseit position.
To ieceive notilication when a wiuget enteis oi leaves locus, install an OnFocusChange
Listener. Example 10-12 shows the listenei neeueu to auu a locus-ielateu leatuie to
the uemo piogiam. It causes a ianuomly positioneu Llack uot to Le auueu automatically
to the DotView eveiy now anu then, whenevei it is in locus.
Exanp|c 10-12. Hand|ing focus
dotView.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override public void onFocusChange(View v, boolean hasFocus) {
Wiring Up the Controller | 179
if (!hasFocus && (null != dotGenerator)) {
dotGenerator.done();
dotGenerator = null;
}
else if (hasFocus && (null == dotGenerator)) {
dotGenerator = new DotGenerator(dots, dotView, Color.BLACK);
new Thread(dotGenerator).start();
}
} });
Theie shoulu Le lew suipiises in the OnFocusChangeListener. Vhen the DotView comes
into locus, it cieates the DotGenerator anu spawns a thieau to iun it. Vhen the wiuget
leaves locus, the DotGenerator is stoppeu anu lieeu. The new uata memLei,
dotGenerator (whose ueclaiation is not shown in the example), is nonnull only when
the DotView is in locus. Theie is an impoitant anu poweilul new tool in the implemen-
tation ol DotGenerator, anu we`ll ietuin to it in a moment.
Focus is tiansleiieu to a paiticulai wiuget Ly calling its View methou, requestFocus.
Vhen requestFocus is calleu loi a new taiget wiuget, the ieguest is passeu up the tiee,
paient Ly paient, to the tiee ioot. The ioot iememLeis the wiuget that is in locus anu
passes suLseguent key events to it uiiectly.
This is exactly how the UI liamewoik changes locus to a new wiuget in iesponse to a
D-pau keystioke. The liamewoik iuentilies the wiuget that will Le in locus next anu
calls that wiuget`s requestFocus methou. This causes the pieviously locuseu wiuget to
lose locus anu the taiget to gain it.
The piocess ol iuentilying the wiuget that will gain locus is complicateu. In oiuei to uo
it, the navigation algoiithm has to peiloim some tiicky calculations that may uepenu
on the locations ol eveiy othei wiuget on the scieen.
Consiuei, loi instance, what happens when the iight D-pau Lutton is piesseu anu the
liamewoik attempts to tianslei locus to the wiuget immeuiately to the iight ol the one
that is cuiiently in locus. Vhen looking at the scieen, it may Le completely oLvious
which wiuget that is. In the View tiee, howevei, it is not neaily so oLvious. The taiget
wiuget may Le at anothei level in the tiee anu seveial Lianches away. Iuentilying it
uepenus on the exact uimensions ol wiugets in yet othei uistant paits ol the tiee. Foi-
tunately, uespite the consiueiaLle complexity, the Nnuioiu UI liamewoik implemen-
tation usually just woiks as expecteu.
Vhen it uoes not, theie aie loui piopeities÷set eithei Ly application methou oi Ly
XML attiiLute÷that can Le useu to loice the uesiieu locus navigation Lehavioi:
nextFocusDown, nextFocusLeft, nextFocusRight, anu nextFocusUp. Setting one ol these
piopeities with a ieleience to a specilic wiuget will ensuie that D-pau navigation tians-
leis locus uiiectly to that wiuget when navigating in the iespective uiiection.
Nnothei complexity ol the locus mechanism is the uistinction that the Nnuioiu UI
liamewoik makes Letween D-pau locus anu touch locus, loi uevices with
touch-sensitive scieens. To unueistanu why this is necessaiy, iecall that on a scieen
180 | Chapter 10:ಗBuilding a View
that uoes not accept touch input, the only way to push a Lutton is to locus on it, using
D-pau navigation, anu then to use the centei D-pau key to geneiate a click. On a scieen
that uoes accept touch events, howevei, theie is nevei any ieason to locus on a Lutton.
Tapping the Lutton clicks it, iegaiuless ol which wiuget happens to Le in locus at the
time. Even on a touch-sensitive scieen, howevei, it is still necessaiy to Le aLle to locus
on a wiuget that accepts keystiokes÷an EditText wiuget, loi instance÷in oiuei to
iuentily it as the taiget loi suLseguent key events. In oiuei to hanule Loth kinus ol locus
coiiectly, you will have to look into View`s hanuling ol FOCUSABLE_IN_TOUCH_MODE, anu
the View methous isFocusableInTouchMode anu isInTouchMode.
In an application with multiple winuows, theie is at least one moie twist in the locus
mechanism: it is possiLle loi a winuow to lose locus without notilying the cuiiently in-
locus wiuget that its locus has Leen lost. This makes sense when you think aLout it. Il
the out-ol-locus winuow is Liought Lack to the top, the wiuget that was in locus in
that winuow will again Le in locus, with no othei action.
Consiuei enteiing a liienu`s phone numLei into an auuiess Look application. Suppose
you momentaiily switch Lack to a phone application to ieliesh youi memoiy ol the
last lew uigits ol his phone numLei. You`u Le annoyeu il, on ietuining to the auuiess
Look, you hau to locus again on the EditText Lox in which you`u Leen typing. You
expect the state to Le just as you lelt it.
On the othei hanu, this Lehavioi can have suipiising siue ellects. In paiticulai, the
implementation ol the auto-uot leatuie piesenteu in Example 10-12 continues to auu
uots to the DotView even when it is hiuuen Ly anothei winuow. Il a Lackgiounu task
shoulu iun only when a paiticulai wiuget is visiLle, that task must Le cleaneu up when
the wiuget loses locus, when the Window loses locus, anu when the Activity is pauseu
oi stoppeu.
Most ol the implementation ol the locus mechanism is in the ViewGroup class, in meth-
ous such as requestFocus anu requestChildFocus. Shoulu it Le necessaiy to implement
an entiiely new locus mechanism, you`ll neeu to look caielully at these methous, anu
oveiiiue them appiopiiately.
Leaving the suLject ol locus anu ietuining to the implementation ol the newly auueu
auto-uot leatuie, Example 10-13 contains the implementation ol DotGenerator.
Exanp|c 10-13. Enqucuing a tas| for thc nain thrcad
private final class DotGenerator implements Runnable {
final Dots dots;
final DotView view;
final int color;
private final Handler hdlr = new Handler();
private final Runnable makeDots = new Runnable() {
public void run() { makeDot(dots, view, color); }
};
private volatile boolean done;
Wiring Up the Controller | 181
// Runs on the main thread
DotGenerator(Dots dots, DotView view, int color) {
this.dots = dots;
this.view = view;
this.color = color;
}
// Runs on the main thread
public void done() { done = true; }
// Runs on a different thread!
public void run() {
while (!done) {
try { Thread.sleep(1000); }
catch (InterruptedException e) { }
hdlr.post(makeDots);
}
}
}
Heie aie some ol the highlights ol the coue:
Cieates an android.os.Handler oLject, the new tool intiouuceu in this section.
Cieates a new anonymous Runnable oLject. It is useu to call MakeDot liom the main
thieau in item +.
The Constiuctoi loi DotGenerator. The DotGenerator is cieateu on the main thieau.
The uot geneiation loop geneiates a new uot aLout eveiy seconu. This is the only
pait ol the coue that iuns on a completely uilleient thieau.
N naïve implementation ol DotGenerator woulu simply call makeDot uiiectly within its
run methou. Doing this woulun`t Le sale, howevei, unless makeDot was thieau-sale÷
anu the Dots anu DotView classes weie too, loi that mattei. This woulu Le tiicky to get
coiiect anu haiu to maintain. In lact, the Nnuioiu UI liamewoik actually loiLius access
to a View liom multiple thieaus. Running the naive implementation woulu cause the
application to lail with an Nnuioiu iuntime eiioi like this:
11-30 02:42:37.471: ERROR/AndroidRuntime(162):
android.view.ViewRoot$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
To get aiounu this iestiiction, DotGenerator cieates a Handler oLject within its con-
stiuctoi. N Handler oLject is associateu with the thieau on which it is cieateu anu pio-
viues sale, concuiient access to a canonical event gueue loi that thieau.
Because DotGenerator cieates a Handler uuiing its own constiuction (which happens
on the main thieau), this Handler is associateu with the main thieau. Now
DotGenerator can use the Handler to engueue a Runnable that calls makeDot liom the
main thieau. Ns you might guess, it tuins out that the main-thieau event gueue on
which the Handler engueues the Runnable is exactly the same one that is useu Ly the UI
182 | Chapter 10:ಗBuilding a View
liamewoik. The call to makeDot is uegueueu anu uispatcheu, like any othei UI event,
in its piopei oiuei. In this case, that causes its Runnable to Le iun. makeDot is calleu liom
the main thieau anu the UI stays single-thieaueu.
This is a veiy impoitant pattein loi couing with the Nnuioiu UI liamewoik. Vhenevei
piocessing staiteu on Lehall ol the usei might take moie than a lew milliseconus to
complete, uoing that piocessing on the main thieau might cause the entiie UI to Lecome
sluggish oi, woise, to lieeze loi a long time. Il the main application thieau uoes not
seivice its event gueue loi a couple ol seconus, the Nnuioiu OS will kill the application
loi Leing uniesponsive. The Handler class allows the piogiammei to avoiu this uangei
Ly uelegating slow oi long-iunning tasks to othei thieaus, so that the main thieau can
continue to seivice the UI. Vhen a task completes, it uses a main-thieau Handler to
engueue an upuate loi the UI.
The uemo application takes a slight shoitcut heie: it engueues the cieation ol a new
uot anu its auuition to the uot mouel on the main thieau. N moie complex application
might pass a main thieau Handler to the Mouel on cieation, anu pioviue a way loi the
UI to get a mouel-thieau Handler liom the mouel. The main thieau woulu ieceive up-
uate events engueueu loi it Ly the Mouel, using its main-thieau Handler. The Mouel,
iunning in its own thieau, woulu use the Looper class to uegueue anu uispatch incoming
messages liom the UI.
Passing events Letween the UI anu long-iunning thieaus in this way uiamatically ie-
uuces the constiaints ieguiieu to maintain thieau salety. In paiticulai, note that il an
engueuing thieau ietains no ieleiences to an engueueu oLject, oi il that oLject is im-
mutaLle, no auuitional synchionization is necessaiy.
The Menu
The linal aspect ol application contiol we`ll covei in this chaptei is the menu. Exam-
ple 10-1+ shows how to implement a simple menu Ly oveiiiuing two Activity methous.
Exanp|c 10-11. |np|cncnting a ncnu
@Override public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, CLEAR_MENU_ID, Menu.NONE, "Clear");
return true;
}

@Override public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
dotModel.clearDots();
return true;
default: ;
}
The Menu | 183
return false;
}
Vhen this coue is auueu to the TouchMe class, clicking the uevice`s Menu key will cause
the application to piesent a menu (laLeleu ¨Cleai¨ at the Lottom ol the scieen), as
shown in Figuie 10-7.
Iigurc 10-7. A sinp|c ncnu
Clicking the Entei key oi tapping the menu item again will cleai the uot wiuget.
Inteiestingly, il you iun this application, you will linu that while the auueu menu item
woiks most ol the time, it uoes not woik when the DotView is in locus. Can you guess
why?
184 | Chapter 10:ಗBuilding a View
Il you guesseu that the pioLlem is causeu Ly the OnKeyListener installeu in the
DotView, you aie coiiect! Ns implementeu in Example 10-15, the listenei swallows the
menu key event Ly ietuining true when it is clickeu. This pievents the stanuaiu View
piocessing ol the menu key keystioke. In oiuei to make the menu woik, the OnKey
Listener neeus a new case, shown in Example 10-15.
Exanp|c 10-15. |nprovcd |cy hand|ing
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
return false;
// ...
The Nnuioiu UI liamewoik also suppoits contextual menus. N ContextMenu appeais in
iesponse to a long click in a wiuget that suppoits it. The coue ieguiieu to auu a con-
textual menu to an application is entiiely analogous to that loi the options menu
shown eailiei except that the iespective methous aie onCreateContextMenu anu
onContextItemSelected. Nuuitionally, one moie call is ieguiieu. In oiuei to suppoit
contextual menus, a wiuget must Le assigneu a View.OnCreateContextMenuListener Ly
calling its View methou, setOnCreateContextMenuListener. Foitunately, since Activity
implements the View.OnCreateContextMenuListener inteilace, a common iuiom looks
like Example 10-16.
Exanp|c 10-1ó. |nsta||ing a ContcxtMcnuListcncr
findViewById(R.id.ctxtMenuView).setOnCreateContextMenuListener(this);
Simply oveiiiuing the uelault, empty Activity implementations ol the context menu
listenei methous will give youi application a context menu.
This chaptei has shown how the Nnuioiu giaphical inteilace woiks oveiall, anu has
given you the tools to manipulate its Lasic components: winuows, Views, anu events.
The lollowing chaptei explains the most uselul wiugets Nnuioiu makes availaLle, anu
Chaptei 12 shows you how to uo youi own giaphics piogiamming.
The Menu | 185
CHAPTER 11
A Widget Bestiary
Ns we have seen, theie aie thiee ways to implement a new Lehavioi in an application.
In incieasing oiuei ol complexity, you can:
º Finu a toolLox wiuget that alieauy uoes neaily what you neeu anu extenu it.
º Use the hanulei mechanism uemonstiateu pieviously in Example 10-+.
º Oveiiiue event ieceivei methous anu implement them youisell.
Hanuling iaw events acioss multiple platloims can Le guite complicateu. Dilleient
uevices, loi instance, may have iauically uilleient keypaus: loi instance, loui-key veisus
live-key D-paus. Some uevices still ieguiie tiiple-tapping to entei alphaLetic inloima-
tion. This kinu ol uiveisity is a seiious issue in the moLile enviionment anu can Le a
nightmaie loi the uevelopei who wants to keep hei application poitaLle.
Vhen uesigning youi application, it`s cleaily smait to let the liamewoik uo as much
as possiLle. The Lest option is to linu some toolLox wiuget that has neaily the Lehavioi
you ieguiie anu extenu it to meet youi neeus. The toolkit pioviues extensive tools loi
uoing this: XML attiiLutes, line-giaineu anu oveiiiuaLle methous, anu so on.
Il it isn`t possiLle to customize an existing wiuget, you shoulu consiuei the listenei
mechanism, uemonstiateu pieviously in Example 10-5. Only when it is necessaiy to
change the existing Lehavioi ol a wiuget shoulu you consiuei oveiiiuing event ieceivei
methous.
Usei inteilace liamewoiks have uilleient names loi the components liom which they`ie
composeu: the text Loxes, Luttons, canvases, anu othei components that you use to
cieate youi unigue application usei inteilace. Nnuioiu geneiically calls them Views,
anu the uocumentation uelines them simply as:
View: Nn oLject that knows how to uiaw itsell to the scieen.
So any oLject that uiaws itsell is a View, anu Views that can contain oi gioup othei
Views aie appiopiiately calleu ViewGioups. Views aie aiiangeu anu uisplayeu on the
scieen accoiuing to a Layout, which gives Nnuioiu hints aLout how you`u like to see
the Views aiiangeu. In the next lew sections we`ll look liist at simple Views, then at
187
ViewGioups, anu linally at Layouts. Since expanuaLility is a coie piinciple loi Nnuioiu,
we will also look at what you neeu to uo to ueline youi own custom Views anu Layouts.
Ns we`ve alieauy seen, Views anu Layouts Loth have attiiLutes that can eithei Le uelineu
in ]ava souice coue oi in the XML lile associateu with the Nctivity that uses the View
oi Layout. Vhen the attiiLutes aie in an XML lile, they aie ¨inllateu¨ at iuntime,
meaning that they aie applieu to theii iespective Views Ly the Nnuioiu liamewoik to
ueteimine how the Views look anu opeiate.
Theie aie so many attiiLutes that it uoesn`t make sense to list them all in these examples.
Ve uesciiLe the key ones, anu the iest aie explaineu in the uocumentation that comes
with the Nnuioiu SDK. N guick seaich loi android.widget.view_name will give you the
class uelinition loi that View, incluuing all the attiiLutes availaLle loi it, anu a uesciip-
tion ol each.
Android Views
The Views in the lollowing section aie the meat anu potatoes ol youi application;
essential wiugets that you`ll use ovei anu ovei anu that youi useis will Le lamiliai with
liom othei applications.
TextView and EditText
N TextView, as shown in the line ¨This is some text¨ in Figuie 11-1, is just what you`u
expect: a place to uisplay a text stiing. The vanilla TextView is loi uisplay only, wheieas
EuitText is a pieuelineu suLclass ol TextView that incluues iich euiting capaLilities.
Each TextView has the attiiLutes you`u expect ol such a component: you can change
its height, wiuth, lont, text coloi, Lackgiounu coloi, anu so loith. TextViews also have
some uselul unigue attiiLutes:
Iigurc 11-1. Tcxt\icw, EditTcxt, and Button
188 | Chapter 11:ಗA Widget Bestiary
autoLink
Il set (tiue), linus URLs in the uisplayeu text anu automatically conveits them to
clickaLle links.
autoText
Il set (tiue), linus anu coiiects simple spelling eiiois in the text.
editable
Il set (tiue), inuicates that the piogiam has uelineu an input methou to ieceive
input text (uelault is lalse loi TextView, anu tiue loi EuitText).
inputMethod
Iuentilies the input methou (EuitText uelines one loi geneiic text).
Example 11-1 shows how to use a TextView anu an EuitText with Buttons. (Buttons
aie coveieu in the next section.) It also shows the XML layout lile (nain.xn|), which
uses pietty stanuaiu anu iecommenueu layout paiameteis.
Exanp|c 11-1. Layout fi|c for Tcxt\icw and Edit\icw cxanp|c
<?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:id="@+id/txtDemo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<EditText
android:id="@+id/eTxtDemo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/btnDone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Log it"
/>
</LinearLayout>
Example 11-2 contains the accompanying ]ava souice (Tcxt\icwDcno.java).
Exanp|c 11-2. java for Tcxt\icw and Edit\icw: Tcxt\icwDcno.java
package com.oreilly.demo;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
Android Views | 189
import android.widget.EditText;
import android.widget.TextView;
public class TextViewDemo extends Activity {
private static TextView txt1;
private static EditText etxt1;
private static Button btn1;
// Create a button click listener for the Done button.
private final Button.OnClickListener btnDoneOnClick = new Button.OnClickListener() {
public void onClick(View v) {
String input = etxt1.getText().toString();
//Log the input string
Log.v("TextViewDemo", input);
etxt1.setText("");
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Get pointers to the Views defined in main.xml
txt1 = (TextView) findViewById(R.id.txtDemo);
etxt1 = (EditText) findViewById(R.id.eTxtDemo);
btn1 = (Button) findViewById(R.id.btnDone);
//Set the string displayed in TextView1
txt1.setText("This is some text.");
//Set the OnClickListener for the Done button
btn1.setOnClickListener(btnDoneOnClick);
}
}
Heie aie some ol the highlights ol the coue:
Delines a ClickListenei that we`ll attach to the ¨Log it¨ Button.
Because onCreate is executeu just once, as soon as Nnuioiu instantiates this View,
we put all the conliguiation we neeu heie.
Loaus the XML layout lile loi the application Ly setting the ContentView to nain.xn|.
Finus the Views that aie uelineu in nain.xn|.
Puts an initial stiing into the TextView. (Ve also coulu have uone this in the XML
lile, as was uone in the Micio]oLs application in ¨Initialization in Micio-
]oLs.java¨ on page +6.)
Connects the Button with the ClickListenei.
190 | Chapter 11:ಗA Widget Bestiary
Now the usei can entei anu euit text in the EuitText, anu when he clicks on ¨Log it¨,
the OnClickListener is calleu anu the text is wiitten to the logcat log. The stiing in the
EuitText is cleaieu out, anu the wiuget is ieauy loi anothei entiy.
Button and ImageButton
The Button View is just a Lutton, piinteu with some text to iuentily it, that the usei
can click to invoke some action. The pievious section cieateu a Button anu connecteu
it to an OnClickListener methou that executes when the Button is clickeu.
Nnuioiu has a veiy visual, moLile-oiienteu usei inteilace, so you might want to use a
Lutton with an image on it iathei than one with text. Nnuioiu pioviues the ImageButton
View loi just that puipose. You can auapt Example 11-2 to use an ImageButton Ly
making one change in the XML lile anu anothei in the ]ava coue:
1. In nain.xn|, ieplace the Button uelinition loi btnDone with an ImageButton:
...
<ImageButton
android:id="@+id/btnDone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
...
2. In Tcxt\icwDcno.java, ieueline btn1 as an ImageButton anu auu a line to set the
image to a PNG image in the drawab|c uiiectoiy:
...
private static ImageButton btn1;
...
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Get pointers to the Views defined in main.xml
txt1 = (TextView) findViewById(R.id.txtDemo);
etxt1 = (EditText) findViewById(R.id.eTxtDemo);
btn1 = (ImageButton) findViewById(R.id.btnDone);
...
//Set the image for the Done button
btn1.setImageResource(R.drawable.log);
...
The Lutton now appeais as shown in Figuie 11-2.
Android Views | 191
Adapters and AdapterViews
Adapters anu AdapterViews aie an impoitant anu uselul Lasis loi seveial ol the views
uiscusseu in the iest ol this chaptei. Using extensions to these classes, you can auuiess
an extiemely wiue vaiiety ol situations.
The AdapterView is a geneiic, list-oiienteu view ol uata. Nny collection ol uata oLjects
that can Le oiueieu in some ielatively staLle way can Le uisplayeu thiough an
AdapterView. Nn AdapterView is always associateu with an Adapter, which acts as the
Liiuge Letween it anu the unueilying uata collection. The Adapter has two
iesponsiLilities:
º Nt the ieguest ol the AdapterView, the Adapter must Le aLle to linu the uata oLject
that coiiesponus to a paiticulai inuex. It must, in othei woius, Le aLle to linu the
uata oLject that is visiLle in the AdapterView at a paiticulai location.
º Inveisely, the Adapter must Le aLle to supply a view thiough which the uata at a
paiticulai inuex can Le uisplayeu.
Iigurc 11-2. Tcxt boxcs with an |nagcButton
192 | Chapter 11:ಗA Widget Bestiary
It takes only a moment`s iellection to unueistanu how the AdapterView woiks: It is a
ViewGroup that contains all the machineiy necessaiy to seive as Loth the View anu
Contiollei loi a collection ol geneiic wiugets. It can lay them out on the uisplay, pass
in clicks anu keystiokes, anu so on. It neeu nevei concein itsell with what the suLviews
actually uisplay; it uistinguishes them only Ly theii inuexes. Vhenevei it neeus to pei-
loim eithei ol the two opeiations that aie not entiiely geneiic÷cieating a new view oi
getting the uata oLject attacheu to a paiticulai view÷it ielies on the Adapter to conveit
an inuex into eithei a uata oLject oi the view ol a uata oLject.
The AdapterView ieguests new views liom an implementation ol the Adapter inteilace,
as it neeus them, loi uisplay. Foi instance, as a usei sciolls though a list ol contacts,
the AdapterView ieguests a new view loi each new contact that Lecomes visiLle. Ns an
optimization, the AdapterView may ollei a view that is no longei visiLle (in this case,
one that has sciolleu oll the uisplay) loi ieuse. This can uiamatically ieuuce memoiy
chuin anu speeu up uisplay.
Vhen olleieu a iecycleu view, howevei, the Adapter must veiily that it is the iight kinu
ol view thiough which to uisplay the uata oLject at the ieguesteu inuex. This is neces-
saiy Lecause the Adapter is not limiteu to ietuining instances ol a single view class in
iesponse to the ieguest loi a view. Il the Adapter iepiesents seveial kinus ol oLjects, it
might cieate seveial uilleient types ol views, each applicaLle to some suLset ol the uata
oLjects in the collection. N list ol contacts, loi instance, might have two entiiely uil-
leient view classes: one loi uisplaying acguaintances that aie cuiiently online anu an-
othei loi those who aie not. The lattei might completely ignoie clicks, wheieas the
loimei woulu open a new chat session when clickeu.
Nlthough AdapterView anu Adapter aie Loth aLstiact anu cannot Le uiiectly instanti-
ateu, the UI toolkit incluues seveial pieLuilt Adapters anu AdapterViews that can Le useu
unmouilieu oi luithei suLclasseu to pioviue youi own customizations. ListAdapter
anu SpinnerAdapter aie paiticulaily uselul Adapters, while ListView, GridView,
Spinner, anu Gallery aie all hanuy suLclasses ol AdapterView. Il you plan to cieate youi
own suLclass ol AdapterView, a guick look at the coue loi one ol these classes will get
you oll to a iunning stait.
N goou example ol the use ol an AdapterView can Le lounu in ¨Galleiy anu Giiu-
View¨ on page 198. The Gallery view in that section is a suLclass ol AdapterView, anu
uses a suLclass ol Adapter calleu ImageAdapter.
CheckBoxes, RadioButtons, and Spinners
The Views we piesent in this section aie pioLaLly lamiliai to you liom othei usei in-
teilaces. Theii puipose is to allow the usei to choose liom multiple options. Check-
Boxes aie typically useu when you want to ollei multiple selections with a yes/no oi
tiue/lalse choice loi each. RauioButtons aie useu when only one choice is alloweu at a
time.
Android Views | 193
Spinneis aie similai to comLo Loxes in some liamewoiks. N comLo Lox typically uis-
plays the cuiiently selecteu option, along with a pull-uown list liom which the usei can
click on anothei option to select it.
Nnuioiu has auapteu these lamiliai components to make them moie uselul in a
touchscieen enviionment. Figuie 11-3 shows the thiee types ol multiple-choice Views
laiu out on an Nnuioiu application, with the Spinnei pulleu uown to show the options.
The layout XML lile that cieateu the scieen in the liguie looks like this:
<?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"
>
<CheckBox
android:id="@+id/cbxBox1"
android:layout_width="20dp"
android:layout_height="20dp"
android:checked="false"
/>
Iigurc 11-3. Chcc|Box, RadioButtons, and Spinncr
194 | Chapter 11:ಗA Widget Bestiary
<TextView
android:id="@+id/txtCheckBox"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="CheckBox: Not checked"
/>
<RadioGroup
android:id="@+id/rgGroup1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="@+id/RB1" android:text="Button1" />
<RadioButton android:id="@+id/RB2" android:text="Button2" />
<RadioButton android:id="@+id/RB3" android:text="Button3" />
</RadioGroup>
<TextView
android:id="@+id/txtRadio"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="RadioGroup: Nothing picked"
/>
<Spinner
android:id="@+id/spnMusketeers"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="2dp"
/>
</LinearLayout>
The lile just lists each View we want on the scieen along with the attiiLutes we want.
N RauioGioup is ieally a ViewGioup, so it contains the appiopiiate RauioButton
Views. Example 11-3 shows the ]ava lile that iesponus to usei clicks.
Exanp|c 11-3. java for Chcc|Box, RadioButtons, and Spinncr
package com.oreilly.select;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.google.android.maps.GeoPoint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
Android Views | 195
import android.widget.AdapterView.OnItemSelectedListener;
public class SelectExample extends Activity {
private CheckBox checkBox;
private TextView txtCheckBox, txtRadio;
private RadioButton rb1, rb2, rb3;
private Spinner spnMusketeers;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
checkBox = (CheckBox) findViewById(R.id.cbxBox1);
txtCheckBox = (TextView) findViewById(R.id.txtCheckBox);
txtRadio = (TextView) findViewById(R.id.txtRadio);
rb1 = (RadioButton) findViewById(R.id.RB1);
rb2 = (RadioButton) findViewById(R.id.RB2);
rb3 = (RadioButton) findViewById(R.id.RB3);
spnMusketeers = (Spinner) findViewById(R.id.spnMusketeers);
// React to events from the CheckBox
checkBox.setOnClickListener(new CheckBox.OnClickListener() {
public void onClick(View v){
if (checkBox.isChecked()) {
txtCheckBox.setText("CheckBox: Box is checked");
}
else
{
txtCheckBox.setText("CheckBox: Not checked");
}
}
});
// React to events from the RadioGroup
rb1.setOnClickListener(new RadioGroup.OnClickListener() {
public void onClick(View v){
txtRadio.setText("Radio: Button 1 picked");
}
});
rb2.setOnClickListener(new RadioGroup.OnClickListener() {
public void onClick(View v){
txtRadio.setText("Radio: Button 2 picked");
}
});
rb3.setOnClickListener(new RadioGroup.OnClickListener() {
public void onClick(View v){
txtRadio.setText("Radio: Button 3 picked");
}
});
196 | Chapter 11:ಗA Widget Bestiary
// Set up the Spinner entries
List<String> lsMusketeers = new ArrayList<String>();
lsMusketeers.add("Athos");
lsMusketeers.add("Porthos");
lsMusketeers.add("Aramis");
ArrayAdapter<String> aspnMusketeers =
new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,
lsMusketeers);
aspnMusketeers.setDropDownViewResource
(android.R.layout.simple_spinner_dropdown_item);
spnMusketeers.setAdapter(aspnMusketeers);
// Set up a callback for the spinner
spnMusketeers.setOnItemSelectedListener(
new OnItemSelectedListener() {
public void onNothingSelected(AdapterView<?> arg0) { }
public void onItemSelected(AdapterView<?> parent, View v,
int position, long id) {
// Code that does something when the Spinner value changes
}
});
}
}
The Views woik as lollows:
Chcc|Box
The CheckBox View takes caie ol llipping its state Lack anu loith anu uisplaying
the appiopiiate checkmaik when the state is tiue. Nll you have to uo is cieate an
¨OnClickListenei¨ to catch click events, anu you can auu whatevei coue you want
to ieact.
RadioGroup
Ns mentioneu eailiei, the RauioGioup View is ieally a ViewGioup that contains
any numLei ol RauioButton Views. The usei can select only one ol the Luttons at
a time, anu you captuie the selections Ly setting OnClickListeneis loi each
RauioButton. Note that clicking on one ol the RauioButtons uoes not liie a click
event loi the RauioGioup.
Spinncr
Spinneis ieguiie the most woik ol these thiee Views, Lut can also pioviue the Lest
use ol scaice scieen ieal estate. Ns shown, the Spinnei is noimally collapseu to the
cuiiently selecteu entiy, anu when you touch the uown aiiow on the iight, it
piesents a uiop-uown list ol the othei choices. To make that happen, you must:
1. Cieate a list ol the selections (which can Le a uynamic list Luilt anu changeu
Ly youi application).
2. Cieate an NiiayNuaptei liom the list that the Spinnei can use loi its uiop-uown
list. Note that the loimats shown loi the NiiayNuaptei (simple_spinner_item
Android Views | 197
anu simple_spinner_dropdown_item) aie uelineu Ly Nnuioiu; they uo not ap-
peai in youi iesouice XML liles.
3. Cieate an onItemSelecteuListenei loi the Spinnei to captuie select events.
The listenei has to contain Loth an onItemSelected methou anu an
onNothingSelected methou.
ViewGroups
ViewGioups aie Views that contain chilu Views. Each ViewGroup class emLouies a uil-
leient set ol assumptions aLout how to uisplay its chilu Views. Nll ViewGioups uescenu
liom the android.view.ViewGroup class. Layouts, which we`ll uiscuss latei in the chap-
tei, aie a suLset ol ViewGioups.
Gallery and GridView
The Galleiy ViewGioup (Figuie 11-+) uisplays multiple items in a hoiizontally sciolling
list. The cuiiently selecteu item is lockeu in the centei ol the scieen. Nny items that
appioach the euge ol the scieen Legin to laue, giving the usei the impiession that theie
may Le moie items ¨aiounu the coinei.¨ The usei can scioll hoiizontally thiough the
items within the galleiy. This ViewGioup is uselul when you want to piesent a laige
set ol possiLle choices to the usei without using too much scieen ieal estate.
N GiiuView (Figuie 11-5, shown latei) is veiy similai to a Galleiy. Like a Galleiy, the
GiiuView uisplays many chilu Views that the usei can manipulate. But in contiast to
a Galleiy, which is a one-uimensional list that the usei can scioll hoiizontally, a Giiu-
View is a two-uimensional aiiay that the usei can scioll veitically.
The Gallery anu GridView classes Loth uescenu liom the AdapterView class, so you neeu
a suLclass ol Nuaptei to pioviue a stanuaiuizeu way to access the unueilying uata. Nny
class that implements the Adapter class must implement the lollowing aLstiact lunc-
tions liom that class:
int getCount
Retuins the numLei ol items in the uata set iepiesenteu Ly the Nuaptei.
Object getItem(int position)
Retuins the oLject in the Nuaptei lunction (Nuaptei class) at the given position.
long getItem(int position)
Retuins the iow ID within the Nuaptei ol the oLject at the given position.
View getView(int position, View convertView, ViewGroup parent)
Retuins a View oLject that will uisplay the uata in the given position in the uata set.
The NpiDemos application`s vicws.Ga||cry1.java lile shows oll the Galleiy ViewGioup
nicely. The uemo uisplays a vaiiety ol images loi the usei to select, anu when the usei
uoes select one, the image`s inuex numLei Liielly appeais as toast.
198 | Chapter 11:ಗA Widget Bestiary
The NpiDemos application also incluues two example GiiuView Nctivities that show
how to use the GiiuView. Ve will not examine the GiiuView heie, Lecause the Galleiy
example is so similai.
Example 11-+ shows how to use a Galleiy ViewGioup. Example 11-+ shows the XML
layout lile (ga||cry_1.xn|).
Exanp|c 11-1. Layout fi|c for Ga||cry cxanp|c
<?xml version="1.0" encoding="utf-8"?>
<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
Heie aie some ol the highlights ol the layout coue:
The id loi the Galleiy View is gallery. Ns you have seen Leloie, the id is useu Ly
the find\icwBy|d lunction to hook a ]ava OLject to the XML oLject nameu in the
layout lile.
Iigurc 11-1. Thc Ga||cry \icwGroup
ViewGroups | 199
layout_width is set to fill_parent so that the Galleiy`s wiuth will Le the same as the
paient`s.
layout_height is set to wrap_content, meaning that the height will Le as high as the
tallest chilu.
Iigurc 11-5. Thc Grid\icw \icwGroup
Now we`ll tuin oui attention to the ]ava implementation, Ga||cry1.java, shown in
Example 11-5. Ve`ve mouilieu the coue liom NpiDemos slightly to iemove some lea-
tuies that uo not auu to oui unueistanuing ol the Galleiy ViewGioup.
Exanp|c 11-5. java for Ga||cry: Ga||cry1.java
public class Gallery1 extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery_1);
// Reference the Gallery view
Gallery g = (Gallery) findViewById(R.id.gallery);
// Set the adapter to our custom adapter (below)
200 | Chapter 11:ಗA Widget Bestiary
g.setAdapter(new ImageAdapter(this));
// Set a item click listener, and just Toast the clicked position
g.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
Toast.makeText(Gallery1.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
}
Heie aie some ol the highlights ol the coue:
In the Galleiy`s onCreate methou, cieate a Gallery oLject hookeu to the id nameu
gallery liom the XML layout.
Display each usei option using the custom auaptei uelineu in Example 11-6 (shown
next).
Set up a click listenei on the Gallery oLject.
Display the the inuex (position) within the ImageNuaptei ol the photo the usei
clickeu on as a Toast pop up.
In Example 11-5, the setAdapter lunction tells the Gallery oLject to use the
ImageAdapter oLject as its Nuaptei. Example 11-6 uelines oui ImageAdapter class. This
ImageAdapter implements all ol the aLstiact lunctions ieguiieu in its Lase class,
BaseAdapter. Foi the simple case ol this uemo, pictuie iesouices iepiesent the uata that
the Galleiy view is uisplaying. Nn integei aiiay, mImageIds, contains the iesouice IDs
ol the pictuie iesouices.
Exanp|c 11-ó. java for Ga||cry`s Adaptcr
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private Integer[] mImageIds = {
R.drawable.gallery_photo_1,
R.drawable.gallery_photo_2,
R.drawable.gallery_photo_3,
R.drawable.gallery_photo_4,
R.drawable.gallery_photo_5,
R.drawable.gallery_photo_6,
R.drawable.gallery_photo_7,
R.drawable.gallery_photo_8
};
public ImageAdapter(Context c) {
mContext = c;
TypedArray a = obtainStyledAttributes(android.R.styleable.Theme);
mGalleryItemBackground = a.getResourceId(
android.R.styleable.Theme_galleryItemBackground, 0);
ViewGroups | 201
a.recycle();
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageResource(mImageIds[position]);
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(136, 88));
// The preferred Gallery item background
i.setBackgroundResource(mGalleryItemBackground);
return i;
}
}
}
Heie aie some ol the highlights ol the coue:
Delines the mImageIds aiiay. Each element holus a iesouice ieleience to an image
that appeais in the Galleiy, anu each image iesouice name maps to the lilename in
the iesouices uiiectoiy. Thus R.drawable.gallery_photo_1 maps uiiectly to /rcs/
drawab|c/ga||cry_photo_1.jpg in the iesouice uiiectoiy.
Sets the image loi this position in the Galleiy to the image in the coiiesponuing
element ol mImageIds.
setScaleType contiols how the image is iesizeu to match the size ol its containei.
This call to setLayoutParams sets the size ol the ImageView containei.
ListView and ListActivity
ListView is similai to Galleiy, Lut uses a veitically sciolling list in place ol Galleiy`s
hoiizontally sciolling list. To cieate a ListView that takes up the entiie scieen, Nnuioiu
pioviues the ListActivity class (Figuie 11-6).
The NpiDemos application incluues many examples ol ListNctivity. The simplest is the
List1 class, which uisplays a huge numLei ol cheese names in a list. The cheese names
aie kept in a simple String aiiay (who knew theie weie that many cheese vaiieties!):
202 | Chapter 11:ಗA Widget Bestiary
public class List1 extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Use an existing ListAdapter that will map an array
// of strings to TextViews
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, mStrings));
}
private String[] mStrings = {
"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance",
"Ackawi",
"Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag",
"Airedale",
...
Iigurc 11-ó. ListActivity
Filling the ListView in the ListNctivity is a simple mattei ol calling setListAdapter anu
passing it an ArrayAdapter that contains a ieleience to the list ol stiings.
ViewGroups | 203
ScrollView
N SciollView is a containei loi anothei View that lets the usei scioll that View veitically
(a sciollLai is optional). N SciollView olten contains a LineaiLayout, which in tuin
contains the Views that make up the loim.
Don`t conluse SciollView with ListView. Both Views piesent the usei with a sciollaLle
set ol Views, Lut the ListView is uesigneu to uisplay a set ol similai things, such as the
cheeses in the pievious section. The SciollView, on the othei hanu, allows an aiLitiaiy
View to scioll veitically. The Nnuioiu uocumentation wains that one shoulu nevei
house a ListView within a SciollView, Lecause that ueleats the peiloimance optimiza-
tions ol a ListView.
N SciollView is a FiameLayout, which means that it can have only one chilu View. The
most populai View loi this puipose is a LineaiLayout.
The lollowing layout coue liom NpiDemos, scro||_vicw_2.xn|, shows how to set up a
SciollView. The XML layout iesouice is sullicient; this example incluues no extia ]ava
coue:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:id="@+id/layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/scroll_view_2_text_1"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/scroll_view_2_button_1"/>
</LinearLayout>
</ScrollView>
Heie aie some ol the highlights ol the coue:
The unnameu SciollView lills the wiuth ol the scieen anu is as tall as it neeus to Le
to contain all ol its contents. It has no sciollLais, Lut that`s not a pioLlem, Lecause
sciollLais act only as visual gueues in Nnuioiu; they`ie not as impoitant in UIs that
scioll Ly llicking as opposeu to mousing.
The chilu view is a LineaiLayout.
204 | Chapter 11:ಗA Widget Bestiary
The XML layout lile has two contiols within the LineaiLayout: a TextView anu a
Button. The ]ava coue that uses this layout cieates 63 moie Luttons, to ensuie that
the example LineaiLayout will Le laigei than the scieen uevice anu Lig enough to
scioll.
Iigurc 11-7. Thc first tab of a TabHost \icwGroup
Iigurc 11-8. Thc sccond tab of a TabHost \icwGroup
TabHost
Most mouein UIs pioviue an inteilace element that lets the usei llip thiough many
pages ol inloimation guickly using taLs, with each ¨scieen¨ ol inloimation availaLle
when its taL is piesseu. Nnuioiu`s option is the TaLHost View. Figuies 11-7 thiough
11-10 show how it opeiates.
Nnuioiu enaLles the uevelopei to choose Letween thiee uilleient appioaches loi setting
the taL`s content. The uevelopei can:
º Set the content ol a taL to an Intent. Figuies 11-7 anu 11-9 use this methou.
º Use a TaLContentFactoiy to cieate the taL`s content on-the-lly. Figuie 11-8 uses
this methou.
º Retiieve the content liom an XML layout lile, much like that ol a iegulai Nctivity.
Figuie 11-10 uses this methou.
ViewGroups | 205
Ve`ll examine each ol these possiLilities using a mouilieu Nctivity liom the NpiDemos
application. The louith taL is not pait ol the NpiDemos, Lut comLines some othei
TaLHost uemonstiation Nctivities in NpiDemos.
Let`s stait Ly looking at the tabs1.xn| layout lile (Example 11-7).
Exanp|c 11-7. Layout fi|c for TabHost (tabs1.xn|)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/view4"
android:background="@drawable/green"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="@string/tabs_4_tab_4"/>
</FrameLayout>
Heie aie some ol the highlights ol the coue:
Delines a TextView view with an id ol view4. Ve`ll inseit the TextView into a taL
in oui ]ava coue. Notice the nice gieen Lackgiounu loi this taL Louy.
The ieleienceu stiing is simply tab4.
Nnu now we`ll uissect the ]ava coue that piouuces the taLs (Example 11-8).
Iigurc 11-9. Thc third tab of a TabHost \icwGroup
Iigurc 11-10. Thc fourth tab of a TabHost \icwGroup
206 | Chapter 11:ಗA Widget Bestiary
Exanp|c 11-8. java for TabHost
public class Tabs4 extends TabActivity implements TabHost.TabContentFactory {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final TabHost tabHost = getTabHost();
LayoutInflater.from(this).inflate(R.layout.tabs4, tabHost.getTabContentView(),
true);
tabHost.addTab(tabHost.newTabSpec("tab1")
.setIndicator("intent")
.setContent(new Intent(this, List1.class)));
tabHost.addTab(tabHost.newTabSpec("tab2")
.setIndicator("factory",
getResources().getDrawable(R.drawable.star_big_on))
.setContent(this));
tabHost.addTab(tabHost.newTabSpec("tab3")
.setIndicator("destroy")
.setContent(new Intent(this, Controls2.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)));
tabHost.addTab(tabHost.newTabSpec("tab4")
.setIndicator("layout")
.setContent(R.id.view4));
}
public View createTabContent(String tag) {
final TextView tv = new TextView(this);
tv.setText("Content for tab with tag " + tag);
return tv;
}
}
Heie aie some ol the highlights ol the coue:
To implement taLs, you neeu to extenu TaLNctivity insteau ol just Nctivity. This
gives you all the taL lunctionality.
The tabHost vaiiaLle allows you to ueline the taLs anu theii contents.
This Lasically says ¨using the LayoutInflater liom my cuiient Context, inllate the
XML layout ieleienceu Ly R.layout.tabs4 into the content section ol the tabHost.¨
Vhew. Ns mentioneu Leloie, XML layout liles aie noimally inllateu automatically
when setContentView iuns. Howevei, in this case the XML layout must Le instanti-
ateu manually. Note that this XML layout is useu only in the louith taL.
Sets up the liist taL (Figuie 11-7). The title is aiLitiaiy, Lut we`ve calleu this taL
intent as uocumentation that its contents aie an Intent.
ViewGroups | 207
Set the content ol the liist taL to the List1.class in this application. This simply
Liings up the ieleienceu class in the taL. This is a slick way to make the contents ol
a iegulai application visiLle insiue a taL.
Now we`ie setting up the seconu taL (Figuie 11-8). This is how you put an image
on a taL lace.
This taL`s contents aie lilleu in Ly a lactoiy methou in this class. Notice that the
class implements the TabHost.TabContentFactory inteilace.
Set the content loi the thiiu taL (Figuie 11-9) liom an Intent. Using an Intent heie
is similai to navigating liom one Nctivity in youi application to anothei Ly using an
intent. Howevei, using taLs, the usei can navigate Lack anu loith Letween sepaiate
paits ol youi application guickly anu easily.
Nuuing this llag to the tabHost cieates a new instance ol the View each time it is
uisplayeu. In the case ol the uemo, all changes to the UI will Le lost il you navigate
away liom the taL anu then Lack to it.
This taL uisplays the TextView liom the XML layout item ieleienceu Ly
R.id.view4. The TextView was set up in item 1 ol Example 11-7.
This is the lactoiy methou that cieates the view loi the seconu taL. The lactoiy must
ietuin a view that the taL will use as its content. In this case, we cieate a veiy simple
TextView that uisplays the tag associateu with the taL.
Layouts
Layouts aie Nnuioiu`s solution to the vaiiety ol scieens that come on Nnuioiu uevices:
they can have uilleient pixel uensities, uilleient uimensions, anu uilleient aspect iatios.
Typical Nnuioiu uevices, such as the HTC G1 moLile phone, even allow changing the
scieen oiientation (poitiait oi lanuscape) while applications aie iunning, so the layout
inliastiuctuie neeus to Le aLle to iesponu on the lly. Layouts aie intenueu to give
uevelopeis a way to expiess the physical ielationship ol Views as they aie uiawn on the
scieen. Ns Nnuioiu inllates the Layout, it uses the uevelopei ieguests to come up with
a scieen layout that Lest appioximates what the uevelopei has askeu loi.
Looking a little ueepei, layouts in Nnuioiu aie in the loim ol a tiee, with a single ioot
anu a hieiaichy ol Views. Look Lack at any ol the XML Layout liles in the pievious
section anu you`ll see that the XML tags cieate just such a hieiaichy, with a scieen
Layout as the ioot ol the tiee. Each View in the tiee is teimeu the parcnt ol the Views
it contains anu the chilu ol the View that contains it. Layout is a two-pass piocess:
Mcasurc pass
Tiaveising the tiee liom the ioot, each View in the layout iecoius its uimensional
ieguest÷in othei woius, how much veitical height anu hoiizontal wiuth it neeus
to uisplay itsell in the linal uisplay.
208 | Chapter 11:ಗA Widget Bestiary
Layout pass
Ngain tiaveising the tiee liom the ioot, each paient View uses the availaLle layout
inloimation to position its chiluien as ieguesteu. Il the ieguests can`t Le lolloweu
explicitly, Nnuioiu uoes its Lest to make eveiything lit on the scieen. Il theie aie
no ieguests given, it uses a uelault set ol layout paiameteis. Each paient can pass
layout inloimation on to its chiluien, telling them wheie they aie positioneu anu
what scieen uimensions they have Leen gianteu (they might get less than they
ieguesteu).
N Layout is a View itsell, so theie`s nothing wiong with having multiple Layouts in a
single layout XML lile÷they just have to Le aiiangeu in a hieiaichy. So it`s peilectly
valiu to have a veitical LineaiLayout that incluues a TaLleLayout as one ol its iows.
You`ll leain a lot moie aLout layouts in Chaptei 12.
Frame Layout
The Fiame Layout is soit ol a null layout specilication. It ieseives space on the scieen
loi a single View to Le uiawn, anu the View is always locateu at the uppei lelt ol the
space. Theie is no way to specily a uilleient location loi the View, anu theie can Le
only one View in the Layout. Il moie than one View is uelineu in the layout lile, they
aie just uiawn on top ol each othei, all pinneu to the uppei-lelt coinei.
LinearLayout
LineaiLayouts aie useu extensively in Nnuioiu applications, anu we useu them in ex-
ample coue eailiei. N LineaiLayout asks that the containeu Views Le layeu out as eithei
a seiies ol iows (veitical LineaiLayout) oi a seiies ol columns (hoiizontal
LineaiLayout). In a veitical LineaiLayout, all the iows aie the same wiuth (the wiuth
ol the wiuest chilu). In a hoiizontal LineaiLayout, theie is one iow ol Views, all the
same height (the height ol the tallest chilu).
Figuie 11-11 shows an example ol a veitical LineaiLayout, anu Figuie 11-12 is an ex-
ample ol a hoiizontal one. Both have EuitText Views as chiluien. Example 11-9 shows
the XML iesouice lile that piouuces the veitical layout, anu Example 11-10 shows the
lile that cieateu the hoiizontal one.
Exanp|c 11-9. \crtica| LincarLayout rcsourcc fi|c
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="EditText1"
Layouts | 209
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="EditText2"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="EditText3"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="EditText4"
/>
</LinearLayout>
Iigurc 11-11. \crtica| LincarLayout
Exanp|c 11-10. Horizonta| LincarLayout rcsourcc fi|c
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
210 | Chapter 11:ಗA Widget Bestiary
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="E1"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="E2"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="E3"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="E4"
/>
</LinearLayout>
Iigurc 11-12. Horizonta| LincarLayout
Layouts | 211
The hoiizontal layout might not look exactly as you woulu think: how come E+ is
naiiowei than the othei thiee? The answei is that theie is a uelault minimum wiuth loi
an EuitText. Il you Luilu anu iun the hoiizontal example anu type something into
EuitText E1, you`ll see that it expanus in wiuth as the line gets longei, which is just
what we askeu loi with android:layout_width="wrap_content".
In auuition to the usual uimensional paiameteis loi chilu Views (wiuth,
height, pauuing), you can incluue a weight loi each chilu (attiiLute
android:layout_weight=;weight). The weight tells the layout managei how you want
to use unlilleu space, anu uelaults to a value ol 0. Il you specily chiluien with weights
gieatei than zeio, the layout managei will allocate unuseu space to each chilu in pio-
poition to its weight.
Figuie 11-13 shows an example ol a LineaiLayout containing loui EuitTexts. The liist
two have no weights assigneu. EuitText3 has a weight ol 1 anu EuitText+ has a weight
ol 2. The ellect is to make EuitText+ twice as Lig as EuitText3, while EuitText1 anu
EuitText2 just split whatevei space the layout leaves ovei.
Iigurc 11-13. Wcightcd LincarLayout
212 | Chapter 11:ಗA Widget Bestiary
TableLayout
N TaLleLayout is just what you`u expect: it lays out the incluueu Views in the loim ol
a taLle (similai to an HTML taLle). Ve can cieate a taLle ol TextViews to show how
you woulu cieate that kinu ol scieen loi an application. Heie`s an example TaLleLayout
XML lile:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tblJobs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button android:text="Cell 11"
android:id="@+id/btnCel11"
android:layout_width="20dip"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/txtCell12"
android:layout_width="20dip"
android:layout_height="wrap_content"
android:text="Cell 12"
/>
<TextView
android:id="@+id/txtCell13"
android:layout_width="20dip"
android:layout_height="wrap_content"
android:text="Cell 13"
/>
<TextView
android:id="@+id/txtCell14"
android:layout_width="20dip"
android:layout_height="wrap_content"
android:text="Cell 14"
/>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button android:text="Cell 21"
android:id="@+id/btnCo21"
android:layout_width="80dip"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/txtCell22"
android:layout_width="80dip"
android:layout_height="wrap_content"
android:text="Cell 22"
/>
<TextView
Layouts | 213
android:id="@+id/txtCell23"
android:layout_width="80dip"
android:layout_height="wrap_content"
android:text="Cell 23"
/>
<TextView
android:id="@+id/txtCell24"
android:layout_width="80dip"
android:layout_height="wrap_content"
android:text="Cell 24"
/>
</TableRow>
</TableLayout>
Figuie 11-1+ shows the iesulting layout on the emulatoi scieen.
Iigurc 11-11. Tab|cLayout
The stiuctuie ol the XML lile is pietty eviuent: the TaLleLayout tags contain a list ol
TaLleRows that in tuin contain the Views you want to appeai on each line ol the taLle.
Notice that the layout_width values aie uilleient in the two iows÷all the wiuths in the
liist iow aie specilieu as 20dip, wheieas the wiuths in the seconu iow aie specilieu as
214 | Chapter 11:ಗA Widget Bestiary
28dip÷yet the columns line up on the scieen. To pieseive the look ol a taLle, Nnuioiu
makes each column as wiue as the wiuest cell in that column.
Ol couise, the cells aie auuiessaLle liom youi ]ava coue, anu you can auu iows pio-
giammatically to the taLle, il that`s what youi application neeus to uo.
AbsoluteLayout
Nn NLsoluteLayout puts views on the scieen wheievei you tell it to. It uoesn`t tiy to
iesize anything, anu it uoesn`t tiy to line anything up; it just puts things wheie it`s tolu.
You might think that it woulu Le an easy type ol layout to use, since you uon`t have to
seconu-guess how the layout managei is going to ieaiiange things on youi scieen, Lut
in piactice the use ol NLsoluteLayout is a Lau iuea loi almost all applications. You
usually want youi application to iun on as many Nnuioiu uevices as possiLle, anu the
stiength ol the Nnuioiu layout managei is that it will automatically auapt youi scieen
layout liom uevice to uevice. NLsoluteLayout Lypasses most ol the layout managei,
anu while youi application may look peilect on the uevice you useu loi uevelopment,
the ouus aie veiy goou that it will look teiiiLle on othei Nnuioiu uevices.
That waining asiue, let`s take a look at an NLsoluteLayout XML lile:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout 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="Upper Left"
android:layout_x="0.0px"
android:layout_y="0.0px"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Middle"
android:layout_x="140.0px"
android:layout_y="200.0px"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Lower Right"
android:layout_x="240.0px"
android:layout_y="400.0px"
/>
</AbsoluteLayout>
Ns with any uimension in a layout lile, the positions can Le expiesseu in pixels (px),
uevice-inuepenuent pixels (dp), scaleu pixels (sp), inches (in), oi millimeteis (mm), anu
Layouts | 215
the uimension has to Le a lloating-point numLei. (Foi moie aLout expiessing sizes, see
¨Dimensions in Nnuioiu¨ on page 51 in Chaptei +.)
Figuie 11-15 shows the iesulting scieen layout. OLviously, the position (0, 0) is the
uppei-lelt coinei ol the uisplay, anu the View is piopeily llush with the coinei. The
lowei-iight coinei on the emulatoi is supposeu to Le (320, +80), Lut the View appeais
to Le a little shy ol that in Loth uimensions.
]ust to caution against the use ol NLsoluteLayout again, we suggest you tiy changing
the emulatoi skin to show the scieen in lanuscape moue (entei emulator
-skin HVGA-L liom a commanu oi teiminal winuow Leloie you iun the application),
anu you can see in Figuie 11-16 that the application no longei looks iight.
RelativeLayout
Ve`ve useu RelativeLayout, olten in comLination with LineaiLayout, thioughout the
M]Nnuioiu application. The auvantage ol RelativeLayout is that you can expiess the
Iigurc 11-15. Abso|utcLayout
216 | Chapter 11:ಗA Widget Bestiary
ielative positioning ol the Views in the scieen, anu the layout managei will uo its Lest
to lit them all on the scieen in the piopei ielations. Nn example lollows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/txtText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text1"
android:gravity="top"
android:layout_alignParentRight="true"
/>
<TextView
android:id="@+id/txtText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text2"
android:layout_below="@+id/txtText1"
/>
<Button
android:id="@+id/btnButton1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="Button1"
android:layout_below="@+id/txtText2"
/>
Iigurc 11-1ó. Sanc Abso|utcLayout in |andscapc nodc
Layouts | 217
<Button
android:id="@+id/btnButton2"
android:layout_width="150dp"
android:layout_height="100dp"
android:text="Button2"
android:layout_toRightOf="@+id/btnButton1"
android:layout_alignTop="@+id/btnButton1"
/>
</RelativeLayout>
Lays out Text1 at the top ol the scieen.
Nligns Text1 with the iight siue ol its paient (which is the scieen itsell).
Places Text2 Lelow Text1.
Places Button1 Lelow Text2.
Places Button2 just to the iight ol Button1.
Nligns the tops ol the two Luttons.
Figuie 11-17 shows what this looks like in poitiait moue (the emulatoi uelault), anu
Figuie 11-18 shows it in lanuscape moue. The layout managei has aujusteu the ai-
iangements in each case to match the layout hints we gave in the XML.
Iigurc 11-17. Rc|ativcLayout in portrait nodc
218 | Chapter 11:ಗA Widget Bestiary
Iigurc 11-18. Rc|ativcLayout in |andscapc nodc
Layouts | 219
CHAPTER 12
Drawing 2D and 3D Graphics
The Nnuioiu menageiie ol wiugets anu the tools loi assemLling them aie convenient,
poweilul, anu covei a Lioau vaiiety ol neeus. Vhat happens, though, when none ol
the existing wiugets ollei what you neeu? MayLe youi application neeus to iepiesent
playing caius, phases ol the moon, oi the powei uiveiteu to the main thiusteis ol a
iocket ship. In that case, you`ll have to know how to ioll youi own.
This chaptei is an oveiview ol giaphics anu animation on Nnuioiu. It`s uiiecteu at
piogiammeis with some Lackgiounu in giaphics, anu goes into guite a Lit ol uepth
aLout ways to twist anu tuin the uisplay. You will uelinitely neeu to supplement this
chaptei with Nnuioiu uocumentation, paiticulaily Lecause the moie auvanceu intei-
laces aie still unueigoing changes. But the technigues heie will help you uazzle youi
useis.
Rolling Your Own Widgets
Ns mentioneu eailiei, ¨wiuget¨ is a just convenient teim loi a suLclass ol
android.view.View, typically loi a leal noue in the view tiee. Many views aie just con-
taineis loi othei views anu aie useu loi layout; we uon`t consiuei them wiugets, Lecause
they uon`t uiiectly inteiact with the usei, hanule events, etc. So the teim ¨wiuget,¨
although inloimal, is uselul loi uiscussing the woikhoise paits ol the usei inteilace that
have the inloimation anu the Lehavioi useis caie aLout.
You can accomplish a lot without cieating a new wiuget. Chaptei 11 constiucteu ap-
plications consisting entiiely ol existing wiugets oi simple suLclasses ol existing wiug-
ets. The coue in that chaptei uemonstiateu Luiluing tiees ol views, laying them out in
coue oi in layout iesouices in XML liles.
Similaily, the Micio]oLs application has a view that contains a list ol names coiie-
sponuing to locations on a map. Ns auuitional locations aie auueu to the map, new
name-uisplaying wiugets aie auueu uynamically to the list. Even this uynamically
changing layout is just a use ol pie-existing wiugets; it uoes not cieate new ones. The
technigues in Micio]oLs aie, liguiatively, auuing oi iemoving Loxes liom a tiee like
the one illustiateu in Figuie 10-3 in Chaptei 10.
221
In contiast, this chaptei shows you how to ioll youi own wiuget, which involves looking
unuei the View hoou.
The simplest customizations stait with TextView, Button, DatePicker, oi one ol the many
wiugets piesenteu in the pievious chaptei. Foi moie extensive customization, you will
implement youi own wiuget as a uiiect suLclass ol View.
N veiy complex wiuget, peihaps useu as an inteilace tool implementeu in seveial places
(even Ly multiple applications), might even Le an entiie package ol classes, only one
ol which is a uescenuant ol View.
This chaptei is aLout giaphics, anu theieloie aLout the View pait ol the
Mouel-View-Contiollei pattein. Viugets also contain Contiollei coue, which is goou
uesign Lecause it keeps togethei all ol the coue ielevant to a Lehavioi anu its iepiesen-
tation on the scieen. This pait ol this chaptei uiscusses only the implementation ol the
View; the implementation ol the Contiollei was uiscusseu in Chaptei 10.
Concentiating on giaphics, then, we can Lieak the tasks ol this chaptei into two es-
sential paits: linuing space on the scieen anu uiawing in that space. The liist task is
known as |ayout. N leal wiuget can asseit its space neeus Ly uelining an onMeasure
methou that the Nnuioiu liamewoik will call at the iight time. The seconu task, actually
ienueiing the wiuget, is hanuleu Ly the wiuget`s onDraw methou.
Layout
Most ol the heavy lilting in the Nnuioiu liamewoik layout mechanism is implemen-
teu Ly containcr vicws. N containei view is one that contains othei views. It is an inteinal
noue in the view tiee anu suLclasses ol ViewGroup (which, in tuin, suLclasses View).
The liamewoik toolkit pioviues a vaiiety ol sophisticateu containei views that pioviue
poweilul anu auaptaLle stiategies loi aiianging a scieen. AbsoluteLayout (see ¨NLso-
luteLayout¨ on page 215), LinearLayout (see ¨LineaiLayout¨ on page 209), anu
RelativeLayout (see ¨RelativeLayout¨ on page 216), to name some common ones, aie
containei views that aie Loth ielatively easy to use anu laiily haiu to ieimplement
coiiectly. Since they aie alieauy availaLle, loitunately you aie unlikely to have to im-
plement most ol the algoiithm uiscusseu heie. Unueistanuing the Lig pictuie, though÷
how the liamewoik manages the layout piocess÷will help you Luilu coiiect, ioLust
wiugets.
Example 12-1 shows a wiuget that is aLout as simple as it can Le, while still woiking.
Il auueu to some Nctivity`s view tiee, this wiuget will lill in the space allocateu to it
with the coloi cyan. Not veiy inteiesting, Lut Leloie we move on to cieate anything
moie complex, let`s look caielully at how this example lullills the two Lasic tasks ol
layout anu uiawing. Ve`ll stait with the layout piocess; uiawing will Le uesciiLeu latei
in the section ¨Canvas Diawing¨ on page 226.
222 | Chapter 12:ಗDrawing 2D and 3D Graphics
Exanp|c 12-1. A trivia| widgct
public class TrivialWidget extends View {
public TrivialWidget(Context context) {
super(context);
setMinimumWidth(100);
setMinimumHeight(20);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getSuggestedMinimumWidth(),
getSuggestedMinimumHeight());
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.CYAN);
}
}
Dynamic layout is necessaiy Lecause the space ieguiiements loi wiugets change uy-
namically. Suppose, loi instance, that a wiuget in a GPS-enaLleu application uisplays
the name ol the city in which you aie cuiiently uiiving. Ns you go liom ¨Ely¨ to ¨Post
Mills,¨ the wiuget ieceives notilication ol the change in location. Vhen it piepaies to
ieuiaw the city name, though, it notices that it uoesn`t have enough ioom loi the whole
name ol the new town. It neeus to ieguest that the scieen Le ieuiawn in a way that
gives it moie space, il that is possiLle.
Layout can Le a suipiisingly complex task anu veiy uillicult to get iight. It is pioLaLly
not veiy haiu to make a paiticulai leal wiuget look iight on a single uevice. On the
othei hanu, it can Le veiy tiicky to get a wiuget that must aiiange chiluien to look iight
on multiple uevices, even when the uimensions ol the scieen change.
Layout is initiateu when the requestLayout methou is invokeu on some view in the view
tiee. Typically, a wiuget calls requestLayout on itsell when it neeus moie space. The
methou coulu Le invokeu, though, liom any place in an application, to inuicate that
some view in the cuiient scieen no longei has enough ioom to uiaw itsell.
The requestLayout methou causes the Nnuioiu UI liamewoik to engueue an event on
the UI event gueue. Vhen the event is piocesseu, in oiuei, the liamewoik gives eveiy
containei view an oppoitunity to ask each ol its chilu wiugets how much space each
chilu woulu like loi uiawing. The piocess is sepaiateu into two phases: measuiing the
chilu views anu then aiianging them in theii new positions. Nll views must implement
the liist phase, Lut the seconu is necessaiy only in the implementations ol containei
views that must manage the layout ol chilu views.
Rolling Your Own Widgets | 223
Measurement
The goal ol the measuiement phase is to pioviue each view with an oppoitunity to
uynamically ieguest the space it woulu iueally like loi uiawing. The UI liamewoik
staits the piocess Ly invoking the measure methou ol the view at the ioot ol the view
tiee. Staiting theie, each containei view asks each ol its chiluien how much space it
woulu pielei. The call is piopagateu to all uescenuants, uepth liist, so that eveiy chilu
gets a chance to compute its size Leloie its paient. The paient computes its own size
Laseu on the sizes ol its chiluien anu iepoits that to its paient, anu so on, up the tiee.
In ¨NssemLling a Giaphical Inteilace¨ on page 161, loi instance, the topmost
LinearLayout asks each ol the nesteu LinearLayout wiugets loi its pieleiieu uimensions.
They in tuin ask the Buttons oi EditText views they contain loi theiis. Each chilu iepoits
its uesiieu size to its paient. The paients then auu up the sizes ol the chiluien, along
with any pauuing they inseit themselves, anu iepoit the total to the topmost
LinearLayout.
Because the liamewoik must guaiantee ceitain Lehaviois loi all Views, uuiing this
piocess, the measure methou is linal anu cannot Le oveiiiuuen. Insteau, measure calls
onMeasure, which wiugets may oveiiiue to claim theii space. In othei woius, wiugets
cannot oveiiiue measure, Lut they can oveiiiue onMeasure.
The aiguments to the onMeasure methou uesciiLe the space the paient is willing to make
availaLle: a wiuth specilication anu a height specilication, measuieu in pixels.
The liamewoik assumes that no view will evei Le smallei than 0 oi Liggei than 2
30
pixels in size anu, theieloie, it uses the high-oiuei Lits ol the passeu int paiametei to
encoue the ncasurcncnt spccification nodc. It is as il onMeasure weie actually calleu
with loui aiguments: the wiuth specilication moue, the wiuth, the height specilication
moue, anu the height. Do not Le tempteu to uo youi own Lit-shilting to sepaiate the
paiis ol aiguments! Insteau, use the static methous MeasureSpec.getMode anu
MeasureSpec.getSize.
The specilication moues uesciiLe how the containei view wants the chilu to inteipiet
the associateu size. Theie aie thiee ol them:
MeasureSpec.EXACTLY
The calling containei view has alieauy ueteimineu the exact size ol the chilu view.
MeasureSpec.AT_MOST
The calling containei view has set a maximum size loi this uimension, Lut the chilu
is liee to ieguest less.
MeasureSpec.UNSPECIFIED
The calling containei view has not imposeu any limits on the chilu, anu so the chilu
may ieguest anything it chooses.
N wiuget is always iesponsiLle loi telling its paient in the view tiee how much space it
neeus. It uoes this Ly calling setMeasuredDimensions to set the piopeities that
then Lecome availaLle to the paient, thiough the methous getMeasuredHeight anu
224 | Chapter 12:ಗDrawing 2D and 3D Graphics
getMeasuredWidth. Il youi implementation oveiiiues onMeasure Lut uoes not call
setMeasuredDimensions, the measure methou will thiow IllegalStateException in-
steau ol completing noimally.
The uelault implementation ol onMeasure, inheiiteu liom View, calls set
MeasuredDimensions with one ol two values, in each uiiection. Il the paient specilies
MeasureSpec.UNSPECIFIED, it uses the uelault size ol the view: the value supplieu Ly
eithei getSuggestedMinimumWidth oi getSuggestedMinimumHeight. Il the paient specilies
eithei ol the othei two moues, the uelault implementation uses the size that was olleieu
Ly the paient. This is a veiy ieasonaLle stiategy anu allows a typical wiuget implemen-
tation to hanule the measuiement phase completely, simply Ly setting the values
ietuineu Ly getSuggestedMinimumWidth anu getSuggestedMinimumHeight.
Youi wiuget may not actually get the space it ieguests. Consiuei a view that is 100
pixels wiue anu has thiee chiluien. It is pioLaLly oLvious how the paient shoulu aiiange
its chiluien il the sum ol the pixel wiuths ieguesteu Ly the chiluien is 100 oi less. Il,
howevei, each chilu ieguests 50 pixels, the paient containei view is not going to Le aLle
to satisly them all.
N containei view has complete contiol ol how it aiianges its chiluien. In the ciicum-
stance just uesciiLeu, it might ueciue to Le ¨laii¨ anu allocate 33 pixels to each chilu.
]ust as easily, it might ueciue to allocate 50 pixels to the leltmost chilu anu 25 to each
ol the othei two. In lact, it might ueciue to give one ol the chiluien the entiie 100 pixels
anu nothing at all to the otheis. Vhatevei its methou, though, in the enu the paient
ueteimines a size anu location loi the Lounuing iectangle loi each chilu.
Nnothei example ol a containei view`s contiol ol the space allocateu to a wiuget comes
liom the example wiuget shown pieviously in Example 12-1. It always ieguests the
amount ol space it pieleis, iegaiuless ol what it is olleieu (unlike the uelault imple-
mentation). This stiategy is hanuy to iememLei loi wiugets that will Le auueu to the
toolkit containeis, notaLly LinearLayout, that implement gravity. Giavity is a piopeity
that some views use to specily the alignment ol theii suLelements. The liist time you
use one ol these containeis, you may Le suipiiseu to linu that, Ly uelault, only the liist
ol youi custom wiugets gets uiawn! You can lix this eithei Ly using the setGravity
methou to change the piopeity to Gravity.FILL oi Ly making youi wiugets insistent
aLout the amount ol space they ieguest.
It is also impoitant to note that a containei view may call a chilu`s measure methou
seveial times uuiing a single measuiement phase. Ns pait ol its implementation ol
onMeasure, a clevei containei view, attempting to lay out a hoiizontal iow ol wiugets,
might call each chilu wiuget`s measure methou with moue MEASURE_SPEC.UNSPECIFIED
anu a wiuth ol 0 to linu out what size the wiuget woulu pielei. Once it has collecteu
the pieleiieu wiuths loi each ol its chiluien, it coulu compaie the sum to the actual
wiuth availaLle (which was specilieu in its paient`s call to its measure methou). Now it
might call each chilu wiuget`s measure methou again, this time with the moue
MeasureSpec.AT_MOST anu a wiuth that is an appiopiiate piopoition ol the space actually
Rolling Your Own Widgets | 225
availaLle. Because measure may Le calleu multiple times, an implementation ol
onMeasure must Le iuempotent anu must not change the application state.
N containei view`s implementation ol onMeasure is likely to Le laiily complex.
ViewGroup, the supeiclass ol all containei views, uoes not supply a uelault implemen-
tation. Each ol the UI liamewoik containei views has its own. Il you contemplate im-
plementing a containei view, you might consiuei Lasing it on one ol them. Il, insteau,
you implement measuiement liom sciatch, you aie still likely to neeu to call measure
loi each chilu anu shoulu consiuei using the ViewGroup helpei methous: measure
Child, measureChildren, anu measureChildWithMargins. Nt the conclusion ol the meas-
uiement phase, a containei view, like any othei wiuget, must iepoit the space it neeus
Ly calling setMeasuredDimensions.
Arrangement
Once all the containei views in the view tiee have hau a chance to negotiate the sizes
ol each ol theii chiluien, the liamewoik Legins the seconu phase ol layout, which
consists ol aiianging the chiluien. Ngain, unless you implement youi own containei
view, you pioLaLly will nevei have to implement youi own aiiangement coue. This
section uesciiLes the unueilying piocess so that you can Lettei unueistanu how it might
allect youi wiugets. The uelault methou, implementeu in View, will woik loi typical
leal wiugets, as uemonstiateu pieviously Ly Example 12-1.
Because a view`s onMeasure methou might Le calleu seveial times, the liamewoik must
use a uilleient methou to signal that the measuiement phase is complete anu that con-
tainei views must lix the linal locations ol theii chiluien. Like the measuiement phase,
the aiiangement phase is implementeu with two methous. The liamewoik invokes a
linal methou, layout, at the top ol the view tiee. The layout methou peiloims pio-
cessing common to all views anu then uelegates to onLayout, which custom wiugets
oveiiiue to implement theii own Lehaviois. N custom implementation ol onLayout must
at least calculate the Lounuing iectangle that it will supply to each chilu when it is
uiawn anu, in tuin, invoke the layout methou loi each chilu (Lecause it might also Le
a paient to othei wiugets).
It is woith ieiteiating that a wiuget is not guaianteeu to ieceive the space it ieguests. It
must Le piepaieu to uiaw itsell in whatevei space is actually allocateu to it. Il it attempts
to uiaw outsiue the space allocateu to it Ly its paient, the uiawing will Le clippeu Ly
the clip iectangle. To exeit line contiol÷to lill exactly the space allocateu to it, loi
instance÷a wiuget must eithei implement onLayout anu iecoiu the uimensions ol the
allocateu space oi inspect the clip iectangle ol the Canvas that is the paiametei to onDraw.
Canvas Drawing
Now that we`ve exploieu how wiugets allocate the space on the scieen in which they
uiaw themselves, we can tuin to couing some wiugets that actually uo some uiawing.
226 | Chapter 12:ಗDrawing 2D and 3D Graphics
The Nnuioiu liamewoik hanules uiawing in a way that shoulu Le lamiliai, now that
you`ve ieau aLout measuiement anu aiiangement. Vhen some pait ol the application
ueteimines that the cuiient scieen uiawing is stale Lecause some state has changeu, it
calls the View methou invalidate. This call causes a ieuiaw event to Le auueu to the
event gueue.
Eventually, when that event is piocesseu, the liamewoik calls the draw methou at the
top ol the view tiee. This time the call is piopagateu pieoiuei, with each view uiawing
itsell Leloie it calls its chiluien. This means that leal views aie uiawn altei theii paients,
which aie, in tuin, uiawn altei theii paients. Views that aie lowei in the tiee appeai to
Le uiawn on top ol those neaiei the ioot ol the tiee.
The draw methou calls onDraw, which a suLclass oveiiiues to implement its custom
ienueiing. Vhen youi wiuget`s onDraw methou is calleu, it must ienuei itsell accoiuing
to the cuiient application state anu ietuin. It tuins out, Ly the way, that neithei
View.draw noi ViewGroup.dispatchDraw (iesponsiLle loi the tiaveisal ol the view tiee) is
linal! Oveiiiue them at youi peiil!
In oiuei to pievent extia painting, the liamewoik maintains some state inloimation
aLout the view, calleu the c|ip rcctang|c. N key concept in the UI liamewoik, the clip
iectangle is pait ol the state passeu in calls to a component`s giaphical ienueiing meth-
ous. It has a location anu size that can Le ietiieveu anu aujusteu thiough methous on
the Canvas, anu it acts like a stencil thiough which a component uoes all ol its uiawing.
By coiiectly setting the size, shape, anu location ol the clip iectangle apeituie, the
liamewoik can pievent a component liom uiawing outsiue its Lounuaiies oi ieuiawing
iegions that aie alieauy coiiectly uiawn.
Beloie pioceeuing to the specilics ol uiawing, let`s again put the uiscussion in the con-
text ol Nnuioiu`s single-thieaueu MVC uesign pattein. Theie aie two essential iules:
º Diawing coue shoulu Le insiue the onDraw methou. Youi wiuget shoulu uiaw itsell
completely, iellecting the piogiam`s cuiient state, when onDraw is invokeu.
º N wiuget shoulu uiaw itsell as guickly as possiLle when onDraw is invokeu. The
miuule ol the call to onDraw is no time to iun a complex uataLase gueiy oi to
ueteimine the status ol some uistant netwoikeu seivice. Nll the state you neeu to
uiaw shoulu Le cacheu anu ieauy loi use at uiawing time. Long-iunning tasks
shoulu use a sepaiate thieau anu the Handler mechanism uesciiLeu in ¨Nuvanceu
Viiing: Focus anu Thieauing¨ on page 179. The mouel state cacheu in the view is
sometimes calleu the vicw-nodc|.
The Nnuioiu UI liamewoik uses loui main classes in uiawing. Il you aie going to im-
plement custom wiugets anu uo youi own uiawing, you will want to Lecome veiy
lamiliai with them:
Canvas (a subc|ass of android.graphics.Canvas)
The canvas has no complete analog in ieal-lile mateiials. You might think ol it as
a complex easel that can oiient, Lenu, anu even ciumple the papei on which you
Rolling Your Own Widgets | 227
aie uiawing in inteiesting ways. It maintains the clip iectangle, the stencil thiough
which you paint. It can also scale uiawings as they aie uiawn, like a photogiaphic
enlaigei. It can even peiloim othei tiansloimations loi which mateiial analogs aie
moie uillicult to linu: mapping colois anu uiawing text along paths.
Paint (a subc|ass of android.graphics.Paint)
This is the meuium with which you will uiaw. It contiols the coloi, tianspaiency,
anu Liush size loi oLjects painteu on the canvas. It also contiols lont, size, anu
style when uiawing text.
Bitnap (a subc|ass of android.graphics.Bitmap)
This is the papei you aie uiawing on. It holus the actual pixels that you uiaw.
Drawab|cs (|i|c|y a subc|ass of android.graphics.drawable.Drawable)
This is the thing you want to uiaw: a iectangle oi image. Nlthough not all ol the
things that you uiaw aie Drawables (text, loi instance, is not), many, especially the
moie complex ones, aie.
Example 12-1 useu only the Canvas, passeu as a paiametei to onDraw, to uo its uiawing.
In oiuei to uo anything moie inteiesting, we will neeu Paint, at the veiy least. Paint
pioviues contiol ovei the coloi anu tianspaiency (alpha) ol the giaphics uiawn with it.
Paint has many, many othei capaLilities, some ol which aie uesciiLeu in
¨Bling¨ on page 2+3. Example 12-2, howevei, is enough to get you staiteu. Exploie
the class uocumentation loi othei uselul attiiLutes.
The giaphic cieateu Ly the coue in the example is shown in Figuie 12-1.
Exanp|c 12-2. Using Paint
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
canvas.drawLine(33, 0, 33, 100, paint);
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
canvas.drawLine(56, 0, 56, 100, paint);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(5);
for (int y = 30, alpha = 255; alpha > 2; alpha >>= 1, y += 10) {
paint.setAlpha(alpha);
canvas.drawLine(0, y, 100, y, paint);
}
}
228 | Chapter 12:ಗDrawing 2D and 3D Graphics
Iigurc 12-1. Using Paint
Vith the auuition ol Paint, we aie piepaieu to unueistanu most ol the othei tools
necessaiy to cieate a uselul wiuget. Example 12-3, loi instance, is the wiuget useu
pieviously in Example 10-7. Vhile still not veiy complex, it uemonstiates all the pieces
ol a lully lunctional wiuget. It hanules layout anu highlighting, anu iellects the state ol
the mouel to which it is attacheu.
Exanp|c 12-3. Dot widgct
package com.oreilly.android.intro.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.View;
import com.oreilly.android.intro.model.Dot;
import com.oreilly.android.intro.model.Dots;
public class DotView extends View {
private final Dots dots;
/**
* @param context the rest of the application
* @param dots the dots we draw
*/
public DotView(Context context, Dots dots) {
super(context);
this.dots = dots;
setMinimumWidth(180);
setMinimumHeight(200);
setFocusable(true);
}
/** @see android.view.View#onMeasure(int, int) */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getSuggestedMinimumWidth(),
getSuggestedMinimumHeight());
Rolling Your Own Widgets | 229
}
/** @see android.view.View#onDraw(android.graphics.Canvas) */
@Override protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setColor(hasFocus() ? Color.BLUE : Color.GRAY);
canvas.drawRect(0, 0, getWidth() - 1, getHeight() -1, paint);
paint.setStyle(Style.FILL);
for (Dot dot : dots.getDots()) {
paint.setColor(dot.getColor());
canvas.drawCircle(
dot.getX(),
dot.getY(),
dot.getDiameter(),
paint);
}
}
}
Ns with Paint, we have only enough space to Legin an exploiation ol Canvas methous.
Theie aie two gioups ol lunctionality, howevei, that aie woith special notice.
Drawing text
The most impoitant Canvas methous aie those useu to uiaw text. Nlthough some
Canvas lunctionality is uuplicateu in othei places, text-ienueiing capaLilities aie not.
In oiuei to put text in youi wiuget, you will have to use the Canvas (oi, ol couise,
suLclass some othei wiuget that uses it).
Canvas methous loi ienueiing text come in paiis: thiee sets ol two signatuies. Exam-
ple 12-+ shows one ol the paiis.
Exanp|c 12-1. A pair of tcxt drawing ncthods
public void drawText(String text, float x, float y, Paint paint)
public void drawText(char[] text, int index, int count, float x, float y, Paint paint)
Theie aie seveial paiis ol methous. In each paii, the liist ol the two methous in the paii
uses String, anu the seconu uses thiee paiameteis to uesciiLe the text: an aiiay ol
char, the inuex inuicating the liist chaiactei in that aiiay to Le uiawn, anu the numLei
ol total chaiacteis in the text to Le ienueieu. In some cases, theie aie auuitional con-
venience methous.
Example 12-5 contains an onDraw methou that uemonstiates the use ol the liist style ol
each ol the thiee paiis ol text ienueiing methous. The output is shown in Figuie 12-2.
230 | Chapter 12:ಗDrawing 2D and 3D Graphics
Exanp|c 12-5. Thrcc ways of drawing tcxt
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawText("Android", 25, 30, paint);
Path path = new Path();
path.addArc(new RectF(10, 50, 90, 200), 240, 90);
paint.setColor(Color.CYAN);
canvas.drawTextOnPath("Android", path, 0, 0, paint);
float[] pos = new float[] {
20, 80,
29, 83,
36, 80,
46, 83,
52, 80,
62, 83,
68, 80
};
paint.setColor(Color.GREEN);
canvas.drawPosText("Android", pos, paint);
}
Ns you can see, the most elementaiy ol the paiis, drawText, simply uiaws text at the
passeu cooiuinates. Vith DrawTextOnPath, on the othei hanu, you can uiaw text along
any Path. The example path is just an aic. It coulu just as easily have Leen a line uiawing
oi a Beziei cuive.
Foi those occasions on which even DrawTextOnPath is insullicient, Canvas olleis
DrawPosText, which lets you specily the exact position ol each chaiactei in the text.
Note that the chaiactei positions aie specilieu Ly alteinating aiiay elements:
x1,y1,x2,y2, anu so on.
Matrix transformations
The seconu inteiesting gioup ol Canvas methous aie the Matrix tiansloimations anu
theii ielateu convenience methous, rotate, scale, anu skew. These methous tiansloim
what you uiaw in ways that will immeuiately Le iecognizaLle to those lamiliai with 3D
Iigurc 12-2. Output fron thrcc ways of drawing tcxt
Rolling Your Own Widgets | 231
giaphics. They allow a single uiawing to Le ienueieu in ways that can make it appeai
as il the viewei weie moving with iespect to the oLjects in the uiawing.
The small application in Example 12-6 uemonstiates the Canvas`s cooiuinate tiansloi-
mation capaLilities.
Exanp|c 12-ó. Using a Canvas
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
public class TranformationalActivity extends Activity {
private interface Transformation {
void transform(Canvas canvas);
String describe();
}
private static class TransfomedViewWidget extends View {
private final Transformation transformation;
public TransfomedViewWidget(Context context, Transformation xform) {
super(context);
transformation = xform;
setMinimumWidth(160);
setMinimumHeight(105);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getSuggestedMinimumWidth(),
getSuggestedMinimumHeight());
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
232 | Chapter 12:ಗDrawing 2D and 3D Graphics
canvas.save();
transformation.transform(canvas);
paint.setTextSize(12);
paint.setColor(Color.GREEN);
canvas.drawText("Hello", 40, 55, paint);
paint.setTextSize(16);
paint.setColor(Color.RED);
canvas.drawText("Android", 35, 65, paint);
canvas.restore();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
Rect r = canvas.getClipBounds();
canvas.drawRect(r, paint);
paint.setTextSize(10);
paint.setColor(Color.BLUE);
canvas.drawText(transformation.describe(), 5, 100, paint);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.transformed);
LinearLayout v1 = (LinearLayout) findViewById(R.id.v_left);
v1.addView(new TransfomedViewWidget(
this,
new Transformation() {
@Override public String describe() { return "identity"; }
@Override public void transform(Canvas canvas) { }
} ));
v1.addView(new TransfomedViewWidget(
this,
new Transformation() {
@Override public String describe() { return "rotate(-30)"; }
@Override public void transform(Canvas canvas) {
canvas.rotate(-30.0F);
} }));
v1.addView(new TransfomedViewWidget(
this,
new Transformation() {
@Override public String describe() { return "scale(.5,.8)"; }
@Override public void transform(Canvas canvas) {
canvas.scale(0.5F, .8F);
} }));
v1.addView(new TransfomedViewWidget(
this,
new Transformation() {
Rolling Your Own Widgets | 233
@Override public String describe() { return "skew(.1,.3)"; }
@Override public void transform(Canvas canvas) {
canvas.skew(0.1F, 0.3F);
} }));
LinearLayout v2 = (LinearLayout) findViewById(R.id.v_right);
v2.addView(new TransfomedViewWidget(
this,
new Transformation() {
@Override public String describe() { return "translate(30,10)"; }
@Override public void transform(Canvas canvas) {
canvas.translate(30.0F, 10.0F);
} }));
v2.addView(new TransfomedViewWidget(
this,
new Transformation() {
@Override public String describe()
{ return "translate(110,-20),rotate(85)"; }
@Override public void transform(Canvas canvas) {
canvas.translate(110.0F, -20.0F);
canvas.rotate(85.0F);
} }));
v2.addView(new TransfomedViewWidget(
this,
new Transformation() {
@Override public String describe()
{ return "translate(-50,-20),scale(2,1.2)"; }
@Override public void transform(Canvas canvas) {
canvas.translate(-50.0F, -20.0F);
canvas.scale(2F, 1.2F);
} }));
v2.addView(new TransfomedViewWidget(
this,
new Transformation() {
@Override public String describe() { return "complex"; }
@Override public void transform(Canvas canvas) {
canvas.translate(-100.0F, -100.0F);
canvas.scale(2.5F, 2F);
canvas.skew(0.1F, 0.3F);
} }));
}
}
The iesults ol this piotiacteu exeicise aie shown in Figuie 12-3.
Heie aie some ol the highlights ol the coue:
Delinition ol the new wiuget, TransfomedViewWidget.
Gets the actual tiansloimation to peiloim liom the seconu aigument ol the
constiuctoi.
onDraw methou ol TransfomedViewWidget.
Pushes the state on the stack thiough save Leloie peiloiming any tiansloimation.
234 | Chapter 12:ಗDrawing 2D and 3D Graphics
Peiloims the tiansloimation passeu in item 2.
Restoies the olu state saveu in item +, having linisheu the tiansloimation.
The Nctivity`s onCreate methou.
Cieates the liist layout view.
Instantiations ol TransfomedViewWidget, auueu to layout view v1.
Cieates a tiansloimation as pait ol the paiametei list to the constiuctoi ol
TransfomedViewWidget.
Cieates the seconu layout view.
Instantiations ol TransfomedViewWidget, auueu to layout view v2.
This small application intiouuces seveial new iueas anu uemonstiates the powei ol
Nnuioiu giaphics loi maintaining state anu nesting changes.
The application uelines a single wiuget, TransformedViewWidget, ol which it cieates
eight instances. Foi layout, the application cieates two views nameu v1 anu v2, ietiiev-
ing theii paiameteis liom iesouices. It then auus loui instances ol TransformedView
Widget to each LinearLayout view. This is an example ol how applications comLine
Iigurc 12-3. Transforncd vicws
Rolling Your Own Widgets | 235
iesouice-Laseu anu uynamic views. Note that the cieation Loth ol the layout views anu
the new wiugets take place within the Nctivity`s onCreate methou.
This application also makes the new wiuget llexiLle thiough a sophisticateu uivision
ol laLoi Letween the wiuget anu its Transformation. Seveial simple oLjects aie uiawn
uiiectly within the uelinition ol TransformedViewWidget, in its onDraw methou:
º N white Lackgiounu
º The woiu ¨Hello¨ in 12-point gieen type
º The woiu ¨Nnuioiu¨ in 16-point ieu type
º N Llack liame
º N Llue laLel
In the miuule ol this, the onDraw methou peiloims a tiansloimation specilieu at its
cieation. The application uelines its own inteilace, calleu Transformation, anu the con-
stiuctoi loi TransformedViewWidget accepts a Transformation as a paiametei. Ve`ll see
in a moment how the callei actually coues a tiansloimation.
It`s impoitant to see liist how the wiuget onDraw pieseives its own text liom Leing
allecteu Ly the Transformation. In this example, we want to make suie that the liame
anu laLel aie uiawn last, so that they aie uiawn ovei anything else uiawn Ly the wiuget,
even il they might oveilap. On the othei hanu, we uo not want the tiansloimation
applieu eailiei to allect them.
Foitunately, the Canvas maintains an inteinal stack onto which we can iecoiu anu
iecovei the tianslation matiix, clip iectangle, anu many othei elements ol mutaLle state
in the Canvas. Taking auvantage ol this stack, onDraw calls save to pieseive its state
Leloie the tiansloimation, anu restore alteiwaiu to iecovei the saveu state.
The iest ol the application contiols the tiansloimation useu in each ol the eight in-
stances ol TransformedViewWidget. Each new instance ol the wiuget is cieateu with its
own anonymous instance ol Tranformation. The image in the aiea laLeleu ¨iuentity¨
has no tianslation applieu. The othei seven aieas aie laLeleu with the tiansloimations
they uemonstiate.
The Lase methous loi Canvas tianslation aie setMatrix anu concatMatrix. These two
methous allow you to Luilu any possiLle tiansloimation. The getMatrix methou allows
you to iecovei a uynamically constiucteu matiix loi latei use. The methous intiouuceu
in the example÷translate, rotate, scale, anu skew÷aie convenience methous that
compose specilic, constiaineu matiixes into the cuiient Canvas state.
Nlthough it may not Le oLvious at liist, these tiansloimation lunctions can Le tiemen-
uously uselul. They allow youi application to appeai to change its point ol view with
iespect to a 3D oLject. It uoesn`t take too much imagination, loi instance, to see the
scene in the sguaie laLeleu ¨scale(.5,.8)¨ as the same as that seen in the sguaie laLeleu
¨iuentity¨, Lut vieweu liom laithei away. Vith a Lit moie imagination, the image in
the Lox laLeleu ¨skew(.1,.3)¨ again coulu Le the untiansloimeu image, Lut this time
236 | Chapter 12:ಗDrawing 2D and 3D Graphics
vieweu liom aLove anu slightly to the siue. Scaling oi tianslating an oLject can make
it appeai to a usei as il the oLject has moveu. Skewing anu iotating can make it appeai
that the oLject has tuineu. Ve will make goou use ol this technigue in animation.
Vhen you consiuei that these tiansloimation lunctions apply to eveiything uiawn on
a canvas÷lines, text, anu even images÷theii impoitance in applications Lecomes even
moie appaient. N view that uisplays thumLnails ol photos coulu Le implementeu tiiv-
ially, though peihaps not optimally, as a view that scales eveiything it uisplays to 10º
ol its actual size. Nn application that simulates what you see as you look to youi lelt
while uiiving uown the stieet might Le implementeu in pait Ly scaling anu skewing a
small numLei ol images.
Drawables
N Drawable is an oLject that knows how to ienuei itsell on a Canvas. Because a
Drawable has complete contiol uuiing ienueiing, even a veiy complex ienueiing piocess
can Le encapsulateu in a way that makes it laiily easy to use.
Examples 12-7 anu 12-8 show the changes necessaiy to implement the pievious ex-
ample, Figuie 12-3, using a Drawable. The coue that uiaws the ieu anu gieen text has
Leen ielactoieu into a HelloAndroidTextDrawable class, useu in ienueiing Ly the
wiuget`s onDraw methou.
Exanp|c 12-7. Using a TcxtDrawab|c
private static class HelloAndroidTextDrawable extends Drawable {
private ColorFilter filter;
private int opacity;
public HelloAndroidTextDrawable() {}
@Override
public void draw(Canvas canvas) {
Paint paint = new Paint();
paint.setColorFilter(filter);
paint.setAlpha(opacity);
paint.setTextSize(12);
paint.setColor(Color.GREEN);
canvas.drawText("Hello", 40, 55, paint);
paint.setTextSize(16);
paint.setColor(Color.RED);
canvas.drawText("Android", 35, 65, paint);
}
@Override
public int getOpacity() { return PixelFormat.TRANSLUCENT; }
@Override
Rolling Your Own Widgets | 237
public void setAlpha(int alpha) { }
@Override
public void setColorFilter(ColorFilter cf) { }
}
Using the new Drawable implementation ieguiies only a lew small changes to the
onDraw methou.
Exanp|c 12-8. Using a Drawab|c widgct
package com.oreilly.android.intro.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
/**A widget that renders a drawable with a transformation */
public class TransformedViewWidget extends View {
/** A transformation */
public interface Transformation {
/** @param canvas */
void transform(Canvas canvas);
/** @return text descriptiont of the transform. */
String describe();
}
private final Transformation transformation;
private final Drawable drawable;
/**
* Render the passed drawable, transformed.
*
* @param context app context
* @param draw the object to be drawn, in transform
* @param xform the transformation
*/
public TransformedViewWidget(
Context context,
Drawable draw,
Transformation xform)
{
super(context);
drawable = draw;
transformation = xform;
setMinimumWidth(160);
setMinimumHeight(135);
238 | Chapter 12:ಗDrawing 2D and 3D Graphics
}
/** @see android.view.View#onMeasure(int, int) */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getSuggestedMinimumWidth(),
getSuggestedMinimumHeight());
}
/** @see android.view.View#onDraw(android.graphics.Canvas) */
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.save();
transformation.transform(canvas);
drawable.draw(canvas);
canvas.restore();
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
Rect r = canvas.getClipBounds();
canvas.drawRect(r, paint);
paint.setTextSize(10);
paint.setColor(Color.BLUE);
canvas.drawText(
transformation.describe(),
5,
getMeasuredHeight() - 5,
paint);
}
}
This coue Legins to uemonstiate the powei ol using a Drawable. This implementation
ol TransformedViewWidget will tiansloim any Drawable, no mattei what it happens to
uiaw. It is no longei tieu to iotating anu scaling oui oiiginal, haiucoueu text. It can Le
ieuseu to tiansloim Loth the text liom the pievious example anu a photo captuieu
liom the cameia, as Figuie 12-+ uemonstiates. It coulu even Le useu to tiansloim a
Drawable animation.
The aLility to encapsulate complex uiawing tasks in a single oLject with a stiaightloi-
waiu NPI is a valuaLle÷anu even necessaiy÷tool in the Nnuioiu toolkit. Drawables
make complex giaphical technigues such as nine-patches anu animation tiactaLle. In
auuition, since they wiap the ienueiing piocess completely, Drawables can Le nesteu to
uecompose complex ienueiing into small ieusaLle pieces.
Consiuei loi a moment how we might extenu the pievious example to make each ol
the six images laue to white ovei a peiiou ol a minute. Ceitainly, we coulu just change
Rolling Your Own Widgets | 239
the coue in Example 12-8 to uo the laue. N uilleient÷anu veiy appealing÷imple-
mentation involves wiiting one new Drawable.
This new Drawable, FaderDrawable, will take, in its constiuctoi, a ieleience to its taiget,
the Drawable that it will laue to white. In auuition, it must have some notion ol time,
pioLaLly an integei÷let`s call it t÷that is inciementeu Ly a timei. Vhenevei the
draw methou ol FaderDrawable is calleu, it liist calls the draw methou ol its taiget. Next,
it paints ovei exactly the same aiea with the coloi white, using the value ol t to uetei-
mine the tianspaiency (alpha value) ol the paint (as uemonstiateu in Example 12-2).
Ns time passes, t gets laigei, the white gets moie anu moie opague, anu the taiget
Drawable laues to white.
This hypothetical FaderDrawable uemonstiates some ol the impoitant leatuies ol
Drawables. Fiist, note that FaderDrawable is nicely ieusaLle: it will laue just aLout any
Drawable. Nlso note that, since FaderDrawable extenus Drawable, we can use it anywheie
that we woulu have useu its taiget, the Drawable that it laues to white. Nny coue that
uses a Drawable in its ienueiing piocess can use a FaderDrawable without change.
Ol couise, a FaderDrawable coulu itsell Le wiappeu. In lact, it seems possiLle to achieve
veiy complex ellects, simply Ly Luiluing a chain ol Drawable wiappeis. The Nnuioiu
toolkit pioviues Drawable wiappeis that suppoit this stiategy, incluuing ClipDrawable,
RotateDrawable, anu ScaleDrawable.
Iigurc 12-1. Transforncd vicws with photos
240 | Chapter 12:ಗDrawing 2D and 3D Graphics
Nt this point you may Le mentally ieuesigning youi entiie UI in teims ol Drawables.
Nlthough a poweilul tool, they aie not a panacea. Theie aie seveial issues to keep in
minu when consiueiing the use ol Drawables.
You may well have noticeu that they shaie a lot ol the lunctionality ol the View class:
location, uimensions, visiLility, etc. It`s not always easy to ueciue when a View shoulu
uiaw uiiectly on the Canvas, when it shoulu uelegate to a suLview, anu when it shoulu
uelegate to one oi moie Drawable oLjects. Theie is even a DrawableContainer class that
allows giouping seveial chilu Drawables within a paient. It is possiLle to Luilu tiees ol
Drawables that paiallel the tiees ol Views we`ve Leen using so lai. In uealing with the
Nnuioiu liamewoik, you just have to accept that sometimes theie is moie than one way
to scale a cat.
One uilleience Letween the two choices is that Drawables uo not implement the View
measuie/layout piotocol, which allows a containei view to negotiate the layout ol its
components in iesponse to changing view size. Vhen a ienueiaLle oLject neeus to auu,
iemove, oi lay out inteinal components, it`s a pietty goou inuication that it shoulu Le
a lull-lleugeu View insteau ol a Drawable.
N seconu issue to consiuei is that Drawables completely wiap the uiawing piocess Le-
cause they aie not uiawn like String oi Rect oLjects. Theie aie, loi instance, no
Canvas methous that will ienuei a Drawable at specilic cooiuinates. You may linu youi-
sell ueliLeiating ovei whethei, in oiuei to ienuei a ceitain image twice, a View onDraw
methou shoulu use two uilleient, immutaLle Drawables oi a single Drawable twice, ie-
setting its cooiuinates.
Peihaps most impoitant, though, is a moie geneiic pioLlem. The iuea ol a chain ol
Drawables woiks Lecause the Drawable inteilace contains no inloimation aLout the in-
teinal implementation ol the Drawable. Vhen youi coue is passeu a Drawable, theie is
no way loi it to know whethei it is something that will ienuei a simple image oi a
complex chain ol ellects that iotates, llashes, anu Lounces. Cleaily this can Le a Lig
auvantage. But it can also Le a pioLlem.
Quite a Lit ol the uiawing piocess is statelul. You set up Paint anu then uiaw with it.
You set up Canvas clip iegions anu tiansloimations anu then uiaw thiough them. Vhen
coopeiating in a chain, il Drawables change state, they must Le veiy caielul that those
changes nevei colliue. The pioLlem is that, when constiucting a Drawable chain, the
possiLility ol collision cannot Le explicit in the oLject`s type Ly uelinition (they aie all
just Drawables). N seemingly small change might have an ellect that is not uesiiaLle anu
is uillicult to ueLug.
To illustiate the pioLlem, consiuei two Drawable wiappei classes, one that is meant to
shiink its contents anu anothei that is meant to iotate them Ly 90 uegiees. Il eithei is
implementeu Ly setting the tiansloimation matiix to a specilic value (insteau ol com-
posing its tiansloimation with any that alieauy exist), composing the two Drawables
may not have the uesiieu ellect. Voise, it might woik peilectly il N wiaps B, Lut not
il B wiaps N! Caielul uocumentation ol how a Drawable is implementeu is essential.
Rolling Your Own Widgets | 241
Bitmaps
The Bitmap is the last memLei ol the loui essentials loi uiawing: something to uiaw (a
String, Rect, etc.), Paint with which to uiaw, a Canvas on which to uiaw, anu the
Bitmap to holu the Lits. Most ol the time, you uon`t have to ueal uiiectly with a
Bitmap, Lecause the Canvas pioviueu as an aigument to the onDraw methou alieauy has
one Lehinu it. Howevei, theie aie ciicumstances unuei which you may want to use a
Bitmap uiiectly.
N common use loi a Bitmap is as a way to cache a uiawing that is time-consuming to
uiaw Lut unlikely to change lieguently. Consiuei, loi example, a uiawing piogiam that
allows the usei to uiaw in multiple layeis. The layeis act as tianspaient oveilays on a
Lase image, anu the usei tuins them oll anu on at will. It might Le veiy expensive to
actually uiaw each inuiviuual layei eveiy time onDraw gets calleu. Insteau, it might Le
lastei to ienuei the entiie uiawing with all visiLle layeis once, anu only upuate it when
the usei changes which aie visiLle.
The implementation ol such an application might look something like Example 12-9.
Exanp|c 12-9. Bitnap caching
private class CachingWidget extends View {
private Bitmap cache;
public CachingWidget(Context context) {
super(context);
setMinimumWidth(200);
setMinimumHeight(200);
}
public void invalidateCache() {
cache = null;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
if (null == cache) {
cache = Bitmap.createBitmap(
getMeasuredWidth(),
getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
drawCachedBitmap(new Canvas(cache));
}
canvas.drawBitmap(cache, 0, 0, new Paint());
}
// ... definition of drawCachedBitmap
}
242 | Chapter 12:ಗDrawing 2D and 3D Graphics
This wiuget noimally just copies the cacheu Bitmap, cache, to the Canvas passeu to
onDraw. Il the cache is maikeu stale (Ly calling invalidateCache), only then will
drawCachedBitmap Le calleu to actually ienuei the wiuget.
The most common way to encountei a Bitmap is as the piogiammatic iepiesentation
ol a giaphics iesouice. Resources.getDrawable ietuins a BitmapDrawable when the ie-
souice is an image.
ComLining these two iueas÷caching an image anu wiapping it in a Drawable÷opens
yet anothei inteiesting winuow. It means that anything that can Le uiawn can also Le
postpiocesseu. Nn application that useu all ol the technigues uemonstiateu in this
chaptei coulu allow a usei to uiaw luinituie in a ioom (cieating a Litmap) anu then to
walk aiounu it (using the matiix tiansloims).
Bling
The Nnuioiu UI liamewoik is a lot moie than a just an intelligent, well-put-togethei
GUI toolkit. Vhen it takes oll its glasses anu shakes out its haii, it can Le uowniight
sexy! The tools mentioneu heie ceitainly uo not make an exhaustive catalog. They
might get you staiteu, though, on the path to making youi application Filthy Rich.
Seveial ol the technigues uiscusseu in this section aie close to the euges
ol the Nnuioiu lanuscape. Ns such, they aie less well estaLlisheu: the
uocumentation is not as thoiough, some ol the leatuies aie cleaily in
tiansition, anu you may even linu Lugs. Il you iun into pioLlems, the
Google Gioup ¨Nnuioiu Developeis¨ is an invaluaLle iesouice. Ques-
tions aLout a paiticulai aspect ol the toolkit have sometimes Leen an-
sweieu Ly the veiy peison iesponsiLle loi implementing that aspect.
Be caielul aLout checking the uates on solutions you linu Ly seaiching
the VeL. Some ol these leatuies aie changing iapiuly, anu coue that
woikeu as iecently as six months ago may not woik now. N coiollaiy,
ol couise, is that any application that gets wiue uistiiLution is likely to
Le iun on platloims that have uilleiing implementations ol the leatuies
uiscusseu heie. By using these technigues, you may limit the liletime ol
youi application anu the numLei ol uevices that it will suppoit.
The iest ol this section consiueis a single application, much like the one useu in Ex-
ample 12-6: a couple ol LinearLayouts that contain multiple instances ol a single wiuget,
each uemonstiating a uilleient giaphics ellect. Example 12-10 contains the key paits
ol the wiuget, with coue uiscusseu pieviously eliueu loi Lievity. The wiuget simply
uiaws a lew giaphical oLjects anu uelines an inteilace thiough which vaiious giaphics
ellects can Le applieu to the ienueiing.
Bling | 243
Exanp|c 12-10. Effccts widgct
public class EffectsWidget extends View {
/** The effect to apply to the drawing */
public interface PaintEffect { void setEffect(Paint paint); }
// ...
// PaintWidget's widget rendering method
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
effect.setEffect(paint);
paint.setColor(Color.DKGRAY);
paint.setStrokeWidth(5);
canvas.drawLine(10, 10, 140, 20, paint);
paint.setTextSize(26);
canvas.drawText("Android", 40, 50, paint);
paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawText(String.valueOf(id), 2.0F, 12.0F, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
canvas.drawRect(canvas.getClipBounds(), paint);
}
}
The application that uses this wiuget, shown in Example 12-11, shoulu also leel lamil-
iai. It cieates seveial copies ol the EffectsWidget, each with its own ellect. Theie aie
two special wiugets: the Lottom wiuget in the iight column is animateu, anu the Lottom
wiuget in the lelt column uses OpenGL animation.
Exanp|c 12-11. Effccts app|ication
private void buildView() {
setContentView(R.layout.main);
LinearLayout view = (LinearLayout) findViewById(R.id.v_left);
view.addView(new EffectsWidget(
this,
1,
new EffectsWidget.PaintEffect() {
@Override public void setEffect(Paint paint) {
paint.setShadowLayer(1, 3, 4, Color.BLUE);
} }));
view.addView(new EffectsWidget(
this,
3,
new EffectsWidget.PaintEffect() {
@Override public void setEffect(Paint paint) {
244 | Chapter 12:ಗDrawing 2D and 3D Graphics
paint.setShader(
new LinearGradient(
0.0F,
0.0F,
160.0F,
80.0F,
new int[] { Color.BLACK, Color.RED, Color.YELLOW },
new float[] { 0.2F, 0.3F, 0.2F },
Shader.TileMode.REPEAT));
} }));
view.addView(new EffectsWidget(
this,
5,
new EffectsWidget.PaintEffect() {
@Override public void setEffect(Paint paint) {
paint.setMaskFilter(
new BlurMaskFilter(2, BlurMaskFilter.Blur.NORMAL));
} }));
// Not and EffectsWidget: this is the OpenGL Anamation widget.
glWidget = new GLDemoWidget(this);
view.addView(glWidget);
view = (LinearLayout) findViewById(R.id.v_right);
view.addView(new EffectsWidget(
this,
2,
new EffectsWidget.PaintEffect() {
@Override public void setEffect(Paint paint) {
paint.setShadowLayer(3, -8, 7, Color.GREEN);
} }));
view.addView(new EffectsWidget(
this,
4,
new EffectsWidget.PaintEffect() {
@Override public void setEffect(Paint paint) {
paint.setShader(
new LinearGradient(
0.0F,
40.0F,
15.0F,
40.0F,
Color.BLUE,
Color.GREEN,
Shader.TileMode.MIRROR));
} }));
// A widget with an animated background
View w = new EffectsWidget(
this,
6,
new EffectsWidget.PaintEffect() {
@Override public void setEffect(Paint paint) { }
});
Bling | 245
view.addView(w);
w.setBackgroundResource(R.drawable.throbber);
// This is, alas, necessary until Cupcake.
w.setOnClickListener(new OnClickListener() {
@Override public void onClick(View v) {
((AnimationDrawable) v.getBackground()).start();
} });
}
Figuie 12-5 shows what the coue looks like when iun. The Lottom two wiugets aie
animateu: the gieen checkeiLoaiu moves liom lelt to iight acioss the wiuget, anu the
Lottom-iight wiuget has a thioLLing ieu Lackgiounu.
Iigurc 12-5. Graphics cffccts
Shadows, Gradients, and Filters
PathEffect, MaskFilter, ColorFilter, Shader, anu ShadowLayer aie all attiiLutes ol Paint.
Nnything uiawn with Paint can Le uiawn unuei the inlluence ol one oi moie ol these
tiansloimations. The top seveial wiugets in Figuie 12-5 give examples ol some ol these
ellects.
Viugets 1 anu 2 uemonstiate shauows. Shauows aie cuiiently contiolleu Ly the
setShadowLayer methou. The aiguments, a Llui iauius anu X anu Y uisplacements,
contiol the appaient uistance anu position ol the light souice that cieates the shauow,
with iespect to the shauoweu oLject. Nlthough this is a veiy neat leatuie, the uocu-
mentation explicitly wains that it is a tempoiaiy NPI. Howevei, it seems unlikely that
the setShadowLayer methou will completely uisappeai oi even that lutuie implemen-
tations will Le Lackwaiu-incompatiLle.
246 | Chapter 12:ಗDrawing 2D and 3D Graphics
The Nnuioiu toolkit contains seveial pieLuilt shaueis. Viugets 3 anu + uemonstiate
one ol them, the LinearGradient shauei. N giauient is a iegulai tiansition Letween
colois that might Le useu, loi example, to give a page Lackgiounu a Lit moie lile,
without iesoiting to expensive Litmap iesouices.
N LinearGradient is specilieu with a vectoi that ueteimines the uiiection anu iate ol
the coloi tiansition, an aiiay ol colois thiough which to tiansition, anu a moue. The
linal aigument, the moue, ueteimines what happens when a single complete tiansition
thiough the giauient is insullicient to covei the entiie painteu oLject. Foi instance, in
wiuget +, the tiansition is only 15 pixels long, wheieas the uiawing is moie than 100
pixels wiue. Using the moue Shader.TileMode.Mirror causes the tiansition to iepeat,
alteinating uiiection acioss the uiawing. In the example, the giauient tiansitions liom
Llue to gieen in 15 pixels, then liom gieen to Llue in the next 15, anu so on acioss the
canvas.
Animation
The Nnuioiu UI toolkit olleis seveial uilleient animation tools. Tiansition
animations÷which the Google uocumentation calls twccncd aninations÷aie suL-
classes ol android.view.animation.Animation: RotateAnimation, TranslateAnimation,
ScaleAnimation, etc. These animations aie useu as tiansitions Letween paiis ol views.
N seconu type ol animation, suLclasses ol android.graphics.drawable.Animation
Drawable, can Le put into the Lackgiounu ol any wiuget to pioviue a wiue vaiiety ol
ellects. Finally, theie is lull-on animation, on top ol a SurfaceView that gives you lull
contiol to uo youi own seat-ol-the-pants animation.
Because Loth ol the liist two types ol animation, tiansition anu Lackgiounu, aie sup-
poiteu Ly View÷the Lase class loi all wiugets÷eveiy wiuget, toolkit, anu custom will
potentially suppoit them.
Transition animation
N tiansition animation is staiteu Ly calling the View methou startAnimation with an
instance ol Animation (oi, ol couise, youi own suLclass). Once installeu, the animation
iuns to completion: tiansition animations have no pause state.
The heait ol the animation is its applyTransformation methou. This methou is calleu
to piouuce successive liames ol the animation. Example 12-12 shows the implemen-
tation ol one tiansloimation. Ns you can see, it uoes not actually geneiate entiie giaph-
ical liames loi the animation. Insteau, it geneiates successive tiansloimations to Le
applieu to a single image Leing animateu. You will iecall, liom the section ¨Matiix
tiansloimations¨ on page 231, that matiix tiansloimations can Le useu to make an
oLject appeai to move. Tiansition animations uepenu on exactly this tiick.
Bling | 247
Exanp|c 12-12. Transition anination
@Override
protected void applyTransformation(float t, Transformation xf) {
Matrix xform = xf.getMatrix();
float z = ((dir > 0) ? 0.0f : -Z_MAX) - (dir * t * Z_MAX);
camera.save();
camera.rotateZ(t * 360);
camera.translate(0.0F, 0.0F, z);
camera.getMatrix(xform);
camera.restore();
xform.preTranslate(-xCenter, -yCenter);
xform.postTranslate(xCenter, yCenter);
}
This paiticulai implementation makes its taiget appeai to spin in the scieen plane (the
rotate methou call), anu at the same time, to shiink into the uistance (the translate
methou call). The matiix that will Le applieu to the taiget image is oLtaineu liom the
Transformation oLject passeu in that call.
This implementation uses camera, an instance ol the utility class Camera. The Camera
class÷not to Le conluseu with the cameia in the phone÷is a utility that makes it
possiLle to iecoiu ienueiing state. It is useu heie to compose the iotation anu tiansla-
tions tiansloimations into a single matiix, which is then stoieu as the animation
tiansloimation.
The liist paiametei to applyTransformation, nameu t, is ellectively the liame numLei.
It is passeu as a lloating-point numLei Letween 0.0 anu 1.0, anu might also Le unuei-
stoou as the peicent ol the animation that is complete. This example uses t to inciease
the appaient uistance along the Z-axis (a line peipenuiculai to the plane ol the scieen)
ol the image Leing animateu, anu to set the piopoition ol one complete iotation thiough
which the image has passeu. Ns t incieases, the animateu image appeais to iotate lui-
thei anu luithei countei-clockwise anu to move laithei anu laithei away, along the
Z-axis, into the uistance.
The preTranslate anu postTranslate opeiations aie necessaiy in oiuei to tianslate the
image aiounu its centei. By uelault, matiix opeiations tiansloim theii taiget aiounu
the oiigin. Il we uiu not peiloim these Liacketing tianslations, the taiget image woulu
appeai to iotate aiounu its uppei-lelt coinei. preTranslate ellectively moves the oiigin
to the centei ol the animation taiget loi the tianslation, anu postTranslate causes the
uelault to Le iestoieu altei the tianslation.
Il you consiuei what a tiansition animation must uo, you`ll iealize that it is likely to
compose two animations: the pievious scieen must Le animateu out anu the next one
animateu in. Example 12-12 suppoits this using the iemaining, unexplaineu vaiiaLle
dir. Its value is eithei 1 oi ÷1, anu it contiols whethei the animateu image seems to
248 | Chapter 12:ಗDrawing 2D and 3D Graphics
shiink into the uistance oi giow into the loiegiounu. Ve neeu only linu a way to
compose a shiink anu a giow animation.
This is uone using the lamiliai Listenei pattein. The Animation class uelines a listenei
nameu Animation.AnimationListener. Nny instance ol Animation that has a nonnull
listenei calls that listenei once when it staits, once when it stops, anu once loi each
iteiation in Letween. Cieating a listenei that notices when the shiinking animation
completes anu spawns a new giowing animation will cieate exactly the ellect we uesiie.
Example 12-13 shows the iest ol the implementation ol the animation.
Exanp|c 12-13. Transition anination conposition
public void runAnimation() {
animateOnce(new AccelerateInterpolator(), this);
}
@Override
public void onAnimationEnd(Animation animation) {
root.post(new Runnable() {
public void run() {
curView.setVisibility(View.GONE);
nextView.setVisibility(View.VISIBLE);
nextView.requestFocus();
new RotationTransitionAnimation(-1, root, nextView, null)
.animateOnce(new DecelerateInterpolator(), null);
} });
}
void animateOnce(
Interpolator interpolator,
Animation.AnimationListener listener)
{
setDuration(700);
setInterpolator(interpolator);
setAnimationListener(listener);
root.startAnimation(this);
}
The runAnimation methou staits the tiansition. The oveiiiuuen AnimationListener
methou, onAnimationEnd, spawns the seconu hall. Calleu when the taiget image appeais
to Le lai in the uistance, it hiues the image Leing animateu out (the curView) anu ieplaces
it with the newly visiLle image, nextView. It then cieates a new animation that, iunning
in ieveise, spins anu giows the new image into the loiegiounu.
The Interpolater class iepiesents a nilty attention to uetail. The values loi t, passeu
to applyTransformation, neeu not Le lineaily uistiiLuteu ovei time. In this implemen-
tation the animation appeais to speeu up as it ieceues, anu then to slow again as the
new image auvances. This is accomplisheu Ly using the two inteipolatois:
AccelerateInterpolator loi the liist hall ol the animation anu DecelerateInter
polator loi the seconu. Vithout the inteipolatoi, the uilleience Letween successive
values ol t, passeu to applyTransformation, woulu Le constant. This woulu make the
Bling | 249
animation appeai to have a constant speeu. The AccelerateInterpolator conveits those
egually spaceu values ol t into values that aie close togethei at the Leginning ol the
animation anu much luithei apait towaiu the enu. This makes the animation appeai
to speeu up. DecelerateInterpolator has exactly the opposite ellect. Nnuioiu also pio-
viues a CycleInterpolator anu LinearInterpolator, loi use as appiopiiate.
Nnimation composition is actually Luilt into the toolkit, using the (peihaps conlusingly
nameu) AnimationSet class. This class pioviues a convenient way to specily a list ol
animations to Le playeu, in oiuei (loitunately not a Set: it is oiueieu anu may ielei to
a given animation moie than once). In auuition, the toolkit pioviues seveial
stanuaiu tiansitions: AlphaAnimation, RotateAnimation, ScaleAnimation, anu
TranslateAnimation. Ceitainly, theie is no neeu loi these tiansitional animations to Le
symmetiic, as they aie in the pievious implementation. N new image might alpha laue
in as the olu one shiinks into a coinei oi sliue up liom the Lottom as the olu one laues
out. The possiLilities aie enuless.
Background animation
Iranc-by-franc animation, as it is calleu in the Google uocumentation, is completely
stiaightloiwaiu: a set ol liames, playeu in oiuei at iegulai inteivals. This kinu ol ani-
mation is implementeu Ly suLclasses ol AnimationDrawable.
Ns suLclasses ol Drawable, AnimationDrawable oLjects can Le useu in any context that
any othei Drawable is useu. The mechanism that animates them, howevei, is not a pait
ol the Drawable itsell. In oiuei to animate, an AnimationDrawable ielies on an exteinal
seivice pioviuei÷an implementation ol the Drawable.Callback inteilace÷to animate
it.
The View class implements this inteilace anu can Le useu to animate an Animation
Drawable. Unloitunately, it will supply animation seivices on|y to the one Drawable
oLject that is installeu as its Lackgiounu with one ol the two methous setBackground
Drawable oi setBackgroundResource.
The goou news, howevei, is that this is pioLaLly sullicient. N Lackgiounu animation
has access to the entiie wiuget canvas. Eveiything it uiaws will appeai to Le Lehinu
anything uiawn Ly the View.onDraw methou, so it woulu Le haiu to use the Lackgiounu
to implement lull-lleugeu spiites (animation integiateu into a static scene). Still, with
clevei use ol the DrawableContainer class (which allows you to animate seveial uilleient
animations simultaneously) anu Lecause the Lackgiounu can Le changeu at any time,
it is possiLle to accomplish guite a Lit without iesoiting to implementing youi own
animation liamewoik.
Nn AnimationDrawable in a view Lackgiounu is entiiely sullicient to uo anything liom,
say, inuicating that some long-iunning activity is taking place÷mayLe wingeu packets
llying acioss the scieen liom a phone to a towei÷to simply making a Lutton`s Lack-
giounu pulse.
250 | Chapter 12:ಗDrawing 2D and 3D Graphics
The pulsing Lutton example is illustiative anu suipiisingly easy to implement. Exam-
ples 12-1+ anu 12-15 show all you neeu. The animation is uelineu as a iesouice, anu
coue applies it to the Lutton.
Exanp|c 12-11. Iranc-by-franc anination (rcsourcc)
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/throbber_f0" android:duration="70" />
<item android:drawable="@drawable/throbber_f1" android:duration="70" />
<item android:drawable="@drawable/throbber_f2" android:duration="70" />
<item android:drawable="@drawable/throbber_f3" android:duration="70" />
<item android:drawable="@drawable/throbber_f4" android:duration="70" />
<item android:drawable="@drawable/throbber_f5" android:duration="70" />
<item android:drawable="@drawable/throbber_f6" android:duration="70" />
</animation-list>

Exanp|c 12-15. Iranc-by-franc anination (codc)
// w is a button that will "throb"
button.setBackgroundResource(R.drawable.throbber);
//!!! This is necessary, but should not be so in Cupcake
button.setOnClickListener(new OnClickListener() {
@Override public void onClick(View v) {
AnimationDrawable animation
= (AnimationDrawable) v.getBackground();
if (animation.isRunning()) { animation.stop(); }
else { animation.start(); }
// button action.
} });
Theie aie seveial gotchas heie, though. Fiist ol all, as ol this wiiting, the animation-
list example in the Google uocumentation uoes not guite woik. Theie is a pioLlem
with the way it iuentilies the animation-list iesouice. To make it woik, uon`t ueline
an android:id in that iesouice. Insteau, simply ielei to the oLject Ly its lilename
(R.drawab|c.throbbcr), as Example 12-15 uemonstiates.
The seconu issue is that a Lug in the V1¸i2 ielease ol the toolkit pievents a Lackgiounu
animation liom Leing staiteu in the Activity.onCreate methou. Il youi application`s
Lackgiounu shoulu Le animateu whenevei it is visiLle, you`ll have to use tiickeiy to
stait it. The example implementation uses an onClick hanulei. Theie aie suggestions
on the VeL that the animation can also Le staiteu successlully liom a thieau that pauses
Liielly Leloie calling AnimationDrawable.start. The Nnuioiu uevelopment team has a
lix loi this pioLlem, so the constiaint shoulu Le ielaxeu with the ielease ol Cupcake.
Finally, il you have woikeu with othei UI liamewoiks, especially MoLile UI liame-
woiks, you may Le accustomeu to painting the view Lackgiounu in the liist couple ol
lines ol the onDraw methou (oi eguivalent). Il you uo that in Nnuioiu, howevei, you will
paint ovei youi animation. It is, in geneial, a goou iuea to get into the haLit ol using
Bling | 251
setBackground to contiol the View Lackgiounu, whethei it is a soliu coloi, a giauient,
an image, oi an animation.
Specilying an AnimationDrawable Ly iesouice is veiy llexiLle. You can specily a list ol
uiawaLle iesouices÷any images you like÷that compiise the animation. Il youi ani-
mation neeus to Le uynamic, AnimationDrawable is a stiaightloiwaiu iecipe loi cieating
a uynamic uiawaLle that can Le animateu in the Lackgiounu ol a View.
Surface view animation
Full-on animation ieguiies a SurfaceView. The SurfaceView pioviues a noue in the view
tiee (anu, theieloie, space on the uisplay) on which any piocess at all can uiaw. The
SurfaceView noue is laiu out, sizeu, anu ieceives clicks anu upuates, just like any othei
wiuget. Insteau ol uiawing, howevei, it simply ieseives space on the scieen, pieventing
othei wiugets liom allecting any ol the pixels within its liame.
Diawing on a SurfaceView ieguiies implementing the SurfaceHolder.Callback intei-
lace. The two methous surfaceCreated anu surfaceDestroyed inloim the implementoi
that the uiawing suilace is availaLle loi uiawing anu that it has Lecome unavailaLle,
iespectively. The aigument to Loth ol the calls is an instance ol yet a thiiu class,
SurfaceHolder. In the inteival Letween these two calls, a uiawing ioutine can call the
SurfaceView methous lockCanvas anu unlockCanvasAndPost to euit the pixels theie.
Il this seems complex, even alongsiue some ol the elaLoiate animation uiscusseu pie-
viously.well, it is. Ns usual, concuiiency incieases the likelihoou ol nasty, haiu-to-
linu Lugs. The client ol a SurfaceView must Le suie that access to any state shaieu acioss
thieaus is piopeily synchionizeu, anu also that it nevei touches the SurfaceView,
Surface, oi Canvas except in the inteival Letween the calls to surfaceCreated anu
surfaceDestroyed. The toolkit coulu cleaily Lenelit liom a moie complete liamewoik
suppoit loi SurfaceView animation.
Il you aie consiueiing SurfaceView animation, you aie pioLaLly also consiueiing
OpenGL giaphics. Ns we`ll see, theie is an extension availaLle loi OpenGL animation
on a SurfaceView. It will tuin up in a somewhat out-ol-the-way place, though.
OpenGL Graphics
The Nnuioiu platloim suppoits OpenGL giaphics in ioughly the same way that a silk
hat suppoits iaLLits. Nlthough this is ceitainly among the most exciting technologies
in Nnuioiu, it is uelinitely at the euge ol the map. It also appeais that just Leloie the
linal Leta ielease, the inteilace unueiwent majoi changes. Much ol the coue anu many
ol the suggestions lounu on the VeL aie oLsolete anu no longei woik.
The NPI V1¸i2 ielease is an implementation ol OpenGL ES 1.0 anu much ol ES 1.1. It
is, essentially, a uomain-specilic language emLeuueu in ]ava. Someone who has Leen
uoing gaming UIs loi a while is likely to Le much moie comloitaLle ueveloping Nnuioiu
252 | Chapter 12:ಗDrawing 2D and 3D Graphics
OpenGL piogiams than a ]ava piogiammei, even a piogiammei who is a ]ava UI
expeit.
Beloie uiscussing the OpenGL giaphics liLiaiy itsell, we shoulu take a minute to con-
siuei exactly how pixels uiawn with OpenGL appeai on the uisplay. The iest ol this
chaptei has uiscusseu the intiicate View liamewoik that Nnuioiu uses to oiganize anu
iepiesent oLjects on the scieen. OpenGL is a language in which an application uesciiLes
an entiie scene that will Le ienueieu Ly an engine that is not only outsiue the ]VM, Lut
possiLly iunning on anothei piocessoi altogethei (the Giaphics Piocessing Unit, oi
GPU). Cooiuinating the two piocessois` views ol the scieen is tiicky.
The SurfaceView, uiscusseu eailiei, is neaily the iight thing. Its puipose is to cieate a
suilace on which a thieau othei than the UI giaphics thieau can uiaw. The tool we`u
like is an extension ol SurfaceView that has a Lit moie suppoit loi concuiiency, com-
Lineu with suppoit loi OpenGL.
It tuins out that theie is exactly such a tool. Nll ol the uemo applications in the Nnuioiu
SDK uistiiLution that uo OpenGL animation uepenu on the utility class GLSurface
View. Since the uemo applications wiitten Ly the cieatois ol Nnuioiu use this class,
consiueiing it loi othei applications seems auvisaLle.
GLSurfaceView uelines an inteilace, GLSurfaceView.Renderer, which uiamatically sim-
plilies the otheiwise oveiwhelming complexity ol using OpenGL anu GLSurfaceView.
GLSurfaceView calls the ienueiei methou getConfigSpec to get its OpenGL conliguiation
inloimation. Two othei methous, sizeChanged anu surfaceCreated, aie calleu Ly the
GLSurfaceView to inloim the ienueiei that its size has changeu oi that it shoulu piepaie
to uiaw, iespectively. Finally, drawFrame, the heait ol the inteilace, is calleu to ienuei
a new OpenGL liame.
Example 12-16 shows the impoitant methous liom the implementation ol an OpenGL
ienueiei.
Exanp|c 12-1ó. Iranc-by-franc anination with OpcnGL
// ... some state set up in the constructor
@Override
public void surfaceCreated(GL10 gl) {
// set up the surface
gl.glDisable(GL10.GL_DITHER);
gl.glHint(
GL10.GL_PERSPECTIVE_CORRECTION_HINT,
GL10.GL_FASTEST);
gl.glClearColor(0.4f, 0.2f, 0.2f, 0.5f);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
// fetch the checker-board
initImage(gl);
Bling | 253
}
@Override
public void drawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// apply the checker-board to the shape
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glTexEnvx(
GL10.GL_TEXTURE_ENV,
GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_MODULATE);
gl.glTexParameterx(
GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_WRAP_S,
GL10.GL_REPEAT);
gl.glTexParameterx(
GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
// animation
int t = (int) (SystemClock.uptimeMillis() % (10 * 1000L));
gl.glTranslatef(6.0f - (0.0013f * t), 0, 0);
// draw
gl.glFrontFace(GL10.GL_CCW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuf);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuf);
gl.glDrawElements(
GL10.GL_TRIANGLE_STRIP,
5,
GL10.GL_UNSIGNED_SHORT, indexBuf);
}
private void initImage(GL10 gl) {
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(
GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(
254 | Chapter 12:ಗDrawing 2D and 3D Graphics
GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(
GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(
GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexEnvf(
GL10.GL_TEXTURE_ENV,
GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
InputStream in
= context.getResources().openRawResource(R.drawable.cb);
Bitmap image;
try { image = BitmapFactory.decodeStream(in); }
finally {
try { in.close(); } catch(IOException e) { }
}
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, image, 0);
image.recycle();
}
The surfaceCreated methou piepaies the scene. It sets seveial OpenGL attiiLutes that
neeu to Le initializeu only when the wiuget gets a new uiawing suilace. In auuition, it
calls initImage, which ieaus in a Litmap iesouice anu stoies it as a 2D textuie. Finally,
when drawFrame is calleu, eveiything is ieauy loi uiawing. The textuie is applieu to a
plane whose veitices weie set up in vertexBuf Ly the constiuctoi, the animation phase
is chosen, anu the scene is ieuiawn.
Bling | 255
CHAPTER 13
Inter-Process Communication
Nnuioiu is uesigneu to host a vaiiety ol applications anu to maximize usei choice. The
platloim is intenueu to eliminate the uuplication ol lunctionality in uilleient applica-
tions, to allow lunctionality to Le uiscoveieu anu invokeu on the lly, anu to let useis
ieplace applications with otheis that ollei similai lunctionality. Npplications must have
as lew uepenuencies as possiLle, anu must Le aLle to contiact out opeiations to othei
applications that may change at the usei`s uiscietion.
Intei-piocess communication (IPC) is thus the Lasis ol key leatuies ol the Nnuioiu
piogiamming mouel. The technigues we`ll look at in this chaptei aie:
|ntcnts
These enaLle an application to select an Nctivity Laseu on the action you want to
invoke anu the uata on which they opeiate. In othei woius, you uon`t neeu a haiu-
coueu path to an application to use its lunctions anu exchange uata with it. Data
can Le passeu in Loth uiiections using Intent oLjects, anu this enaLles a convenient,
high-level system ol intei-piocess communication.
Rcnotc ncthods
This leatuie iesemLles the iemote pioceuuie calls (RPCs) olleieu Ly othei systems:
it makes NPIs accessiLle iemotely. Remote oLjects allow you to make methou calls
that look ¨local¨ Lut aie executeu in anothei piocess. They involve the use ol
Nnuioiu`s inteilace uelinition language (NIDL).
In this chaptei, we will see how these leatuies woik anu how they can Le useu in
applications.
Nnuioiu applications coulu avoiu intei-piocess communication anu pioviue lunctions
in packages loaueu Ly the applications that neeu them. Il applications hau to exchange
uata, they coulu use the lilesystem oi othei tiauitional Unix/Linux IPC mechanisms
(sockets, shaieu memoiy, etc.). But these piactices aie eiioi pione anu haiu to main-
tain. In paiticulai, some ol the pioLlems incluue:
257
º LiLiaiies aie uillicult to shaie among multiple ]ava piocesses. ]ava was uesigneu
to have thieaus, not piocesses, shaie common coue iesouices.
º Shaiing auuiess space easily leaus to eiiois anu inappiopiiate access to piivate uata.
Conseguently, mouein piogiamming enviionments have moveu on to moie ioLust
component-like systems. Intents anu iemote methous lit the Lill excellently loi
Nnuioiu.
Intents: Simple, Low-Overhead IPC
The Nnuioiu system uses Intent oLjects to enaLle applications to specily an Nctivity
oi Seivice. Intent oLjects also uelivei uata liom one application to anothei, pioviuing
a simple anu convenient loim ol IPC.
The Intent class, the Nctivity class, anu Nnuioiu`s Intent-Laseu intei-piocess commu-
nication solve one ol the usei inteilace pioLlems ol smaitphone platloims that suppoit
multiple sepaiate applications: they leel like a collection ol sepaiate piogiams. You
uon`t have the simplicity ol navigating a hieiaichical usei inteilace, as in simplei leatuie
phones, anu you uon`t have multiple winuows, as on a PC usei inteilace. The way
Nctivities woik togethei on Nnuioiu makes it possiLle to make a seamless usei inteilace
out ol multiple applications, anu intei-piocess communication can enhance coopeia-
tion among applications.
Intent Objects Used in Inter-Process Communication
Ve`ll stait with how the client makes a ieguest. Seveial classes aie involveu:
Activity anu Context
Ve`ve seen Activity oLjects useu thioughout this Look. The Context class, a paient
class ol Activity anu Service, contains the methous loi senuing Intent oLjects
liom one Activity oLject to anothei, whethei in the same piocess oi a uilleient
one. So eveiy place you have an Activity suLclass÷ which is neaily eveiy place in
youi application that neeus to uisplay a UI÷you have the methous loi slinging
Intent oLjects aiounu to othei Nctivity instances elsewheie in the Nnuioiu system.
Intent
Intent oLjects aie passeu liom piocess to piocess, using methous such as
startActivity anu startActivityForResult.
The Intent class itsell pioviues constiuctois, accessois, anu othei utilities loi han-
uling the content ol an Intent oLject, Lut no methous loi moving Intent oLjects.
Nn impoitant set ol accessois aie those nameu putExtra. Seveial methous with this
name anu uilleient aiguments÷hence uilleient signatuies÷let you attach ¨extia¨
uata to an Intent. This uata can Le useu loi geneial-puipose intei-piocess com-
munication. The liist examples in this chaptei will use this kinu ol simple intei-
piocess communication.
258 | Chapter 13:ಗInter-Process Communication
Activity Objects and Navigating the User Interface Hierarchy
Most moLile hanuset usei inteilaces consist ol a linkeu weL, oi hieiaichy, ol
¨scieens¨÷usei inteilace views that occupy the whole scieen, except loi aieas wheie
titles anu inuicatoi icons aie uisplayeu anu wheie solt-key laLels (il any) aie uisplayeu.
Usually, these hieiaichies aie implementeu Ly a single piogiam that manages a ¨stack¨
ol scieens Lackwaiu liom the cuiient scieen (anu sometimes loiwaiu, as well, as in an
iPou-like UI). Intent anu Nctivity oLjects woik togethei, using intei-piocess commu-
nication, to link uilleient paits ol uilleient applications` usei inteilaces into a coheient
usei expeiience with navigation that is unilieu anu seamless when moving Letween
applications. In this section we`ll show how UI navigation anu intei-piocess commu-
nication go hanu-in-hanu.
Example: An Intent to Pick How We Say “Hello World”
Nlmost eveiyone wiites ¨Hello Voilu¨ piogiams. So theie is a neaily univeisal neeu
to augment these piogiams anu pievent them liom getting uull Ly pioviuing a choice
ol gieetings. That is what Example 13-1 uoes.
Exanp|c 13-1. An |ntcnt that chooscs a|tcrnatc ¨Hc||o Wor|d¨ strings
package example.sayhello;
import example.sayhello.R;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* An activity returning a result
*/
public class SayHello extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
// Call the parent class
super.onCreate(savedInstanceState);
// Put up the view for acquiring some input from the user
setContentView(R.layout.main);
// Set up the listeners for the buttons
((Button)findViewById(R.id.hello)).setOnClickListener(helloListener);
((Button)findViewById(R.id.goaway)).setOnClickListener(goAwayListener);
}
Intents: Simple, Low-Overhead IPC | 259
private OnClickListener helloListener = new OnClickListener()
{
public void onClick(View v)
{
returnResult("Hello, other Android!");
}
};
private OnClickListener goAwayListener = new OnClickListener()
{
public void onClick(View v)
{
returnResult("Get off my lawn, damn kids!");
}
};
// Put a result in an Intent object and set the result for this activity
void returnResult(String greeting) {
// Create the Intent object
Intent i = new Intent();
// Put an extra named "result" in the intent
i.putextra("result", greeting);
// Make this Intent the result for this activity
setResult(RESULT_OK, i);
// End this activity
finish();
}
}
Example 13-2 shows the layout lile that specilies the usei inteilace pioviueu Ly this
activity.
Exanp|c 13-2. Rcsourcc for a|tcrnatc ¨Hc||o Wor|d¨ strings
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:padding="4dip"
android:gravity="center_horizontal"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingBottom="8dip"
android:text="Say hello, or not"/>
<Button android:id="@+id/hello"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:text="Hello">
<requestFocus />
</Button>
260 | Chapter 13:ಗInter-Process Communication
<Button android:id="@+id/goaway"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:text="Go away">
</Button>
</LinearLayout>
Iigurc 13-1. Output of sinp|c ¨Hc||o Wor|d¨ progran
This layout uesciiLes a scieen with two Luttons. The listeneis loi these Luttons aie
calleu HelloListener anu GoAwayListener. In the ]ava coue in Example 13-1, the listenei
methous call returnResult, passing the stiing that will Le ietuineu.
You can tiy this piogiam as a stanualone application. Cieate a new Nnuioiu pioject
with the package nameu example.sayhello anu an activity nameu SayHello. Use Ex-
ample 13-1 loi the SayHello class anu Example 13-2 loi the nain.xn| layout lile. Vhen
iun, the application will uisplay Figuie 13-1.
Vhen you click on oi piess one ol the Luttons, the piogiam linishes anu uisappeais
liom the scieen. It also cieates an Intent oLject useu as a ¨iesult¨ loi the activity.
Intents: Simple, Low-Overhead IPC | 261
Let`s take a closei look at how it uoes that. You may want to iun the piogiam unuei
the ueLuggei anu set a Lieakpoint on the liist line ol the returnResult methou, wheie
we cieate an Intent oLject, anu lollow along using the ¨step ovei¨ commanu in the
ueLuggei.
Fiist, an Intent oLject is cieateu. This is what gets moveu liom this piocess to the
piocess that staiteu this Nctivity:
// Create the Intent object
Intent i = new Intent();
Heie we will see how Intent oLjects lacilitate intei-piocess communications: you can
laLel anu associate seveial types ol uata with an Intent oLject anu senu these ¨stow-
aways¨ with the oLject liom one piocess to anothei. Heie we call putExtra to auu uata
to the Intent. Its liist aigument is a String that laLels the uata; heie we use ¨iesult¨ as
the laLel. The seconu aigument, the actual payloau, can Le any uata type suppoiteu Ly
the uilleient putExtra methous (which uillei in the aiguments they take); in oui simple
example, we use a String loi the payloau as well:
// Put an extra named "result" in the intent
i.putExtra("result", greeting);
The returnResult methou ¨ietuins¨ the iesult, not to the methou that calls this methou,
Lut thiough an Intent oLject to the coue that staiteu this instance ol SayHello. The
lollowing line sets the iesult:
// Make this Intent the result for this activity
setResult(RESULT_OK, i);
In this example, howevei, nothing happens to oui iesult. NoLouy expects it, anu no-
Louy uses it. Next we will change that, anu see how one application can use a iesult
piouuceu Ly anothei.
Getting a Result via Inter-Process Communication
This section mouilies the ¨Hello Voilu¨ application liom an eailiei chaptei to show
how Nnuioiu can make sepaiate Nctivity oLjects in sepaiate piogiams seem ol-a-piece.
This veision uses one Nctivity to enaLle the usei to choose which gieeting to put on
the scieen in anothei Nctivity. N copy ol the uata put into the Intent oLject in the
pievious section enus up in an Intent oLject in the HelloWorldActivity Nctivity.
To enaLle a client to linu the Intent, the seivei assigns it a laLel calleu an action. In this
case, we`ll call oui action PICK, shown heie in Example 13-3.
Exanp|c 13-3. Hc||oWor|dActivity.java
package example.helloworld;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
262 | Chapter 13:ಗInter-Process Communication
import android.widget.TextView;
public class HelloWorldActivity extends Activity {
TextView helloView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Make a text view and set it to be the content view
helloView = new TextView(this);
setContentView(helloView);
// Make an Intent instance to fill in
Intent helloIntent = new Intent();
// Set the action, and type
helloIntent.setAction("android.intent.action.PICK");
helloIntent.setType("vnd.example.greeting/vnd.example.greeting-text");
// Ask an activity that matches our Intent object
startActivityForResult(helloIntent, 0);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent result)
{
if (resultCode == RESULT_OK) {
String greeting = result.getStringExtra("result");
helloView.setText(greeting);
}
}
}
The changes we maue will stait an Nctivity in a sepaiate application anu a sepaiate
piocess to pioviue the usei inteilace loi selecting a gieeting. Nltei that gieeting is ie-
tuineu Ly the othei Nctivity, this one uses it to say hello.
Run the piogiam. You will see the usei inteilace piesenteu Ly the SayHello piogiam,
just as in Figuie 13-1. But this time, when you piess one ol the two Luttons, the scieen
will uisplay the gieeting you selecteu (Figuie 13-2).
Let`s take a closei look at how it`s uone. Heie, again, you may want to lollow along
using the ueLuggei.
Diu you iun the SayHello piogiam yet? You neeu to uo that Leloie
you iun oui mouilieu HelloWorldActivity piogiam. The Nnuioiu emu-
latoi installs piogiams the liist time you iun them, so once you iun
SayHello it will stay aiounu as long as the emulatoi is iunning. But il
the piogiam hasn`t Leen iun yet, the startActivityForResult call in the
cuiient example will lail, Lecause Nnuioiu cannot linu SayHello.
Intents: Simple, Low-Overhead IPC | 263
Fiist, we neeu to stait oui helpei application, which we uo using an Intent oLject:
// Make an Intent instance to fill in
Intent helloIntent = new Intent();

Then, we neeu to specily an Nctivity that is neithei a pait ol oui application noi pait
ol an Nctivity in any ol the piogiams that come with Nnuioiu:
// Set the action, and type
helloIntent.setAction("android.intent.action.PICK");
helloIntent.setType("vnd.example.greeting/vnd.example.greeting-text");
The setType methou ieguiies a MIME type. Ve will use a venuoi-specilic MIME type
unigue to oui puipose (Ly venuoi heie, I mean us). Ns a iesult, oui SayHello activity is
launcheu Lecause it has an Intent liltei that matches the paiameteis we have set in this
Intent oLject.
Now we call the startActivityForResult methou, passing the Intent oLject we cieateu
to holu the inloimation that tells the Nnuioiu liamewoik to linu an Nctivity matching
the specilications in oui Intent: the PICK action anu the ieguesteu MIME type. Ve uon`t
Iigurc 13-2. Output of ¨Hc||o Wor|d¨ progran aftcr uscr sc|cction
264 | Chapter 13:ಗInter-Process Communication
explicitly ieguest the SayHello Nctivity÷we might want to ieplace it with something
else at some point÷Lut loi now, that activity is what Nnuioiu will linu:
// Ask an activity that matches our Intent object
startActivityForResult(helloIntent, 0);
The startActivityForResult methou navigates to a UI that oLtains inloimation anu
ietuins it. This is a goou illustiation ol using IPC loi a task that coulu otheiwise have
ieguiieu ieuunuant coue in all applications that neeu similai inloimation.
Now SayHello shoulu iun anu uisplay its usei inteilace loi selecting a gieeting. Vhen
you have selecteu a gieeting anu the setResult methou is calleu, Nnuioiu`s intei-piocess
communication system will move the iesult to this piocess, anu the OnActivityResult
methou will Le calleu. Ve`ve uelineu it as lollows:
protected void onActivityResult(int requestCode, int resultCode, Intent result) {
if (resultCode == RESULT_OK) {
String greeting = result.getStringExtra("result");
helloView.setText(greeting);
}
The methou calls getStringExtra to access the gieeting we have chosen. It uses the
setText methou ol the TextView class to uisplay oui selecteu gieeting.
To summaiize, in this example one piogiam (SayHello) acguiies some inloimation anu
supplies it to anothei piogiam (HelloWorldActivity). Ve have successlully useu intei-
piocess communication.
Nnuioiu incluues a component system Laseu on iemote oLjects anu methous, which
we`ll examine in the next section. This is a poweilul leatuie with many uses, Lut iemote
methou calls aie oveikill in many cases. Ns you uesign youi piogiams, liist consiuei
whethei youi intei-piocess communications neeus lit what Intents anu the Context
class`s Intent-ielateu methous can uo. Paiticulaily when you`ie using intei-piocess
communication to pioviue a usei inteilace in an Nctivity, this high-level loim ol IPC is
easy to use anu appiopiiate to the task.
Remote Methods and AIDL
This section uesciiLes how one piogiam can pioviue othei piogiams with access to its
methous. N numLei ol impoitant Nnuioiu NPIs use this leatuie. Foi instance, the
TelephonyManager intiouuceu in Chaptei 15 uses a iemote oLject inteilace in oiuei to
manage anu shaie the phone haiuwaie in an Nnuioiu uevice.
Theie aie thiee steps to cieating anu using iemote methous in Nnuioiu:
1. Deline the inteilace in the NIDL.
2. Implement the inteilace. That is, wiite methous that match the signatuies in the
inteilace anu that peiloim the opeiations you want in the piogiam that pioviues
the uesiieu seivices.
Remote Methods and AIDL | 265
3. Invoke the methous wheie you want to use them.
Android Interface Definition Language
To communicate liom one piocess to anothei, uata stoieu in memoiy has to Le moveu
acioss piocess Lounuaiies. That means the uata has to Le ¨maishalleu¨÷packageu loi
tianspoit÷anu ¨unmaishalleu¨÷put into the iight memLei vaiiaLles altei the uata
has Leen moveu acioss the piocess Lounuaiy. (Some Nnuioiu uocumentation uses the
woiu ¨llatteneu,¨ with the connotation ol taking a uata stoieu in seveial oLjects anu
tuining it into a ¨llat¨ aiiay ol Lytes that can Le sent Letween piocesses.)
]ava`s Lasic types, such as String, aie easy to maishall, Lut complex types, such as
multiuimensional aiiays, aie much haiuei. Maishalling uata spieau in an oLject that
holus ieleiences to othei oLjects ieguiies lollowing eveiy ieleience anu maishalling all
the uata that it ieleiences.
Usually, maishalling anu unmaishalling is peiloimeu on the paiameteis in a iemote
methou call, to let you pass uata liom one application to anothei anu ietuin iesults.
Maishalling anu unmaishalling uata is teuious, anu you woulu linu it haiu to unuei-
stanu coue that hau to caiiy out the task eveiy place it uses intei-piocess communica-
tion. Theieloie, most implementations ol iemote oLjects oi components use an
inteilace uelinition language that geneiates calls to maishalling methous. The syntax
ol the inteilace uelinition language iesemLles the main language in use (]ava in this
case), so that a iemote pioceuuie call closely iesemLles a noimal methou call. Howevei,
the inteilace uelinition language ieally is a sepaiate language.
NIDL syntax is iuentical to ]ava inteilace uelinition syntax, except that in NIDL you
can laLel the paiameteis loi iemote methou calls as in, out, oi inout. Nny paiametei
laLeleu in will Le tiansleiieu to the iemote methou, wheieas any paiametei laLeleu
out will Le ietuineu to the callei liom the iemote methou. In the example, liom the
NpiDemos application we use heie, the keywoius inuicating in anu out paiameteis aie
not useu. The uelaults apply: all paiameteis aie in, the ietuin value is useu loi ietuining
uata liom the iemote methou, anu any paiametei laLeleu inout will tianslei uata to the
iemote methou anu ielei to a value tiansleiieu liom the iemote methou when it ietuins.
In the example, the NIDL coue is theieloie completely compatiLle, in syntax, to ]ava
coue.
Vhen you save youi NIDL lile in Eclipse, the Nnuioiu Eclipse plug-in compiles it. Both
the calling anu implementing siue ol a iemote methou inteilace shaie the inloimation
in the NIDL lile.
Foi the examples in this section, we`ie exceipting coue liom the |Sccondary.aid| lile in
the NpiDemos application.
This is how you specily an inteilace to a iemote oLject:
interface ISecondary {
/**
266 | Chapter 13:ಗInter-Process Communication
* Request the PID of this service, to do evil things with it.
*/
int getPid();
/**
* This demonstrates the basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
This looks like ]ava coue, Lut it isn`t. It looks like an inteilace uelinition. Theie aie two
methou signatuies, anu no implementation ol the methous. That is all NIDL neeus to
cieate coue that moves the paiameteis Letween applications. Next we will take a look
at the coue geneiateu Ly NIDL to see exactly how the paiameteis aie moveu liom one
piocess to anothei, anu to see how to implement the NPI uelineu in this NIDL uelinition.
The Nnuioiu SDK plug-in loi Eclipse automatically compiles this coue to ]ava, iesulting
in the lollowing set ol ]ava uelinitions. Noimally this coue is not loimatteu loi ieaua-
Lility, so what you see heie looks uilleient liom the lile you see in the NpiDemos pioject
in youi Eclipse IDE. But it is the same ]ava coue:
package com.example.android.apis.app;
import java.lang.String;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Binder;
import android.os.Parcel;
/**
* Example of a secondary interface associated with a service. (Note that
* the interface itself doesn't impact, it is just a matter of how you
* retrieve it from the service.)
*/
public interface ISecondary extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder
implements com.example.android.apis.app.ISecondary {
private static final java.lang.String DESCRIPTOR =
"com.example.android.apis.app.ISecondary";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an ISecondary interface,
* generating a proxy if needed.
Remote Methods and AIDL | 267
*/
public static
com.example.android.apis.app.ISecondary asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin =
(android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) &&
(iin instanceof com.example.android.apis.app.ISecondary))) {
return ((com.example.android.apis.app.ISecondary) iin);
}
return new com.example.android.apis.app.ISecondary.Stub.Proxy(obj);
}
public android.os.IBinder asBinder() {
return this;
}
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel
reply,
int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getPid: {
data.enforceInterface(DESCRIPTOR);
int _result = this.getPid();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_basicTypes: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0 != data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
268 | Chapter 13:ಗInter-Process Communication
private static class Proxy implements
com.example.android.apis.app.ISecondary {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/**
* Request the PID of this service, to do evil things with it.
*/
public int getPid() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* This demonstrates the basic types that you can use as parameters
* and return values in AIDL.
*/
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat,
double aDouble, java.lang.String aString)
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean) ? (1) : (0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
Remote Methods and AIDL | 269
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getPid = (IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_basicTypes = (IBinder.FIRST_CALL_TRANSACTION
+ 1);
}
/**
* Request the PID of this service, to do evil things with it.
*/
public int getPid() throws android.os.RemoteException;
/**
* This demonstrates the basic types that you can use as parameters
* and return values in AIDL.
*/
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, java.lang.String aString) throws android.os.RemoteException;
}
That`s a lot ol coue! Now you can appieciate the value ol NIDL insteau ol Luiluing a
iemote oLject inteilace Ly hanu. Nltei we see what is going on insiue the
NIDL-geneiateu coue, we will take a look at the othei two steps to cieating anu using
a iemote oLject inteilace: implementing the methous anu invoking them.
Classes Underlying AIDL-Generated Interfaces
Now let`s take a look at the android.os.IInterface class. It`s a Lase type on which all
the inteilaces cieateu Ly NIDL aie Luilt, so they can Le ieleienceu thiough ieleiences
ol the same type. ISecondary extenus IInterface.
Most ol the coue in the ISecondary inteilace is pait ol the uelinition ol an aLstiact class
calleu Stub. You implement iemote methous Ly extenuing the Stub class. Eveiy iemote
inteilace has this class, Lut Lecause it is insiue the inteilace cieateu Ly NIDL paiticulai
to youi iemote methous, theie is no name conllict.
The woiu ¨stuL¨ was chosen to ielei to this class Lecause iemote methou systems woik
Ly cieating a methou on the client with the same name as the methou that iuns on the
seivei. The client methou is consiueieu a ¨stuL¨ Lecause it uoesn`t actually caiiy out
the opeiation ieguesteu; it just maishalls the uata, senus it to the seivei, anu unmai-
shalls the ietuin value. Ve`ll show some uetails latei in this chaptei.
270 | Chapter 13:ಗInter-Process Communication
Implementing the Stub interface
So how uo you wiite the coue that actually implements these iemote methou calls? In
this case, the implementation is in the class RemoteService ol the NpiDemos application,
anu the lollowing exceipt shows the methou uelinitions. The liist line extenus the
aLstiact class anu makes a new instance ol it:
private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
public int getPid() {
return Process.myPid();
}
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString) {
}
};
This is all you neeu to uo to tuin a methou in youi application into a iemote methou.
The iest ol the woik ol invoking the methou in the othei application, passing the pa-
iameteis, anu iesponuing with a ietuin value liom the iemote methou is peiloimeu Ly
coue geneiateu Ly NIDL in the Stub aLstiact class.
So, loi a iemote inteilace geneiateu Ly NIDL, the coue takes the aLstiact Stub class anu
implements the methou coue that will actually Le useu. But how uoes uata liom anothei
piocess get to these methous? That is wheie the onTransact methou comes in.
The onTransact methou (see the NIDL-geneiateu coue shown eailiei) is calleu when
uata in a Parcel oLject is ueliveieu to a iemote inteilace in an Nnuioiu piogiam. This
methou is geneiateu Ly NIDL loi each iemote inteilace. In this case, it ieaus each
aigument to the methou liom a Parcel oLject, makes the methou call, anu wiites the
iesult to anothei Parcel oLject useu loi the ietuin value ol a iemote methou.
Parcel oLjects aie what ]ava applications in Nnuioiu pass to the Nnuioiu IPC mecha-
nism loi moving Letween piocesses. In the simple IPC example eailiei in this chaptei,
unueilying the Context methou calls useu to move Intent oLjects Letween applications,
the Intent oLject anu the ¨extias¨ uata associateu with it aie maishalleu, oi ¨llatteneu,¨
into a Parcel oLject to Le moveu liom one piocess to anothei anu ieconstituteu into
an Intent oLject with the same extias in the othei piocess.
Basic types such as long anu int aie maishalleu anu unmaishalleu Ly methous in the
Parcel class. Othei classes in the Nnuioiu Lase classes, such as Intent anu String,
implement the PaicelaLle inteilace. Ns the name suggests, this pioviues an inteilace loi
the Parcel class to maishall those oLjects. Nnu on top ol that, implementing the
PaicelaLle inteilace in youi classes enaLles them to Le maishalleu, unmaishalleu, anu
moveu liom one application to anothei.
Getting an instance of the remote Proxy object
Theie is one moie pait to this stoiy: how uoes a uilleient application linu out aLout
the inteilace calleu ISeconuaiy, anu how uoes the callei ol the iemote methou actually
call these methous? The answei is in the asInterface methou ol the Stub class, anu the
Remote Methods and AIDL | 271
Proxy class nesteu within Stub. Nnu that means that any application that wants to make
a iemote methou call must shaie the inteilace uelinition with the application that im-
plements the inteilace. In piactical teims, that means that the calling application anu
the application that implements the iemote inteilace have to Le compileu with the same
NIDL liles.
Now let`s take a look at how the iemote inteilace gets calleu. In the NpiDemos coue
we aie using as an example heie, this happens in the RemoteServiceBinding class, wheie
the asInterface methou is calleu:
mSecondaryService =
ISecondary.Stub.asInterface(service);
The paiametei nameu service heie is a ieleience to an IBinuei inteilace. The Binder
aLstiact class implements IBinuei, anu the Stub class (the guts ol what NIDL has gen-
eiateu) extenus Binuei. Let`s see how this paiametei is useu in the asInterface methou:
public static com.example.android.apis.app.ISecondary asInterface(android.os.IBinder
obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)
obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.android.apis.app.ISecondary))) {
return ((com.example.android.apis.app.ISecondary) iin);
}
return new com.example.android.apis.app.ISecondary.Stub.Proxy(obj);
}
Heie the paiametei is nameu obj, anu liist it is testeu to see whethei it is null. Then,
asInteilace checks to see whethei theie is an instance ol ISeconuaiy with the coiiect
name. Vhat that means is that the ¨iemote¨ inteilace we weie looking loi is actually
in the same application as the coue calling it. Nnu that means no intei-piocess com-
munication is necessaiy. Otheiwise, il it isn`t a local inteilace, an instance ol the
Proxy oLject is cieateu. RememLei that this coue is executing in the context ol the
application that wants to call the iemote inteilace.
The Proxy class is the counteipait ol the Stub aLstiact class. It may seem a little minu-
Lenuing that the Proxy class, which implements ISeconuaiy, is uelineu insiue the
Stub class, which is itsell insiue the ISeconuaiy inteilace, Lut it tuins out to Le con-
venient. Otheiwise, moie class liles woulu have to Le cieateu Ly NIDL, anu somehow
uses ol those classes manageu.
Looking insiue the Proxy class, we see that it has methous that have the same signatuie
as the iemote methous uelineu in the NIDL lile. Heie, unlike in the aLstiact class
Stub, the methous aie implementeu, anu the implementations cieate Paicel oLjects anu
lill them with the ¨llatteneu¨ paiameteis in exactly the iight oiuei loi the onTransact
methou to ¨unllatten¨ them anu call the iemote ncthods.
272 | Chapter 13:ಗInter-Process Communication
That means an application calls a iemote methou Ly getting an instance ol the Proxy
class anu calling the iemote methous as il they weie local. You can see this heie, ex-
ceipteu liom the RemoteServiceBinding class:
int pid = mSecondaryService.getPid();
Recall that mSecondaryService is ietuineu liom the ISecondary.Stub.asInterface
methou. Because the callei gets a Proxy oLject anu the iemote methous aie implementeu
in a Stub oLject, anu Lecause Loth Proxy anu Stub implement ISeconuaiy, it all looks
like a local methou call, Lut the implementations ol the methous aie completely uil-
leient in the calling application anu the application that implements the iemote
methous.
To ieview:
º You ueline iemote inteilaces in NIDL. They look like ]ava inteilaces, Lut aie not.
º NIDL tuins youi iemote inteilace uelinition into a ]ava inteilace with Stub anu
Proxy classes nesteu insiue.
º Both the application that calls the iemote methou anu the application that imple-
ments it use the same NIDL lile anu the same geneiateu inteilace.
The application calling the iemote inteilace gets an instance ol the Proxy class that
implements the veiy same inteilace it is uelineu insiue ol. The instance also implements
¨pioxy¨ methous with the same signatuie as the iemote methous, Lut they package up
theii paiameteis into a Parcel oLject anu senu them oll to the application that imple-
ments the iemote methous anu unpackages anu ietuins the iesults.
In the iemote application, a conciete class extenuing Stub has implementations ol the
iemote methous. The onTransact methou ¨unllattens¨ uata in a Parcel oLject, calls the
iemote methous anu ¨llattens¨ the iesult, wiites it into a Paicel, anu senus that
Parcel oLject Lack to the calling application.
Howevei, il Loth the calling application anu the iemote seivice aie not, in lact, iemote
liom one anothei, an instance ol the conciete class that implements the not-so-iemote
methous is useu insteau, cutting out the intei-piocess communication il it is not neeueu.
Publishing an Interface
The seivei pub|ishcs an inteilace to make it possiLle loi othei activities to linu it. PuL-
lishing is accomplisheu Ly oveiiiuing the onBind methou ol the Service class (uesciiLeu
in ¨Nnuioiu Seivice Lilecycle¨ on page 10).
N client calls the bindService methou ol the Context class, causing a call to the seivei`s
onBind methou. The bindService anu onBind methous aie the ¨hanushake¨ ieguiieu to
stait using a iemote inteilace in a specilic Service oLject in a specilic piocess iunning
in the Nnuioiu enviionment. Heie is the example ol an onBind implementation liom
the the class RemoteService in the NpiDemos application:
Remote Methods and AIDL | 273
@Override
public IBinder onBind(Intent intent) {
// Select the interface to return. If your service only implements
// a single interface, you can just return it here without checking
// the Intent.
if (IRemoteService.class.getName().equals(intent.getAction())) {
return mBinder;
}
if (ISecondary.class.getName().equals(intent.getAction())) {
return mSecondaryBinder;
}
return null;
}
mBinder anu mSecondaryBinder ielei to oLjects implementing the StuL inteilace. You
will see the implementation ol mSecondaryBinder in the next section, wheie implemen-
tation ol the StuL inteilace is explaineu. Let`s take a look at this methou in uetail. Fiist,
the inteilace ieguesteu uepenus on matching the name ol the inteilace, which is passeu
in the action paiametei ol the Intent oLject:
if
(IRemoteService.class.getName().equals(intent.getAction())) {
return mBinder;
}
In the client application looking loi this inteilace, the contents ol the Intent oLject
weie specilieu in a call to the bindService methou ol the Context class. That means that
a piogiam puLlishing a iemote methou inteilace must Le a suLclass ol Service. But a
piogiam using a iemote methou inteilace can Le any suLclass ol Context, incluuing
Activity anu Service.
The Intent oLject is useu to specily the inteilace. The class name ol the inteilace is the
action paiametei ol the Intent.
Il the inteilace matches, the onBind methou ietuins an IBinder instance, an instance ol
the Stub inteilace in the iemote inteilace.
Android IPC Compared with Java Native Interface (JNI)
Remote pioceuuie calls (RPC) using Nnuioiu`s intei-piocess communications laigely
ieplace the use ol the ]ava Native Inteilace (]NI) in Nnuioiu. In almost all cases, a
iemote pioceuuie call is ellicient enough to make it a supeiioi alteinative to loauing a
liLiaiy÷especially one that uynamically allocates a signilicant amount ol memoiy÷
into the ]ava viitual machine`s auuiess space. Nnu il a piocess exposing an RPC intei-
lace lails, it is less likely to Liing uown the Nnuioiu UI with it.
Nnuioiu intei-piocess communication Lehaves a lot like ]NI: the callei`s thieau is
Llockeu until the iesult is ietuineu. Maishalling uata acioss the IPC Lounuaiy is aLout
the same amount ol woik as uata conveisions in ]NI. But Binuei-Laseu iemote pioce-
uuie calls have a signilicant auvantage ovei ]NI: il non-]ava coue ciashes oi iuns out
274 | Chapter 13:ಗInter-Process Communication
ol memoiy, the callei ol a iemote pioceuuie call gets an eiioi that must Le hanuleu,
Lut the ]ava application uoes not ciash. Remote pioceuuie calls aie a moie ioLust way
to call ¨exteinal¨ liLiaiies anu suLject the ]ava application to lewei iisks in the loim ol
clashing memoiy management stiategies anu othei uilleiences Letween ]ava applica-
tions anu liLiaiies implementeu in languages othei than ]ava.
What Binder Doesn’t Do
Theie aie at least thiee things Binuei uoesn`t uo, compaieu with othei systems capaLle
ol pioviuing similai lunctionality:
º Binuei uoes not manage veision inloimation.
º Binuei uoes not tiaveise netwoiks.
º It uoes not enaLle applications to uiscovei inteilaces.
Some intei-piocess communications systems enaLle the two siues ol an intei-piocess
NPI to negotiate veision compatiLility. Binuei, along with the highei-level mechanisms
Luilt on Binuei, uoes not uo this. This means NPIs Luilt on Binuei shoulu iemain com-
patiLle with oluei veisions il the NPIs aie open loi othei applications to use, anu it
means that consumeis ol iemote NPIs shoulu Le iesilient to lailuies causeu Ly incom-
patiLilities. Make suie to hanule those exceptions!
Binuei-Laseu intei-piocess communication is also limiteu to a single noue: it won`t take
you acioss the netwoik to othei Nnuioiu systems. This is a limitation, to Le suie, Lut
it is appiopiiate to a moLile hanuset, wheie enupoint-to-enupoint uata connections aie
iaiely useu anu olten Llockeu Ly the iouting in a moLile uata netwoik.
Binder and Linux
Binuei is not a wiuely useu IPC mechanism in Linux. D-BUS is the most wiuely useu
IPC mechanism, anu has Lecome commonly useu in Loth seivei anu uesktop Linux
uistiiLutions anu in numeious applications anu uaemons. In contiast, Binuei was ue-
velopeu Ly Palm, aLanuoneu, open-souiceu as OpenBinuei, anu suLseguently auopteu
Ly Google loi Nnuioiu.
Binuei may not Le the choice ol most othei Linux uistiiLutions, Lut it isn`t a Lau choice:
Binuei is useu thioughout Nnuioiu, incluuing peiloimance-ciitical paits ol Nnuioiu,
such as the Suilace Flingei, Nnuioiu`s system loi shaiing the scieen among multiple
piocesses. Binuei is simple anu peiloimant. It is also an example ol the ways in which
Nnuioiu uiveiges liom the typical use ol Linux in moLile hanusets anu othei small
uevices.
Nnuioiu is not a shiunken uesktop Linux. The use ol Binuei, the way Linux usei IDs
aie useu to ¨sanuLox¨ applications, the unigue 2D giaphics liLiaiy, anu othei uesign
uecisions aie all in the seivice ol making Nnuioiu an iueal platloim loi iunning Nnuioiu
applications. It is ueLataLle whethei eveiy uesign uecision that uiveiges liom stanuaius
Remote Methods and AIDL | 275
was woith it, anu uevelopeis who have staiteu poiting anu extenuing Nnuioiu actively
ueLate these issues, Lut some things aie ceitain:
º Nnuioiu peiloims well. None ol the unigue uesign uecisions that went into Nn-
uioiu weie to the uetiiment ol peiloimance. Nnuioiu peiloimance is goou enough
to allow multitasking÷something Npple aLjuies in iPhone so as not to iisk the
multimeuia usei expeiience.
º Nnuioiu is not attempting to set a geneial uiiection loi Linux, oi even loi emLeuueu
Linux. Nnuioiu has, ol couise, chaiteu a iauically uilleient couise loi application
uevelopment. Nnuioiu is consciously uilleient anu optimizeu loi a iange ol smait-
phone haiuwaie: Lig anu poweilul enough to iun a Liowsei, Lut not encioaching
on the laptop loimat enough to neeu a multiwinuow usei inteilace. Nnuioiu, as a
whole, is meant to Le just iight loi its intenueu puipose.
276 | Chapter 13:ಗInter-Process Communication
CHAPTER 14
Simple Phone Calls
Nnuioiu pioviues the usei with seveial ways ol staiting phone calls: liom the contact
list, liom the call histoiy, using a uialei that uisplays a 12-key uialpau on the scieen,
etc. Nll ol these soltwaie mouules use the same application to stait a phone call. Youi
piogiam can initiate a phone call in the same way: Ly using an Intent oLject to ask
Nnuioiu`s specializeu telephony application to make the call. Ve`ll covei that techni-
gue in this chaptei, anu take a look Lehinu the scenes at how the piocess woiks.
In Chaptei 15, we`ll intiouuce Nnuioiu classes that give you moie inloimation aLout
telephony, such as tiacking the state ol the call you maue.
Quick and Easy Phone Calls
Nnuioiu incluues an application calleu PhoneNpp that emLouies the lunctions ol a
moLile phone. Thiough the use ol Intent oLjects, Nnuioiu enaLles applications to tell
othei applications to peiloim ceitain opeiations, such as initiating a phone call. To
enaLle youi application to initiate a phone call, a methou like the one in Exam-
ple 1+-1 will uo the joL.
Exanp|c 11-1. How to na|c a phonc ca||
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:9785551212"));
startActivity(callIntent);
} catch (ActivityNotFoundException activityException) {
Log.e("dialing-example", "Call failed", activityException);
}
}
Vhat happens when you stait a phone call uepenus, in pait, on the telephone netwoik.
The numLei may Le incoiiect. The netwoik may Le Lusy oi otheiwise unavailaLle. The
call can Le inteiiupteu. Heie, howevei, you see no eiioi-hanuling logic, except loi
catching anu logging exceptions that can Le thiown il Nnuioiu`s system encounteis a
277
pioLlem when linuing applications that can piocess Intent oLjects. Insteau, the
PhoneNpp application, which alieauy has coue loi inteipieting anu iemeuiating eiiois,
hanules the joL liom the time the phone call is staiteu.
Vhen an application just wants to stait phone calls, making it hanule all these con-
tingencies is a laige Luiuen. Systems that pioviue a telephony NPI place that Luiuen
on application authois when, in most cases, all an application neeus is to stait a phone
call÷not to manage the lilecycle ol a phone call.
Staiting a phone call is a multistep opeiation. Heie we`ll take a uetaileu look at each
step in the execution ol the call methou shown in Example 1+-1. Nlong the way, we`ll
see how it uses Nnuioiu`s system ol Intent oLjects anu Intent lilteis.
Creating an Example Application to Run the call Method
To test the methou in Example 1+-1, cieate a new Nnuioiu pioject in Eclipse Ly selecting
File ൺNew ൺPioject ൺOthei.... Vhen the ¨Select a Vizaiu¨ uialog appeais, select
Nnuioiu ൺNnuioiu Pioject. Vhen you see the new pioject uialog, lill it in as shown in
Figuie 1+-1.
Piess Finish to cieate a pioject nameu dialing-example in youi Eclipse woikspace. (The
complete coue loi this example is also on the Look`s weLsite.) You will see this pioject
in the Package Exploiei pane ol youi Eclipse IDE. Expanu the pioject to see a set ol
lolueis, incluuing one nameu src. Expanu this loluei to see a package nameu
cxanp|c.dia|ing. Expanu that package anu you will see two ]ava souice liles, one ol
which is nameu dia|ing.java. This lile contains the coue in Example 1+-2.
Exanp|c 11-2. Sctting up an app|ication to na|c phonc ca||s
package example.dialing;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class dialing extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
278 | Chapter 14:ಗSimple Phone Calls
This is wheie you will put the coue that invokes oui call methou.
Iigurc 11-1. Crcating a phonc projcct in Ec|ipsc
Embedding the Code Snippet in a Simple Application
Now that you have cieateu a simple Nnuioiu application, you can use it to isolate anu
oLseive opeiations, such as staiting a phone call.
Copy the methou we cieateu in ¨Cieating an Example Npplication to Run the call
Methou¨ on page 278 to the dialing class in the dia|ing.java lile. Then, auu a line to
the onCreate methou that calls the call methou. The iesults shoulu look something
like Example 1+-3.
Quick and Easy Phone Calls | 279
Exanp|c 11-3. Thc dia|ing c|ass with ca|| ncthod and its invocation
package example.dialing;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class dialing extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
call();
}
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:9785551212"));
startActivity(callIntent);
} catch (ActivityNotFoundException activityException) {
Log.e("dialing-example", "Call failed", activityException);
}
}

Make suie youi piogiam compiles anu iuns. To iun the piogiam, select the Run ൺ
Run commanu. Vhen the Run Ns uialog appeais, select Nnuioiu Npplication. Il you
have lolloweu the steps in this chaptei, the iesult shoulu Le uisplayeu in the Nnuioiu
emulatoi winuow (Figuie 1+-2).
You can use the ieu ¨enu¨ Lutton on the phone uepicteu in the emulatoi to let the usei
enu the simulateu phone call.
Exploring the Phone Code Through the Debugger
Ve will use the Eclipse ueLuggei, set Lieakpoints, anu inspect class memLeis in the
iunning application to oLseive what is going on insiue this example. The use ol the
ueLuggei with Nnuioiu is uesciiLeu in Chaptei 5. Il you have not useu a ueLuggei
Leloie, uon`t woiiy: we will use a limiteu set ol ueLugging capaLilities heie to oLseive
a piogiam that woiks coiiectly. ]ust lollow the steps in this section anu let the ueLuggei
show you what is happening.
Fiist, we will set a Lieakpoint wheie we want to stait oLseiving what is happening
insiue the application. To set a Lieakpoint, uouLle-click on the lelt maigin ol the view
that shows the piogiam coue in Eclipse. N Llue uot will appeai. Il you change youi
280 | Chapter 14:ಗSimple Phone Calls
minu anu ueciue not to inseit a Lieakpoint, uouLle-click again on the Llue uot, anu it
will uisappeai.
Nll we want is to stop execution ol the piogiam at the point wheie we want to stait
inspecting what happens to the memLeis ol this instance ol the dialing class. To uo
this, set a Lieakpoint on line 21 ol the piogiam. You can tell which line you aie on Ly
clicking a line in the piogiam. In the status Lai at the Lottom ol the Eclipse winuow,
you will see two numLeis sepaiateu Ly a colon. The liist numLei is the line numLei
wheie you just clickeu, anu the seconu numLei is the chaiactei position on that line
wheie the inseition point is iight now.
Stait the application with the ueLuggei Ly selecting Run ൺ DeLug, anu when the
¨DeLug as¨ uialog appeais, select Nnuioiu Npplication.
The piogiam will stop at the Lieakpoint, altei the Nnuioiu emulatoi appeais on youi
scieen Lut Leloie the appeaiance ol the uialei shown in Figuie 1+-2. Eclipse will switch
to a dcbug pcrspcctivc: a set ol views conliguieu loi ueLugging a piogiam insteau ol
euiting it. Eclipse will ask il you want to switch peispectives the liist time you iun the
Iigurc 11-2. Dia|cr starts
Exploring the Phone Code Through the Debugger | 281
ueLuggei; you can save youi answei il you want Eclipse to uo the same thing each time
you stait ueLugging.
In the ueLug peispective, the view uisplaying the piogiam coue will show a small aiiow
oveilapping the Llue uot in the lelt maigin. This line ol coue will Le highlighteu. The
piogiam has stoppeu Leloie executing the ]ava Lytecoues coiiesponuing to the ]ava
souice coue on this line ol the piogiam.
Figuie 1+-3 shows the Eclipse winuow in ueLug peispective with contents similai to
those that shoulu appeai on youi scieen. The main inloimation to look loi is that the
piogiam stoppeu executing on the line wheie you set the Lieakpoint.
Creating an Instance of an Intent
The line ol coue wheie the piogiam stoppeu in the pievious section looks like this:
Intent callIntent = new Intent(Intent.ACTION_CALL);
This cieates an instance ol the Intent class. Use the ¨step ovei¨ commanu to execute
this line, Ly selecting the Run ൺStep Ovei option liom the menu oi any ol the shoitcuts
availaLle in Eclipse.
Iigurc 11-3. Ec|ipsc dcbuggcr stoppcd in ca|| ncthod
282 | Chapter 14:ಗSimple Phone Calls
¨Step ovei¨ uoes not mean ¨skip.¨ Insteau, it tells the ueLuggei to iun
the entiie line ol coue anu all the methou calls it contains (the Intent
constiuctoi, in this case) insteau ol enteiing the methou calls anu going
thiough them line Ly line. It isn`t uselul to see the inteinals ol the Intent
constiuctoi. So ¨step ovei¨ cieates the Intent anu piesents you with the
next line ol youi own coue.
The ueLuggei also has commanus loi ¨stepping into¨ methous anu
¨stepping out¨ ol the methou cuiiently Leing executeu. These com-
manus aie moie convenient than setting moie Lieakpoints anu using
the Resume commanu.
Now that we have useu the new opeiatoi anu the Intent constiuctoi with an aigument
that specilies we want to initialize the Intent with the Intent.ACTION_CALL constant, we
have an instance ol the Intent class. The action we use, ACTION_CALL, will enaLle Nn-
uioiu to linu PhoneNpp oi any othei piogiam the usei may install that olleis the
ACTION_CALL action.
Let`s take a look insiue Ly enteiing the VaiiaLles view in Eclipse. You will see two
columns in this view. The liist column shows the names ol the vaiiaLles, anu the seconu
column shows theii values. In oui case, the names ielei to instances ol classes, anu the
values consist ol the class name anu the ID ol the instance.
That`s not veiy inloimative! Let`s look insiue these instances anu see what they contain.
Click on the tiiangle icon in the lelt maigin next to the vaiiaLle nameu callIntent.
Now you see all the memLeis ol the Intent class anu the values loi this instance ol the
Intent class. The only memLei that has a nonuelault value is mAction. Its value is the
stiing "android.intent.action.CALL". This is the iesult ol calling the Intent class`s
constiuctoi with the aigument we useu.
Adding Data to an Instance of an Intent
So lai, oui instance ol the Intent class has enough inloimation to tell the Nnuioiu
system we want to stait a phone call, Lut not enough to tell it what numLei to call.
Nltei cieating the Intent instance with the inloimation that means ¨we want to call a
numLei,¨ in the next line we will auu to it the numLei to call:
callIntent.setData(Uri.parse("tel:9785551212"));
Two things happen on this line ol coue: an instance ol a Uri is cieateu, anu we use that
instance as an aigument to the setData methou ol the Intent class. Step ovei this line
ol coue, anu then let`s see what happens to the vaiiaLles we aie inspecting.
Look at the VaiiaLle view in Eclipse anu you will see that the mData memLei ol this
instance ol the Intent now ieleis to the instance ol Uri that was ietuineu liom the paise
methou ol the Uri class. Nnu il you click on the tiiangle icon next to ¨mData¨, you will
see the memLeis ol the Uri class, incluuing the uriString memLei that ieleis to the
Exploring the Phone Code Through the Debugger | 283
stiing tel:9785551212. Now oui instance ol the Intent class contains all the inloimation
we neeu to stait a phone call.
Vhy use a URI? Nll moLile numLeis conloim to the E.16+ stanuaiu, so why not use a
String oLject containing a valiu E.16+ numLei? N URI has the auvantage ol geneiality.
Nll paits ol Nnuioiu aie ieplaceaLle anu the components ol Nnuioiu that hanule this
paiticulai Intent oLject coulu Le augmenteu oi ieplaceu Ly a mouule that can also
connect VoIP calls with SIP URIs oi Gmail auuiesses.
Initiating a Phone Call
The next line in oui piogiam looks like this:
startActivity(callIntent);
This looks like we want to stait an Nctivity, using the Intent oLject we cieateu. But
why uon`t we neeu to specily an instance, oi even a class, when we call
startActivity? Because oui piogiam is an instance ol the Activity class. Ve aie calling
a methou ol the class this oLject is an instance ol. Ve coulu have useu the lollowing
insteau:
this.startActivity(callIntent);
Oui piogiam is alieauy an Nctivity, Lut we now want to stait a new instance ol the
Activity class÷one that can hanule the Intent instance we cieateu. The Nnuioiu
liamewoik hanules the call Ly seaiching loi an Intent that matches oui ieguest loi
ACTION_CALL. Let`s step ovei this line anu see what happens.
Now the aiiow in the lelt maigin ol the coue view points to the last line ol the call
methou, just Leloie the methou ietuins. The emulatoi winuow shows the Nnuioiu call
status application uisplaying the numLei we specilieu. It shoulu look like Fig-
uie 1+-2, shown eailiei in this chaptei.
The lact that we steppeu ovei this line ol coue anu can now continue executing oui
piogiam means that making a phone call this way is asynchionous: it allows oui pio-
giam to continue iunning while the uialei piogiam makes the phone call.
Nnuioiu is a collection ol applications, anu the application you aie ueLugging places
no iestiictions on othei applications that can Le iunning at the same time.
Exception Handling
Vhat il something goes wiong? The coue in the call methou that staits the uialei is
wiappeu in a tiy/catch Llock. The catch statement contains a line ol coue that logs an
eiioi il the startActivity methou thiows an exception ol the type ActivityNot
FoundException. Il a methou can thiow an exception that inuicates an eiioi, the call to
that methou shoulu Le in a tiy/catch Llock that catches that type ol exception. In this
case, we use Nnuioiu`s logging lacility to iecoiu the eiioi.
284 | Chapter 14:ಗSimple Phone Calls
Ve uo not catch all exceptions, Lecause unexpecteu exceptions inuicate
lailuies a piogiam cannot, in geneial, iecovei liom.
Let`s make an exception happen. Ve can uo this Ly iemoving pait ol the uata neeueu
to have the startActivity methou call woik coiiectly. Comment out line 22 ol the
coue, as shown:
// callIntent.setData(Uri.parse("tel:9785551212"));
Now make some changes to Lieakpoints. Cleai the Lieakpoint on line 21, anu set a
Lieakpoint on line 25, wheie, in the catch clause, the methou ol the Log class is calleu
to log the caught exception. Use the Run ൺDeLug commanu again to stait the piogiam.
This time you will see execution stop at the new Lieakpoint you set. You will also see
that an exception has Leen thiown. The DeLug view in Eclipse shows a stac| bac|-
tracc, a list ol all the methous calleu when the exception was thiown. The VaiiaLles
view shows that activityException now ieleis to the exception that was thiown. Look
at the memLeis ol the exception to see the inloimation this exception pioviues.
Il you examine the exception that was thiown (you can uo this Ly hoveiing youi mouse
ovei activityException) you will see that the explanation loi the exception ieaus ¨No
activity lounu to hanule intent.¨ That is, in the case ol an Intent oLject cieateu with
Intent.ACTION_CALL as the aigument to the constiuctoi, it also neeus the uata ol the
Intent to Le set coiiectly in oiuei to linu an activity to piocess that Intent.
Android Application-Level Modularity and Telephony
Getting mouulaiity iight is uillicult. In the case ol Nnuioiu, the pioLlem is especially
uillicult: moLile phones weie not uesigneu to have ieplaceaLle soltwaie components,
Lut Nnuioiu is all aLout ieplaceaLle, mouulai paits. Eveiy pait ol the Nnuioiu appli-
cation enviionment, even coie components that hanule phone calls anu talk to the
moLile iauio, can Le ieplaceu Ly coue you can wiite.
How uo you avoiu peiplexing piogiam authois with too much complexity managing
the inteilaces anu the veisions ol the inteilaces Letween mouules? The moLile iauio in
a hanuset has a paiticulaily complex inteilace. In auuition to the oLvious lunctionality
loi staiting anu enuing phone calls anu iepoiting state anu eiioi conuitions, it also
encompasses ciitical lunctions such as emeigency calls, anu oLscuie lunctions such as
¨MMI coues¨ that enaLle useis to access leatuies ol the phone anu moLile netwoik
thiough special uialing stiings.
Nnuioiu pioviues a piactical, usaLle, anu llexiLle system loi mouulaiity loi telephony
applications. It uses the Nnuioiu system ol Intent oLjects anu activities that listen loi
Intent oLjects that inuicate they shoulu hanule a paiticulai ieguest. In this case, we
see that the Intent class anu the activities anu uata you neeu to specily when making
Android Application-Level Modularity and Telephony | 285
a phone call aie easy to use. Ve also see that application-level mouulaiity is a Loon to
piacticality: Lecause you uon`t neeu to tiack the innei woikings ol a phone call÷
PhoneNpp uoes it loi you.
Nnuioiu uoes all ol this without ieplacing, mouilying, oi auuing ieguiiements to the
mouulaiity tools pioviueu Ly ]ava. You still have class liLiaiies, iellection, anu othei
tools loi making anu using existing ]ava soltwaie mouules.
In the next chaptei, you will see what happens insiue ol Nnuioiu`s telephony soltwaie,
all the way uown to how the moLile iauio is commanueu to stait a phone call.
286 | Chapter 14:ಗSimple Phone Calls
CHAPTER 15
Telephony State Information and
Android Telephony Classes
The pievious chaptei showeu how to use Nnuioiu`s Luilt-in PhoneNpp application,
which simplilies the task ol placing ol phone calls. This chaptei shows you how to get
moie inloimation aLout telephone seivice anu the actual calls you make.
Nltei an example that puts one ol the telephony leatuies to use, we`ll piesent a shoit
guiue to PhoneNpp inteinals.
Ve use the teim ¨telephony¨ to ielei to the paits ol the Nnuioiu system
that uepenu on a iauio communicating with the puLlic lanu moLile
netwoik (PLMN) to pioviue communication anu location lunctions.
Shaiing the use ol this iauio among multiple applications is a key goal
loi Nnuioiu`s telephony mouules.
Operations Offered by the android.telephony Package
The android.telephony package contains a set ol classes that can Le useu Ly any ap-
plication in the Nnuioiu enviionment to monitoi the state ol Nnuioiu`s moLile netwoik
connection. It also contains classes loi locating a uevice using the moLile netwoik.
Finally, it olleis utility classes loi paising, loimatting, anu otheiwise managing phone
numLeis, although theie is no aichitectuial Lenelit to locating those classes in this
package.
The telephony package uoes not allow you to place, enu, oi otheiwise meuule in phone
calls; it locuses on ietiieving inloimation anu giving useis an inteilace to euit telephone
numLeis. Ve`ll explain latei why Nnuioiu ieseives the actual contiol ovei phone calls
to PhoneNpp.
287
Package Summary
The android.telephony package contains the lollowing packages:
CellLocation
Methous to ieguest location inloimation.
PhoneNumberFormattingTextWatcher
CallLack methous that notily an application aLout changes to phone numLeis
themselves. Vhen useu with a TextView oLject, it loimats the text as a phone num-
Lei using methous in the PhoneNumberUtils class.
PhoneNumberUtils
N utility class that contains methous loi piocessing stiings containing phone
numLeis.
PhoneStateListener
CallLack methous that tiack changes in the state ol the moLile netwoik connection,
the call, oi othei telephony oLjects.
ServiceState
Methous that ietuin inloimation aLout the cuiient moLile netwoik seivice pio-
viuei anu the availaLility ol seivice.
TelephonyManager
Methous that pioviue inloimation aLout the state ol moLile seivice, the call state,
the SIM, the netwoik, the suLsciiLei to the moLile seivice, voicemail, anu othei
ielateu inloimation.
Because these classes uon`t contiol haiuwaie oi change state inloimation aLout phone
calls, they uon`t have any access contiol.
Limitations on What Applications Can Do with the Phone
Some ieaueis may Le uisappointeu to see that the android.telephony package limits
theii access to getting inloimation, anu uoes not pioviue uiiect contiol ovei the uialei
oi the state ol a call. Theie aie goou ieasons loi this. Essentially, pioviuing a low-level
telephony NPI that can Le shaieu among multiple applications is peiilous.
N moLile hanuset is a state machine that keeps tiack ol the moLile iauio iepoits, pio-
viues auuiLle call state inuications to the usei, anu enaLles the usei to pioviue inputs
that mouily that state. Even il you coulu uesign an NPI that woulu, hypothetically, shaie
a moLile iauio among multiple applications on a pei-call Lasis, the usei inteilace anu
eigonomic uesign that woulu go along with shaieu contiol among multiple applications
woulu Le uillicult anu pioLaLly even intiactaLle. N phone is not like a PC with a uesktop
usei inteilace: you can`t shaie contiol ovei the paits ol a uevice that constitute the
phone the way you can shaie the scieen ol a PC.
Nnuioiu pioviues a woikaLle solution that keeps telephony usaLle while making as
much ol the system open to youi applications as is piacticaLle. Ns we saw in the
288 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
pievious chaptei, PhoneNpp exposes an Intent that lets othei applications initiate
phone calls, while enaLling a single application to contiol the moLile iauio in an Nn-
uioiu hanuset. The android.telephony package luithei exposes inloimation aLout tel-
ephone seivice anu the calls maue Ly an application.
It`s uselul to think ol telephony on Nnuioiu as an inteilace that keeps ciitical lunctions
piivate while pioviuing puLlic NPIs loi lunctions wheie it is sale to uo so. This is a goou
example ol a successlul Nnuioiu uesign stiategy.
Example: Determining the State of a Call
This section shows how to tiack the state ol a phone call. It auus some ol the classes
uesciiLeu in the pievious section to the application shown in ¨Cieating an Example
Npplication to Run the call Methou¨ on page 278, which linus anu uses PhoneNpp to
stait anu contiol a phone call. Heie, in auuition to staiting a phone call anu letting
PhoneNpp contiol it, the application gets some inloimation aLout the call as it is
happening.
In oiuei to get this inloimation, we neeu to extenu the PhoneStateListener class, make
an instance ol oui suLclass, anu pass that instance to the TelephonyManager.listen
methou. Example 15-1 shows the coue loi oui suLclass ol the PhoneStateListener class.
Exanp|c 15-1. Dcfining a Listcncr for tc|cphonc ca|| statc
private class ListenToPhoneState extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("telephony-example", "State changed: " + stateName(state));
}
String stateName(int state) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: return "Idle";
case TelephonyManager.CALL_STATE_OFFHOOK: return "Off hook";
case TelephonyManager.CALL_STATE_RINGING: return "Ringing";
}
return Integer.toString(state);
}
}
The lines we`ve highlighteu aie:
Oveiiiues the onCallStateChanged methou ol the PhoneStateListener class.
Nuus a message to Nnuioiu`s log whenevei the state changes.
Chooses meaninglul stiings to iepiesent call states.
In this suLclass ol the PhoneStateListener class, we oveiiiue the onCallStateChanged
methou, which Nnuioiu calls when a call`s state changes. Ve use the Log class, a static
Operations Offered by the android.telephony Package | 289
class with utility methous loi logging inloimation, to log the changes as Nnuioiu passes
them to us.
Finally, oui stateName methou uecoues the states that coiiesponu to the constants ue-
lineu in the TelephonyManager class to make the log moie ieauaLle.
Retuining to oui main application liom ¨Cieating an Example Npplication to Run the
call Methou¨ on page 278, we have to change it Ly cieating a Listenei anu assigning
oui suLclass ol PhoneStateListener to it. Heie is the coue loi the entiie mouilieu ex-
ample application, which now tiacks anu logs state tiansitions:
package example.telephony;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class telephonyExplorer extends Activity {
ListenToPhoneState listener;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
call();
}
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:9785551212"));
startActivity(callIntent);
TelephonyManager tManager = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
listener = new ListenToPhoneState();
tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (ActivityNotFoundException activityException) {
Log.e("telephony-example", "Call failed", activityException);
}
}
private class ListenToPhoneState extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("telephony-example", "State changed: " + stateName(state));
}
290 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
String stateName(int state) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: return "Idle";
case TelephonyManager.CALL_STATE_OFFHOOK: return "Off hook";
case TelephonyManager.CALL_STATE_RINGING: return "Ringing";
}
return Integer.toString(state);
}
}
}
The lines we`ve highlighteu aie:
New classes that must Le impoiteu to auu a Listenei loi the telephone call state.
Nuus a uelinition loi the Listenei.
Connects to Nnuioiu`s telephone call managei.
Nssigns oui extenueu Listener class (uelineu at item 5) to the vaiiaLle uelineu in
item 2.
Coue liom Example 15-1, uelining oui Listenei.
Running this application iesults in output to the log winuow in Eclipse that shoulu
look something like this:
11-19 01:47:03.704: INFO/telephony-example(159): State changed: Idle
11-19 01:47:04.774: INFO/telephony-example(159): State changed: Off hook
Android Telephony Internals
The iest ol this chaptei coveis telephony-ielateu classes in the inteinals package that
only PhoneNpp uses, android.internal.telephony. This package is layeieu ovei an im-
plementation ol telephony inteinals loi a paiticulai telephony technology, such as GSM
oi CDMN. That layei, in tuin, communicates with a Rauio Inteilace Layei (RIL) that
is implementeu as a uaemon in Nnuioiu.
Figuie 15-1 shows the aichitectuie ol the Nnuioiu telephony system. PhoneNpp sup-
poits an Intent that enaLles othei applications to stait phone calls. The Telephony
Managei is availaLle thiough Listeneis, as shown in the pievious section.
Inter-Process Communication and AIDL in the
android.internal.telephony Package
Many ol the inteinal packages use the iemote methous leatuie uiscusseu in ¨Remote
Methous anu NIDL¨ on page 265. The TelephonyManager anu PhoneStateListener
classes iely on this to communicate with PhoneNpp. The ServiceManager class is also
useu.
Android Telephony Internals | 291
To maishall uata loi iemote methous, the package incluues NIDL liles. Foi instance,
the lollowing NIDL comes liom |PhoncStatcListcncr.aid|:
oneway interface IPhoneStateListener {
void onServiceStateChanged(in ServiceState serviceState);
void onSignalStrengthChanged(int asu);
void onMessageWaitingIndicatorChanged(boolean mwi);
void onCallForwardingIndicatorChanged(boolean cfi);
// we use bundle here instead of CellLocation so it can get the right subclass
void onCellLocationChanged(in Bundle location);
void onCallStateChanged(int state, String incomingNumber);
void onDataConnectionStateChanged(int state);
void onDataActivity(int direction);
}
The android.internal.telephony Package
This package contains the classes anu inteilaces PhoneNpp uses to pioviue seivices to
othei applications that want to stait phone calls, anu classes that ueline an NPI to the
RIL.
PhoneNpp, like all paits ol Nnuioiu, is theoietically ieplaceaLle. Il youi application
neeus to mouily the classes useu Ly PhoneNpp, youi application will pioLaLly have to
ieplace oi mouily PhoneNpp, anu shoulu pioviue the same seivices to othei applica-
tions, using the classes in this package.
PhoneApp
Internal telephony API
GSM telephony implementation
RIL
GSM RIL library
Iigurc 15-1. Laycrs of tc|cphony pac|agcs
292 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
The uesciiption ol these classes shoulu help you unueistanu how Nnuioiu inteilaces
to a moLile iauio, anu the capaLilities that aie exposeu÷anu not exposeu÷Ly
PhoneNpp to othei applications. This is a laige anu complex package, anu a complete
unueistanuing will ieguiie ieauing the Nnuioiu souice coue. These uesciiptions will
help you linu wheie to stait loi youi puiposes:
ATParseEx
Extenus RuntimeException anu is thiown Ly methous ol the ATResponseParser
class.
ATResponseParser
This class paises pait ol the NT commanu syntax useu to communicate with the
moLile iauio haiuwaie in a moLile hanuset. This is, in lact, a commanu syntax veiy
much like the NT commanu syntax useu Ly mouems, a stanuaiu uesciiLeu in the
3GPP uocument numLei TS 27.007 anu ielateu specilications. This piotocol loi
contiolling moLile iauios is wiuely useu.
Call
This class is an aLstiact Lase class. Othei classes use it as a Lasis loi oLjects that
iepiesent phone calls anu the state ol those calls.
CallerInfo
This class holus inloimation aLout the paity that oiiginateu an incoming call. This
class staits with callei ID inloimation liom the moLile netwoik inteilace anu looks
up othei inloimation aLout a callei in the uataLase ol contacts.
CallerInfoAsyncQuery
This class enaLles asynchionous uataLase gueiies loi inloimation that coulu Le
lounu aLout a callei Laseu on the callei ID inloimation.
CallStateException
The class extenus Exception anu is thiown Ly methous that maintain call state in
cases wheie state is inconsistent.
Connection
This class is an aLstiact Lase class useu Ly othei classes, anu is a Lasis loi oLjects
that iepiesent connections on the moLile netwoik anu the state ol these connec-
tions. Connection oLjects can Le associateu with a Call oLject, Lut they can also
exist inuepenuently. The uata in a Connection oLject can Le especially uselul in
uiagnosing the ieason a call laileu.
DefaultPhoneNotifier
This class implements the PhoneNotiliei inteilace in oiuei to ieceive notilications
liom a Phone oLject. It then uses the Nnuioiu seivice system to communicate state
to Nctivity instances that have iegisteieu to ieceive those notilications. See the
Handler anu Mailbox classes loi inloimation on how to ieceive notilications.
Android Telephony Internals | 293
IPhoneStateListener
This inteilace uelines the signatuies ol methous an application implements to ie-
ceive notilication ol call state change, anu changes to loiwaiuing anu message-
waiting states.
IPhoneSubInfo
This inteilace is useu to oLtain suLsciiLei inloimation.
ITelephony
This inteilace uelines the intei-piocess inteilace useu in TelephonyManagei to
enaLle applications to communicate with PhoneNpp.
ITelephonyRegistry
This inteilace is the callLack inteilace liom the RIL uaemon.
MmiCode
This inteilace uelines callLacks ielateu to ¨MMI coues.¨ These aie special numLeis
a usei can uial anu key seguences that a usei can entei uuiing a call to access,
contiol, anu auministei supplementaiy seivices, such as call waiting, call holu, etc.
MMI coues anu ielateu lunctionality aie uesciiLeu in the 3GPP uocument numLei
TS 22.030.
Phone
This inteilace incluues callLacks anu methous loi accessing the state ol a moLile
phone.
PhoneBase
This class is an aLstiact Lase class that implements the Phone inteilace.
PhoneFactory
This class contains methous useu to cieate instances ol the GSMPhone class, a suL-
class ol the Phone class.
PhoneNotifier
This inteilace specilies the NPI a telephony implementation uses to notily a phone
state listenei ol state changes.
PhoneStateIntentReceiver
This class hanules Intent oLjects that have intent types specilieu in the
TelephonyIntents class. This class enaLles Nnuioiu applications to use the Intents
system to oLtain phone state inloimation.
PhoneSubInfo
This class contains methous loi oLtaining inloimation aLout a moLile seivice suL-
sciiLei, such as the unigue iuentilying numLei loi the hanuset (IMEI), the unigue
iuentilying numLei loi the suLsciiLei (IMSI), the seiial numLei ol the SIM caiu, etc.
SimCard
This inteilace uelines the NPI loi accessing the SIM caiu.
294 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
TelephonyIntents
This class uelines constants loi Lioaucast intents that have similai lunctionality to
the TelephonyManagei NPI.
TelephonyProperties
This class uelines the constants useu with the SystemProperties class loi setting
anu getting telephony-ielateu piopeities.
These classes aie not uocumenteu in the Nnuioiu SDK uocumentation, Lut the ue-
sciiptions heie shoulu give you some unueistanuing ol the souice coue loi these classes.
The android.internal.telephony.gsm Package
Many ol the classes anu inteilaces in the pievious section aie typical ol a ]ava NPI that
can have multiple implementations. The implementations ol the NPI uelineu in the
telephony.internal package coiiesponu to a liLiaiy useu in the RIL. To Lettei unuei-
stanu this NPI, we will look at one implementation heie that suppoits GSM.
Thus, this section uelves luithei into the telephony inteinals ol Nnuioiu, looking es-
pecially at how the inteilaces anu aLstiact Lase classes aie implementeu anu suLclasseu
to enaLle access to the lunctionality ol GSM telephony. Nlthough it may seem that
specilications such as TS 27.007 covei moLile telephony in geneial, this layei ol Nn-
uioiu actually has to accommouate vaiiations in moLile telephony stanuaius. In CDMN
telephony, loi instance, the SIM caiu is an optional pait ol the stanuaiu anu is iaiely
piesent in CDMN hanusets. In this case, the package uesciiLeu in this section woulu
Le ieplaceu Ly a CDMN-oiienteu package with a similai aichitectuial ielationship to
the highei-level classes uesciiLeu in the pievious section. The RIL coue is also specilic
to the type ol telephony in the hanuset.
Nt the RIL layei, the uilleiences Letween GSM anu CDMN aie mainly outsiue the coie
lunctionality ol making phone calls, so you may Le wonueiing why all these layeis anu
NPIs aie necessaiy. But, as the uesciiption ol the classes specilic to communicating with
a GSM RIL will show, theie aie plenty ol uilleiences in uetail, such as SIM caius, the
type ol moLile uata netwoik, etc. These make it impiactical to uesign a univeisal in-
teilace to moLile iauios, uespite the use ol a stanuaiu piotocol loi communicating with
them:
AdnRecord
This class is useu to loau anu stoie NLLieviateu Dialing NumLeis (NDNs) to anu
liom the SIM caiu. NDNs aie shoit numLeis useu loi inloimation calls, emeigency
calls, etc.
AdnRecordCache
This class caches anu enaLles access to NDNs.
Android Telephony Internals | 295
ApnSetting
This class holus uata specilying the access point name (NPN) anu othei paiameteis
loi connecting to Geneial Packet Rauio Seivice (GPRS) anu 3G moLile uata net-
woiks. This moLile uata technology is specilic to GSM netwoiks.
BaseCommands
This class implements the CommanusInteilace inteilace, which is useu thioughout
the GSM telephony classes to communicate with the GSM iauio.
CallFailCause
This inteilace uelines constants loi uecouing lailuie cause coues.
CallForwardInfo
This class holus uata that coiiesponus to the paiameteis ol a call-loiwaiuing com-
manu to the RIL.
CallTracker
This class maps inloimation liom the RIL to state tiansitions loi the GSMCall class.
CommandException
This class is an exception thiown when the RIL iepoits an eiioi liom a commanu.
CommandsInterface
This inteilace uelines the NPI to the GSM RIL. This inteilace is implementeu Ly
the BaseCommands class.
DataConnectionTracker
This tiacks the state ol GPRS packet uata piotocol (PDP) connections. This type
ol connection is specilic to GSM moLile uata.
DataLink
This class implements the DataLinkInteilace inteilace anu is useu in the PPPLink
class, which manages point to point piotocol (PPP) links in GPRS netwoiking.
DataLinkInterface
This class uelines the NPI loi connecting anu uisconnecting PPP links.
DriverCall
This class paises inloimation, in NT commanu syntax, liom the moLile iauio, anu
tuins it into call state inloimation.
EncodeException
This class is an exception thiown Ly methous ol the GSM alphaLet class, which
encoues UTF-16 (as useu in ]ava) into the 7-Lit SMS chaiactei set.
GSMAlphabet
This class is a utility class containing static methous loi encouing UTF-16 to the
7-Lit SMS chaiactei set.
GSMCall
This class extenus the Call class, anu implements the aLstiact methous ol that
class, theieLy implementing paits ol the Nnuioiu telephony inteinals NPI. This
class mouels calls in GSM telephony.
296 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
GSMConnection
This class extenus the Connection class, anu like the GSMCall class, implements the
aLstiact methous ol the Connection class. This class mouels connections in GSM
telephony.
GSMPhone
This class extenus the Phone class anu, as with Loth the GSMCall anu
GSMConnection classes, implements the aLstiact methous ol the Phone class.
GsmMmiCode
This class implements the MmiCoue inteilace anu the pait ol the telephony NPI
uelineu in that inteilace.
GsmSimCard
This class implements the SimCaiu inteilace, anothei pait ol the implementation
ol the telephony inteinals NPI. This class enaLles access to uata in the SIM caiu.
ISimPhoneBook
This inteilace uelines an NPI loi accessing NDN iecoius stoieu in the SIM caiu.
ISms
This inteilace uelines the NPI loi senuing SMS messages.
MccTable
This class is a utility class that contains a taLle ol MoLile Countiy Coues (MCCs).
In piinciple, these coues aie not specilic to a GSM RIL, Lut they aie specilic to this
implementation ol a GSM RIL.
NetworkInfo
This class is a containei loi netwoik state inloimation.
PDPContextState
This contains uata aLout a PDP session, incluuing the IP auuiess.
PdpConnection
This class contains inloimation aLout the uata connection associateu with a PDP
context.
PppLink
This class extenus DataLink anu implements DataLinkInteilace to pioviue an
implementation ol this pait ol the RIL inteilace.
RIL
This class extenus the BaseCommands class anu also implements the
CommanusInteilace inteilace, loiming a complete implementation ol the inteilace
loi senuing commanus to the RIL. This is wheie communication with the RIL takes
place. Nn instance ol the RIL class is cieateu in the PhoneFactory class, in the couise
ol cieating an instance ol the GSMPhone class.
RILConstants
This inteilace uelines constants useu in the RIL class.
Android Telephony Internals | 297
ServiceStateTracker
This class polls the RIL uaemon loi signal stiength anu tiacks othei aspects ol the
state ol moLile seivice.
SIMFileHandler
This enaLles access to the SIM lilesystem.
SIMRecords
This class enaLles access to specilic liles in the SIM lilesystem containing inloi-
mation such as the suLsciiLei`s IMSI.
SimConstants
This inteilace contains constants useu in othei classes accessing uata in the SIM.
SimException
This class extenus Exception anu is useu in othei classes to thiow an exception
ielateu to eiiois accessing uata in the SIM.
SimFileNotFound
This class extenus SimException anu is useu in the SimIoResult class in specilic eiioi
conuitions.
SimPhoneBookInterfaceManager
This class extenus ISimPhoneBook anu pioviues a seivice inteilace loi accessing
NDN iecoius in the SIM.
SimProvider
This class extenus ContentProvider anu cieates a content pioviuei inteilace to SIM
NDN/SDN/FDN iecoius in the SIM.
SimSmsInterfaceManager
This class extenus ISms anu cieates a seivice inteilace loi accessing SMS messages
stoieu in the SIM.
SimTlv
This class is an oLject inteilace loi accessing tag-length-value iecoius in the SIM,
anu is useu in the SIMRecords class.
SimUtils
This class contains static utility methous loi manipulating uata encoueu in
Linaiy-coueu uecimal anu othei encouings encounteieu in SIM uata.
SMSDispatcher
This class implements the senuing ol SMS messages anu notilies applications that
use the Hanulei inteilace to this class iegaiuing the status ol SMS messages.
SmsHeader
This class contains constants anu methous loi uecouing SMS heaueis.
SmsRawData
This class implements PaicelaLle anu is useu in implementing seivice inteilaces loi
accessing SIM uata.
298 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
SmsResponse
This class associates a message ieleience with an acknowleugment.
SuppServiceNotification
This class contains constants loi uecouing inloimation aLout supplementaiy
seivices.
VoiceMailConstants
This class paises inloimation in the ctc/voiccnai|-conf.xn| fi|c.
Theie is anothei package oiganizeu hieiaichically unuei the internal.telephony.gsm
package: the stk package, which contains classes loi accessing the SIM. This package
is not exposeu outsiue the internal.telephony.gsm package anu is Leyonu the scope ol
this chaptei.
Exploring Android Telephony Internals
N lot ol coue lies Letween cieating an ACTION_CALL Intent oLject anu uialing a call. Heie
we will go even ueepei into Nnuioiu`s telephony system to see what Nnuioiu is telling
the moLile iauio, anu match that up with what we have uone in the example application
eailiei in this chaptei.
To see how, anu when, Nnuioiu actually commanus the haiuwaie to uial a numLei,
we can use Nnuioiu`s logging system. To access the log Lullei loi inloimation aLout
the tiallic Letween Nnuioiu soltwaie anu the moLile iauio, we will also have to use the
Nnuioiu DeLug Biiuge, adb. Ve will stait a shell that can iun commanus in the emu-
latoi, anu we will use the logcat utility to uisplay logging inloimation as it Lecomes
availaLle.
Fiist, set a Lieakpoint in the example application on line 25, wheie the Intent oLject
is cieateu anu Leloie the call to the startActivity methou.
Then, stait the application with the ueLuggei: Select Run ൺDeLug. Vhen the ¨DeLug
as¨ uialog appeais, select Nnuioiu Npplication.
The application will iun anu stop at the Lieakpoint.
Now look at the log. Open a commanu-line winuow anu change youi woiking uiiectoiy
to the uiiectoiy wheie you have put the Nnuioiu SDK. Theie you shoulu see a uiiectoiy
nameu too|s. Change youi woiking uiiectoiy to too|s. You shoulu see a piogiam theie
nameu adb.
Next, use adb to linu the name ol the emulatoi that is iunning as a iesult ol staiting the
application with the ueLuggei. Type the lollowing:
./adb devices
adb will list all the emulatois iunning, which shoulu Le just one. The output will look
something like this:
Android Telephony Internals | 299
...
emulator-5554 device
Now use adb to stait a shell that can iun piogiams in the emulatoi (il adb linus
an emulatoi with a uilleient name on youi system, use that name insteau ol
¨emulatoi-555+¨):
./adb -s emulator-5554 shell
This will iesult in a shell piompt:
#
The shell you aie now typing commanus into is executing those commanus in the
emulatoi. Now use the logcat commanu to show the log ol tiallic Letween the moLile
iauio anu the RIL:
# logcat -b radio
This will iesult in a lengthy listing ol NT commanus anu iesponses. Foi the most pait,
they aie asking loi anu iepoiting the signal stiength. This is what the RIL anu the moLile
iauio aie uoing when nothing else is going on.
The lines taggeu D/AT aie the veiLatim NT commanus exchangeu Letween the moLile
iauio anu the RIL. The ones laLeleu AT> aie liom the RIL to the moLile iauio, anu the
ones laLeleu AT< aie liom the moLile iauio to the RIL. The othei lines in the log aie a
moie-ieauaLle uecouing ol the inloimation in the NT commanus. You can see the pait
ol the RIL inteilace in ]ava logging ieguests sent to the RIL uaemon, RILD, anu the
RIL coue in RILD logging as it senus the appiopiiate NT commanus to the moLile iauio
anu uecoues the iesults.
Now use the Eclipse ueLuggei to step ovei the line wheie the Intent oLject is cieateu.
Looking at the log output, you see that nothing inteiesting has happeneu yet: the RIL
anu the moLile iauio (ieally, an emulation ol a moLile iauio) aie polling the signal
stiength. Step ovei the next line, wheie the phone numLei is auueu to the Intent oLject
anu, similaily, nothing has happeneu yet.
Now step ovei the next line, which shoulu look like this:
startActivity(callIntent);
Heie we get guite a Lit ol inteiesting output liom the loggei. It shoulu look something
like this:
D/GSM ( 85): [GSMConn] update: parent=DIALING, hasNewParent=false,
wasConnectingInOrOut=true, wasHolding=false, isConnectingInOrOut=true,changed=false
D/RILJ ( 85): [0161]> SET_MUTE false
D/RIL ( 22): onRequest: SET_MUTE
D/RILJ ( 85): [0161]< SET_MUTE error:
com.android.internal.telephony.gsm.CommandException: REQUEST_NOT_SUPPORTED
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0162]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
300 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
D/AT ( 22): AT< +CLCC: 1,0,2,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0162]< GET_CURRENT_CALLS [id=1,mo,DIALING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=DIALING, hasNewParent=false,
wasConnectingInOrOut=true, wasHolding=false, isConnectingInOrOut=true, changed=false
D/AT ( 22): AT< RING
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0163]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,3,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0163]< GET_CURRENT_CALLS [id=1,mo,ALERTING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ALERTING, hasNewParent=false,
wasConnectingInOrOut=true, wasHolding=false, isConnectingInOrOut=true, changed=true
D/RILJ ( 85): [0164]> SET_MUTE false
D/RIL ( 22): onRequest: SET_MUTE
D/RILJ ( 85): [0164]< SET_MUTE error:
com.android.internal.telephony.gsm.CommandException:
REQUEST_NOT_SUPPORTED
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0165]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,3,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0165]< GET_CURRENT_CALLS [id=1,mo,ALERTING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ALERTING, hasNewParent=false,
wasConnectingInOrOut=true,
wasHolding=false, isConnectingInOrOut=true, changed=false
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0166]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,3,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0166]< GET_CURRENT_CALLS [id=1,mo,ALERTING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ALERTING, hasNewParent=false,
wasConnectingInOrOut=true,
wasHolding=false, isConnectingInOrOut=true, changed=false
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0167]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< RING
D/AT ( 22): AT< +CLCC: 1,0,0,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0167]< GET_CURRENT_CALLS [id=1,mo,ACTIVE,voice,norm,129,0]
D/RILJ ( 85): [0168]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,0,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0168]< GET_CURRENT_CALLS [id=1,mo,ACTIVE,voice,norm,129,0]
Android Telephony Internals | 301
D/GSM ( 85): [GSMConn] update: parent=ACTIVE, hasNewParent=false,
wasConnectingInOrOut=true,
wasHolding=false, isConnectingInOrOut=false, changed=true
D/GSM ( 85): [GSMConn] onConnectedInOrOut: connectTime=1225978001674
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0169]> SET_MUTE false
D/RIL ( 22): onRequest: SET_MUTE
D/RILJ ( 85): [0169]< SET_MUTE error:
com.android.internal.telephony.gsm.CommandException:
REQUEST_NOT_SUPPORTED
D/RILJ ( 85): [0170]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,0,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0170]< GET_CURRENT_CALLS [id=1,mo,ACTIVE,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ACTIVE, hasNewParent=false,
wasConnectingInOrOut=false,
wasHolding=false, isConnectingInOrOut=false, changed=false
Vhat you aie seeing heie is a moLile call Leing staiteu. The call goes thiough thiee
states: ¨uialing,¨ ¨aleiting,¨ anu ¨active.¨ Take a look at how the moLile iauio iepoits
the state ol a call. Heie the call is in the ¨uialing¨ state:
+CLCC: 1,0,2,0,0,"9785551212",129
Heie the call is in the ¨aleiting¨ state:
+CLCC: 1,0,3,0,0,"9785551212",129
Heie the call is in the ¨active¨ state:
+CLCC: 1,0,0,0,0,"9785551212",129
The thiiu numLei in the list ol paiameteis in the NT commanu iesponse inuicates the
state ol this call. The classes that mouel the connection, call, anu netwoik state in
PhoneNpp anu the TelephonyManagei NPI keep tiack ol what RILD is telling the mo-
Lile iauio anu what the moLile iauio is telling RILD, anu this is wheie that inloimation
comes liom.
Now piess the ieu Enu Lutton (the one with the pictuie ol a telephone ieceivei) to enu
the call. Look loi the NT commanus that ieau the state change liom the moLile iauio,
anu at the coiiesponuing TelephonyManager methou call that notilies the application ol
the change.
Android and VoIP
You may have come to the enu ol this uesciiption ol Nnuioiu telephony suipiiseu, anu
peihaps uisappointeu, to linu no mention ol Voice ovei IP (VoIP). Nltei all, GoogleTalk
suppoits voice calls liom PC to PC. Vhy was this capaLility omitteu liom the coie
telephony lunctionality ol Nnuioiu?
302 | Chapter 15:ಗTelephony State Information and Android Telephony Classes
Nnuioiu was not uesigneu to tieat VoIP calls anu moLile calls similaily oi, liom a
piogiammei`s peispective, thiough the same NPIs. Vhat you see uesciiLeu in this
chaptei is an aLstiaction loi moLile telephony, not telephony in geneial. NT commanus
that aie neaily univeisal in moLile telephony÷anu that aie not useu outsiue moLile
telephony÷peivaue the NPIs uesciiLeu heie all the way up to the PhoneNpp applica-
tion. The intei-piocess inteilaces aie uesigneu aiounu capaLilities ol moLile telephony,
moLile messaging, anu moLile uata.
Ns a iesult, uesigneis ol VoIP technologies loi Nnuioiu aie lelt with some uesign ueci-
sions. The cuiient uiiection tieats VoIP as a sepaiate application anu makes it possiLle
in the lutuie to pioviue a veiy high-level integiation with othei paits ol the system÷
loi example, suppoiting the ACTION_CALL call in Intent oLjects. This uevelopment
woulu give the usei a choice Letween Nnuioiu`s Luilt-in moLile telephony anu an auu-
on loi VoIP telephony.
N ueepei integiation ol moLile telephony anu VoIP can Le implementeu in Nnuioiu,
Lut it woulu ieguiie extenuing the lunctionality ol PhoneNpp to encompass Loth IP
anu conventional moLile telephony, while pioviuing a compatiLle inteilace to appli-
cations wiitten to Nnuioiu`s TelephonyManagei NPI.
Android and VoIP | 303
APPENDIX
Wireless Protocols
Il you`ie new to moLile uevelopment, the plethoia ol wiieless telephony acionyms can
Le conlusing at liist. The goou news is that, loi the most pait, you can ignoie them
Lecause you uon`t know exactly which enviionment youi application will iun in. The
Lau news is that youi application shoulu Le piepaieu to iun in a|| ol the enviionments.
To help you lollow the ueLates, stanuaius, anu uiscussions that inevitaLly aiise when
uiscussing cellulai anu wiieless technologies, this appenuix intiouuces the main pio-
tocols in histoiical oiuei.
Prehistory
Vhen moLile phones weie liist inventeu in the 19+0s, they weie just analog iauios
uiiven liom a cai Latteiy. The system was aptly nameu MoLile Telephone System
(MTS), anu it was woelully inaueguate. In spite ol the high cost ol seivice, waiting lists
to oLtain the seivice weie long Lecause MTS olleieu only a lew channels in any geog-
iaphy. Nn ¨impioveu¨ veision calleu IMTS, intiouuceu in the 1960s, helpeu some, Lut
was still lai shoit ol the uemanu.
The liist analog cellulai iauio moLile phone systems staiteu to appeai in 1969 anu the
eaily 1970s÷with phones still the size ol a Liielcase. The vaiious cellulai technologies
in Noith Nmeiica conveigeu aiounu the Nuvanceu MoLile Phone Seivice (NMPS)
stanuaiu, still analog technology Lut now Laseu on cellulai iauios that coulu ieuse the
lieguency spectium anu weie stanuaiuizeu acioss manulactuieis. Nt this time Euiope
hau no less than nine uilleient analog moLile phone technology stanuaius, one loi each
majoi iegion anu countiy in the continent.
The Dawn of Second Generation (2G) Digital Cellular
Roaming in Euiope was oLviously impossiLle. Paitly to alleviate this pioLlem, the
Euiopean opeiatois ueciueu to stanuaiuize the next geneiation ol moLile phones Ly
loiming the Euiopean Telecommunications Stanuaius Institute (ETSI). In the eaily
305
1980s, ETSI uevelopeu a uigital moLile phone stanuaiu known as GSM (oiiginally
Groupc Spccia| Mobi|c, latei GloLal System loi MoLile Communications). The GSM
stanuaiu incluueu something teimeu Shoit Message Seivice (SMS), which useu spaie
Lanuwiuth on the contiol channel to senu anu ieceive shoit 160-Lyte messages.
The GSM system anu some othei uigital cellulai stanuaius (such as the uigital successoi
to NMPS in Noith Nmeiica, D-NMPS, oi IS-5+) multiplex uilleient voice calleis on a
common iauio lieguency Ly using time uivision multiplexing (Time Division Multiple
Nccess, oi TDMN). Essentially, the signal liom each usei is iapiuly sampleu, anu sam-
ples liom uilleient useis aie inteileaveu anu Lioaucast in an assigneu time slot. The
sampleu speech is ieassemLleu at the ieceiving enu ol the signal, anu in this way mul-
tiple useis can shaie a single iauio channel.
The cellulai piotocols aie actually guite a Lit moie complex than this simple explana-
tion woulu imply. Nt the same time the iauio signal is Leing sampleu anu uesampleu,
it is also hopping aiounu to a pieset seguence ol lieguencies, anu samples aie Leing
ieoiueieu in time, all in oiuei to ieuuce moLile ellects such as inteileience, jittei, uiop-
outs, anu multipath uistoition.
In the veiy late 1980s, Qualcomm intiouuceu a new uigital system in the U.S. teimeu
CDMN, loi Coue Division Multiple Nccess (latei also calleu IS-95 anu still latei
cumaOne). Insteau ol uiviuing each voice signal into time-Laseu uivisions, CDMN
tiansmitteu all ol the signals on multiple iauio lieguencies at the same time.
But how to keep the signals liom inteileiing with each othei? In CDMN, the signals
make use ol oithogonal ¨coues¨ that ueline which ol the lieguencies aie useu loi which
signal. The signal is tiansmitteu on a numLei ol lieguencies uelineu Ly the coue, anu
can Le extiacteu on the ieceiving enu Ly sampling only those lieguencies assigneu to
this paiticulai coue. The othei signals on those same lieguencies aie aveiageu out as
noise Lecause they uon`t appeai consistently in most ol the lieguencies. CDMN pioveu
to Le much moie ellicient at spectium use than TDMN, Lut GSM hau alieauy taken
holu, anu was the moie populai stanuaiu woiluwiue.
The 2G moLile piotocols weie mainly uesigneu loi voice, Lut also pioviueu the liist
ieal channels loi uata. Nt liist the uata iates weie slow, the coveiage spotty, anu the
technology inellicient in its use ol the availaLle Lanuwiuth Lecause it was Laseu on
ciicuit switching. The optimistically nameu High Speeu Ciicuit Switcheu Data
(HSCSD) system useu multiple GSM channels anu was iateu at 28.8 to 6+ kiloLits pei
seconu, though it iaiely achieveu even a liaction ol that speeu. In the 1990s, HSCSD
was ieplaceu with the Geneial Packet Rauio System (GPRS) stanuaiu, the liist packet-
switcheu technology loi GSM.
Improved Digital Cellular (2.5G)
In the late 1990s, opeiatois coulu see that uemanu loi voice phones was satuiating.
They coulu loiesee the uay when eveiyLouy who wanteu a moLile phone woulu have
306 | Appendix:ಗWireless Protocols
one. Nt the same time, the Inteinet was Lecoming uLiguitous, anu useis weie staiting
to uemanu Lettei uata access liom theii moLile phones. Opeiatois lookeu loi ways to
expanu the uata capacity ol theii moLile netwoiks while taking auvantage ol theii ex-
isting inliastiuctuie investments. GSM opeiatois expanueu theii GSM/GPRS netwoiks
to a new stanuaiu calleu Enhanceu Data loi GSM Evolution (EDGE), which luithei
impioveu availaLle uata iates anu maue ellicient use ol GSM eguipment the opeiatois
alieauy hau installeu. CDMN opeiatois capitalizeu on similai impiovements in that
uomain, with stanuaius such as CDMN2000 1X. The theoietical uata iates weie now
in the hunuieus ol kiloLits pei seconu, though the actual uata iates weie still much
lowei. Phones iunning Nnuioiu can Le expecteu to have at least 2.5G uata connectivity.
N seconu wave ol uata access impiovement (sometimes ieleiieu to as 2.75G) luithei
impioveu uata iates, implementeu Ly High Speeu Packet Nccess (HSPN) loi GSM anu
EV-DO (EVolution Data Optimizeu, oi sometimes tianslateu as EVolution Data Only)
loi CDMN. Theoietical uata iates weie now in the multimegaLit-pei-seconu iange, anu
most Nnuioiu phones can Le expecteu to have these technologies, il not 3G.
The Rise of 3G
Nlso in the 1990s, the Euiopean telecom community staiteu uelining the next geneia-
tion ol moLile technology, liist thiough ETSI anu then thiough a new oiganization
calleu 3iu Geneiation Paitneiship Piogiam (3GPP). The stanuaiu uevelopeu Ly 3GPP
is calleu Univeisal MoLile Telecommunications Stanuaiu (UMTS), anu though Laseu
lunuamentally on ViueLanu CDMN (VCDMN) technology, was caielully uesigneu
to allow Loth GSM anu CDMN opeiatois to evolve theii netwoiks elliciently liom theii
installeu inliastiuctuie to the new stanuaiu. This woulu allow opeiatois aiounu the
woilu to conveige to a new common stanuaiu loi 3G.
'
In the eaily 2000s, opeiatois spent huge sums ol money to puichase spectium loi 3G
wiieless netwoiks. 3G netwoiks aie now Leing ueployeu woiluwiue, anu ovei the next
lew yeais, new smaitphones (incluuing Nnuioiu-Laseu phones) will all incoipoiate 3G
technologies.
The Future: 4G
So what`s next? The stanuaius Louies aie Lack at woik uelining the louith geneiation
ol wiieless netwoik piotocols, sometimes teimeu LTE (loi Long Teim Evolution). The
appaient winnei is a gioup ol piotocols calleu Oithogonal Fieguency Division Multi-
plexing (OFDM), oi sometimes OFDMN (the ¨N¨ is loi Nccess). These piotocols use
'
Except loi opeiatois in the People`s RepuLlic ol China, wheie the goveinment manuateu its own veision ol
UMTS, calleu Time Division-Synchionous Coue Division Multiple Nccess (TD-SCDMN). TD-SCDMN uses
TDMN as well as CDMN to pioviue some unigue auvantages loi uata tiallic. It also avoius the neeu loi PRC
hanuset makeis to pay ioyalties loi most VCDMN intellectual piopeity.
The Future: 4G | 307
iauio lieguency suLcaiiieis to luithei impiove the uata iates achievaLle loi wiieless
uevices. Similai piotocols aie useu in the ViMNX stanuaius (the highei Lanuwiuth,
longei-iange lollow-on to ViFi), Lut it is not cleai how ViMNX anu LTE will ielate to
one anothei.
]ust as with 3G, a iounu ol spectium auctions is staiting to take place loi +G, anu
opeiatois aie alieauy investing laige sums ol money into getting ieauy loi +G seivices.
Sullice to say that youi applications Luilt loi Nnuioiu will someuay encountei phones
iunning +G piotocols, anu will Le aLle to take auvantage ol the highei uata iates anu
lowei latencies that will come with these piotocols.
To wiap up, Figuie N-1 shows the evolution ol piotocols uiscusseu in this chaptei in
ielation to the uecaue in which they weie liist ueployeu anu the ellective Lanuwiuth
they achieve.
2010
2005
2000
1995
1990
10Kb/s 100Kb/s
HSCSD (24.2Kb–64Kb)
1M/s
Theoretical speed range (log scale)
D
e
p
l
o
y
m
e
n
t

t
i
m
e

f
r
a
m
e
10M/s 100M/s
GSM/GPRS (up to 114Kb)
CDMA/1xRTT (up to 144Kb)
GSM/Edge (up to 474Kb)
CDMA/EV-DO (400Kb–2Mb)
WCDMA/HSPA (up to 10Mb)
TD-SCDMA (up to 2MB)
WiMAX (up to 75Mb)
Iigurc A-1. Mobi|c protoco|s, bandwidth, and datcs of dcp|oyncnt
308 | Appendix:ಗWireless Protocols
Index
Symbols and Numbers
= (pounu sign)
auL shell piompt anu, 73
uelining colois, +9
(Lackslashes), escaping chaiacteis, 10+
e ampeisanu, iunning auL logcat, 73
2D giaphics, 221÷255
2G (seconu geneiation) uigital cellulais, 305
3D giaphics, 221÷255
matiix tiansloimations anu, 231
3iu Geneiation Paitneiship Piogiam (3GPP),
307
+G (louith geneiation uigital cellulais), 307
A
NLLieviateu Dialing NumLeis (see NDNs)
NLsoluteLayout, 215÷216
NCCESS¸FINE¸LOCNTION peimission, +5
NCCESS¸LOCNTION¸EXTRN¸COMMNND
S peimission, +5
NCCESS¸MOCK¸LOCNTION peimission,
+5
action attiiLute, +6
NCTION¸CNLL constant, 283, 299
VoIP anu, 303
Nctivities, 6, 103
NnuioiuManilest.xml lile anu, +5
Bunules anu, +7
class methous, 8, +6
Google Maps, 139
intei-piocess communication, 258
lilecycle ol, 8÷10
MapNctivities, pausing/iesuming anu, 1++
NotePau application, 117
<activity> tag, 1+0
Nuapteis, 192÷193
NuapteiViews, 192÷193
auL (Nnuioiu DeLug Biiuge) inteilace, 58, 71÷
7+
install commanu, 35
logcat utility, 299
phones, connecting to, +0
USB uiiveis, loauing, 39
NuLRecoiu class, 295
NuLRecoiuCache class, 295
NDNs (NLLieviateu Dialing NumLeis), 295
NDT (Nnuioiu Developei Tool), 13
ueLuggei tool, 6+÷67
installing, 17
Nuvanceu MoLile Phone Seivice (see NMPS)
NIDL (Nnuioiu`s Inteilace Delinition
Language), 257
classes, 270÷273
iemote methous anu, 265÷276
Nlliance (see Open Hanuset Nlliance)
ampeisanu (e), iunning auL logcat, 73
NMPS (Nuvanceu MoLile Phone Seivice), 305
Nnuioiu DeLug Biiuge (see auL inteilace)
Nnuioiu Developei Tool (NDT), 13
installing, 17
Nnuioiu Execution Enviionment, 5
Nnuioiu LiLiaiy, 22
Nnuioiu Maiket, 87
Nnuioiu Platloim Poiting Kit, 5
Nnuioiu Seivice Lilecycle, 10
Nnuioiu Soltwaie Development Kit (see SDK)
.anuioiu suLuiiectoiy, 93
Nnuioiu toolkit, 12
anuioiu.inteinal.telephony package, 291
Ve`u like to heai youi suggestions loi impioving oui inuexes. Senu email to indcx¿orci||y.con.
309
anuioiu.os.DeLug, 76
anuioiu.os.IInteilace class, 270
anuioiu.telephony package, 287÷291
anuioiu.view.View class, 221
anuioiu.view.ViewGioup class, 162
anuioiu:apiKey attiiLute, 50
anuioiu:authoiities attiiLute (<pioviuei>),
128
anuioiu:Lackgiounu attiiLute, +9
anuioiu:clickaLle attiiLute, 50
anuioiu:giavity (TextView) attiiLute, 50
anuioiu:icon attiiLute, +5
anuioiu:iu attiiLute, +9
anuioiu:laLel attiiLute, +6
anuioiu:layout¸alignPaientBottom attiiLute,
51
anuioiu:layout¸centeiHoiizontal (TextView)
attiiLute, 50
anuioiu:layout¸centeiInPaient attiiLute, 51
anuioiu:layout¸height attiiLute, +8, +9
Button wiuget, 51
anuioiu:layout¸wiuth attiiLute, +8, +9
Button wiuget, 51
anuioiu:name attiiLute, +5
anuioiu:name tag, 129
anuioiu:oiientation attiiLute, +8
anuioiu:text attiiLute
Button wiugets anu, 51
TextView, 50
anuioiu:textColoi (TextView) attiiLute, 50
anuioiu:textSize attiiLute
Button wiugets anu, 51
TextView, 50
NnuioiuManilest.xml
MapView liLiaiies anu, 1+0
NotePau applications anu, 117
NnuioiuManilest.xml lile, 31, 38
application setup in, 81÷83
euitoi, 36
initialization paiameteis in, ++÷+6
location without maps anu, 1+8
upuating, 128
NnuioiuRuntime log, 73
Nnuioiu`s Inteilace Delinition Language (see
NIDL)
animation, 2+7÷252
Lackgiounu, 250÷252
suilace view, 252
tiansition, 2+7÷250
Npache license, 5
NPI keys, geneiating, 90÷95, 1+0
apiKeys, 1+0
.apk liles, 36
anuioiu paiametei anu, ++
uninstall auL commanu anu, 7+
NpnSetting class, 296
<application> tag, 1+0
Npplication view (manilest lile), 36
applications
Luiluing anu iunning, 33÷+1
components ol, 6
loauing anu staiting, 35
signing anu puLlishing, 87÷97
uploauing, 96
aiiangement (layout), 226
assets suLuiiectoiy, 22, 31
NTPaiseEx class, 293
NTResponsePaisei class, 293
autoLink attiiLute (TextView), 189
autoText attiiLute (TextView), 189
B
Lackgiounu animation, 250÷252
Lackslashes (), escaping chaiacteis, 10+
.Lashic lile, 16
.Lash¸piolile lile, 16
Latteiies, 138
MapNctivities, pausing anu iesuming, 1++
Linaiy uata, uata stoiage loi, 123
Binuei, 275
Bitmap, 228, 2+2
Lioaucast ieceiveis, 7
Bunule uata type, +7
Bunule oLject, 8
Button class, 167
Button View, 53, 191
callLacks, cieating, 5+
Button wiugets, 51
C
Call class, 293
CalleiInlo class, 293
CalleiInloNsyncQueiy class, 293
CallFailCause class, 296
CallFoiwaiuInlo class, 296
CallStateException class, 293
CallTiackei class, 296
310 | Index
CNLL¸PHONE peimission, +5
Canvas class, 227
canvas uiawing, 226÷237
cat shell commanu, 73
categoiy attiiLute, +6
cumaOne, 306
Cell IDs, 137
CellLocation package (anuioiu.telephony),
288
ceitilicates, geneiating
while ueLugging, 93÷95
ceitilicates, signing/geneiating, 90÷95
CheckBoxes, 193÷198
chiluien ol View tiees, 208
.class liles, 36
.classpath lile, 31
clip iectangles, 227
closeu netwoiks, ueveloping moLile
applications anu, +
Coue Division Multiple Nccess (CDMN), 306
ColoiFiltei (Paint), 2+6
colois, +9
columns (uataLases), 101
cieating, 12+
Commanu Pattein, 168
CommanuException class, 296
CommanusInteilace inteilace, 296
components ol applications, 6
concatMatiix methou, 236
Connection class, 293
Console anu Tasks Views (DeLug peispective),
3+
Console/Tasks/Piopeities pane (DeLug
Peispective), 66
constiuctois (uataLase), 103
consumeu events, 178
Contact Managei application, 28
containei views, 162, 222
measuiement ol, 22+
content pioviueis, 7, 101÷136, 101, 11+÷136
consuming, 129÷136
implementing, 118÷129
content iesolvei, 121
ContentPioviuei class, 119
ContentPioviuei methou
NotePau anu, 119
ContentValues oLject, 127
CONTENT¸URI, uelining, 121
Context class, 258
inteilaces, puLlishing, 273
Context.staitSeivice(Intent) methou, 10
cieate, ieau, upuate, uelete (see CRUD)
CRUD (cieate, ieau, upuate anu uelete), 101
Cuisois NPI, 107, 110
D
D-pau locus, 180
Dalvik DeLug Monitoi Seivice (see DDMS)
Dalvik viitual machine, 18, 36
Luilu system, 57
uata stoiage, 122
uataLases, 53, 101
ueleting uata liom, 113
mouilying, 110÷11+
ieauing uata liom, 107÷110
upuating, 112
DNTNBNSE¸NNME vaiiaLle (NotePau), 119
DNTNBNSE¸VERSION vaiiaLle (NotePau),
120
DataConnectionTiackei class, 296
DataLink class, 296
DataLinkInteilace class, 296
DDMS (Dalvik DeLug Monitoi Seivice), 58,
7+
peispective, 3+
upuating locations anu, 153
DeLug pane (DeLug peispective), 65
DeLug peispective, 3+
Logcat, 67
ueLug peispective, 281
ueLug signatuies, 91
ueLugging, 57÷80, 280
tools loi, 57
while signing ceitilicates, 93÷95
DelaultPhoneNotiliei class, 293
uelete methou, 110, 128
ContentPioviuei methou, extenuing, 119
uevelopment enviionment, 13÷26
cieating, 1+÷18
uevice-inuepenuent pixels (see up uimensions)
uevices auL commanu, 73
Devices pane (DDMS), 7+
.uex liles, 36
uimensions loi elements, 51
uiiectoiies, Luiluing applications anu, 20
uispatchKeyEvent methou, 159
uoc (uocumentation) loluei, 31
up (uevice-inuepenuent pixels) uimensions, 51
Index | 311
positioning, 215
uiaw methou (onDiaw), 227, 2+0
uiawaLle loluei, 32
icon liles anu, +5
DiawaLleContainei class, 2+1
DiawaLles, 228, 237÷2+2
DiiveiCall class, 296
E
Eclipse DeLuggei, 57, 6+÷67
Eclipse IDE, 13
Luiluing anu iunning applications with, 33
installing, 15
peispectives (see peispectives, Eclipse)
sic loluei anu, 31
staiting applications, 18
Eclipse ]ava Euitoi, 57, 58÷80
Eclipse Package Exploiei (see Package Exploiei
(Eclipse))
EDGE (Enhanceu Data loi GSM Evolution),
307
euitaLle attiiLute (TextView), 189
Euitoi pane (DeLug peispective), 65
EuitText, 188÷191
ueLugging, 62
Emacs, 16
emul, 3+
Emulatoi Contiol pane (DDMS), 75
emulatois
NLsoluteLayout, 216
ueLugging applications anu, 67
emulatoi contiol view, using DDMS
peispective anu, 3+
locations, upuating on, 152
testing applications on, 13, 18
EncoueException class, 296
Enu Usei License Ngieement (EULN), 87
attaching, 89
Enhanceu Data loi GSM Evolution (EDGE),
307
enviionment vaiiaLles, 13, 16
eiiois, 57÷80
]ava, 58÷6+
ETSI (Euiopean Telecommunications
Stanuaius Institute), 305
EULN (Enu Usei License Ngieement), 87
attaching, 89
Euiopean Telecommunications Stanuaius
Institute (ETSI), 305
event hanuleis, 166
alteinative ways to hanule, 177÷179
event gueues, 159
events, 159, 177
(see also event hanuleis)
exception hanuling, 28+
execSQL methou, 110
execution enviionment, 5
F
lill¸paient value, 50
lilteis, 2+6
linuViewByIu methou, 166
linish methou, 9
lix geo commanu, 152
locus, 179÷183, 179
louith geneiation (+G) uigital cellulais, 307
liagmentation, ueveloping moLile applications
anu, 3
Fiame Layout, 209
liame-Ly-liame animation, 250
¨liienu linueis¨ applications, 28
G
G1 Nnuioiu moLile phone, 3
Galleiy View, 198÷202
Ganymeue, 15
geuit euitoi, 16
geo utility, 152
getCount lunction (Nuaptei class), 198
getItem( ) lunction (Nuaptei class), 198
getSystemSeivice( ) methou, 150
getType methou, 129
ContentPioviuei methou, extenuing, 119
getView( ) lunction (Nuaptei class), 198
GloLal Positioning System (see GPS)
GloLal System loi MoLile Communications
(see GMS)
GMS (GloLal System loi MoLile
Communications), 306
Google Maps activity, 139
GPL license, +
GPS (GloLal Positioning System), 138
maps anu, 28
GPX liles, 153
giauients, 2+6
Giaphical Usei Inteilace (see GUI aichitectuie)
giaphics, +9
312 | Index
2D anu 3D, uiawing, 221÷255
canvas uiawing, 226÷237
OpenGL, 252÷255
giavity, 225
GiiuView, 198÷202
GSMNlphaLet class, 296
GSMCall class, 296
GSMConnection class, 297
GsmMmiCoue class, 297
GSMPhone class, 297
GsmSimCaiu class, 297
GUI (Giaphical Usei Inteilace) aichitectuie,
157÷161
assemLling, 161÷166
H
hanuset manulactuieis, 5
host-taiget uevelopment enviionments, 13
I
icons
cieating anu attaching, 89
suLuiiectoiies loi, +5
IDEs (integiateu uevelopment enviionments),
13, 18
IllegalStateException, 225
IM (Instant Messaging), 28
in (inches) uimensions, 52
positioning layouts, 215
initialization, ++÷56
NnuioiuManilest.xml anu, ++÷+6
inputMethou attiiLute (TextView), 189
inseit methou, 110
ContentPioviuei methou, extenuing, 119
INSERT statement, 110
install commanu (auL), 35, 73
Instant Messaging (see IM)
Instiumentation view (manilest lile), 38
integiateu uevelopment enviionments (see
IDEs)
Intent class, 258
intent ieceiveis, 7
Intent.NCTION¸CNLL constant, 283
intents, 6, 258÷265
Google Maps, cieating, 139
instance, cieating, 282
intei-piocess communication (see IPC)
inteichangeaLle applications, 6
INTERNET peimission, +5
invaliuate methou, 227
IPC (intei-piocess communication), 257÷276
anuioiu.inteinal.telephony package anu,
291
getting iesults via, 262
IPhoneStateListenei inteilace, 29+
IPhoneSuLInlo inteilace, 29+
IS-95, 306
ISeconuaiy inteilace, 270
ISimPhoneBook inteilace, 297
ISms inteilace, 297
ITelephony inteilace, 29+
ITelephonyRegistiy inteilace, 29+
J
jaisignei tool, 91, 95
]ava Development Kit (]DK), 13
installing, 1+
]ava Development Tool (]DT), 15
]ava Native Inteilace (]NI), 27+
]ava peispective, 33
]ava piogiamming language, +
NIDL syntax anu, 266
compilei, 57
Eclipse ]ava Euitoi, 58
initialization anu, 52÷56
sic loluei anu, 31
XML anu, +3
]DK (]ava Development Kit), 13
installing, 1+
]DT (]ava Development Tool), 15
]NI (]ava Native Inteilace), 27+
K
key paiis, geneiating, 92
KeyEvents, 176
KeyPau, 1+7
keys, geneiating, 90÷95
keytool utility, 92
MD5 lingeipiints anu, 9+
KML liles, 153
L
layout loluei, 32
layout pass in layouts, 209
layouts, 23, 16+, 208÷218
wiugets, uiawing, 222÷226
Index | 313
LBS (Location Baseu Seivices), 137
mapping anu, 139
lilecycles
Nctivities, 8÷10
Nnuioiu seivice, 10
limiteu iesouices ol moLile phones, 5
LineaiLayout Views, 163, 209÷213
Linux, 13, 275
cieating uevelopment enviionments on, 1+
keinel, +
PNTH enviionment vaiiaLles, setting up,
16
Linux-Laseu phones, 3
ListNctivity, 131, 202
ListView, 202
loauURL(Stiing) methou, 63
location, 137÷15+
pioviueis, connecting to, 1+9
without maps, 1+8÷15+
Location Baseu Seivices (see LBS)
Location Emulatoi lunction, 75
LocationOveilay, 53
Logcat, 67÷71
iuntime eiiois, solving, 69
logcat auL commanu, 73, 299
LogCat view (DDMS), 3+
Logcat/Consol/Outline/Piopeities pane
(DDMS), 75
logliles, ueLugging applications anu, 67
Long Teim Evolution (LTE), 307
ls shell commanu, 73
LTE (Long Teim Evolution), 307
M
Mac OS X, 13
cieating uevelopment enviionments on, 1+
PNTH vaiiaLle, setting up, 17
manageuQueiy methou, 119, 132
Manilest paiameteis, ++
manilest suLuiiectoiy, 22
Map NPI key, 93
MapNctivity, 1+0
pausing anu iesuming, 1++
mapping, 137÷15+
maps, 28, 137
(see also mapping)
HashMap, 55
MapView anu, +9, 53
MapViews anu, 35
zooming, 1+3
MapView, 35, +9, 53, 1+0
woiking with, 1+0÷1+8
maishalleu uata, 266
mashups, 6
MaskFiltei (Paint), 2+6
matiix tiansloimations, 231÷237
MccTaLle class, 297
MD5 lingeipiints, 93
measuie methou, 225
measuie pass (layouts), 208
measuieChilu methou, 226
measuieChiluien methou, 226
measuieChiluVithMaigins methou, 226
measuiement (layout), 22+÷226
measuiement specilication moue, 22+
MeasuieSpec.NT¸MOST specilication moue,
22+
MeasuieSpec.EXNCTLY specilication moue,
22+
MeasuieSpec.UNSPECIFIED specilication
moue, 22+
menu Luttons, 1+5
Miciosolt Vinuows MoLile, +
millimeteis (mm) uimensions, 52
millimeteis (mm), positioning layouts, 215
MIME types, 129, 26+
MimiCoue inteilace, 29+
mksucaiu utility, 76
mm (millimeteis) uimensions, 52
positioning layouts, 215
moLile mashups, 6
moLile opeiatois, 5
MoLile Telephone System (MTS), 305
Mouel, 158
listening to, 168÷173
state, 160
Mouel-View-Contiollei pattein, 157, 222
mOpenHelpei instance vaiiaLle (NotePau),
120
MTS (MoLile Telephone System), 305
N
NetwoikInlo class, 297
NoteEuitoi Nctivity, 116
NoteList Nctivity, 116
NotePau (Nnuioiu), 116÷118
class anu instance vaiiaLles loi, 119
NotePauPioviuei class, 118
314 | Index
NOTES vaiiaLle (NotePau), 120
NotesList class, 118
NOTES¸ID vaiiaLle (NotePau), 121
NOTES¸TNBLE¸NNME vaiiaLle (NotePau),
120
O
OFDM (Oithogonal Fieguency Division
Multiplexing), 307
onBinu methou, 10, 273
onCallStateChangeu methou, 289
OnClickListenei methou, 5+, 167, 191
checkLoxes anu, 197
onCieate methou, 8
ContentPioviuei methou, extenuing, 119
onStait methou anu, 10
SQLiteOpenHelpei class anu, 102
onCieateOptionsMenu methou, 1+6
onDestioy methou, 9, 10
onDiaw methou, 227, 236
OnFocusChangeListenei class, 180
onKey methous, 178
onKeyDown methou, 177
onLayout methou, 226
onMeasuie methou, 226
onPause methou, 9, 10
onResume methou, 9, 10
onStait methou, 9
onCieate methou, 10
onStop methou, 9, 10
onTouchEvent methou, 177
onTiansact methou (NIDL), 271
onUpuate methou, 10+
onUpgiaue methou, 102
Open Hanuset Nlliance, 3, +
open souice soltwaie, +
OpenGL giaphics, 252÷255
Oithogonal Fieguency Division Multiplexing
(OFDM), 307
Outline pane (DeLug peispective), 65
Outline view (DeLug peispective), 3+
Oveiview view (manilest lile), 36
P
Package Exploiei (Eclipse), 25, 59
Package Exploiei (]ava peispective), 33
package paiametei (manilest), ++
Paint, 228, 2+6
paients ol View tiees, 208
PNTH enviionment vaiiaLles, setting up, 13,
16
PathEllect attiiLute (Paint), 2+6
PupConnection class, 297
PDPContextState class, 297
peiloimance ol emulation veisus uevice, 88
peimissions, +5
Peimissions view (manilest lile), 38
peisistent uata stoiage, 101÷136
peispectives (Eclipse), 33
DDMS, 7+
DeLug, 65
Logcat, 67
Phone inteilace, 29+
PhoneBase class, 29+
PhoneFactoiy class, 29+
PhoneNotiliei inteilace, 29+
PhoneNumLeiFoimattingTextVatchei
package (anuioiu.telephony), 288
PhoneNumLeiUtils package
(anuioiu.telephony), 288
phones, connecting to, 277÷286
PhoneStateIntentReceivei class, 29+
PhoneStateListenei package
(anuioiu.telephony), 288
PhoneSuLInlo class, 29+
pixels (px) uimensions, 51
positioning layouts, 215
Platloim Poiting Kit (Nnuioiu), 5
PNG liles, cieating icons with, 89
points (pts) uimensions, 52
pounu sign (=)
auL shell piompt anu, 73
uelining colois, +9
PppLink class, 297
pieoiuei tiaveisal, 159
piivate keys, 92
.pioject lile, 31
piojection paiametei (manageuQueiy), 132
piopiietaiy soltwaie stacks, ueveloping moLile
applications anu, +
<pioviuei> tag, 128
pioviueis, connecting to, 1+9
Pioxy oLjects, 271
ps shell commanu, 73
pts (points) uimensions, 52
puLlic keys, geneiating, 92
puLlishing applications, 87÷97
Index | 315
pull iemote local auL commanu, 7+
push local iemote auL commanu, 7+
px (pixels) uimensions, 51
positioning layouts, 215
Q
QEMU emulatoi, 39
gueiy methou, 110
ContentPioviuei methou, extenuing, 119
R
R.java lile, 32, 36, +7
Rauio Inteilace Layei (RIL), 291
RauioButtons, 193÷198
ielational uataLases, 101
RelativeLayout, 216
iemote methous, 257
iemote pioceuuie calls (RPCs), 27+
ieguestFocus methou, 180
ies (iesouices) suLuiiectoiy, 22, 31
icon liles anu, +5
.ies liles, 20
iesouices suLuiiectoiy (see ies suLuiiectoiy)
RIL (Rauio Inteilace Layei), 291
RIL class, 297
RILConstants inteilace, 297
im shell commanu, 73
iotate methou, 2+8
iows (uataLases), 101
RPCs (Remote Pioceuuie Calls), 27+
iuntime uata collection, 75
S
Satellite View (MapView), 1+1
saveuInstanceState Lunule, 23
scaleu pixels (sp) uimensions, 52
positioning layouts, 215
Scieen Captuie pane (DDMS), 75
scieen iesolution/oiientation ol emulation
veisus uevice, 88
SciollView, 20+
SDK (Soltwaie Development Kit), 5, 13
DDMS, 7+
ueLugging (see ueLugging)
installing, 15
seconu geneiation (2G) uigital cellulais, 305
SELECT statements, 102
selection paiametei (manageuQueiy), 132
selectionNigs paiametei (manageuQueiy),
132
semiconuuctoi companies, 5
Seiies 60 (Nokia), +
seivei (auL), 71
seivices, 7, 273
SeiviceState package (anuioiu.telephony), 288
SeiviceStateTiackei class, 298
setClickaLle map attiiLute, 1+3
setEnaLleu map attiiLute, 1+3
setMatiix methou, 236
setMeasuieuDimensions methou, 22+
setOnClickListenei methou, 167
setSatellite map attiiLute, 1+3
setStieetView map attiiLute, 1+3
setTiallic map attiiLute, 1+3
Shauei (Paint), 2+6
ShauowLayei (Paint), 2+6
shauows, 2+6
shell auL commanu, 73
signing applications, 87÷97
SimCaiu inteilace, 29+
SimConstants inteilace, 298
SimException class, 298
SIMFileHanulei class, 298
SimFileNotFounu class, 298
SimPhoneBookInteilaceManagei class, 298
SimPioviuei class, 298
SIMRecoius class, 298
SimSmsInteilaceManagei class, 298
SimTlv class, 298
SimUtils class, 298
SMSDispatchei class, 298
SmsHeauei class, 298
SmsRawData class, 298
SmsResponse class, 299
sNotesPiojectionMap vaiiaLle (NotePau), 120
social netwoiking, 27÷30
Soltwaie Development Kit (see SDK)
soltwaie, wiiting loi moLile applications, 5
soitOiuei paiametei (manageuQueiy), 132
Souice Euitoi (]ava peispective), 33
souice liles, 20
Souice View (DeLug peispective), 3+
souices (sic) suLuiiectoiy, 20, 30
sp (scaleu pixels) uimensions, 52
positioning layouts, 215
Spinnei View, 50, 193÷198
SQL (see uataLases)
316 | Index
SQLite, 53, 101÷136
auL shell anu, 73
as a uataLase engine, 102
upuating uata, 127
sglite3 auL commanu, 73
SQLiteDataLase class
mouilying uataLases, 110
SQLiteOpenHelpei class, 102
sic (souices) suLuiiectoiy, 20, 30
.sic liles, 20
stack Lacktiaces, 285
staitNctivity methou, 139, 258
staitNctivityFoiResult methou, 258, 26+
staitNnimation methou (View), 2+7
staitMethouTiacing, 76
Step Ovei Lutton (DeLug toolLai), 66
stopMethouTiacing, 76
Stieet View (MapView), 1+1
StuL inteilace, implementing, 271
suLuiiectoiies, Luiluing applications anu, 20
supei lunction, 103
SuppSeiviceNotilication class, 299
suilace view animation, 252
suilaceCieateu methou, 252
suilaceDestioyeu methou, 252
SuilaceHoluei.CallLack inteilace, 252
sUiiMatchei vaiiaLle (NotePau), 120
synchionizeu Llocks, 161, 183
T
T-MoLile phones, iunning applications, 39÷
+1
TaLLeu Views (]ava peispective), 33
TaLContentFactoiy, 205
TaLHost, 205÷208
TaLleLayout, 213÷215
tag:piioiity liltei specs, 73
TDMN (Time Division Multiple Nccess), 306
Telephony, 75, 285, 287÷303
inteinals, 291÷302
TelephonyIntents class, 295
TelephonyManagei package
(anuioiu.telephony), 288
TelephonyPiopeities class, 295
text, uiawing, 230
TextView, 2+, 188÷191
element (XML), 50
thieaus, 179÷183
Thieaus/Heap/File Exploiei pane (DDMS), 35,
7+
Time Division Multiple Nccess (see TDMN)
TitleEuitoi Nctivity, 116
TitleEuitoi class, 118
toolkit, 12
tools (ueLugging), 57
touch events, listening loi, 173
touch locus, 180
touchscieen opeiation ol emulation veisus
uevice, 88
tiace analysis, 75
Tiaceview, 58, 75÷80
Tiallic View (MapView), 1+1
tiansition animation, 2+7÷250
tianslate methou, 2+8
tiiangulation, 138
U
ULuntu Linux
Dappei Diake, 1+
USB uiiveis, loauing loi NDB, +0
UI component oLjects, 160
UMTS (Univeisal MoLile Telecommunications
Stanuaiu), 307
uniloim iesouice iuentiliei (URI), 115
uninstall auL commanu, 7+
Univeisal MoLile Telecommunications
Stanuaiu (UMTS), 307
unmaishalleu uata, 266
unsigneu veisions ol applications, 95
upuate methou, 110
ContentPioviuei methou, extenuing, 119
UPDNTE statements, 102, 127
uii paiametei (manageuQueiy), 132
URIs (uniloim iesouice iuentilieis), 115
<uses-peimission anuioiu:name=...> element,
+5
USP uiiveis, ueLugging on phones, 39
V
values loluei, 33
VaiiaLles anu Bieakpoints pane (DeLug
peispective), 65
VaiiaLles, Bieakpoints anu Expiessions view
(DeLug peispective), 3+
veisions, loi applications, 90
vi euitoi, 16
Index | 317
View class, 158
view-mouel, 227
ViewGioups, 162, 198÷208
containei views anu, 222
wiugets anu, 222
Views, 33, 188÷198
Luiluing, 157÷185
wiugets anu, 221
VoiceMailConstants class, 299
VoIP (Voice ovei IP), 302
W
VCDMN (ViueLanu CDMN), 307
VeL Stanuaiu Tools (VST), 15
VHERE clause, 127
ViueLanu CDMN (VCDMN), 307
wiugets, 187÷218
2D anu 3D giaphics anu, 221÷2+3
Button, 51
Vinuows, 13, 1+
enviionment vaiiaLles, setting up, 16
USB uiiveis, loauing loi NDB, 39
Vinuows MoLile (Miciosolt), +
wiieless piotocols, 305÷308
VST (VeL Stanuaiu Tools), 15
X
x.tiace lile, 77
XML (eXtensiLle Maikup Language), 23
NnuioiuManilest.xml lile anu, 31
initialization paiameteis in, ++÷+6
]ava coue anu, +3
Z
zoomIn methou, 1+3
zoomInFixing( ) methou, 1++
zoomOut methou, 1++
zoomToSpan( ) methou, 1++
318 | Index
About the Authors
Rick Rogers has Leen ueveloping anu maiketing emLeuueu systems loi moie than 30
yeais. He has locuseu on soltwaie loi moLile phones loi the last nine yeais, woiking
with Linux anu othei opeiating enviionments loi companies such as Compag, Intel,
anu Maivell Semiconuuctoi. He is cuiiently a moLile solutions aichitect at Vinu Rivei
Systems.
John Lombardo has Leen woiking with Linux since veision 0.9. His liist Look,
Enbcddcd Linux (Sams), was puLlisheu in 2001. Since then, he`s woikeu on seveial
emLeuueu piouucts, incluuing phones anu iouteis. ]ohn holus a B.S. in computei sci-
ence anu is woiking on his M.B.N.
Zigurd Mednieks is chiel usei inteilace aichitect at D2 Technologies, a leauing pio-
viuei ol IP communications technology, anu is also a consultant anu auvisoi to
companies in the lielu ol emLeuueu usei inteilaces. He has helu senioi management
positions at companies making moLile games, communications eguipment, anu com-
putei telephony applications, anu has wiitten anu contiiLuteu to Looks on piogiam-
ming anu communications technology.
BIake Meike has moie than 10 yeais ol expeiience with ]ava. He has uevelopeu
applications using most ol the GUI toolkits anu seveial ol the ]ava moLile uevice plat-
loims. He likes Nnuioiu a lot.
Colophon
The animal on the covei ol Android App|ication Dcvc|opncnt is an Eastein guoll
(Dasyurus vivcrrinus), an enuangeieu maisupial otheiwise known as the Eastein native
cat. Eastein guolls giow to aLout the same size as householu cats, anu theii thick lui
ianges in coloi liom giay to Liown anu is uotteu with white spots. Howevei, unlike
otheis ol its kinu (the Tigei guoll, loi example), no spots covei its long, haiiy tail.
No longei wiuespieau thioughout mainlanu Nustialia, the Eastein guoll iemains com-
mon in Tasmania. It lives in iain loiests anu alpine aieas, though it pieleis uiy giass-
lanus anu loiests Loiueieu Ly pastoial agiicultuial lielus. Vithin these haLitats, the
Eastein guoll hunts loi small mammals anu steals loou liom the much laigei Tasmanian
uevil Ly night; Ly uay, it slumLeis in logs anu in nests in unueigiounu Luiiows.
Vhile lemale Eastein guolls can Liith up to 30 LaLies, typically only 6 will suivive, as
the mothei only has 6 teats in hei pouch loi hei chiluien. Male anu lemale Eastein
guolls ieach sexual matuiation less than a yeai altei Leing Loin. Pioviueu it suivives
inlancy, the guoll will live an aveiage lile span ol six yeais.
Nlthough some laimeis uislike the guoll Lecause it occasionally leeus on chickens anu
othei small mammals (guolls will leeu on injuieu oi ill laim animals), the guoll also
Lenelits laimeis Ly consuming ciop pests, mice, anu caiiion.
The covei image is liom Voou`s Aninatc Crcation \o|. |. The covei lont is NuoLe ITC
Gaiamonu. The text lont is Linotype Biika; the heauing lont is NuoLe Myiiau Con-
uenseu; anu the coue lont is LucasFont`s TheSansMonoConuenseu.

Android Application Development

Beijing • Cambridge • Farnham • Köln • Sebastopol • Taipei • Tokyo

Android Application Development

Editor: Production Editor: Copyeditor: Proofreader: Printing History:

Indexer: Cover Designer: Interior Designer: Illustrator:

TM

Table of Contents

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix

Part I. Development Kit Walk-Through
1. Getting to Know Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2. Setting Up Your Android Development Environment . . . . . . . . . . . . . . . . . . . . . . . . . 13

3. Using the Android Development Environment for Real Applications . . . . . . . . . . . . 27

iii

4. Under the Covers: Startup Code and Resources in the MJAndroid Application . . . . 43

5. Debugging Android Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

6. The ApiDemos Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

7. Signing and Publishing Your Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

iv | Table of Contents

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building a View . . . . . . . . 157 Table of Contents | v . . . . . . . . . . . . . . . .Part II. . . . Programming Topics 8. . . . . . . . . . . . . . . . . . Location and Mapping . . . . . . Persistent Data Storage: SQLite Databases and Content Providers . . . . . . . . 137 10. . . . . . . . . . 101 9. . . . . . . . . . . . . . . . . . .

257 vi | Table of Contents . . . Drawing 2D and 3D Graphics . . . . . Inter-Process Communication . . . .11. . . . . . . . . . . . . . . . . . . . . . . . . . . 187 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 13. . . . . . . . . . . . . . . . . A Widget Bestiary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . 309 Table of Contents | vii . . . . . . . . . . . . . . . . 287 Appendix: Wireless Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Telephony State Information and Android Telephony Classes . . . . . . . . . . . . . . . . . . .14. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simple Phone Calls . . . 277 15. . . . . . . . . . . . . . .

.

Preface Audience ix .

How This Book Is Organized adb x | Preface .

Conventions Used in This Book Constant width Constant width bold Constant width italic Using Code Examples Preface | xi .

Safari® Books Online How to Contact Us xii | Preface .

Acknowledgments Rick Rogers John Lombardo Zigurd Mednieks Blake Meike Preface | xiii .

.

PART I Development Kit Walk-Through .

.

CHAPTER 1 Getting to Know Android Why Android? 3 .

The Open Handset Alliance 4 | Chapter 1: Getting to Know Android .

The Android Execution Environment The Android Execution Environment | 5 .

Components of an Android Application 6 | Chapter 1: Getting to Know Android .

content://contacts/people Components of an Android Application | 7 .

Start activity User navigates back to activity onCreate() onStart() onRestart() In foreground? Process is killed Activity becomes YES visible onResume() Activity interacts with user onPause() NO Activity comes to foreground Activity no longer visible onStop() onDestroy() Activity exits Android Activity Lifecycle onCreate onCreate Bundle 8 | Chapter 1: Getting to Know Android .

onStart onStart onResume onStop onResume onStart onResume onPause onStop onDestroy finish Android Activity Lifecycle | 9 .

bind onCreate onBind onStop onStop onStart onDestroy onDestroy onStart How This Book Fits Together 10 | Chapter 1: Getting to Know Android .startService(Intent) onCreate onStart onStart onResume onPause onPause onResume onBind Service onStart IBind Context.Android Service Lifecycle onCreate onStart Context.

SQLite How This Book Fits Together | 11 .

12 | Chapter 1: Getting to Know Android .

CHAPTER 2 Setting Up Your Android Development Environment Setting Up Your Development Environment 13 .

Creating an Android Development Environment chmod +x jdk-6version-linuxi586.bin 14 | Chapter 2: Setting Up Your Android Development Environment .

Setting Up Your Development Environment | 15 .

16 | Chapter 2: Setting Up Your Android Development Environment .

export PATH=${PATH}:your_sdk_dir/tools your_sdk_dir export PATH=${PATH}:your_sdk_dir/tools your_sdk_dir Setting Up Your Development Environment | 17 .

Android Where We’re Going Starting a New Android Application: HelloWorld 18 | Chapter 2: Setting Up Your Android Development Environment .Hello.

com.oreilly.helloworld Hello WorldActivity

Hello, Android | 19

HelloWorldActivity

20 | Chapter 2: Setting Up Your Android Development Environment

Hello, Android | 21

Writing HelloWorld
HelloWorldActivity.java
package com.oreilly.helloworld; import android.app.Activity; import android.os.Bundle; public class HelloWorldActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }

22 | Chapter 2: Setting Up Your Android Development Environment

Hello WorldActivity savedInstanceState OnCreate OnCreate

OnCreate
setContentView (R.layout.main);

<?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>

Hello, Android | 23

xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"

android:layout_width="fill_parent" android:layout_height="wrap_content"

android:text="@string/hello"

Running HelloWorld

24 | Chapter 2: Setting Up Your Android Development Environment

android:text hello app_name app_name HelloAndroid Hello. Android | 25 .

26 | Chapter 2: Setting Up Your Android Development Environment .

CHAPTER 3 Using the Android Development Environment for Real Applications MicroJobs: This Book’s Main Sample Application Android and Social Networking 27 .

MicroJobs 28 | Chapter 3: Using the Android Development Environment for Real Applications .

Android and Social Networking | 29 .

Downloading the MJAndroid Code A Brief Tour of the MJAndroid Code The Project Root Folder (MJAndroid) 30 | Chapter 3: Using the Android Development Environment for Real Applications .

The Source Folder (src) com.mjandroid A Brief Tour of the MJAndroid Code | 31 .microjobsinc.

The Resource Folder (res) 32 | Chapter 3: Using the Android Development Environment for Real Applications .

First Steps: Building and Running the MicroJobs Application A Very Short Tour of the Android SDK/Eclipse IDE First Steps: Building and Running the MicroJobs Application | 33 .

34 | Chapter 3: Using the Android Development Environment for Real Applications .

apk First Steps: Building and Running the MicroJobs Application | 35 .0.0.Loading and Starting the Application Running the MJAndroid Code $ emulator $ adb install MJAndroid-1.

Digging a Little Deeper: What Can Go Wrong? 36 | Chapter 3: Using the Android Development Environment for Real Applications .

com.action.maps <action android:name="android.intent.android.category.intent.google.MAIN" /> <category android:name="android.LAUNCHER" /> First Steps: Building and Running the MicroJobs Application | 37 .

ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.permission.permission.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.CALL_PHONE" /> 38 | Chapter 3: Using the Android Development Environment for Real Applications .INTERNET" /> <uses-permission android:name="android.<uses-permission android:name="android.permission.ACCESS_LOCA TION_EXTRA_COMMANDS" /> <uses-permission android:name="android.

Running an Application on the T-Mobile Phone Enable USB debugging on your phone Load the USB driver for ADB First Steps: Building and Running the MicroJobs Application | 39 .

MODE="0666" chmod a+rx /etc/udev/rules.d/50-android.SUBSYSTEM=="usb_device". MODE="0666" SUBSYSTEM=="usb". SYSFS{idVendor}=="0bb4". SYSFS{idVendor}=="0bb4".rules Connecting the phone adb devices >adb devices List of devices attached emulator-5554 device HT840GZ12968 device 40 | Chapter 3: Using the Android Development Environment for Real Applications .

Running MicroJobs on the phone Summary Summary | 41 .

.

CHAPTER 4 Under the Covers: Startup Code and Resources in the MJAndroid Application 43 .

google.android.permission.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.action.ACCESS_LOCATION_EXTRA_COMMANDS" /> <uses-permission android:name="android.android.permission.intent.mjandroid" android:versionCode="1" android:versionName="1.INTERNET" /> <application android:icon="@drawable/icon2"> <uses-library android:name="com.CALL_PHONE" /> <uses-permission android:name="android.MAIN" /> <category android:name="android.microjobsinc.xml <?xml version="1.Initialization Parameters in AndroidManifest.permission.maps" /> <activity android:name=".0"> <uses-permission android:name="android.com/apk/res/android" package="com.permission.mjandroid" android:versionCode android:versionName 44 | Chapter 4: Under the Covers: Startup Code and Resources in the MJAndroid Application .category.ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.intent.microjobsinc.permission.MicroJobs" android:label="@string/app_name"> <intent-filter> <action android:name="android.LAUNCHER" /> </intent-filter> </activity> package="com.ACCESS_FINE_LOCATION" /> <uses-permission android:name= "android.

.xml | 45 . android.permission ACCESS_FINE_LOCATION ACCESS_LOCATION_EXTRA_COMMANDS CALL_PHONE ACCESS_MOCK_LOCATION INTERNET android:icon="@drawable/icon2" android:name Initialization Parameters in AndroidManifest.<uses-permission android:name=.Manifest..

java MicroJobs /** * MicroJobs */ public class MicroJobs extends MapActivity { MJOverlay onCreate 46 | Chapter 4: Under the Covers: Startup Code and Resources in the MJAndroid Application .android:label action category Initialization in MicroJobs.

maps.java | 47 .com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffc5d1d4" > <com.google. longitude.layout.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.onCreate(savedInstanceState).android.MapView Initialization in MicroJobs.Bundle) */ @Override public void onCreate(Bundle savedInstanceState) { super.android. /** * Called when the activity is first created.MapActivity#onCreate(android. MicroJobsDatabase db. * * @see com. double latitude.os.MapView mvMap. MyLocationOverlay mMyLocationOverlay. setContentView(R.google. onCreate savedInstanceStte onCreate onCreate savedInstanceState onCreate setContentView <?xml version="1.android.maps.main).

android:id="@+id/mapmain" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="0P18K0TAE0dO2GifdtbuScgEGLWe3p4CYUQngMg" /> <TextView android:id="@+id/lblMicroJobsToday" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="MicroJobs for You Today Near:" android:textSize="20dp" android:textColor="#FF000000" android:layout_centerHorizontal="true" android:gravity="top" /> <Spinner android:id="@+id/spnLocations" android:layout_width="250dp" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="2dp" android:layout_below="@+id/lblMicroJobsToday" /> <Button android:id="@+id/btnShowList" android:layout_width="150dp" android:layout_height="wrap_content" android:text="List Jobs" android:textSize="20sp" android:gravity="center_vertical" android:layout_centerInParent="true" android:layout_alignParentBottom="true" /> </RelativeLayout> android:orientation android:layout_width android:layout_height 48 | Chapter 4: Under the Covers: Startup Code and Resources in the MJAndroid Application .

java | 49 .MapView android:id android:layout_width android:layout_height fill_parent Initialization in MicroJobs.maps.google.google.android:background Colors in Android # <com.android.MapView com.android.maps.

android:clickable android:apiKey <TextView android:text android:textSize android:textColor android:layout_centerHorizontal android:gravity top center_vertical layout_centerHorizontal bottom <Spinner android:layout_below 50 | Chapter 4: Under the Covers: Startup Code and Resources in the MJAndroid Application .

java | 51 .id lblMicroJobsToday <Button android:layout_width android:layout_height android:text android:textSize android:layout_centerInParent android:layout_alignParentBottom android:gravity=bottom Dimensions in Android Initialization in MicroJobs.

getController(). 52 | Chapter 4: Under the Covers: Startup Code and Resources in the MJAndroid Application .LOCATION_SERVICE)).runOnFirstFix( new Runnable() { public void run() { mc.More Initialization of MicroJobs.setZoom(16).getMyLocation()).animateTo(mMyLocationOverlay. mvMap = (MapView) findViewById(R.id. mc. mMyLocationOverlay. // Get current position final Location myLocation = getCurrentLocation((LocationManager) getSystemService(Context. mMyLocationOverlay = new MyLocationOverlay(this.java db = new MicroJobsDatabase(this). // get the map controller final MapController mc = mvMap.id.mapmain). mvMap).spnLocations). Spinner spnLocations = (Spinner) findViewById(R.

} }).btnShowList). Button btnList = (Button) findViewById(R.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { Initialization in MicroJobs.id. SQLite MicroJobsDatabase getCurrentLocation LocationManager Manager getSystemService Location findViewById spnLocations findViewById MapView MapController LocationOverlay LocationOverlay MapView Button Spinner // Create a button click listener for the List Jobs button.java | 53 . btnList.

aspnLocations. hmLocations. // Load a HashMap with locations and positions List<String> lsLocations = new ArrayList<String>().R. startActivity(intent). (int)worker. (int)worker. hmLocations.getColLoc1Name()). lsLocations.add("Current Location").R. hmLocations.layout.add(worker.getColLoc2Lat(). lsLocations.getColLoc2Long())). (int)worker. // Add favorite locations from this user's record in workers table worker = db. btnList Spinner MapView OnClickListener OnClickListener onClick btnList startActivity onClick() onClick() 54 | Chapter 4: Under the Covers: Startup Code and Resources in the MJAndroid Application .getColLoc1Lat(). (int) longitude)). spnLocations. new GeoPoint((int) latitude.getColLoc2Name(). GeoPoint> hmLocations = new HashMap<String.add(worker. ArrayAdapter<String> aspnLocations = new ArrayAdapter<String>(this.getColLoc3Long())).setAdapter(aspnLocations).getColLoc1Long())). lsLocations).getApplication().getColLoc3Lat(). new GeoPoint((int)worker.this.class). } }). lsLocations.put(worker.getColLoc2Name()). final HashMap<String.getColLoc3Name(). lsLocations.setDropDownViewResource(android.put(worker.layout.Intent intent = new Intent(MicroJobs. new GeoPoint((int)worker.getWorker(). GeoPoint>().put("Current Location".simple_spinner_item. new GeoPoint((int)worker. android. hmLocations. MicroJobsList.simple_spinner_dropdown_item).getColLoc1Name().add(worker.getColLoc3Name()).put(worker.

setOnItemSelectedListener( new OnItemSelectedListener() { public void onNothingSelected(AdapterView<?> arg0) { } public void onItemSelected(AdapterView<?> parent.R.invalidate(). mc. int position.animateTo(hmLocations. } })." // Set up a callback for the spinner spnLocations. if ("Current Location".equals(vt. } else { mc.animateTo(new GeoPoint((int) latitude.getText())) { latitude = myLocation.getLatitude().getLongitude(). } Initialization in MicroJobs. View v.layout.getText())). (int) longitude)).setDropDownViewResource(android. long id) { TextView vt = (TextView) v.lsLocations hmLocations Current Location worker = db. } mvMap.get(vt.java | 55 .simple_spin ner_dropdown_item). lsLocations hmLocations aspnLocations setAdapter "aspnLocations. longitude = myLocation.getWorker().

onItemSelected onNothingSelected Current Location if Current Location Summary SQL 56 | Chapter 4: Under the Covers: Startup Code and Resources in the MJAndroid Application .

CHAPTER 5 Debugging Android Applications The Tools 57 .

layout.adb Eclipse Java Editor Java Errors R R.main 58 | Chapter 5: Debugging Android Applications .

R

R

<?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"

Eclipse Java Editor | 59

android:text="Enter URL:" /> <EditText android:id="@+id/URL" android:layout_width="fill_parent" android:layout_height="60.0dip" android:maxLines="1" <Button android:id="@+id/btnGo" android:layout_width="wrap_content" android:layout_height="60.0dip" android:text="Go" /> <WebView android:id="@+id/wvBrowser" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <LinearLayout>

package com.oreilly.debug; import android.app.Activity; import android.os.Bundle; public class DebugTest extends Activity { private EditText txtURL; private Button btnGo; private WebView wvBrowser; // Set up an onClick routine to gather URLs entered by the user private final Button.OnClickListener btnGoOnClick = new Button.OnClickListener() { public void onClick(View v) { try { wvBrowser.loadURL(); } catch (Exception e) {} } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Find the Views in the layout file txtURL = (EditText) findViewById(R.id.txtURL); btnGo = (Button) findViewById(R.id.btnGo); btnGo.setOnClickListener(btnGoOnClick); wvBrowser = (WebView) findViewById(R.id.wvBrowser); } }

60 | Chapter 5: Debugging Android Applications

wvBrowser

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.oreilly.debug" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".DebugTest" 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-permission android:name="android.permission.INTERNET"></uses-permission> </manifest>

Eclipse Java Editor | 61

EditText EditText

/>

</LinearLayout> </LinearLayout> Layout>

<Linear

btnGo

62 | Chapter 5: Debugging Android Applications

loadURL(String) toString onClick
public void onClick(View v) { try { wvBrowser.loadUrl(txtURL.getText().toString()); } catch (Exception e) {} }

Eclipse Java Editor | 63

URL txtURL

www.oreilly.com http://www.oreilly.com http://
public void onClick(View v) { try { String sURL = txtURL.getText().toString(); if(sURL.substring(0,6).equals("http://")) { wvBrowser.loadUrl(sURL); }else{ sURL = "http://" + sURL; wvBrowser.loadUrl(sURL); } } catch (Exception e) {} }

www.oreilly.com http://www.oreilly.com

The Debugger

64 | Chapter 5: Debugging Android Applications

oreilly.com this v OnCreate Eclipse Java Editor | 65 .http://www.

sURL www.substring(0.oreilly.com if http:// sURL http:// sURL.6) http:/ substring / 66 | Chapter 5: Debugging Android Applications .

Logcat Eclipse Java Editor | 67 .

11-28 12:10:31.mjandroid/.microjobsinc.475: INFO/ActivityManager(52): Start proc com.microjobsinc.MicroJobs: pid=163 uid=10017 gids={3003} 68 | Chapter 5: Debugging Android Applications .mjandroid for activity com.

lang.microjobsinc.mjandroid.mjandroid/com.microjobsinc.Looking at logcat to solve runtime errors java.Constructor Eclipse Java Editor | 69 .MicroJobs}: android.lang.reflect.RuntimeException: Unable to start activity ComponentInfo{com.view.InflateException: Binary XML file line #8: Error inflating class java.

java:2140) at android.<init>(MapView.Handler.system.java:564) at android.main(ZygoteInit.Activity.PhoneWindow.ActivityThread.android.constructNative(Native Method) java.InflateException: Binary XML file line #8: Error inflating class java.android.view.view.access$1800(ActivityThread.reflect.lang.os.impl.internal.app.app.invoke(Method. See the MapView documentation for details.java:123) at android.java:227) at android.reflect.java:1569) at com.java:424) android.ZygoteInit.java:2156) at android.LayoutInflater.java:132) at android.LayoutInflater.java:499) Caused by: java.<init>(MapView.java:263) at com.callActivityOnCreate(Instrumentation.reflect.maps.google.newInstance(Constructor.app.app.mjandroid.reflect.ActivityThread.loop(Looper.internal.Method.main(ActivityThread.google.os.java:497) at dalvik.android.app.ActivityThread$H.lang.android.IllegalArgumentException: You need to specify an API Key for each MapView.Constructor.lang. at com.ActivityThread.MapView.app.java:2103) Caused at at at at by: java. [Throwable exception]) 70 | Chapter 5: Debugging Android Applications .MicroJobs.lang.ZygoteInit$MethodAndArgsCaller.MapView.invokeNative(Native Method) at java.rInflate(LayoutInflater.java:3742) at java.java:244) Writing your own logcat entries Log.inflate(LayoutInflater.java:512) at android.google.lang.<init>(MapView.onCreate(MicroJobs.view.NativeStart.createViewFromTag(LayoutInflater.Looper.setContentView(PhoneWindow.performLaunchActivity(ActivityThread.policy.LayoutInflater.at android.handleLaunchActivity(ActivityThread.LayoutInflater.java:227) java.inflate(LayoutInflater.x(String tag.view.LayoutInflater.LayoutInflater.maps.java:739) at com.os.java:1580) at android.android.java:617) at android.java:112) at android.view.java:320) at android.java:88) at android.maps.createView(LayoutInflater.run(ZygoteInit.lang.reflect.main(Native Method) Caused by: android.view.internal.java:1122) at android.Constructor at android.InvocationTargetException com.setContentView(Activity.Constructor.android.microjobsinc.performLaunchActivity(ActivityThread.handleMessage(ActivityThread.view.app.ActivityThread.dispatchMessage(Handler.MapView.Method.inflate(LayoutInflater.java:276) at com.java:515) at com.os.reflect.createView(LayoutInflater.LayoutInflater.Instrumentation.ActivityThread.lang.view. String message.app.java:407) at android.

If -p is not specified.directs command to the USB device or emulator with the given serial number . returns an error if more than one emulator is running.copy file/dir from device .list all connected devices .invalidate(). which must be an absolute path. "Unable to animate map".0.getMyLocation()).directs command to the only connected USB device returns an error if more than one USB device is present. .copy file/dir to device . } catch (Exception e) { Log. the ANDROID_PRODUCT_OUT environment variable is used.20 -d adb -e -s <serial number> -p <product name or path> devices device commands: adb push <local> <remote> adb pull <remote> <local> adb sync [ <directory> ] . Android Debug Bridge (adb) adb adb adb adb adb Android Debug Bridge version 1.animateTo(mMyLocationOverlay.i("MicroJobs".directs command to the only running emulator. } mvMap. e). or a relative/absolute path to a product out directory like 'out/target/product/sooner'. .x v d i w e onItemSelected Spinner try { mc. .simple product name like 'sooner'.copy host -> device only if changed (see 'adb help all') Eclipse Java Editor | 71 .

Run PPP over USB. both /system and /data partitions will be updated.Eg.show version num . <tty> refers to the tty for PPP stream. 72 | Chapter 5: Debugging Android Applications .flash the data partition - block until device is online ensure that there is a server running kill the server if it is running prints: offline | bootloader | device prints: <product-id> prints: <serial-number> continuously print device status for a specified device .don't touch the data partition .wipe the data partition . Note: you should not automatically start a PDP connection.If it is "system" or "data". adb help adb version DATAOPTS: (no option) -w -d scripting: adb wait-for-device adb start-server adb kill-server adb get-state adb get-product adb get-serialno adb status-window adb remount . Eg.show this help message .remounts the /system partition on the device read-write networking: adb ppp <tty> [parameters] . only the corresponding partition is updated. . defaultroute debug dump local notty usepeerdns adb sync notes: adb sync [ <directory> ] <localdir> can be interpreted in several ways: . dev:/dev/omap_csmi_tty1 [parameters] .adb adb adb adb adb shell shell <command> emu <command> logcat [ <filter-spec> ] forward <local> <remote> - adb jdwp adb install [-l] [-r] <file> - adb uninstall [-k] <package> adb bugreport - run remote shell interactively run remote shell command run emulator console command View device log forward socket connections forward specs are one of: tcp:<port> localabstract:<unix domain socket name> localreserved:<unix domain socket name> localfilesystem:<unix domain socket name> dev:<character device name> jdwp:<process pid> (remote only) list PIDs of processes hosting a JDWP transport push this package file to the device and install it ('-l' means forward-lock the app) ('-r' means reinstall the app.If <directory> is not specified. keeping its data) remove this app package from the device ('-k' means keep the data and cache directories) return all information from the device that should be included in a bug report.

mjandroid/databases/MJAndroid adb logcat filter_spec & tag:priority tag priority AndroidRuntime adb logcat AndroidRuntime:E & adb -b radio & adb -b events & adb install -l -r file_spec -l Eclipse Java Editor | 73 .adb adb adb devices adb adb -s adb shell # ls cat rm ps exit sqlite3 path_to_database adb shell SQLite -e data/data/com.micro jobsinc.

-r file_spec adb uninstall -k package package adb uninstall com.microjobsinc.mjandroid -k adb push local remote local adb pull remote local remote DDMS: Dalvik Debug Monitor Service 74 | Chapter 5: Debugging Android Applications .

Traceview Eclipse Java Editor | 75 .

Trace data collection startMethodTracing stopMethodTracing mksdcard mksdcard $ mksdcard -l ANDROID 1024M filename mksdcard -sdcard filename .os..Debug. public void onCreate(Bundle savedInstanceState) { super. . 76 | Chapter 5: Debugging Android Applications .. import android.onCreate(savedInstanceState)..startMethodTracing("x"). // start trace Debug..

stopMethodTracing().onDestroy()..trace Eclipse Java Editor | 77 .. // stop tracing when application ends @Override public void onDestroy() { super. } $ adb pull sdcard/x.trace x.. Debug.trace $ traceview pathnamex.

78 | Chapter 5: Debugging Android Applications .

dmtracedump Eclipse Java Editor | 79 .

Summary 80 | Chapter 5: Debugging Android Applications .

READ_CONTACTS" /> android:name="android.permission.CAMERA" /> android:name="android.permission.permission.VIBRATE" /> android:name="android.apis"> <uses-permission <uses-permission <uses-permission <uses-permission <uses-permission <uses-permission android:name="android.WRITE_CONTACTS" /> android:name="android.permission.CHAPTER 6 The ApiDemos Application Application Setup in the Manifest File <manifest xmlns:android="http://schemas.android.permission.ACCESS_COARSE_LOCATION" /> android:name="android.example.com/apk/res/android" package="com.permission.android.INTERNET" /> <application android:name="ApiDemosApplication" android:label="@string/activity_sample_code" android:icon="@drawable/app_sample_code" > 81 .

category.DEFAULT" /> <category android:name="android.maps" /> <activity android:name="ApiDemos"> <intent-filter> <action android:name="android.intent.intent.intent.<uses-library android:name="com.MAIN" /> <category android:name="android.action.android.LAUNCHER" /> </intent-filter> </activity> ApiDemosApplication ApiDemos ApiDemos queryIntentActivities ApiDemosApplication Application onCreate onCreate onCreate onTerminate 82 | Chapter 6: The ApiDemos Application .google.category.

*Activity.VIBRATOR_SERVICE SENSOR_SERVICE autoLink TextView LogTextBox Finding the Source to an Interesting Example Custom Title Demo App.*Title Finding the Source to an Interesting Example | 83 .*Custom.

name activity_custom_title activity_custom_title android:label activity .Link activity Adding Your Own Examples to ApiDemos 84 | Chapter 6: The ApiDemos Application .CustomTitle android:name Activity Linkify Demo Text/Linkify android:label android:name Activity .text.app.

example.com/apk/res/android"> <TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Guess my favorite color:" /> <RadioGroup android:id="@+id/RadioGroup01" android:layout_below="@id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"> <RadioButton android:id="@+id/redButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Red" /> <RadioButton android:id="@+id/greenButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Green" /> <RadioButton android:id="@+id/blueButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Blue" /> </RadioGroup> </RelativeLayout> TextView RadioButton RelativeLayout01 RadioGroup TextView RadioGroup RadioGroup01 redButton greenButton blueButton package com.view. extends Activity{ public class ToastTest Adding Your Own Examples to ApiDemos | 85 . android.Toast.RadioButton.View. since this //class is in a sub-package. import com.widget. android. //Need the following import to get access to the app resources.example.Bundle.R.apis.android.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/RelativeLayout01" android:layout_width="wrap_content " android:layout_height="wrap_content" xmlns:android="http://schemas. import import import import import android.apis. android.android.os.widget.view.android. android.Activity.toast_test <?xml version="1.app.

*/ @Override public void onCreate(Bundle savedInstanceState) { super. "Ooooh. Toast. } } Activity ContentView RadioButton OnClickListener redButton toast_test <activity android:name=".MAIN" /> <category android:name="android. } }).layout. setContentView(R.onCreate(savedInstanceState).redButton). red".SAMPLE_CODE" /> </intent-filter> </activity> 86 | Chapter 6: The ApiDemos Application .view.show().action.intent.intent.OnClickListener(){ public void onClick(View v){ Toast./** Called when the activity is first created. redButton.id. final RadioButton redButton = (RadioButton) findViewById(R.category.LENGTH_SHORT).setOnClickListener(new View.ToastTest" android:label="Views/ToastTest" > <intent-filter> <action android:name="android.makeText(ToastTest.this.toast_test).

CHAPTER 7 Signing and Publishing Your Application 87 .

jarsigner Test Your Application 88 | Chapter 7: Signing and Publishing Your Application .

.maps" /> <activity android:name=".Attach an End User License Agreement If Desired Create and Attach an Icon and Label <application android:icon="@drawable/icon2" android:debuggable="true"> <uses-library android:name="com.google.MicroJobs" android:label="@string/app_name"> <intent-filter> ..android. Create and Attach an Icon and Label | 89 .

com/apk/res/android" package="com.mjandroid" android:versionCode="1" android:versionName="1.android.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.0"> versionCode Obtaining a Signing Certificate and API Key 90 | Chapter 7: Signing and Publishing Your Application .Clean Up for Release android:debuggable=true Version Your Application <?xml version="1.microjobsinc.

jarsigner Getting a Signing Certificate for an Application You Are Going to Ship Obtaining a Signing Certificate and API Key | 91 .

keystore -alias mjkey -keyalg RSA -validity 10000 keytool -v -keystore mjkey -alias -validity keytool keytool -keyalg -genkey 92 | Chapter 7: Signing and Publishing Your Application .Generating a key pair (public and private keys) and a signing certificate keytool keytool keytool $ keytool -genkey -v -keystore microjobs.

keytool keytool keytool Getting a Signing Certificate While Debugging apiKey Getting the MD5 fingerprint of your Debug signing certificate your_username your_username Obtaining a Signing Certificate and API Key | 93 .

keystore 94 | Chapter 7: Signing and Publishing Your Application .android/debug.keytool $ keytool -list -alias androiddebugkey -keystore ~/.apk..keystore -storepass android -keypass android -keystore keytool What Happens When My Debug Signing Certificate Expires? debug: [echo] Packaging bin/samples-debug.. [exec] Debug Certificate expired on 8/4/08 3:43 PM Getting a Map API Key from Google keytool $ keytool -list -alias mjkey -keystore microjobs. and signing it with a debug key.

android.maps.keystore $ jarsigner -verbose -keystore microjobs.keystore MJAndroid.keytool <com.google.apk mjkey Signing Your Application | 95 .MapView android:id="@+id/mapmain" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="0P18K0TAE0dO2GifdtbuScgEGLWe3p4CYUQngMg" /> apiKey Signing Your Application Android Tools jarsigner microjobs.

Retesting Your Application Publishing on Android Market Signing Up As an Android Developer Uploading Your Application 96 | Chapter 7: Signing and Publishing Your Application .

Publishing on Android Market | 97 .

.

PART II Programming Topics .

.

CHAPTER 8 Persistent Data Storage: SQLite Databases and Content Providers Databases 101 .

SQLite SELECT UPDATE SQLite Basic Structure of the MicroJobsDatabase Class MicroJobsDatabase MicroJobsDatabase onCreate onUpgrade SQLiteOpenHelper onCreate 102 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .

onUpgrade MicroJobsDatabase MicroJobsDatabase DATABASE_NAME "MicroJobs" adb pull adb DATABASE_VERSION DATABASE_VERSION onUpgrade MicroJobsDatabase super MicroJobsDatabase ContentProvider Context Context Context getContext Context Activity onCreate onCreate MicroJobsDatabase onCreate onCreate Databases | 103 .

. description TEXT. title TEXT..getString(R.. status) VALUES (NULL. end_time INTEGER. employer_id INTEGER. 'Filled').. . INSERT INTO status (_id . status) VALUES (NULL. <string name="MicroJobsDatabase_onCreate">" CREATE TABLE jobs (_id INTEGER PRIMARY KEY AUTOINCREMENT.split("\n")...String onCreate MicroJobsDatabase_onCreate sql String[] sql = mContext. start_time INTEGER.MicroJobsDatabase_onCreate). "</string> getString ###BOT_TEXT###quot;

Related Interests

MicroJobs Database_onCreate onCreate SQL onUpdate onUpdate onCreate <string name="MicroJobsDatabase_onUpgrade">" DROP TABLE IF EXISTS jobs DROP TABLE IF EXISTS employers 104 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . 'Applied For'). . CREATE TABLE employers( _id INTEGER.. . INSERT INTO status (_id . . INSERT INTO status (_id . CREATE TABLE status( _id INTEGER PRIMARY KEY AUTOINCREMENT. 'Open'). employer_name TEXT. status) VALUES (NULL. CREATE TABLE workers( _id INTEGER PRIMARY KEY AUTOINCREMENT.string. status INTEGER)..

getString(R. db. this. DATABASE_VERSION).e("Error creating tables and debug data". import .string.mjandroid.beginTransaction().DROP TABLE IF EXISTS workers DROP TABLE IF EXISTS status "</string> <string> </string> MicroJobsDatabase. DATABASE_NAME. Since this is not a Content Provider. null.. /** The version of the database that this class understands. /** Keep track of context so that we can load SQL from string resources */ private final Context mContext.setTransactionSuccessful().. * no other applications will have access to the database.microjobsinc.java MicroJobsDatabase. */ private static final int DATABASE_VERSION = 1. db. /** * Provides access to the MicroJobs database.toString()). try { // Create tables and test data execMultipleSQL(db. */ public class MicroJobsDatabase extends SQLiteOpenHelper { /** The name of the database file on the file system */ private static final String DATABASE_NAME = "MicroJobs". } /** Called when it is time to create the database */ @Override public void onCreate(SQLiteDatabase db) { String[] sql = mContext. e.mContext = context. } catch (SQLException e) { Log. sql). Databases | 105 . /** Constructor */ public MicroJobsDatabase(Context context) { super(context.MicroJobsDatabase_onCreate).split("\n").java (structure): package com.

getString(R.MicroJobsDatabase_onUpgrade).split("\n").trim().length()>0) db. int oldVersion. onCreate(db).endTransaction(). not rebuild from scratch. db. } // This is cheating. "Upgrading database from version " + oldVersion + " to " + newVersion + ". } /** * Execute all of the SQL statements in the String[] array * @param db The database on which to execute the statements * @param sql An array of SQL statements to execute */ private void execMultipleSQL(SQLiteDatabase db.setTransactionSuccessful(). } finally { db. } finally { db.execSQL(s). String[] sql){ for( String s : sql ) if (s. throw e. In the real world. String[] sql = mContext. } } MicroJobsDatabase getReadableDatabase Context getWritableDatabase 106 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .throw e.toString()). db.beginTransaction(). you'll need to add columns.e("Error upgrading tables and debug data".endTransaction().LOG_TAG. sql). } } /** Called when the database must be upgraded */ @Override public void onUpgrade(SQLiteDatabase db. int newVersion) { Log. } catch (SQLException e) { Log. e. which will destroy all old data").w(MicroJobs. try { execMultipleSQL(db.string.

Databases | 107 ..Reading Data from the Database MicroJobsDatabase getJobs MicroJobsDatabase JobsCursor JobsCursor getJobs title employer_name public class MicroJobsDatabase extends SQLiteOpenHelper { ..

/** Return a sorted JobsCursor * @param sortBy the sort criteria */ public JobsCursor getJobs(JobsCursor.SortBy sortBy) { String sql = JobsCursor. sql. query). String editTable. private JobsCursor(SQLiteDatabase db. SQLiteCursorDriver driver.rawQueryWithFactory( new JobsCursor. public static class JobsCursor extends SQLiteCursor{ public static enum SortBy{ title. c. SQLiteQuery query) { super(db. employer_name._id")).employer_id = employers. SQLiteQuery query) { return new JobsCursor(db. employers "+ "WHERE jobs.} public String getColEmployerName() {return getString(getColumnIndexOrThrow("employer_name")).} public String getColTitle() {return getString(getColumnIndexOrThrow("title")). query). latitude.. driver.} public long getColLatitude() {return getLong(getColumnIndexOrThrow("latitude")). longitude.moveToFirst(). } . employer_name } private static final String QUERY = "SELECT jobs.} public long getColStatus(){return getLong(getColumnIndexOrThrow("status")). editTable. JobsCursor c = (JobsCursor) d.toString(). editTable.CursorFactory{ @Override public Cursor newCursor(SQLiteDatabase db. null. SQLiteCursorDriver driver.. return c.} } sortBy 108 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . } private static class Factory implements SQLiteDatabase.} public long getColLongitude() {return getLong(getColumnIndexOrThrow("longitude")).QUERY + sortBy. } } public long getColJobsId() {return getLong(getColumnIndexOrThrow("jobs.Factory(). status "+ "FROM jobs. null). driver. String editTable. title._id "+ "ORDER BY ". SQLiteDatabase d = getReadableDatabase()._id.

getJobs(JobsCursor.SortBy. JobsCursor cursor = db.QUERY QUERY getJobs MicroJobsDatabase getJobs toString JobsCursor JobsCursor JobsCursor Factory SQLiteDatabase rawQueryWith rawQuery Cursor JobsCursor moveToFirst Cursor getJobs enum Factory JobsCursor JobsCursor getColTitle title getJobs MicroJobsDatabase db = new MicroJobsDatabase(this). Databases | 109 .title).

rowNum++){ cursor.getText().id. rowNum<cursor.addJob(employer. doSomethingWith(cursor.toString()).toString(). } MicroJobsDatabase JobsCursor this SortBy JobsCursor Modifying the Database SQLiteDatabase insert query update execSQL delete Inserting data into the database INSERT INSERT db.getColTitle()).getCount(). addJob addJob insert 110 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . txtTitle.for( int rowNum=0. txtDescription.getText().moveToPosition(rowNum).

} catch (SQLException e) { Log. 3)". * @param employer_id The employer offering the job * @param title The job title * @param description The job description */ public void addJob(long employer_id. } } Databases | 111 . map. 0. description. map.e("Error writing new job". end_time. bindArgs). status) " + "VALUES ( NULL. start_time./** * Add a new job to the database. title. title). ?. String title. e. title. String title. try{ getWritableDatabase(). 0.toString()). map).e("Error writing new job".toString()). The job will have a status of open.put("title".put("employer_id".put("description". try{ getWritableDatabase(). map. ?. ?.insert("jobs". Object[] bindArgs = new Object[]{employer_id. * @param employer_id The employer offering the job * @param title The job title * @param description The job description */ public void addJob(long employer_id. The job will have a status of open. employer_id. e. null. String description){ String sql = "INSERT INTO jobs (_id. String description){ ContentValues map = new ContentValues().Object> ContentValues ContentValues insert nullColumnHack HashMap ContentValues execSQL /** * Add a new job to the database. description}.execSQL(sql. } } ContentValues HashMap<String. employer_id). } catch (SQLException e) { Log. description).

put("description".toString(job_id)}. 112 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .put("employer_id". map. long employer_id. txtTitle.getText(). String title. map. map. String[] whereArgs = new String[]{Long. String description) { ContentValues map = new ContentValues(). txtDescription. employer.id. description). title).getText().put("title". * @param job_id The job id of the existing job * @param employer_id The employer offering the job * @param title The job title * @param description The job description */ public void editJob(long job_id.toString(). employer_id).sql bindArgs execSQL String StringBuilder Updating data already in the database editJob db. editJob editJob update /** * Update a job in the database.toString()).editJob((long)job_id.

} catch (SQLException e) { Log. bindArgs).e("Error writing new job". } } update execSQL /** * Update a job in the database. "+ " title = ?. String title. } catch (SQLException e) { Log. job_id}.toString()).e("Error writing new job". try{ getWritableDatabase(). "+ " description = ? "+ "WHERE _id = ? ". long employer_id. map.update("jobs". } } employer_id Deleting data in the database Databases | 113 .toString()). String description) { String sql = "UPDATE jobs " + "SET employer_id = ?.execSQL(sql. * @param job_id The job id of the existing job * @param employer_id The employer offering the job * @param title The job title * @param description The job description */ public void editJob(long job_id. e. Object[] bindArgs = new Object[]{employer_id. description. whereArgs).try{ getWritableDatabase(). e. "_id=?". title.

* @param job_id The job id of the job to delete */ public void deleteJob(long job_id) { String[] whereArgs = new String[]{Long. deleteJob MicroJobsDatabase delete /** * Delete a job from the database.e("Error deleteing job".format( "DELETE FROM jobs " + "WHERE _id = '%d' ". try{ getWritableDatabase().deleteJob(job_id). e. e. "_id=?".execSQL(sql). } catch (SQLException e) { Log.toString()). job_id).toString(job_id)}.db. } } execSQL /** * Delete a job from the database. * @param job_id The job id of the job to delete */ public void deleteJob(long job_id) { String sql = String.delete("jobs". try{ getWritableDatabase(). whereArgs).e("Error deleteing job". } } Content Providers 114 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .toString()). } catch (SQLException e) { Log.

create read update delete SQLite Content Providers | 115 .

_id INTEGER PRIMARY KEY AUTOINCREMENT AUTOINCREMENT title note created modified 116 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . created INTEGER. title TEXT.Introducing NotePad Activities Database NotePad CREATE TABLE notes ( _id INTEGER PRIMARY KEY. note TEXT. modified INTEGER ).

cursor.google.NotePad".note".parse("content://" + AUTHORITY + "/notes").android.Structure of the source code <provider> <provider> <application> android:icon NoteEditor notes NotePadProvider NotePad Activity notes AUTHORITY Notes Note NotePad Notes public final class NotePad { public static final String AUTHORITY = "com. private NotePad() {}// This class cannot be instantiated /** Notes table */ public static final class Notes implements BaseColumns { // This class cannot be instantiated private Notes() {} // This class cannot be instantiated public static final Uri CONTENT_URI = Uri.provider.google. public static final String CONTENT_TYPE = "vnd.dir/vnd. Content Providers | 117 .

public static final String TITLE = "title".note".cursor. } } NotePadProvider NotesList TitleEditor Content Providers NotePadProvider Implementing a content provider ContentProvider CONTENT_URI <provider> 118 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . public static final String MODIFIED_DATE = "modified". public static final String CREATED_DATE = "created".item/vnd.android. public static final String NOTE = "note".public static final String CONTENT_ITEM_TYPE= "vnd.google.

Extend ContentProvider. static final int DATABASE_VERSION = 2.db". static final String NOTES_TABLE_NAME = "notes". ContentProvider public class NotePadProvider extends ContentProvider NotePadProvider ContentProvider onCreate getType insert query ContentProvider managedQuery update ContentProvider delete ContentProvider NotePadProvider class and instance variables. DATABASE_NAME Content Providers | 119 . DatabaseHelper mOpenHelper. ContentProvider private private private private static final String DATABASE_NAME = "note_pad.

CREATED_DATE).TITLE. private static final int NOTES = 1. sNotesProjectionMap = new HashMap<String. sNotesProjectionMap. Notes.put(Notes.addURI(NotePad.. sUriMatcher. String> sNotesProjectionMap.put(Notes.put(Notes. sUriMatcher. Notes.CREATED_DATE.NOTE). NOTE_ID). Notes.. "notes". static { sUriMatcher = new UriMatcher(UriMatcher.onUpdate NOTES_TABLE_NAME notes mOpenHelper insert query update onCreate delete NotePadContentProvider notes private static HashMap<String. sNotesProjectionMap. NOTES). ._ID.NO_MATCH).AUTHORITY. sNotesProjectionMap.TITLE).addURI(NotePad. sNotesProjectionMap. "notes/#".AUTHORITY. } sNotesProjectionMap HashMap NotePadContentProvider sNotesProjectionMap sUriMatcher sUriMatcher NOTES NOTES sUriMatcher NotePadContentProvider NOTES_ID 120 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . Notes._ID).MODIFIED_DATE). Notes.NOTE. private static final int NOTE_ID = 2.put(Notes. String>().DATABASE_VERSION DatabaseHelper.MODIFIED_DATE. sNotesProjectionMap. private static final UriMatcher sUriMatcher.put(Notes.

NotePad com.google.google.provider NotePad CONTENT_URI content://contacts/people/1 content://contacts/people/1/phone/3 Content Providers | 121 .NOTES_ID sUriMatcher Define CONTENT_URI. CONTENT_URI CONTENT_URI CONTENT_URI content:// com.provider.

google.android.cursor.dir/ phone CONTENT_URI CONTENT_URI NotePad public static final Uri AUTHORITY public final class NotePad { public static final String AUTHORITY = "com. } private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context.android.provider.parse("content://" + AUTHORITY + "/notes"). } @Override 122 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .person vnd. DATABASE_NAME.android.item/ vnd.android. null.cursor. onCreate SQLite ContentProvider NotePadProvider onCreate @Override public boolean onCreate() { mOpenHelper = new DatabaseHelper(getContext()). CONTENT_URI public static final class Notes implements BaseColumns { public static final Uri CONTENT_URI = Uri.item/phone vnd.item/phone vnd. Create the data storage. return true.cursor.NotePad".cursor. DATABASE_VERSION).

execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " (" + Notes. onCreate(db)." + Notes._ID + " INTEGER PRIMARY KEY. } } Helper DatabaseHelper DatabaseHelper onCreate SQLiteOpen onUpgrade DatabaseHelper mOpenHelper execSQL Data Store for Binary Data content:// content:// content:// content:// Content Providers | 123 ." + Notes.NOTE + " TEXT.TITLE + " TEXT.execSQL("DROP TABLE IF EXISTS notes")." + Notes.not nice to do in a real app! db.MODIFIED_DATE + " INTEGER" + ")."). int newver) { // destroy the old version -. } @Override public void onUpgrade(SQLiteDatabase db.public void onCreate(SQLiteDatabase db) { db." + Notes. int oldver.CREATED_DATE + " INTEGER.

_data TEXT ).CREATE TABLE user ( _id INTEGER PRIMARY KEY AUTOINCREMENT. picture TEXT ). CREATE TABLE user ( _id INTEGER PRIMARY KEY AUTOINCREMENT. SQL SQLite NotePadProvider NotePadProvider 124 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .io. name TEXT. password TEXT. password TEXT. CREATE TABLE userPicture ( _id INTEGER PRIMARY KEY AUTOINCREMENT. picture BLOB ).OutputStream ContentResolver _data openOutputStream Create the column names. picture userPicture user _data content:// userPicture user ContentResolver ContentResolver java. name TEXT.

string.r.currentTimeMillis()). if (values. } Create data (insert). if (initialValues != null) values = new ContentValues(initialValues).put(NotePad.R. } ContentValues values. now).Notes.put(NotePad.CREATED_DATE) == false) values. if (values.TITLE) == false) { Resources r = Resources.MODIFIED_DATE) == false) values.Notes.containsKey(NotePad.Supporting binary data.Notes.valueOf(System.containsKey(NotePad.MODIFIED_DATE.containsKey(NotePad. Long now = Long.Notes. now). ContentValues initialValues) { // Validate the requested uri if (sUriMatcher. ContentResolver Declare column specification strings.TITLE.getString(android.Notes.untitled)).CREATED_DATE.put(NotePad. values. NotePad. // Make sure that the fields are all set if (values.Notes NotePadProvider _id _id NotePadProvider _id _id _id INTEGER PRIMARY KEY AUTOINCREMENT _id _ids Implement the Cursor. Content Providers | 125 . ContentProvider insert query update delete NotePadProvider ContentProvider insert ContentProvider ContentValues @Override public Uri insert(Uri uri.getSystem().match(uri) != NOTES) { throw new IllegalArgumentException("Unknown URI " + uri).Notes. else values = new ContentValues().

} Read/select data (query).withAppendedId(NotePad.DEFAULT_SORT_ORDER. qb.appendWhere(Notes. return noteUri.notifyChange(noteUri. case NOTE_ID: qb. } else { orderBy = sortOrder.Notes. String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(). Notes.setProjectionMap(sNotesProjectionMap). if (TextUtils.isEmpty(sortOrder)) { orderBy = NotePad.put(NotePad. long rowId = db.Notes.NOTE. } throw new SQLException("Failed to insert row into " + uri). null).rowId). getContext()._ID + "=" + uri. } 126 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .NOTE. } // If no sort order is specified use the default String orderBy.getPathSegments().getWritableDatabase(). qb. values).get(1)).Notes. if (rowId > 0) { Uri noteUri=ContentUris.Notes.setTables(NOTES_TABLE_NAME).getContentResolver(). default: throw new IllegalArgumentException("Unknown URI " + uri).insert(NOTES_TABLE_NAME.setTables(NOTES_TABLE_NAME).CONTENT_URI. NotePadProvider SQLite QueryBuilder SQLiteQueryBuilder NOTE_ID WHERE NotePadProvider @Override public Cursor query(Uri uri.containsKey(NotePad. String selection. } SQLiteDatabase db = mOpenHelper.NOTE) == false) { values. break. break. String[] projection. String[] selectionArgs. qb.setProjectionMap(sNotesProjectionMap).match(uri)) { case NOTES: qb.if (values. ""). switch (sUriMatcher.

switch (sUriMatcher. return c.String where. NotePadProvider SQLiteDatabase ContentValues where ContentValues SQLiteDatabase where update whereArgs where whereArgs dogName 'Jackson' "dogName='Jackson'" update where update values ContentProvider whereArg ContentProvider where "dogName=?" whereArgs whereArgs @Override public int update(Uri uri.selectionArgs.null.orderBy). int count. dogName Content Providers | 127 . break.getReadableDatabase(). whereArgs). Cursor c=qb.match(uri)) { case NOTES: count = db.ContentValues values.update(NOTES_TABLE_NAME.setNotificationUri(getContext(). uri).getWritableDatabase(). where. // Tell cursor what uri to watch.// Get the database and run the query SQLiteDatabase db = mOpenHelper.projection.getContentResolver(). values. } Update data.query(db.null.String[] whereArgs) { SQLiteDatabase db = mOpenHelper.selection. so it knows when its source data changes c.

xml. default: throw new IllegalArgumentException("Unknown URI " + uri). whereArgs)._ID + "=" + noteId + (!TextUtils.getContentResolver(). update case NOTE_ID: String noteId = uri.get(1).notifyChange(uri. default: throw new IllegalArgumentException("Unknown URI " + uri). return count. String where.getContentResolver().delete(NOTES_TABLE_NAME.match(uri)) { case NOTES: count = db.getPathSegments(). values. null).NotePad" /> android:authorities <provider> 128 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . } Updating AndroidManifest. count = db.getPathSegments().isEmpty(where)?" AND ("+where+')':""). count = db._ID + "=" + noteId + (!TextUtils. break. <provider> <provider> <provider android:name="NotePadProvider" android:authorities="com.delete(NOTES_TABLE_NAME.update(NOTES_TABLE_NAME. Notes.provider. NotePadProvider delete @Override public int delete(Uri uri.getWritableDatabase(). } Delete data. break. whereArgs). whereArgs).case NOTE_ID: String noteId = uri. String[] whereArgs) { SQLiteDatabase db = mOpenHelper. where. int count. Notes. return count.notifyChange(uri. } getContext().get(1). } getContext(). break.google. switch (sUriMatcher. null).isEmpty(where)?" AND ("+where+')':"").

android.note N vnd.cursor.google.CONTENT_TYPE.item/ getType vnd.CONTENT_ITEM_TYPE.cursor.note case NOTE_ID: return Notes.google.android.note getType vnd.cursor.cursor. NotePadProvider getType vnd.cursor.google.dir/vnd.dir/vnd.android:name AUTHORITY NotePad NotePadProvider Define MIME types. // vnd.android.dir @Override public String getType(Uri uri) { switch (sUriMatcher.item vnd.android.android.cursor.android.google.item/vnd. // vnd.note default: throw new IllegalArgumentException("Unknown URI " + uri).match(uri)) { case NOTES: return Notes. } } Consuming a Content Provider NotePadProvider NotePadProvider NotePadProvider Content Providers | 129 .

insert(intent.ACTION_INSERT. final String action = intent. and create a new entry // in the container. } .getData(). } NotesList NotesList ACTION_INSERT insert onCreate ACTION_INSERT mUri = getContentResolver().ACTION_EDIT.. null). mUri = getContentResolver(). null)... // Do some setup based on the action being performed..insert(intent. 130 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers ..onCreate(savedInstanceState).equals(action)) { .. .getData().equals(action)) { // Requested to insert: set that state. } else if (Intent.NotePadProvider ContentProvider Create data (insert) NoteEditor @Override protected void onCreate(Bundle savedInstanceState) { super.getAction(). if (Intent. final Intent intent = getIntent(). if (mUri == null) { // Creating the new note failed finish(). } // Do something with the new note here. return.

getData null update ContentResolver ContentResolver Content Providers | 131 .mUri mUri ListActivity ContentResolver Activity NotesList ContextWrapper ContextWrapper.getContentResolver insert ContentResolver intent.

private static final String[] PROJECTION = new String[] { Notes. Intent intent = getIntent()...TITLE.getData() == null) { intent. @Override protected void onCreate(Bundle savedInstanceState) { super. // 1 }.._ID. setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT). . // 0 Notes.Read/query data managedQuery query managedQuery uri Activity projection String selection String selectionArgs String NULL sortOrder String NULL ORDER BY NotePadProvider public class NotesList extends ListActivity { .CONTENT_URI). // If no data was given in the Intent (because we were started // as a MAIN activity). then use our default content provider.setData(Notes.onCreate(savedInstanceState). } NULL 132 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers . if (intent..

Cursor cursor = managedQuery(getIntent().OnClickListener { /** An array of the columns we are interested in.id. */ private static final String[] PROJECTION = new String[] { NotePad. null.text1 }). new int[] { android.setOnCreateContextMenuListener(this). new String[] { Notes.DEFAULT_SORT_ORDER). PROJECTION. // Used to map notes entries from the database to views SimpleCursorAdapter adapter = new SimpleCursorAdapter( this.TITLE }.getData(). The Activity will handle closing // and requerying the cursor when needed. cursor. // 0 Content Providers | 133 . setListAdapter(adapter). } managedQuery DEFAULT_KEYS_SHORTCUTS managedQuery setListAdapter Update data TitleEditor TitleEditor public class TitleEditor extends Activity implements View.noteslist_item. null. Notes.layout.// Inform the list we provide context menus for items getListView()._ID. // Perform a managed query.Notes. R.R.

null. */ private Cursor mCursor. // Set up click handlers for the text field and button mText = (EditText) this.title_editor). 134 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .getData().findViewById(R.setOnClickListener(this). /** Index of the title column */ private static final int COLUMN_INDEX_TITLE = 1. /** Cursor providing access to the note whose title we are editing. */ private EditText mText. Used to extract the text when done. TitleEditor PROJECTION managedQuery COLUMN_INDEX_TITLE TITLE mUri PROJECTION mCursor mText EditText onCreate @Override public void onCreate(Bundle savedInstanceState) { super. /** The content URI to the note that's being edited.Notes. null).title). /** The EditText field from our UI.id.NotePad. null.onCreate(savedInstanceState). PROJECTION. mText. // Get the uri of the note whose title we want to edit mUri = getIntent(). // 1 }. // Get a cursor to access the note mCursor = managedQuery(mUri.layout.TITLE. setContentView(R. */ private Uri mUri.

getString(COLUMN_INDEX_TITLE)).update(mUri. } } onPause @Override protected void onPause() { super. } ContentView setContentView managedQuery onClick onCreate onResume @Override protected void onResume() { super. } } ContentValues ContentResolver values ContentResolver Content Providers | 135 .onPause(). mText.setOnClickListener(this). getContentResolver().moveToFirst(). // Initialize the text with the title column from the cursor if (mCursor != null) { mCursor. null).put(Notes. null.Button b = (Button) findViewById(R.toString()).id. mText.ok). values.setText(mCursor.onResume(). if (mCursor != null) { // Write the title back to the note ContentValues values = new ContentValues().TITLE. b. values.getText().

info.getData(). } finish onPause Delete data NotesList @Override public boolean onContextItemSelected(MenuItem item) { AdapterView. getContentResolver(). } } return false. info = (AdapterView. switch (item. null. } MenuItem ContentResolver delete 136 | Chapter 8: Persistent Data Storage: SQLite Databases and Content Providers .getItemId()) { case MENU_ITEM_DELETE: { // Delete the note that the context menu is for Uri noteUri = ContentUris.withAppendedId(getIntent(). just finish this activity.AdapterContextMenuInfo info. finish(). // onPause will be called. null). return true. and we save our data there.AdapterContextMenuInfo) item.id).getMenuInfo() .delete(noteUri.TitleEditor onClick public void onClick(View v) { // When the user clicks.

CHAPTER 9 Location and Mapping Location-Based Services 137 .

138 | Chapter 9: Location and Mapping .

Uri uri) action Uri geo:latitude.Mapping The Google Maps Activity new Intent(String action.422006. The Google Maps Activity | 139 .longitude?z=zoom geo:0.084095").-122.0?qmy_street_address geo:0. "geo:37.0?qbusiness_near_city startActivity(Intent intent) ACTION_VIEW Intent intent = new Intent(ACTION_VIEW.longitude geo:latitude. startActivity(intent).

google.android.The MapView and MapActivity <application android:icon="@drawable/icon2"> <uses-library android:name="com.maps" /> uses-library line <application> <activity> apiKey Working with MapViews 140 | Chapter 9: Location and Mapping .

getIntrinsicHeight()).setEnabled(true).getController(). } }).add(new MJJobsOverlay(marker)).setClickable(true).getMyLocation()). mc. mvMap.id.animateTo(mMyLocationOverlay.setBounds(0. marker.MapView and MyLocationOverlay Initialization MyLocationOverlay @Override public void onCreate(Bundle savedInstanceState) { . marker. 0. mvMap).android_tiny_image).runOnFirstFix( new Runnable() { public void run() { mc.getOverlays(). mvMap = (MapView) findViewById(R.setZoom(16).getDrawable(R.. Working with MapViews | 141 .getIntrinsicWidth().. mvMap. marker. mMyLocationOverlay = new MyLocationOverlay(this. // get the map controller final MapController mc = mvMap. mMyLocationOverlay. mvMap.mapmain). Drawable marker = getResources().drawable.

setZoom(16).setSatellite(false).getMyLocation() mMyLocationOverlay mvMap mvMap runOnFirstFix isRouteDisplayed() false 142 | Chapter 9: Location and Mapping ..mvMap. .. } mvMap MapView mMyLocationOverlay mMyLocationOverlay runOnFirstFix mMyLocationOverlay. mvMap. // start out with a general zoom mc.setTraffic(false). /** * Required method to indicate whether we display routes */ @Override protected boolean isRouteDisplayed() { return false. mvMap.setStreetView(false).

View setSatellite setTraffic setStreetView Zooming in Android Maps zoomIn Working with MapViews | 143 .setClickable true setEnabled android.view.

google. int ypixel) zoomToSpan(int latSpanE6. int ypixel). int longSpanE6) zoomToSpan(2500000.android.maps. 1000000) Pausing and Resuming a MapActivity onPause() onResume onPause /** * @see com.zoomOut setZoom(int zoomlevel) zoomInFixing(int xpixel.MapActivity#onPause() */ @Override public void onPause() { onResume 144 | Chapter 9: Location and Mapping . zoomOutFixing(int xpixel.

map_menu_zoom_in)). } Working with MapViews | 145 . 1. Menu.NONE.MapActivity#onResume() */ @Override public void onResume() { super. } /** * @see com.NONE.NONE. 3. menu.onResume().maps.android.add(Menu.onPause().NONE.google. 5. getString(R.NONE.NONE.Menu) */ @Override public boolean onCreateOptionsMenu(Menu menu) { boolean supRetVal = super. menu. getString(R. Menu.NONE.view. menu.enableMyLocation().Activity#onCreateOptionsMenu(android.NONE. 0.app.super.add(Menu. mMyLocationOverlay. getString(R. menu.NONE.onCreateOptionsMenu(menu).map_menu_set_traffic)).NONE. 4. Menu. getString(R.string.add(Menu. getString(R.string. Menu.add(Menu. menu. 2.string.add(Menu.disableMyLocation().NONE.map_menu_set_satellite)). return supRetVal.add(Menu. menu. getString(R.map_menu_zoom_out)). } Controlling the Map with Menu Buttons /** * Set up menus for this page * * @see android.NONE.string. Menu.map_menu_set_map)).map_menu_show_list)). mMyLocationOverlay. Menu.string.string.

add Menu.isSatellite()).Activity#onOptionsItemSelected(android.isStreetView()).add int groupid menu.getItemId()) { case 0: // Zoom in zoomIn(). return true. case 2: // Toggle satellite views mvMap.NONE int titleRes getString onOptionsItemSelected /** * @see android. case 4: 146 | Chapter 9: Location and Mapping .MenuItem) */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.app.view. return true.setSatellite(!mvMap.setStreetView(!mvMap. return true. case 3: // Toggle street views mvMap. case 1: // Zoom out zoomOut(). return true.NONE int itemid int order itemid Menu.onCreateOptionsMenu menu.

return true. KeyEvent event) { switch (keyCode) { case KeyEvent.view.setTraffic(!mvMap. MicroJobsList.// Toggle traffic views mvMap.app. } } onKeyDown KEYCODE_A KEYCODE_Z KEYCODE_SHIFT_RIGHT KEYCODE_SPACE KEYCODE_SHIFT_LEFT KEYCODE_CAMERA KEYCODE_VOLUME_UP Working with MapViews | 147 . return true.KeyEvent) */ @Override public boolean onKeyDown(int keyCode.this.KEYCODE_BACK: // go back (meaning exit the app) finish(). return true. } MenuItem Controlling the Map with the KeyPad /** * @see android.Activity#onKeyDown(int.class)). return true. case KeyEvent. case KeyEvent. } return false.KEYCODE_DPAD_DOWN: // zoom out zoomOut(). default: return false. case 5: // Show the job list activity startActivity(new Intent(MicroJobs.isTraffic()). android.KEYCODE_DPAD_UP: // zoom in zoomIn(). return true.

permission.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/lblLatitude" android:layout_width="fill_parent" android:layout_height="wrap_content" 148 | Chapter 9: Location and Mapping .com/apk/res/android" package="com.action.android.ACCESS_FINE_LOCATION <?xml version="1.Main" android:label="@string/app_name"> <intent-filter> <action android:name="android.ACCESS_FINE_LOCATION"> </uses-permission> </manifest> <?xml version="1.0.microjobsinc.MAIN" /> <category android:name="android.category.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".dloc" android:versionCode="1" android:versionName="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.permission.intent.intent.android.Location Without Maps The Manifest and Layout Files uses-permission android.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.

android.getLongitude())). import import import import import import android.location.onCreate(savedInstanceState). setContentView(R.Location. Location Without Maps | 149 . // get handle for LocationManager LocationManager lm = (LocationManager) getSystemService(Context.content. // fill in the TextViews tvLatitude.os.toString(loc.setText(Double. tvLongitude.id.android:text="Latitude:" /> <TextView android:id="@+id/tvLatitude" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/lblLongitude" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Longitude:" /> <TextView android:id="@+id/tvLongitude" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> Connecting to a Location Provider and Getting Location Updates LocationProvider package com.layout.tvLongitude). android.getLatitude())).location.LocationManager.widget.tvLatitude).app.TextView. // connect to the GPS location service Location loc = lm. android.getLastKnownLocation("gps").main).setText(Double.toString(loc. */ @Override public void onCreate(Bundle savedInstanceState) { super.Activity.microjobsinc.dloc. android.Bundle. // find the TextViews TextView tvLatitude = (TextView)findViewById(R. public class Main extends Activity { /** Called when the activity is first created. android. TextView tvLongitude = (TextView)findViewById(R.Context.id.LOCATION_SERVICE).

dloc.Activity.main). android.os. // get handle for LocationManager LocationManager lm = (LocationManager) getSystemService(Context. android. public class Main extends Activity { private LocationManager lm.onCreate(savedInstanceState). public TextView tvLatitude. tvLongitude = (TextView)findViewById(R.location. */ @Override public void onCreate(Bundle savedInstanceState) { super.content.LOCATION_SERV getLastKnownLocation("provider") LocationManager LocationManager LocationManager DispLocListener DispLocListener LocationListener onCreate package com.id. public TextView tvLongitude.Context. android.widget.LOCATION_SERVICE). private LocationListener locListenD.tvLongitude).layout.location.app.} } LocationManager ICE) LocationManager getSystemService(Context.location.microjobsinc. import import import import import import import android. // find the TextViews tvLatitude = (TextView)findViewById(R.TextView. android. android.Location.id. setContentView(R.LocationManager. /** Called when the activity is first created. // connect to the GPS location service 150 | Chapter 9: Location and Mapping .LocationListener. android.Bundle.tvLatitude).

Bundle extras) { } } } onCreate LocationManager String provider long minTime DispLocListener requestLocationUpdates LocationManager float minDistance Location Manager LocationListener listener DispLocListener Location Without Maps | 151 .Location loc = lm. tvLongitude. lm.0f. } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider.getLongitude())).toString(location.setText(Double. 30000L.getLastKnownLocation("gps"). tvLongitude.toString(loc.getLatitude())). int status. // ask the Location Manager to send us location updates locListenD = new DispLocListener().toString(loc.getLongitude())). locListenD).requestLocationUpdates("gps".setText(Double. // fill in the TextViews tvLatitude.getLatitude())).setText(Double.toString(location.setText(Double. } private class DispLocListener implements LocationListener { @Override public void onLocationChanged(Location location) { // update TextViews tvLatitude. 10.

onPause onResume /** * Turn off location updates if we're paused */ @Override public void onPause() { super. 10.requestLocationUpdates("gps". locListenD).onResume(). lm. } Updating the Emulated Location Using geo to update location geo geo fix geo fix LocationProvider telnet localhost 5554 Android Console: type 'help' for a list of commands OK geo fix -122. } /** * Resume location updates when we're resumed */ @Override public void onResume() { super.842232 38.411908 0 OK 152 | Chapter 9: Location and Mapping . lm.removeUpdates(locListenD). 30000L.0f.onPause().

geo fix longitude latitude altitude Using DDMS to update location Location Without Maps | 153 .

google.3</scale> <Icon> <href>http://maps.png</href> </Icon> <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> </IconStyle> 154 | Chapter 9: Location and Mapping .kml</name> <StyleMap id="msn_ylw-pushpin"> <Pair> <key>normal</key> <styleUrl>#sn_ylw-pushpin</styleUrl> </Pair> <Pair> <key>highlight</key> <styleUrl>#sh_ylw-pushpin</styleUrl> </Pair> </StyleMap> <Style id="sh_ylw-pushpin"> <IconStyle> <scale>1.<?xml version="1.2"> <Document> <name>OR1.1</scale> <Icon> <href>http://maps.0" encoding="UTF-8"?> <kml xmlns="http://earth.png</href> </Icon> <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/> </IconStyle> <ListStyle> </ListStyle> </Style> <Style id="sn_ylw-pushpin"> <IconStyle> <scale>1.google.com/mapfiles/kml/pushpin/ylw-pushpin.google.com/mapfiles/kml/pushpin/ylw-pushpin.com/kml/2.

38922415809942</latitude> <altitude>0</altitude> <range>14591.7911077944045.0</coordinates> </Point> </Placemark> <Placemark> <name>OR2</name> <LookAt> <longitude>-122.41500788727795.0</coordinates> </Point> </Placemark> <Placemark> <name>OR3</name> <LookAt> <longitude>-122.3819544049429</latitude> <altitude>0</altitude> <range>11881.04087372005871314</heading> <altitudeMode>relativeToGround</altitudeMode> </LookAt> <styleUrl>#msn_ylw-pushpin</styleUrl> <Point> <coordinates>-122.006283077460853e-010</heading> <altitudeMode>relativeToGround</altitudeMode> </LookAt> <styleUrl>#msn_ylw-pushpin</styleUrl> <Point> <coordinates>-122.3330990845</range> <tilt>0</tilt> <heading>-8.40273084940345.8064486052584.<ListStyle> </ListStyle> </Style> <Placemark> <name>OR1</name> <LookAt> <longitude>-122.006283077460853e-010</heading> <altitudeMode>relativeToGround</altitudeMode> </LookAt> <styleUrl>#msn_ylw-pushpin</styleUrl> <Point> <coordinates>-122.38.7166300043</range> <tilt>0</tilt> <heading>0.8239277647483.7677364592949</longitude> <latitude>38.3330990845</range> <tilt>0</tilt> <heading>-8.7583711698369</longitude> <latitude>38.7677364592949</longitude> <latitude>38.0</coordinates> </Point> </Placemark> ..38.38..3819544049429</latitude> <altitude>0</altitude> <range>11881. Location Without Maps | 155 .40786910573772.

.

CHAPTER 10 Building a View Android GUI Architecture The Model 157 .

View Controller invalidate update Model The View View 158 | Chapter 10: Building a View . taps. etc.redraw key press.

The Controller KeyEvent KeyEvent dispatchKeyEvent View Putting It Together Android GUI Architecture | 159 .

EditText View View MotionEvent Button 160 | Chapter 10: Building a View .

View Assembling a Graphical Interface | 161 .view.synchronized Assembling a Graphical Interface MapActivity MyLocationOverlay android.

Bundle.android. @Override public void onCreate(Bundle state) { super. android.LTGRAY). root = new LinearLayout(this).LayoutParams. android. root.intro.Button. android.view. public class AndroidDemo extends Activity { private LinearLayout root.onCreate(state).EditText.ViewGroup.os.setLayoutParams(containerParams).android.graphics.LayoutParams.Activity.Gravity. ViewGroup.0F).LayoutParams containerParams = new LinearLayout. import import import import import import import import android.app.setBackgroundColor(Color.LayoutParams( ViewGroup.widget.oreilly. 1. LinearLayout.FILL_PARENT.FILL_PARENT.ViewGroup View View TextView View TextView package com. root.view.LayoutParams widgetParams = new LinearLayout. android.VERTICAL). 0. root.widget.Color.LinearLayout. android. android. ViewGroup.FILL_PARENT. 162 | Chapter 10: Building a View .setOrientation(LinearLayout.0F).view.widget. LinearLayout.LayoutParams.LayoutParams.WRAP_CONTENT.LayoutParams( ViewGroup. android.

ll.string.setLayoutParams(containerParams).labelRed).setLayoutParams(widgetParams). ll.string. b. b = new Button(this). setContentView(root).defaultLeftText).setText(R.setText(R.setBackgroundColor(Color. tb.DKGRAY).setBackgroundColor(Color. } } LinearLayout View LinearLayout LinearLayout LinearLayout LinearLayout Assembling a Graphical Interface | 163 . b.setOrientation(LinearLayout.GREEN). root. ll.setLayoutParams(widgetParams).setText(R. tb.addView(ll).setFocusable(false).labelGreen). tb. ll.addView(b).setLayoutParams(widgetParams).setText(R.setFocusable(false). ll. tb. tb.addView(b).setTextColor(Color. EditText tb = new EditText(this).HORIZONTAL).defaultRightText). ll.addView(ll).setLayoutParams(widgetParams).GRAY).LinearLayout ll = new LinearLayout(this).addView(tb). ll = new LinearLayout(this). Button b = new Button(this).setOrientation(LinearLayout. b.addView(tb).setTextColor(Color.setLayoutParams(containerParams). b. ll. b.RED).string.string. ll. root. b. tb = new EditText(this). tb.HORIZONTAL). ll. ll.

os.android.app.Bundle.intro. import android. /** * Android UI demo program 164 | Chapter 10: Building a View .Activity.oreilly.View LinearLayout (vertical) LinearLayout (horizontal) LinearLayout (horizontal) Text Text Red button Green button package com. import android.

@Override public void onCreate(Bundle state) { super.*/ public class AndroidDemo extends Activity { private LinearLayout root.main).id.onCreate(state).root).layout.com/apk/res/android" android:id="@+id/root" android:orientation="vertical" android:background="@drawable/lt_gray" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="horizontal" android:background="@drawable/gray" android:layout_width="fill_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/text1" android:text="@string/defaultLeftText" android:focusable="false" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"/> <EditText android:id="@+id/text2" android:text="@string/defaultRightText" android:focusable="false" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:background="@drawable/dk_gray" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:id="@+id/button1" android:text="@string/labelRed" android:textColor="@drawable/red" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"/> Assembling a Graphical Interface | 165 .android. root = (LinearLayout) findViewById(R. setContentView(R. } } <LinearLayout xmlns:android="http://schemas.

id.text2). } } 166 | Chapter 10: Building a View . tb2.OnClickListener() { @Override public void onClick(View arg0) { tb1.onCreate(state). ((Button) findViewById(R. final EditText tb1 = (EditText) findViewById(R.nextInt(200))).layout.button2)).valueOf(rand.text1).main). final EditText tb2 = (EditText) findViewById(R. setContentView(R.nextInt(200))).id.setText(String.setText(String.<Button android:id="@+id/button2" android:text="@string/labelGreen" android:textColor="@drawable/green" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"/> </LinearLayout> </LinearLayout> LinearLayout android:id Activity findViewById Wiring Up the Controller @Override public void onCreate(Bundle state) { super.id.valueOf(rand.setOnClickListener( new Button.

). } EditText setText OnClickListener EditText invalidate Button setOnClickListener Button OnClickListener OnClickListener Button View setOnClickListener onClick onClick Button View Wiring Up the Controller | 167 .

id.id.setOnClickListener(listener).button1)).setText(String.valueOf(rand.main). final EditText tb1 = (EditText) findViewById(R. final EditText tb2 = (EditText) findViewById(R. tb2.layout.nextInt(200))).button2)).id.setOnClickListener(listener).nextInt(200))).id. } }.text1). ((Button) findViewById(R. ((Button) findViewById(R. Button.View View View OnClickListener View setOnClickListener @Override public void onCreate(Bundle state) { super. setContentView(R.OnClickListener() { @Override public void onClick(View arg0) { tb1.OnClickListener listener = new Button.valueOf(rand.setText(String.text2). } Listening to the Model Button View 168 | Chapter 10: Building a View .onCreate(state).

} } package com.color = color. /** * @param x horizontal coordinate. this. } /** @return the horizontal coordinate. * @param y vertical coordinate.android.oreilly.android. * @param diameter dot diameter. Wiring Up the Controller | 169 . int color. */ public final class Dot { private final float x. * @param color the color. int diameter) { this. this. /** A dot: the coordinates. } /** @return the vertical coordinate. y. color and size.model. */ public int getColor() { return color. */ public Dot(float x. this.String EditText package com. */ public float getY() { return y.model.y = y. float y. private final int diameter.intro. } /** @return the color. private final int color. } /** @return the dot diameter.oreilly.diameter = diameter. */ public float getX() { return x. */ public int getDiameter() { return diameter.intro.x = x.

*/ public void clearDots() { dots.Collections. int color.util. } /** @return the list of dots.util. notifyListener(). private DotsChangeListener dotsChangeListener. y. } /** * @param x dot horizontal coordinate. /** A list of dots. } private final LinkedList<Dot> dots = new LinkedList<Dot>(). */ public void addDot(float x.add(new Dot(x. } /** Delete all the dots. import java. diameter)). color. } } } 170 | Chapter 10: Building a View . float y. } private void notifyListener() { if (null != dotsChangeListener) { dotsChangeListener.util. } /** @return the most recently added dot.import java. /** @param l the new change listener.List. * @param diameter dot size.clear(). */ public Dot getLastDot() { return (dots.onDotsChange(this). * @param y dot vertical coordinate.unmodifiableList(dots). int diameter) { dots. private final List<Dot> safeDots = Collections. notifyListener(). */ void onDotsChange(Dots dots). import java. */ public class Dots { /** DotChangeListener.LinkedList. or null. * @param color dot color. */ public interface DotsChangeListener { /** @param dots the dots that changed.getLast().size() <= 0) ? null : dots. */ public void setDotsChangeListener(DotsChangeListener l) { dotsChangeListener = l. */ public List<Dot> getDots() { return safeDots.

os.oreilly. 0). */ @Override public void onCreate(Bundle state) { super.id. private final Random rand = new Random().graphics.Dots.android.View.intro.Color.setOnClickListener( new Button.Random.root)). Color.DotView package com.DotView.intro.widget.button2)).Dot. /** Android UI demo program */ public class TouchMe extends Activity { public static final int DOT_DIAMETER = 6. import android.view.onCreate(state).LinearLayout. dotView. import android. /** Called when the activity is first created. ((LinearLayout) findViewById(R.model.widget. import com.Button.addView(dotView. final Dots dotModel = new Dots(). // install the view setContentView(R. ((Button) findViewById(R. import com. DotView dotView. import android.android.intro. // wire up the controller ((Button) findViewById(R.android.Bundle.widget.layout. import android. import android.oreilly. } }).oreilly.app.EditText.view.util.id. dotView = new DotView(this.oreilly.setOnClickListener( Wiring Up the Controller | 171 .RED).intro. import com. 10 import android.button1)). dotModel). import android.OnClickListener() { @Override public void onClick(View v) { makeDot(dots.Activity.android.id. import java.model.main).

Color. final EditText tb1 = (EditText) findViewById(R. } } setOnClickListener makeDot makeDot onClick dotsChangedListener Dot View makeDot DotView invalidate 172 | Chapter 10: Building a View .text1). DOT_DIAMETER + (rand. color.setText((null == d) ? "" : String.text2). tb2.new Button. tb1.getWidth() . dotView.nextFloat() * (view. } }).getX())).getY())). DOT_DIAMETER).DotsChangeListener() { @Override public void onDotsChange(Dots d) { Dot d = dots.getLastDot(). dots. } }). final EditText tb2 = (EditText) findViewById(R. DotView view.OnClickListener() { @Override public void onClick(View v) { makeDot(dots.valueOf(d.getHeight() . } /** * @param dots the dots we're drawing * @param view the view in which we're drawing dots * @param color the color of the dot */ void makeDot(Dots dots.setDotsChangeListener(new Dots.valueOf(d.GREEN).nextFloat() * (view.pad)).invalidate().addDot( DOT_DIAMETER + (rand.id. dotView.pad)). int color) { int pad = (DOT_DIAMETER + 2) * 2. dots.id.setText((null == d) ? "" : String.

DotView clickHandler makeDot Color.GREEN Dot OnClickHandler makeDot DotsChangedListener DotView Listening for Touch Events DotView Wiring Up the Controller | 173 .

} dots.getY(). DOT_DIAMETER). event. MotionEvent DOWN UP MOVE UP UP MotionEvent CANCEL DOWN MOVE DOWN getHistoricalX getHistoricalY onTouch OnTouchListener DotView private static final class TrackingTouchListener implements View.addDot(event. Color.getAction()) { return false. return true.ACTION_DOWN != event. } 174 | Chapter 10: Building a View .OnTouchListener { private final Dots mDots. } }).OnTouchListener() { @Override public boolean onTouch(View v. MotionEvent event) { if (MotionEvent. TrackingTouchListener(Dots dots) { mDots = dots.onCreate dotView.getX().CYAN.setOnTouchListener(new View.

i++) { addDot( mDots. } addDot( mDots.getAction()) { case MotionEvent.getHistorySize(). evt. y. default: return false. MotionEvent evt) { switch (evt. } private void addDot(Dots dots. evt. evt. evt.ACTION_MOVE: for (int i = 0. evt.CYAN.getY().@Override public boolean onTouch(View v. evt. (int) ((p * s * Dot.getHistoricalSize(i)). case MotionEvent. return true. } break. n = evt.getPressure().ACTION_DOWN: break. float s) { dots.addDot( x.getHistoricalX(i).getHistoricalY(i). i < n. Color. float p. evt. float y.DIAMETER) + 1)).getHistoricalPressure(i). float x. evt.getX().getSize()). } } MotionEvent getHistorySize getHistory Wiring Up the Controller | 175 .

MotionEvents MotionEvents View dispatchTouchEvent onTrackballEvent MotionEvents onTrackballEvent dispatchTrackballEvent dispatchTrackballEvent View MotionEvents Listening for Key Events 176 | Chapter 10: Building a View .

} makeDot(dots..ACTION_UP != event. boolean onKeyDown onTouchEvent View Wiring Up the Controller | 177 .KEYCODE_ENTER: color = Color.. break. Alternative Ways to Handle Events onKey on.BLUE. case KeyEvent.setFocusable(true). switch (keyCode) { case KeyEvent.getAction()) { int color = Color.YELLOW. color). KeyEvent event) { if (KeyEvent.KEYCODE_SPACE: color = Color. } }). } return true.MAGENTA. int keyCode. dotView. default: .EditText KeyEvent OnKeyListener DOWN UP UP KeyEvent MULTIPLE getRepeatCount View MULTIPLE setOnKeyListener KeyEvent DOWN MotionEvent MULTIPLE dotView.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v. break. dotView.

switch (keyCode) { case KeyEvent.BLUE.MAGENTA. KeyEvent event) { if (KeyEvent.getAction()) { int color = Color.ACTION_UP != event. int keyCode.KEYCODE_ENTER: color = Color.YELLOW. break.OnTouchListener OnKeyListener View false true View View View View View View View View EditText KeyEvent EditText onKey true onKey false EditText EditText EditText EditText new OnKeyListener() { @Override public boolean onKey(View v. case KeyEvent.KEYCODE_SPACE: color = Color. 178 | Chapter 10: Building a View .

Callback View Advanced Wiring: Focus and Threading MotionEvents KeyEvent EditText setFocusable View EditText OnFocusChange Listener DotView dotView. color). boolean hasFocus) { Wiring Up the Controller | 179 . dotView.KEYCODE_9). } } OnKeyHandler View DispatchKeyEvent false onKeyDown onKeyUp DispatchKeyEvent onKeyHandler View onKeyMultiple KeyEvent.KEYCODE_0) ||(keyCode > KeyEvent.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v. } return (keyCode < KeyEvent.break. } makeDot(dotModel. default: .

BLACK). dotView.if (!hasFocus && (null != dotGenerator)) { dotGenerator. new Thread(dotGenerator).start().done(). OnFocusChangeListener DotGenerator DotGenerator dotGenerator DotView DotGenerator View requestFocus DotView requestFocus requestFocus nextFocusDown nextFocusLeft nextFocusRight nextFocusUp 180 | Chapter 10: Building a View . dotGenerator = null. } else if (hasFocus && (null == dotGenerator)) { dotGenerator = new DotGenerator(dots. } } }). Color.

final DotView view. private final Runnable makeDots = new Runnable() { public void run() { makeDot(dots.EditText View isFocusableInTouchMode FOCUSABLE_IN_TOUCH_MODE isInTouchMode View EditText DotView Window Activity ViewGroup requestFocus requestChildFocus DotGenerator private final class DotGenerator implements Runnable { final Dots dots. Wiring Up the Controller | 181 . private volatile boolean done. final int color. private final Handler hdlr = new Handler(). } }. view. color).

color = color.471: ERROR/AndroidRuntime(162): android.post(makeDots). } // Runs on a different thread! public void run() { while (!done) { try { Thread.sleep(1000). DotGenerator Handler DotGenerator DotGenerator Handler Handler Handler Handler Runnable Handler Runnable makeDot 182 | Chapter 10: Building a View . DotView view. } } } android.view = view.Vi