Download as pdf or txt
Download as pdf or txt
You are on page 1of 318

Gii thiu

Ti liu Lp trnh Android c bn l bn dch chn lc ni dung t trang


developer.android.com - trang Web do chnh Google xy dng v chia
s min ph cho cc lp trnh vin Android. Vi mong mun sinh vin
hc tp c tt nht mn ny, b phn Bn quyn v Xut bn i hc
FPT thc hin chuyn ng ti liu sang ting Vit v cung cp min
ph cho sinh vin FPT Polytechnic di dng file PDF lu trn trang Web
lms.poly.edu.vn.
V y l ln chuyn ng u tin ti liu Lp trnh Android c bn ny,
nn d rt c gng trong cc khu bin tp, hiu nh, ch bn, song
thiu st l iu khng th trnh khi. B phn Bn quyn v Xut bn rt
mong nhn c kin ng gp ca qu c gi gn xa hon thin
bn dch trong nhng ln ti.
Mi kin ng gp xin vui lng gi v:
B phn Bn quyn v Xut bn - i hc FPT
a ch: Tng 2, nh F, ta nh Vit c (VAS), khu th M nh I,
T Lim, H Ni.
Email: publishing@fpt.edu.vn
FPT Polytechnic tin tng rng, tiu ch Thc hc - Thc nghip s l
mc ch cao p nht ca mt n v o to. Chng ta hy cng chia
s mc ch ny c c mt mi trng o to tt, xy dng c
nhng gi tr thit thc, gip cho mi sinh vin vng vng trn con ng
s nghip ca mnh.
Thng 04 nm 2014

Mc lc

Mc lc
1. Android, nn tng di ng ph bin nht th gii ...................................................3
2. Intent v b lc Intent ..............................................................................................7
3. Kin thc c bn v ng dng .............................................................................22
4. File AndroidManifest.xml ......................................................................................30
5. Giao din ngi dng trn mobile ........................................................................38
5.1 Tng quan v giao din ngi dng ..............................................................38
5.2 Layout ............................................................................................................40
5.2.1 Layout tuyn tnh .................................................................................50
5.2.2 Layout tng i .................................................................................52
5.2.3 List View ..............................................................................................55
5.2.4 Grid View ............................................................................................58
5.3 Cc s kin u vo .....................................................................................62
5.4 Menu ..............................................................................................................68
5.5 Thng bo ......................................................................................................88
5.5.1 To thng bo ......................................................................................91
5.5.2 Qun l thng bo ................................................................................95
5.5.3 Bo ton tri nghim iu hng khi khi ng Activity ......................96
5.5.4 Hin th tin trnh trong thng bo ......................................................100
5.6 Thnh phn ty chnh ..................................................................................104
6. X l u vo t bn phm ..................................................................................112
6.1 Xc nh kiu phng tin nhp liu ...........................................................113
6.2 X l trng thi hin th ca phng tin nhp liu .....................................116
6.3 H tr iu hng qua bn phm ................................................................118
6.4 X l cc action t bn phm .......................................................................121
7. Widget ca ng dng .........................................................................................123
8. Activity ................................................................................................................148
9. Ty chn lu tr .................................................................................................162
10. Content Provider ................................................................................................170
10.1 C bn v content provider ........................................................................170
10.2 To content provider ..................................................................................188
10.3 Provider Calendar ......................................................................................205
10.4 Provider Contacts ......................................................................................224
11. Thit k sao cho ng dng c th phn hi tt ..................................................265
12. Service ...............................................................................................................269
13. Lp BroadcastReceiver ......................................................................................284
14. Mo bo mt .......................................................................................................295
15. WebView ............................................................................................................307

Mc lc
15.1 Tng quan v lp WebView .......................................................................307
15.2 Xy dng ng dng Web trong WebView .................................................310

Lp trnh Android c bn

1. Android, nn tng di ng ph bin nht th gii


Android l nn tng ca hng trm triu thit b di ng ti hn 190 quc gia trn th
gii. Trong cc nn tng di ng (mobile platform), y l nn tng c ci t nhiu
nht v c tc pht trin rt nhanh - mi ngy, hng triu ngi dng bt thit b
Android ca h ln ln u tin ri bt u tm kim cc ng dng, tr chi cng nhng
ni dung s khc.
Android cung cp cho bn mt nn tng tt nht ton cu nhm to ra cc ng dng v
tr chi cho ngi dng Android mi ni, cng vi l mt th trng m phn
phi chng ngay tc th.

S tng trng ca Android th hin qua s lng thit b c kch hot

Quan h i tc v nn tng ci t ton cu


T vic xy dng trn s ng gp ca cng ng m ngun m Linux (open-source
Linux community) cng hn 300 phn cng, phn mm v cc nh mng i tc,
Android mau chng tr thnh h iu hnh di ng pht trin nhanh nht.

Mi ngy c hn 1 triu thit b Android mi c kch hot trn ton


th gii.
Tnh m ca Android khin ngi tiu dng yu thch nn tng ny v cc nh pht
trin ng dng cng vy, iu thc y s tng trng mnh trong lnh vc tiu
th ng dng. Ngi dng Android ti hn 1,5 t ng dng v tr chi t Google Play
mi thng.
Cng vi cc i tc, Android lin tc m rng ranh gii gia phn cng vi phn mm,
nhm mang li nhng tnh nng mi cho ngi dng v cc nh pht trin. i vi nh
pht trin, s i mi ca Android cho php bn xy dng nhng ng dng mnh m,
khc bit, dng cng ngh di ng mi nht.

Lp trnh Android c bn

Framework(1) pht trin mnh m


Rt d ti u ha mt h nh phn cho in thoi, my tnh bng
(tablet) v cc thit b khc.
Android cung cp mi th bn cn xy dng v tri nghim ng dng mc tt
nht. N cng cung cp mt m hnh ng dng n, cho php bn trin khai rng ri
ng dng ca mnh ti hng trm triu ngi dng trn mt lot thit b - t in thoi
cho ti my tnh bng v cn hn th na.
Android cng a ra nhng cng c to ng dng c giao din p mt v tn dng
li th t kh nng phn cng c sn trn tng thit b. N cng t ng thch nghi vi
giao din ngi dng (user interface - UI) t c s ti u nht trn tng thit
b, trong khi vn a ra nhiu iu khin (control) nh bn mun, thng qua giao din
ngi dng trn cc loi thit b khc nhau.
V d, bn c th to mt ng dng h nh phn sao cho ng dng ny c ti u
ha cho c in thoi ln cc dng my tnh bng. Bn c th khai bo giao din ngi
dng ca mnh mt cch gn nh trong tp cc ti nguyn XML, mt tp dnh cho
nhng thnh phn chung i vi tt c cc dng, trong khi nhng tp khc dng cho
vic ti u ha theo c trng ca in thoi hoc my tnh bng. Khi chy, Android p
dng ng tp ti nguyn da trn kch thc mn hnh, mt , v tr,
Nhm gip bn pht trin hiu qu, cc cng c pht trin Android (Android Development
Tools - ADT) cung cp cho bn mt mi trng pht trin tch hp (Integrated
Development Environment - IDE) y cho Java vi nhng tnh nng tin tin
pht trin, g li (debugging) v ng gi (packing) cc ng dng Android. S dng
IDE, bn c th pht trin ng dng trn mi thit b Android c sn, hoc to cc thit
b o (virtual device) gi lp bt k cu hnh phn cng no.

C 1,5 t lt ti v mi thng v con s ny vn tip tc tng. Hy


a ng dng ca bn ra trc mt hng triu ngi dng theo quy
m ca Google.

Th trng m phn phi cc ng dng ca bn


Google Play l th trng hng u cho vic bn v phn phi cc ng dng Android.
Khi pht hnh mt ng dng trn Google Play, bn chm c vo nn tng khng
l c ci t ca Android.

(1)

Tp cc ti nguyn to nn khung nn cho vic pht trin h thng.

Lp trnh Android c bn

L mt th trng m, Google Play cho php bn kim sot cch thc bn cc sn


phm ca mnh. Bn c th pht hnh mi thi im bn mun, vi tn sut ty v
ti nhng khch hng bn quan tm. Bn cng c th phn phi rng khp trn mi th
trng v thit b hay tp trung vo nhng phn khc, thit b c th, hoc theo phm
vi ca kh nng phn cng.
Bn c th thu li nhun theo cch hp l nht cho doanh nghip ca mnh - mt ph
hoc min ph, vi cc sn phm nhng trong ng dng (in-app) hoc ng k theo
di (subscription) - m bo t c s cam kt v thu nhp tt nht. Bn cng c
th kim sot hon ton gi c cho ng dng ca mnh v cc sn phm nhng trong
ng dng, ng thi c th thit lp hoc thay i gi vi bt c loi tin t c h
tr vo mi thi im.
Ngoi s pht trin ca nn tng khch hng, Google Play gip bn xy dng tm
nhn v cam kt thng qua ng dng v thng hiu ca bn. Khi ng dng ca bn
dn tr nn ph bin, Google Play xp cho chng v tr cao hn trong biu xp
hng ng u mi tun, tin hnh xp hng v m bo nhng v tr tt nht cho
ng dng trong kho.
c ci t sn trong hng trm triu thit b Android trn th gii, Google Play c th
l mt phng tin pht trin cho doanh nghip ca bn.

Lp trnh Android c bn

KHI NG
Tt c nhng g bn cn bt u pht trin ng dng cho Android u c y, trn
trang developer.android.com. Bn s tm thy mi th trn trang Web ny, t nhng
SDK (b cng c pht trin phn mm - Software Developement Kit), ti liu hng
dn API, ch dn thit k, thng tin v chiu xoay (landscape) ca thit b hin ti cho
ti cch bn c th phn phi v thu li nhun t cc ng dng.
Cc ng dng u c xy dng theo nhng cch khc nhau, nhng chng ti
cu trc nhng thng tin cn thit gip bn xy dng mt ng dng thnh ba mc chnh
di y, i din cho quy trnh pht trin ng dng chung:

Thit k
Trc khi vit mt dng m, bn cn thit k giao din ngi dng v lm cho n ph
hp vi tri nghim ngi dng trn Android. Mc d bn c th bit ngi dng s
lm g vi ng dng ca mnh, song bn vn nn dng li tp trung vo cch ngi
dng s tng tc vi n. Thit k ca bn nn c style p, n gin, mnh m v
c iu chnh hng ti tri nghim trn Android.
V vy, bt k bn l mt ca hng nh ch c mt ngi hay l mt nhm ln nhiu
ngi th cng nn nghin cu cc ch dn Design (Thit k) trc tin.

Pht trin
Mt khi thit k ca bn hon thin, tt c nhng g bn cn l cc cng c bin
tng thit k ng dng thnh hin thc. Framework ca Android cung cp cho
bn cc giao din lp trnh ng dng (Application Programming Interface - API) xy
dng nhng ng dng c th khai thc ton b li th ca phn cng thit b, thit b
ph kin kt ni (connected accessory device), mng Internet, cc tnh nng phn mm
v nhiu hn na. Vi sc mnh ca Android, sc mnh m ng dng ca bn c th
em li l khng gii hn.
Mi kin thc bn cn hc v framework v cc cng c pht trin ng dng u c
trong mc (Develop) (Pht trin) ca ti liu hng dn.

Phn phi
Hin gi, ng dng ca bn hon tt. Chng ta xy dng ng dng h
tr nhiu kch c v mt mn hnh, ng thi kim th (test) n trn trnh gi lp
(emulator) Android cng nh trn cc thit b tht. Bn sn sng em ng dng
ca mnh i phn phi.
Bc tip theo ph thuc vo nhiu yu t, chng hn nh chin lc tin t v loi
thit b h tr ng dng ca bn. Mi thng tin bn cn bt u qu trnh ny u c
trong mc (Distribute) (Phn phi).

Lp trnh Android c bn

2. Intent v b lc Intent
B ba trong cc thnh phn chnh (core component) ca mt ng dng - activity (mt
thnh phn ca ng dng cung cp giao din ngi dng tng tc nhm thc hin
mt cng vic no ), service (lung dch v chy ngm trong Android) v broadcast
receiver (trnh thu nhn cc thng tin bn ngoi gi ti) - c kch hot thng qua bn
tin (message), gi l cc intent. Vic gi v nhn intent l c s cho vic lin kt khi
chy v sau ny gia nhng thnh phn trong cng mt hoc cc ng dng khc nhau.
Bn thn i tng Intent l mt cu trc d liu th ng cha m t tru tng
v mt activity c thc hin - hoc, trong trng hp ca broadcast th thng l
m t v iu g xy ra v c cng b. C nhiu c ch ring bit gi Intent
cho mi loi thnh phn ca h thng:

Mt i tng Intent c truyn ti Context.startActivity() hoc


Activity.startActivityForResult() nhm khi ng mt activity hoc
ly activity hin c lm vic mi. (Intent cng c th c truyn ti Activity.
setResult() tr v thng tin cho activity gi startActivityForResult()).

Mt i tng Intent c truyn ti Context.startService() khi to


mt service hoc gi i nhng ch lnh mi ti mt service ang chy. Tng t,
mt intent c th c truyn ti Context.bindService() thit lp mt
kt ni gia thnh phn gi v service ch. Intent c th ty khi to service nu
nh service cha chy sn.

Cc i tng Intent truyn ti bt c phng thc broadcast no (chng hn


nh Context.sendBroadcast(), Context.sendOrderedBroadcast()
hay Context.sendStickyBroadcast()) c gi ti tt c cc broadcast
receiver cng h thng. Nhiu loi tin broadcast nh vy bt ngun t m h thng
(system code).

Trong mi trng hp, h thng Android s tm activity, service hoc tp cc broadcast


receiver thch hp phn hi intent v khi to chng, nu cn. Khng c s chng
cho bn trong cc h thng nhn tin ny: Intent broadcast ch c gi ti broadcast
receiver ch khng bao gi c gi ti activity hay service. Mt intent truyn ti
startactivity() ch c gi ti mt activity ch khng bao gi c gi ti mt
service hay broadcast receiver, v c nh vy.
Ti liu ny bt u vi mt m t v i tng Intent. Sau , ti liu i vo m t
nhng quy tc m Android s dng kt ni cc intent vi cc thnh phn - cch phn
tch u l nhng thnh phn nn nhn thng ip intent. i vi cc intent khng ch
r mt thnh phn ch mt cch tng minh, qu trnh ny lin quan n vic kim
th i tng intent da vo b lc intent (intent filter) lin kt vi nhng thnh phn
ch c kh nng.

Cc i tng Intent
Mt i tng Intent l mt tp thng tin. i tng ny cha thng tin v c im
ca thnh phn nhn intent (nh action c thc hin v d liu thc hin action
), cng vi l thng tin v c im ca h thng Android (nh danh mc ca
thnh phn x l intent v cc lnh khi chy mt activity ch). Phn ln i tng
Intent c th bao gm:

Lp trnh Android c bn
Tn thnh phn
Tn ca thnh phn x l intent. Trng ny l mt i tng ComponentName
- mt s kt hp tn lp (class) y ca thnh phn ch (chng hn nh
com.example.project.app.FreneticActivity) vi tn gi (package)
t trong file k khai (manifest file) ca ng dng, ni cha cc thnh phn (v d
nh com.example.project). Phn thng tin tn gi trong ComponentName
v tn gi c thit lp trong file k khai khng nht thit phi trng nhau.
Tn thnh phn l khng bt buc. Nu c thit lp, i tng Intent c
gi ti mt th hin (instance) ca lp ch nh. Cn nu cha c thit lp,
Android s dng thng tin khc trong i tng Intent t thnh phn ch thch
hp - xem mc Phn tch Intent (Intent Resolution) s c trnh by phn
sau ca ti liu ny.
Tn thnh phn c thit lp bng cch s dng setComponent(),
setClass() hoc setClassName() v c c bi getComponent().
Action
Mt chui (string) cha tn ca action c thc hin - hoc, trong trng hp cc
intent broadcast, y s l action xy ra v ang c bo co. Lp Intent nh
ngha mt vi hng s action, gm:

Hng s

Thnh phn ch

Action

ACTION_CALL

activity

Khi to mt cuc gi in thoi.

ACTION_EDIT

activity

Hin th d liu cho ngi dng


thc hin chnh sa.

ACTION_MAIN

activity

Bt u vi activity khi to
ca mt nhim v v khng c
d liu u vo (input), ng
thi khng tr v d liu u ra
(output).

ACTION_SYNC

activity

ng b d liu trn my ch
(server) vi d liu trn thit b
di ng.

ACTION_BATTERY_LOW

broadcast receiver

Mt cnh bo rng pin sp ht.

ACTION_HEADSET_PLUG

broadcast receiver

Mt b tai nghe c gn
vo thit b, hoc c rt ra t
thit b.

ACTION_SCREEN_ON

broadcast receiver

Mn hnh c bt ln.

ACTION_TIMEZONE_
CHANGED

broadcast receiver

Cc thng s thit lp cho mi


gi (time zone) thay i.

Lp trnh Android c bn
Xem m t lp Intent tm hiu danh sch cc hng s c sn cho nhng
action chung. Cc action khc c nh ngha u trong Android API. Bn
cng c th t nh ngha cc chui action kch hot nhng thnh phn c mt
trong ng dng ca mnh. Cc chui m bn to ra nn bao gm tn gi ng dng
nh mt tin t - v d: com.example.project.SHOW_COLOR.
Action quyt nh phn ln cch m cc thng tin cn li ca intent c cu trc ngoi tr cc trng data v extras - cng nhiu nh vic mt tn phng thc
(method) quyt nh tp cc tham s v gi tr tr v. Do vy, nn s dng nhng
tn action c th nht trong kh nng, ng thi kt hp cht ch chng vi cc
trng khc ca intent. Ni cch khc, thay v nh ngha mt action ring l, hy
nh ngha c mt giao thc (protocol) cho nhng i tng intent m cc thnh
phn trong ng dng ca bn c th x l.
Action trong mt i tng Intent c phng thc setAction() thit lp v
c c bi getAction().
D liu
Thnh phn URI (Uniform Resource Identifier - nh dng ti nguyn thng nht)
ca d liu c thc thi v loi MIME (Multipurpose internet mail extension - M
rng th tn Internet a nng) ca d liu . Nhng action khc nhau c kt
hp vi cc loi c t d liu khc nhau thnh tng cp. V d, nu trng action
l ACTION_EDIT, trng d liu s cha URI ca ti liu c hin th chnh
sa. Nu hnh ng l ACTION_CALL, trng d liu s l tel: URI vi s in
thoi gi. Tng t, nu action l ACTION_VIEW v trng d liu l http: URI,
activity nhn c s c gi ti v, ng thi hin th bt c d liu no m
URI tr ti.
Khi khp mt intent vi mt thnh phn c kh nng x l d liu, iu quan
trng cn bit l loi ca d liu (loi MIME) cng vi URI ca d liu y. V d,
khng nn gi mt thnh phn c kh nng hin th d liu hnh nh chy mt
file m thanh.
Trong nhiu trng hp, loi d liu c th c suy on t URI - ngoi tr cc
content: URI cho thy rng d liu c nh v trn thit b v do mt Content
Provider (trnh cung cp ni dung) kim sot (xem mc Content provider bn
di)). Tuy nhin, loi d liu c th c thit lp mt cch tng minh trong
i tng Intent. Phng thc setData() nh r rng d liu ch nh mt URI,
setType() nh r rng n ch nh mt loi MIME, cn setDataAndType()
cho bit n va l mt URI va l mt loi MIME. c URI s dng getData(),
c loi d liu s dng getType().
Hng mc
Mt chui cha thng tin b sung v nhng loi thnh phn x l intent. i tng
intent c th cha mt s lng khng gii hn cc m t hng mc (category).
Tng t nh cch lm vi action, lp Intent nh ngha mt vi hng s hng
mc, bao gm:

Lp trnh Android c bn
Hng s

ngha

CATEGORY_BROWSABLE

Activity ch c th c trnh duyt (browser) kch


hot (invoke) mt cch an ton hin th d liu do
mt ng dn (link) tr ti - v d nh mt bc nh
hoc mt tin nhn e-mail (th in t).

CATEGORY_GADGET

Activity c th c nhng vo bn trong activity


khc v l activity c th lm nn cho cc gadget
(nhng ng dng nh c thit k vi tnh lp
rp c).

CATEGORY_HOME

Activity hin th mn hnh chnh (home screen),


mn hnh u tin m ngi dng thy khi bt thit
b ln hoc khi button (nt) Home c nhn.

CATEGORY_LAUNCHER

Activity c th l activity khi to ca mt tc v


(task) v c lit k mc cao nht ca mn hnh
chnh ng dng (application launcher).

CATEGORY_PREFERENCE

Activity ch l mt bng thit lp ty chnh c nhn


(preference panel).

Xem m t lp Intent c c danh sch y v cc hng mc.


Phng thc addCategory() t mt hng mc vo trong mt i tng
Intent, removeCategory() xa mt hng mc thm vo trc , trong khi
getCategories() ly ra tp tt c cc hng mc hin c ca i tng.
Cc thnh phn ph
Cc cp kha-gi tr (key-value) b sung thng tin s c gi ti thnh phn
x l intent. Tng t mt vi action c gn vi nhng loi URI d liu
c th, mt s intent s c gn vi cc thnh phn ph (extra). V d,
mt intent ACTION_TIMEZONE_CHANGED c thnh phn ph time-zone
nhn din cc mi gi mi, cn ACTION_HEADSET_PLUG c thnh phn ph
state (trng thi) nh r hin gi b tai nghe c cm vo hay rt ra khi
thit b, cng vi l thnh phn name cho loi tai nghe. Nu bn to ra
mt action SHOW_COLOR, gi tr mu (color value) s c t trong mt cp
kha-gi tr ph.
i tng Intent c mt lot phng thc put...() chn nhiu loi d liu ph
tr v nhm phng thc tng t get... () c d liu. Nhng phng
thc song song ny nm trong cc i tng Bundle. Thc t, cc thnh phn
ph c th c ci t v c nh mt Bundle bng cch s dng cc phng
thc putExtras() v getExtras().
C
C nhiu loi c (flag) khc nhau. Nhiu loi hng dn cho h thng Android cch
thc thi mt activity (v d, activity thuc v tc v no) v cch x l activity sau
khi thc thi (v d, n nm trong danh sch nhng activity gn y khng). Tt c
cc c ny c nh ngha trong lp Intent.

10

Lp trnh Android c bn
H thng Android v nhng ng dng i km nn tng dng cc i tng Intent
va gi i cc tin broadcast ca h thng ban u va kch hot nhng thnh phn
xc nh trong h thng. Mun bit cch cu trc mt intent kch hot mt thnh
phn h thng, mi bn tham kho mc List of intents (Danh sch intent).
Phn tch Intent
Cc Intent c th c chia thnh hai nhm:

Intent tng minh (explicit intent) quy nh thnh phn ch bng tn ca n (trng
tn thnh phn - Component Name cp trn, c mt gi tr thit lp). Do
cc nh pht trin ca nhng ng dng khc khng bit tn thnh phn ng dng
ca nhau, nn cc intent tng minh thng c dng cho nhng thng ip ni
b trong ng dng - v d, mt activity khi chy mt service cp con hay thc thi
mt activity anh em ca n.

Intent ngm nh (implicit intent) khng tn thnh phn ch (trng tn thnh


phn trng). Intent ngm nh thng c dng kch hot cc thnh phn
trong nhng ng dng khc.

Android truyn mt intent ngm nh ti mt th hin ca lp ch c ch nh. Khng


c g khc trong i tng Intent ngoi tn thnh phn quan trng i vi vic xc nh
u l thnh phn nhn intent.
Cn mt chin thut khc cho cc intent ngm nh. Khi thnh phn ch khng c
ch nh tng minh, h thng Android phi tm ra thnh phn (hoc cc thnh phn) tt
nht x l intent - mt activity hoc service ring l thc hin action c yu cu
hoc tp cc broadcast receiver phn hi thng bo broadcast. H thng Android c
th lm iu bng cch so snh ni dung ca i tng Intent vi cc b lc intent,
nhng cu trc lin quan n cc thnh phn c kh nng nhn intent. B lc a ra
cc kh nng ca mt thnh phn v phn nh nhng intent m n c th x l c.
B lc em n cho thnh phn kh nng nhn c cc intent ngm nh ca loi
c a ra. Nu mt thnh phn khng c bt k b lc intent no, n c th ch nhn
c nhng intent tng minh. Mt thnh phn c b lc c th nhn c c intent
tng minh ln ngm nh.
Ch c ba kha cnh ca mt i tng Intent c xt n khi i tng c kim
th da vo mt b lc intent:
action
d liu (c URI ln kiu d liu)
hng mc
Cc thnh phn ph v c khng tham gia vo vic gii quyt thnh phn no s
nhn intent.

B lc intent
thng bo cho h thng bit chng c th x l nhng intent ngm nh no, cc
activity, service v broadcast receiver c th c mt hay nhiu b lc intent. Mi b lc
m t mt kh nng ca mt thnh phn, mt tp intent m thnh phn sn sng nhn.
Kt qu l, n lc ra cc intent mong mun v loi b nhng intent khng mong mun -

11

Lp trnh Android c bn
ch gm cc intent ngm nh (nhng intent ny khng t tn cho lp ch). Mt intent
tng minh lun c gi ti ch ca n, bt k n cha ni dung g; b lc khng lm
nhim v tra cu ni dung. Tuy nhin, mt intent ngm nh ch c gi ti mt thnh
phn khi n c th vt qua c cc b lc ca thnh phn .
Mt thnh phn c nhiu b lc ring bit cho tng vic n c th lm, cho mi giao
din m n biu din ti ngi dng. V d, activity c tn NoteEditor ca ng dng
Note Pad c hai b lc - mt khi ng vi mt ghi ch c th gip ngi dung c
th xem hoc chnh sa, mt b lc khc bt u vi mt ghi ch mi, trng hon
ton ngi dng c th in vo ri lu li. (Tt c cc b lc ca Note Pad u
c miu t trong mc V d v Note Pad s trnh by v sau).

B lc v bo mt
Mt b lc intent khng th dng cho mc ch bo mt (security). Trong khi m mt
thnh phn ch nhn nhng dng intent ngm nh nht nh, b lc khng lm g
ngn nga cc intent tng minh nhm ti thnh phn . Mc d mt b lc c th
hn ch cc intent, song mt thnh phn s c yu cu x l mt s action v ngun
d liu nht nh. Tuy nhin, ai vn c th t mt intent tng minh cnh mt action
v ngun d liu khc ri t tn thnh phn ging vi thnh phn ch.
B lc intent l mt th hin ca lp IntentFilter. Tuy nhin, do h thng Android
phi bit v kh nng ca mt thnh phn trc khi thc thi thnh phn , nn cc
b lc intent thng khng c thit lp trong m Java m ch ng vai tr l cc
phn t (element) <intent-filter> trong file k khai (AndroidManifest.xml)
ca ng dng. (Mt ngoi l l nhng b lc cho broadcast receiver c ng k ng
l gi Context.registerReceiver(); chng c to trc tip di dng cc
i tng IntentFilter).
Mt b lc c cc trng song song vi cc trng action, d liu v hng mc ca
mt i tng Intent. Mt intent ngm nh c kim th bng b lc c ba trng.
c chuyn ti thnh phn s hu b lc, n phi vt qua c ba kim th. Nu
tht bi cho d ch trong mt kim th, h thng Android s khng gi n ti thnh phn
- t nht l khng da trn c s ca b lc . Tuy nhin, do mi thnh phn c th c
nhiu b lc intent, nn mt intent khng vt qua mt trong cc b lc ca thnh phn
li c th vt qua b lc khc.
Mi kim th c m t chi tit di y:
Kim th action
Mt phn t <intent-filter> trong file k khai lit k cc action di dng nhng
phn t con <action>. V d:
<intent-filter . . . >
<action android:name=com.example.project.SHOW_CURRENT />
<action android:name=com.example.project.SHOW_RECENT />
<action android:name=com.example.project.SHOW_PENDING />
. . .
</intent-filter>

12

Lp trnh Android c bn
V d trn cho thy, trong khi mt i tng Intent ch t tn cho mt action th mt b
lc c th lit k nhiu hn th. Danh sch khng th trng; mt b lc phi cha t
nht mt phn t <action>, hoc n s chn (block) tt c cc intent.
vt qua kim th ny, action c n nh trong i tng Intent phi khp
vi mt trong cc action c lit k trong b lc. Nu i tng hoc b lc khng ch
nh mt action, kt qu s nh sau:

Nu b lc tht bi trong vic lit k bt c action no, intent khng c g so


khp, nn tt c intent s tht bi trong bi kim th. Khng intent no c kh nng
vt qua b lc.

Mt khc, mt i tng Intent khng n nh mt action s t ng vt qua bi


kim th - min l b lc cha t nht mt action.

Kim th hng mc
Mt phn t <intent-filter> lit k cc hng mc di dng nhng phn t con.
V d:
<intent-filter . . . >
<category android:name=android.intent.category.DEFAULT />
<category android:name=android.intent.category.BROWSABLE />
. . .
</intent-filter>

Lu , cc hng s m t lc trc cho cc action v hng mc u khng c s


dng trong file k khai. Ton b gi tr ca chui c s dng thay vo . V d, chui
android.intent.category.BROWSABLE trong v d trn tng ng vi hng
s CATEGORY_BROWSABLE cp trc trong ti liu ny. Tng t, chui
android.intent.action.EDIT tng ng vi hng s ACTION_EDIT.
mt intent vt qua kim th hng mc, mi hng mc trong i tng Intent u
phi khp vi mt hng mc trong b lc. B lc c th lit k nhng hng mc b
sung, nhng khng th loi b cc hng mc trong intent.
V nguyn tc, mt i tng Intent khng c hng mc lun vt qua bi kim th,
bt k trong b lc cha g. iu ny ng trong hu ht trng hp. Tuy nhin, vi mt
ngoi l, Android x l tt c cc intent ngm nh thng qua startActivity() nh
th l chng cha t nht mt hng mc: android.intent.category.DEFAULT
(hng s CATEGORY_DEFAULT). V vy, cc activity sn sng nhn nhng intent ngm
nh u phi bao gm android.intent.category.DEFAULT trong cc b lc
intent ca chng. (Nhng b lc vi thit lp android.intent.action.MAIN
v android.intent.category.LAUNCHER l ngoi l. Chng nh du cc
activity bt u tc v mi v c biu din trong mn hnh khi ng. Chng c
th bao gm android.intent.category.DEFAULT trong danh sch cc hng
mc, nhng iu ny l khng cn thit). Tham kho mc S dng tnh nng so khp
intent bit thm thng tin v cc b lc ny.

13

Lp trnh Android c bn
Kim th d liu
Tng t action v hng mc, c t d liu (data specification) ca mt b lc intent
c bao gm trong mt phn t con. V, vi nhng trng hp nh vy, phn t con
c th xut hin nhiu ln, hoc khng ln no. V d:
<intent-filter . . . >
<data android:mimeType=video/mpeg android:scheme=http . . . />
<data android:mimeType=audio/mpeg android:scheme=http . . . />
. . .
</intent-filter>

Mi phn t <data> c th xc nh mt URI v mt kiu d liu (kiu MIME a


phng tin). C nhiu thuc tnh ring bit - lc (scheme), host, port (cng) v
ng dn (path) - i vi tng phn ca URI:
scheme://host:port/path

V d, trong URI di y,
content://com.example.project:200/folder/subfolder/etc

lc l content, host l com.example.project, port l 200, cn ng


dn l folder/subfolder/etc. Host v port cng nhau to thnh chui nh danh
(authority) ca URI; nu khng n nh host, port s b b qua.
Mi thuc tnh u khng bt buc, nhng chng lin quan vi nhau: mt nh danh
c ngha, lc phi c n nh. mt ng dn c ngha, c lc v nh
danh u phi c n nh.
Khi URI trong i tng Intent c so snh vi c t URI trong b lc, n ch c
i snh vi nhng b phn ca URI thc s c cp trong b lc. V d, nu mt
b lc ch n nh mt lc , tt c cc URI vi lc u khp vi b lc. Nu
mt b lc n nh mt lc v mt nh danh nhng khng c ng dn th tt c
cc URI c lc v nh danh tng t u khp, bt k ng dn nh th no.
Nu mt b lc n nh mt lc , mt nh danh v mt ng dn th ch nhng
URI c lc , nh danh v ng dn mi khp. Tuy nhin, mt c t ng
dn trong b lc c th cha cc k t i din (wildcard) yu cu ch mt phn
ng dn l khp.
Thuc tnh type ca phn t <data> xc nh kiu MIME ca d liu. N ph bin
cc b lc hn so vi URI. C i tng Intent ln b lc u c th s dng k t i
din * cho trng loi con (subtype) - v d, text/* hoc audio/* - ch ra bt
c loi con no khp.
Qu trnh kim th d liu so snh c URI ln kiu d liu trong i tng Intent vi
mt URI v kiu d liu xc nh trong b lc. Nguyn tc nh sau:
a. Mt i tng Intent khng cha URI hay kiu d liu s vt qua kim th
ch khi b lc tng t khng n nh bt k URI hoc kiu d liu no.
b. Mt i tng Intent cha URI nhng khng c kiu d liu (v khng th suy
ra mt kiu d liu t URI) s vt qua kim th ch khi URI ca n khp vi
mt URI trong b lc, cn b lc tng t khng n nh kiu no. y s l

14

Lp trnh Android c bn
trng hp duy nht cho cc URI nh mailto: v tel: m khng cp
n d liu thc t.
c. Mt i tng Intent cha mt kiu d liu nhng khng c URI s vt qua
kim th ch khi b lc lit k cng kiu d liu v tng t vy, khng xc
nh URI no.
d. Mt i tng Intent cha c URI ln kiu d liu (hoc c th suy ra kiu d
liu t URI) vt qua phn kim th kiu d liu ch khi kiu ca n khp vi
mt kiu c lit k trong b lc. N vt qua phn kim th URI khi URI
ca n khp vi mt URI trong b lc, hoc nu n cha content: URI hay
file: URI v b lc khng xc nh URI no. Ni cch khc, mt thnh phn
c coi l h tr d liu content: v file:, nu b lc ca n ch lit k
kiu d liu.
Nu mt intent c th vt qua cc b lc ca nhiu activity hoc service, ngi dng
s c hi thnh phn no c kch hot. Mt ngoi l xy ra khi khng c thnh
phn ch no c tm thy.

Cc trng hp ph bin
Nguyn tc cui cng trnh by trn dnh cho vic kim th d liu, nguyn tc (d),
phn nh mong mun rng cc thnh phn c th ly d liu ni b t mt file hoc
Content Provider. Do , b lc ca chng c th lit k ch mt kiu d liu m khng
cn xc nh tng minh tn lc content: v file:. y l mt trng hp in
hnh. V d, mt phn t <data> nh sau cho Android bit thnh phn c th ly d
liu hnh nh t Content Provider v hin th n:
<data android:mimeType="image/*" />

Do hu ht d liu u sn sng c xut ra t Content Provider, nn cc b lc ch


n nh kiu d liu m khng cha URI l trng hp ph bin nht.
Mt cu hnh thng dng khc l cc b lc vi mt lc v mt kiu d liu. V d,
mt phn t <data> nh sau cho Android bit thnh phn c th ly d liu video t
mng (network) v hin th n:
<data android:scheme=http android:type=video/* />

V d, hy xem xt iu m cc ng dng trnh duyt (browser application) lm khi


ngi dung nhn vo mt lin kt trn trang Web. Trc tin, ng dng trnh duyt s
c gng hin th d liu (n c th thc hin iu ny nu lin kt dn n mt trang
HTML). Nu khng th hin th d liu, ng dng s t intent ngm nh cng vi lc
v kiu d liu ri khi ng mt activity c th lm c vic . Nu khng c
activity no ph hp, ng dng s yu cu trnh qun l ti v (download manager) ti
d liu xung. N c t di quyn kim sot ca Content Provider c mt b
activity ln hn (nhng activity c b lc ch n nh kiu d liu) c th phn hi li.

15

Lp trnh Android c bn
Hu ht ng dng u c mt cch lm mi li m khng cn tham chiu ti
bt k d liu c th no. Nhng activity c th khi to cc ng dng c b lc
vi android.intent.action.MAIN c xc nh di dng action. Nu c
hin th trong mn hnh chnh (laucher) ca ng dng, chng cng xc nh hng mc
android.intent.category.LAUNCHER:
<intent-filter . . . >
<action android:name=android.intent.action.MAIN />

<category android:name=android.intent.category.LAUNCHER />


</intent-filter>

S dng tnh nng so khp intent


Cc intent c so khp vi b lc intent khng ch nhm khm ph thnh phn ch
kch hot m cn nhm pht hin iu g v tp cc thnh phn/b phn trn thit
b. V d, h thng Android to ra mn hnh khi ng ca ng dng, mn hnh mc
cao nht cho thy cc ng dng sn sng ngi dng khi ng, bng cch tm
tt c cc activity vi b lc intent c ch nh action android.intent.action.
MAIN v hng mc android.intent.category.LAUNCHER (nh minh ha
mc trc). Sau , n hin th biu tng (icon) v nhn (label) ca cc activity
trong mn hnh khi ng. Tng t, n khm ph mn hnh chnh bng cch tm kim
activity c cha android.intent.category.HOME trong b lc ca n.
ng dng ca bn c th s dng cch so khp intent tng t. PackageManager
c mt tp cc phng thc query...() tr v tt c nhng thnh phn c th chp
nhn mt intent c th, v mt chui tng t cc phng thc resolve...() xc nh
thnh phn ph hp nht phn hi li intent. V d, queryIntentActivities()
tr v danh sch tt c cc activity c th thc thi vi intent vt qua b lc lm
tham s, v queryIntentServices() tr v danh sch tng t cc service. C
hai phng thc u khng kch hot cc thnh phn; chng ch lit k nhng activity
c th phn hi. C mt phng thc tng t, queryBroadcastReceivers(),
cho cc broadcast receiver.

V d v Note Pad
ng dng Note Pad cho php ngi dng c th duyt qua mt danh sch cc ghi ch
(note), xem chi tit tng mc trong danh sch, chnh sa cc mc v thm mc mi vo
danh sch. Phn ny xem xt cc b lc intent c khai bo (declared) trong file k khai.
(Nu ang lm vic ngoi tuyn trong SDK (Software Developement Kit - B cng c pht
trin phn mm), bn c th tm thy ton b file ngun cho ng dng v d ny, bao gm
c file k khai ca n ti <sdk>/samples/NotePad/index.html. Nu bn ang
xem ti liu trc tuyn, cc file ngun u c mc Tutorials and Sample (V d mu v
ti liu hng dn ging dy) ti y).
Trong file k khai ca n, ng dng Note Pad khai bo ba activity, mi activity ng vi
t nht mt b lc intent. N cng khai bo mt Content Provider qun l d liu ghi
ch. y l ni dung file k khai:

16

Lp trnh Android c bn
<manifest xmlns:android=http://schemas.android.com/apk/res/android
package=com.example.android.notepad>
<application android:icon=@drawable/app_notes
android:label=@string/app_name >
<provider android:name=NotePadProvider
android:authorities=com.google.provider.NotePad />
<activity android:name=NotesList android:label=@string/title_notes_list>
<intent-filter>
<action android:name=android.intent.action.MAIN />
<category android:name=android.intent.category.LAUNCHER />
</intent-filter>
<intent-filter>
<action android:name=android.intent.action.VIEW />
<action android:name=android.intent.action.EDIT />
<action android:name=android.intent.action.PICK />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.dir/vnd.google.note />
</intent-filter>
<intent-filter>
<action android:name=android.intent.action.GET_CONTENT />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.item/vnd.google.note />
</intent-filter>
</activity>
<activity android:name=NoteEditor
android:theme=@android:style/Theme.Light
android:label=@string/title_note >
<intent-filter android:label=@string/resolve_edit>
<action android:name=android.intent.action.VIEW />
<action android:name=android.intent.action.EDIT />
<action android:name=com.android.notepad.action.EDIT_NOTE />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.item/vnd.google.note />
</intent-filter>
<intent-filter>
<action android:name=android.intent.action.INSERT />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.dir/vnd.google.note />
</intent-filter>
</activity>
<activity android:name=TitleEditor
android:label=@string/title_edit_title
android:theme=@android:style/Theme.Dialog>
<intent-filter android:label=@string/resolve_title>
<action android:name=com.android.notepad.action.EDIT_TITLE />
<category android:name=android.intent.category.DEFAULT />

17

Lp trnh Android c bn
<category android:name=android.intent.category.ALTERNATIVE />
<category android:name=android.intent.category.SELECTED_ALTERNATIVE />
<data android:mimeType=vnd.android.cursor.item/vnd.google.note />
</intent-filter>
</activity>
</application>
</manifest>

Activity u tin, NotesList, khc bit vi nhng activity khc v thc t, n hot
ng trn mt danh mc ghi ch (danh sch ghi ch) thay v trn mt ghi ch n l.
NotesList thng c dng lm giao din ngi dng u tin, khi mi truy cp
ng dng. N c th lm ba vic c m t bng ba b lc intent:
<intent-filter>
<action android:name=android.intent.action.MAIN />
<category android:name=android.intent.category.LAUNCHER />
</intent-filter>

B lc ny khai bo im bt u chnh (main entry point) cho ng dng Note Pad.


Action MAIN chun l im bt u khng i hi bt c thng tin no khc trong i
tng Intent (v d nh khng c c t d liu), cn hng mc LAUNCHER cho thy
im bt u nn c lit k trong mn hnh chnh ca ng dng.
<intent-filter>
<action android:name=android.intent.action.VIEW />
<action android:name=android.intent.action.EDIT />
<action android:name=android.intent.action.PICK />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.dir/vnd.google.note />
</intent-filter>

B lc ny khai bo nhng th m activity c th lm trn mt danh mc cc ghi


ch. N c th cho php ngi dung xem hoc chnh sa danh mc (thng qua
action VIEW v EDIT), hoc chn mt ghi ch c bit t danh mc (thng qua
action PICK).
Thuc tnh mimeType ca phn t <data> quy nh loi d liu m cc action ny
c th hot ng cng. N ng rng activity c th c mt con tr (cursor) trn khng
hoc nhiu mc (vnd.android.cursor.dir) t Content Provider nm gi d liu
Note Pad (vnd.google.note). i tng Intent thc thi activity s bao gm mt
content: URI xc nh chnh xc d liu ca dng ny v activity nn m ra.
Lu , hng mc DEFAULT cng c cung cp trong b lc ny. l do cc phng
thc Context.startActivity() v Activity.startActivityForResult()
coi mi intent u cha hng mc DEFAULT - ch vi hai ngoi l:

18

oo

Cc intent nh danh activity ch mt cch tng minh.

oo

Cc intent bao gm action MAIN v hng mc LAUNCHER.

Lp trnh Android c bn
Do , hng mc DEFAULT l cn thit cho tt c cc b lc - ngoi tr nhng b lc
vi action MAIN v hng mc LAUNCHER. (Cc b lc intent khng cn quan tm n
nhng intent tng minh).
<intent-filter>
<action android:name=android.intent.action.GET_CONTENT />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.item/vnd.google.note />
</intent-filter>

B lc ny m t kh nng ca activity trong vic tr li mt ghi ch c ngi


dng chn, khng i hi bt c c t ca th mc no m ngi dung nn chn
t . Action GET_CONTENT tng t nh action PICK. Trong c hai trng hp,
activity tr v cho URI mt ghi ch c ngi dung chn. (Trong mi trng hp,
n c tr v cho activity gi l startActivityForResult() bt u activity
NoteList). Tuy nhin, ti y, i tng gi (caller) s xc nh kiu d liu mong
mun thay v th mc d liu m ngi dung s chn trong .
Kiu d liu, vnd.android.cursor.item/vnd.google.note, ch ra dng d
liu ca activity c th tr v - mt URI cho mt ghi ch n l. T URI c tr v, i
tng gi c th c mt con tr cho ng mt mc (vnd.android.cursor.item)
t Content Provider dung cha d liu Note Pad (vnd.google.note).
Ni cch khc, i vi action PICK trong b lc trc , kiu d liu ch ra dng ca
d liu m activity c th hin th cho ngi dung. i vi b lc GET_CONTENT, n ch
ra dng ca d liu m activity c th tr v cho i tng gi.
Nh c trang b nhng kh nng y, cc intent sau y s gii quyt activity
NotesList:
action: android.intent.action.MAIN
Thc thi activity m khng c d liu xc nh.
action: android.intent.action.MAIN
hng mc: android.intent.category.LAUNCHER
Thc thi activity m khng c d liu c chn xc nh. y thc s l
intent c mn hnh chnh s dng sinh ra danh sch cp cao nht ca
n. Tt c cc activity vi nhng b lc khp vi action v hng mc ny u
c thm vo danh sch.
action: android.intent.action.VIEW
d liu: content://com.google.provider.NotePad/notes
Ra lnh cho activity hin th mt danh sch cc ghi ch di content://
com.google.provider.NotePad/notes. Sau , ngi dng c th
duyt danh sch v ly thng tin v cc mc trong .
action: android.intent.action.PICK
d liu: content://com.google.provider.NotePad/notes
Ra lnh cho activity hin th mt danh sch cc ghi ch di content://
com.google.provider.NotePad/notes. Sau , ngi dng c th

19

Lp trnh Android c bn
chn mt ghi ch t danh sch, v activity s tr URI cho mc v activity
khi ng activity NoteList.
action: android.intent.action.GET_CONTENT
kiu d liu: vnd.android.cursor.item/vnd.google.note
Ra lnh cho activity cung cp mt mc n trong d liu Note Pad.
Activity th hai, NoteEditor, cho ngi dng thy mt mc ghi ch n, ng thi cho
php h chnh sa n. N c th lm hai iu c m t bng hai b lc intent di y:
<intent-filter android:label=@string/resolve_edit>
<action android:name=android.intent.action.VIEW />
<action android:name=android.intent.action.EDIT />
<action android:name=com.android.notepad.action.EDIT_NOTE />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.item/vnd.google.note />
</intent-filter>

Mc ch trc tin v chnh yu ca activity ny l cho php ngi dung tng tc


vi mt ghi ch n l - XEM (VIEW) hoc CHNH SA (EDIT) ghi ch. (Hng mc
EDIT_NOTE tng t nh EDIT). Intent s cha URI cho d liu khp vi kiu MIME
vnd.android.cursor.item/vnd.google.note - l URI cho mt ghi ch
n, c th. Thng thng, s l mt URI tr v bi action PICK hoc GET_CONTENT ca activity NoteList.
Cng nh trc y, b lc ny lit k hng mc DEFAULT sao cho activity c th c
thc thi bi cc intent khng xc nh mt cch tng minh lp NoteEditor.
<intent-filter>
<action android:name=android.intent.action.INSERT />
<category android:name=android.intent.category.DEFAULT />
<data android:mimeType=vnd.android.cursor.dir/vnd.google.note />
</intent-filter>

Mc ch th hai ca activity ny l cho php ngi dung to mt ghi ch mi, ghi ch


ny s CHN (INSERT) vo mt th mc ghi ch tn ti. Intent s cha URI cho d
liu khp vi kiu MIME vnd.android.cursor.dir/vnd.google.note - l
URI cho th mc m ghi ch s c t vo .
Vi nhng kh nng trn, cc intent sau s gii quyt activity NoteEditor:
action: android.intent.action.VIEW
d liu: content://com.google.provider.NotePad/notes/ID
Ra lnh cho activity hin th ni dung ca ghi ch xc nh bi ID. ( bit
thm chi tit v cch cc content: URI xc nh tng thnh vin ca mt
nhm, xem mc Content Provider bn di).
action: android.intent.action.EDIT
d liu: content://com.google.provider.NotePad/notes/ID

20

Lp trnh Android c bn
Ra lnh cho activity hin th ni dung ca ghi ch xc nh bi ID, ng thi
cho php ngi dng chnh sa n. Nu ngi dung lu cc thay i, activity
s cp nht d liu cho ghi ch trong Content Provider.
action: android.intent.action.INSERT
d liu: content://com.google.provider.NotePad/notes
Ra lnh cho activity to mt ghi ch mi trong danh sch ghi ch mi, rng ti
content://com.google.provider.notepad/notes, ng thi cho
php ngi dng chnh sa n. Nu ngi dung lu ghi ch, URI ca n c
tr v cho i tng gi.
Activity cui cng, TitleEditor, cho php ngi dng chnh sa tiu (title) ca
ghi ch. Vic ny c th c thc thi bng cch trc tip kch hot activity (nh thit
lp tn thnh phn ca n trong Intent mt cch tng minh), m khng cn s dng
b lc intent no. Nhng y, chng ta cn bt ly c hi ch ra cch trin khai nhng
activity thay th trn d liu c sn:
<intent-filter android:label=@string/resolve_title>
<action android:name=com.android.notepad.action.EDIT_TITLE />
<category android:name=android.intent.category.DEFAULT />
<category android:name=android.intent.category.ALTERNATIVE />
<category android:name=android.intent.category.SELECTED_ALTERNATIVE />
<data android:mimeType=vnd.android.cursor.item/vnd.google.note />
</intent-filter>

B lc n cho activity ny s dng mt action ty chnh gi l com.android.


notepad.action.EDIT_TITLE. N phi c kch hot trn mt ghi ch c th
(loi d liu vnd.android.cursor.item/vnd.google.note), ging nh cc
action VIEW v EDIT lc trc. Tuy nhin, y, activity hin th tiu cha trong d
liu ghi ch ch khng phi bn thn ni dung ca ghi ch.
Ngoi vic h tr hng mc DEFAULT nh thng l, trnh chnh sa tiu (title editor)
cn h tr hai tiu chun hng mc khc: ALTERNATIVE v SELECTED_ALTERNATIVE.
Nhng hng mc ny xc nh cc activity c th biu din cho ngi dung trong mt menu
gm cc ty chn (cng nh hng mc LAUNCHER xc nh nhng activity nn c
biu din cho ngi dng trong mn hnh chnh ca ng dng). Lu , b lc cn h r
mt nhn tng minh (thng qua android:label=@string/resolve_title)
kim sot tt hn nhng g ngi dung thy khi trnh by vi activity ny nh l mt
action thay th cho d liu m h ang xem. ( bit thm thng tin v cc hng mc
ny v vic xy dng nhng menu ty chn, xem cc phng thc PackageManager.
queryIntentActivityOptions() v Menu.addIntentOptions()).
Nh c trang b nhng kh nng trn, cc intent sau s gii quyt activity
TitleEditor:
action: com.android.notepad.action.EDIT_TITLE
d liu: content://com.google.provider.NotePad/notes/ID
Ra lnh cho activity hin th tiu lin kt vi ghi ch ID, ng thi cho php ngi
dng chnh sa tiu .

21

Lp trnh Android c bn

3. Kin thc c bn v ng dng


Cc ng dng Android c vit bng ngn ng lp trnh Java. Cc cng c thuc
Android SDK bin dch (compile) m ngun - km theo bt c file d liu v ti nguyn
no - thnh mt gi Android (package), l mt file lu tr (archive file) vi hu t
.apk. Ton b m ngun trong mt file .apk c coi l mt ng dng, y chnh l
file m cc thit b nn Android dng ci t ng dng.
Khi c ci t trn thit b, mi ng dng Android u sng trong vng sandbox
(mi trng o chy ng dng) bo mt ca mnh:

H iu hnh Android l h thng Linux a ngi dng (multi-user), trong mi ng


dng li l mt ngi dng khc.

Theo mc nh, h thng gn (assign) cho mi ng dng mt user ID duy nht (ID
ny ch c h thng dng v ng dng khng bit ti n). H thng thit lp
quyn (permission) cho tt c cc file trong ng dng, sao cho ch duy nht user
ID c gn cho ng dng mi c th truy cp (access) vo nhng file ny.

Mi tin trnh u c my o (virtual machine - VM) ring ca n, nn m ca mt


ng dng s chy c lp vi cc ng dng khc.

Theo mc nh, mi ng dng s chy trong tin trnh Linux ca ring mnh. Android
khi ng tin trnh khi c bt c thnh phn no ca ng dng cn c thc thi,
sau tt tin trnh khi n khng cn cn thit hoc khi h thng phi khi phc
(recover) b nh (memory) cho cc ng dng khc.

Bng cch ny, h thng Android p dng nguyn l c quyn ti thiu (principle of
least privelege). l: Theo mc nh, mi ng dng ch c quyn truy cp ti nhng
thnh phn m ng dng yu cu phi lm vic cho n v khng th hn na. iu
ny to ra mt mi trng rt an ton, trong mt ng dng khng th truy cp vo
nhng phn thuc h thng m n khng c cp quyn.
Tuy nhin, c nhiu cch mt ng dng chia s d liu vi nhng ng dng khc
v mt ng dng truy cp vo cc dch v ca h thng:

C th sp xp cho hai ng dng chia s cng user ID chng c th truy cp


vo cc file ca nhau. bo ton ti nguyn h thng, nhng ng dng c user
ID ging nhau cng c th sp xp chy trong cng mt tin trnh v chia s
cng mt my o (cc ng dng phi c ng k (sign) vi cng mt chng
nhn (certificate)).

Mt ng dng c th yu cu quyn truy cp d liu ca thit b, v d nh danh


b lin lc ca ngi dng, tin nhn SMS, khng gian lu tr c mount (gn
kt) vo h thng (tc th SD), camera, Bluetooth,... Mi quyn ca ng dng phi
c ngi dng cho php trong thi gian ci t.

Cc ni dung bn trn bao gm nhng kin thc c bn v cch thc mt ng dng


Android tn ti trong h thng. Phn cn li ca ti liu ny gii thiu:

Cc thnh phn framework ct li lm nn ng dng ca bn.

File k khai, trong bn khai bo nhng thnh phn v tnh nng thit b cn thit
cho ng dng.

22

Lp trnh Android c bn

Cc ti nguyn c tch bit khi m ng dng v cho php ng dng ti u ha


hnh vi (behavior) ca n cho nhiu loi cu hnh thit b khc nhau.

Cc thnh phn ca ng dng


Cc thnh phn (component) ca ng dng ng vai tr l nhng vin gch nn tng
cn thit xy dng mt ng dng Android. Mi thnh phn l mt im khc nhau
m nh n, h thng c th truy cp vo ng dng. Khng phi tt c cc thnh phn
u l im bt u cho ngi dung v mt s s ph thuc vo nhng thnh phn cn
li. Tuy nhin, mi thnh phn u c thc th (entity) ring v ng mt vai tr c th mi thnh phn l mt vin gch c nht quyt nh hnh vi tng quan ca ng dng.
C bn loi thnh phn khc nhau ca ng dng. Mi loi phc v cho mt mc ch
khc nhau v c vng i (lifecycle) khc bit xc nh cch thc thnh phn c to
ra cng nh hy b.
Sau y l bn loi thnh phn ca ng dng:
Activity
Activity biu din mt mn hnh (screen) vi giao din ngi dng trn . V d,
mt ng dng e-mail c th c mt activity lit k danh sch nhng e-mail mi,
mt activity khc son tho e-mail v mt activity khc dng c e-mail. Mc
d cc activity lm vic cng nhau to nn tri nghim ngi dng ng nht
trong ng dng e-mail, song chng li c lp vi nhau. Nh vy, mt ng dng
khc c th khi ng bt c mt activity no trong s chng (nu ng dng e-mail
cho php iu ny). V d, mt ng dng camera c th khi ng activity trong
ng dng e-mail son tho mail mi, trong ngi dng c th chia s mt
bc nh.
Mt activity c ci t l lp con ca Activity v bn c th tham kho thm
thng tin v n trong hng dn cho nh pht trin Activity.
Service
Service l thnh phn chy ngm (background) thc hin mt chui hot ng
hoc thc hin cng vic cho cc tin trnh t xa (remote process). Service khng
cung cp giao din ngi dng. V d, mt service c th chi nhc, service ny
chy ngm trong khi ngi dung ang s dng mt ng dng khc, hoc n c
th ly d liu trn mng m khng ngn ngi dng tng tc vi activity khc.
Thnh phn khc, chng hn nh mt activity, c th khi ng mt service v
n chy hoc lin kt (bind) vi n tng tc.
Mt service c ci t l lp con ca Service v bn c th tham kho thm thng
tin v n trong hng dn cho nh pht trin Service.
Content Provider
Content provider qun l mt tp d liu ca ng dng c chia s. Bn c th
lu tr d liu trong h thng file, trong c s d liu SQLite, trn Web hay bt k
ni lu tr lu di no m ng dng c th truy cp. Thng qua Content Provider,
cc ng dng khc c th truy vn (query) hoc thm ch sa i d liu (nu
Content Provider cho php). V d, h thng Android cung cp mt Content Provider

23

Lp trnh Android c bn
qun l thng tin lin lc ca ngi dung. Nh vy, mt ng dng bt k vi
quyn ph hp c th truy vn mt phn ca Content Provider (chng hn nh
ContactsContract.Data) c v ghi thng tin v mt ngi c th no ).
Cc Content Provider cng rt hu ch trong vic c, ghi d liu ring t i vi
ng dng ca bn v khng chia s i. V d, ng dng mu Note Pad dng mt
Content Provider lu cc ghi ch.
Content Provider c ci t l mt lp con ca ContentProvider v phi
ci t mt tp cc API chun cho php nhng ng dng khc thc hin cc giao
dch (transaction). bit thm thng tin, xem hng dn cho nh pht trin
Content Providers (Trnh cung cp ni dung)..
Broadcast receiver
Broadcast receiver l thnh phn phn hi li cc thng bo qung b ca ton h
thng. Nhiu broadcast xut pht t h thng - v d, mt broadcast thng bo rng
mn hnh tt, pin sp ht hoc mt bc nh ang c chp. Cc ng dng
cng c th khi to broadcast - v d, cho nhng ng dng khc bit rng mt
s d liu c ti v thit b v sn sng cho ngi dng s dng. Mc d cc
broadcast receiver khng hin th giao din ngi dng, song chng c th to mt
thng bo qua thanh trng thi (create a status bar notification) bo cho ngi
dung khi xy ra mt s kin broadcast. Mc d thng th mt broadcast receiver
ch l mt cng ra (gateway) ti cc thnh phn khc v dng thc hin mt
khi lng cng vic rt nh. V d, broadcast receiver c th khi to mt service
thc hin mt s vic da trn s kin.
Broadcast receiver c ci t l mt lp con ca BroadcastReceiver v mi
broadcast c gi di dng mt i tng Intent. bit thm thng tin, xem
lp BroadcastReceiver.
Mt kha cnh c o trong thit k h thng Android l bt c ng dng no cng c
th khi ng thnh phn ca ng dng khc. V d, nu bn mun chp mt bc nh
bng camera ca thit b, c th mt ng dng khc s lm iu v ng dng ca
bn s s dng n, thay v bn phi t pht trin mt activity chp nh. Bn khng
phi kt hp cht ch hoc thm ch lin kt ti ma ngun t ng dng camera. Thay
vo , bn ch cn lm mt vic n gin l khi ng activity c chc nng chp nh
trong ng dng camera. Khi hon thnh, bc nh c tr v cho ng dng ca
bn bn c th s dng n. i vi ngi dng, c v nh camera thc s l mt
phn trong ng dng ca bn.
Khi h thng khi ng mt thnh phn, n khi ng tin trnh cho ng dng (nu
n cha chy sn) v khi to cc lp cn thit cho thnh phn. V d, nu ng dng
ca bn khi ng activity trong ng dng camera chp mt bc nh, activity s
chy trong tin trnh thuc v ng dng camera ch khng phi trong tin trnh thuc
v ng dng ca bn. Do , khng ging nh cc ng dng trn hu ht nhng h
thng khc, cc ng dng Android khng c im bt u n l (v d nh khng c
hm (function) main()).
Do h thng chy tng ng dng trong mt tin trnh ring, vi quyn file hn ch truy
cp vo cc ng dng khc, nn ng dng ca bn khng th trc tip kch hot mt
thnh phn t ng dng khc. Tuy nhin, h thng Android li c kh nng thc hin

24

Lp trnh Android c bn
iu . V vy, kch hot mt thnh phn trong ng dng khc, bn phi gi mt
thng ip ti h thng xc nh intent ca mnh khi ng mt thnh phn c th.
Sau , h thng s kch hot thnh phn cho bn.

Kch hot cc thnh phn


Ba trong bn loi thnh phn - activity, service v broadcast receiver - c kch hot
bng mt thng ip khng ng b (asynchronous message) gi l mt intent. Cc
intent kt ni nhng thnh phn ring r li vi nhau trong lc chy chng trnh (bn
c th hnh dung chng nh nhng ngi truyn th yu cu mt action t cc thnh
phn khc), bt k thnh phn thuc v ng dng ca bn hay ng dng khc.
Mi intent c to ra vi mt i tng Intent, i tng ny nh ngha mt thng
ip (message) kch hot mt thnh phn c th hoc mt loi (type) thnh phn c
th - mt intent c th l intent tng minh hoc khng tng minh.
i vi cc activity v service, mt intent nh ngha mt action thc thi (v d,
xem (view) hoc gi (send) ci g ), ng thi c th xc nh URI ca d liu
thao tc vi (y l mt trong s nhng thng tin m thnh phn ang c khi
ng cn bit). V d, mt intent c th truyn t mt yu cu (request) ti mt activity
m mt tm nh hoc mt trang Web. Trong vi trng hp, bn c th khi ng
mt activity nhn kt qu, khi activity cng tr v kt qu di dng mt Intent
(v d, bn c th to mt intent cho php ngi dng chn mt thng tin lin lc c
nhn v tr v intent ny cho bn - intent c tr v s bao gm c URI ch ti s lin
lc trong danh b chn).
i vi cc broadcast receiver, intent ch n thun nh ngha thng bo ang c
pht i (v d, mt broadcast cho thy rng pin sp ht ch bao gm mt chui ni dung
l battery is low - c ngha l pin yu).
Mt thnh phn khc khng c cc intent kch hot l Content Provider. Thay vo
, Content Provider c kch hot khi l thnh phn ch ca mt yu cu t mt
ContentResolver. Trnh x l ni dung (content resolver) x l tt c cc giao dch
trc tip vi Content Provider, nn thnh phn ang thc hin giao dch vi content
provider khng phi lm cng vic trn m thay vo s gi cc phng thc ca i
tng ContentResolver. iu ny sinh ra mt tng (layer) tru tng gia Content
Provider v thnh phn yu cu thng tin (cho mc ch bo mt).
Mt s phng thc dng kch hot tng loi thnh phn:

Bn c th khi ng mt activity (hoc cung cp cho n mt action thc


thi) bng cch truyn mt Intent ti phng thc startActivity() hoc
startActivityForResult() (khi bn mun activity tr v kt qu).

Bn c th khi ng mt service (hoc a ra ch th mi ti mt service ang


chy) bng cch truyn mt Intent ti phng thc startService(). Hoc,
bn c th gn vo mt service bng cch truyn mt Intent ti phng thc
bindService().

Bn c th khi to mt broadcast bng cch truyn mt Intent ti cc


phng thc nh sendBroadcast(), sendOrderedBroadcast() hoc
sendStickyBroadcast().

25

Lp trnh Android c bn

Bn c th thc hin mt truy vn ti Content Provider bng cch gi phng thc


query() trn mt ContentResolver.

bit thm thng tin v cch s dng intent, xem ti liu Intents and Intent Filters
(Intent v b lc intent). Thng tin tham kho v vic kch hot cc thnh phn
c th cng c cung cp trong nhng ti liu sau: Activity, Service, Broadcast
Receiver v Content Providers.

File k khai
Trc khi h thng Android c th khi ng mt thnh phn ca ng dng, h thng
phi bit thnh phn tn ti hay cha bng cch c file AndroidManifest.
xml ca ng dng (file k khai). ng dng ca bn phi khai bo tt c cc thnh
phn ca n trong file k khai v file ny phi lu th mc gc (root) ca project (d
n) ng dng.
Ngoi vic khai bo cc thnh phn ca ng dng, file k khai c th thc hin mt s
vic khc nh:

Xc nh quyn ngi dung m ng dng i hi, nh quyn truy cp Internet hoc


quyn c thng tin lin lc trong danh b ca ngi dng.

Khai bo API Level (Cp API) ti thiu cn thit cho ng dng, da vo vic ng
dng s dng nhng API no.

Khai bo cc tnh nng phn cng v phn mm c ng dng yu cu hoc s


dng, chng hn nh camera, dch v bluetooth hay mn hnh cm ng a im
(multitouch screen).

Cc th vin API m ng dng cn lin kt ti (ngoi cc API trong framework Android),


chng hn nh Google Maps library (th vin Google Maps).

V cn nhiu vic khc na.

Khai bo cc thnh phn


Nhim v chnh ca file k khai l thng bo cho h thng v cc thnh phn ca ng
dng. V d, mt file k khai c th khai bo mt activity nh sau:
<?xml version=1.0 encoding=utf-8?>
<manifest ... >
<application android:icon=@drawable/app_icon.png ... >
<activity android:name=com.example.project.ExampleActivity
android:label=@string/example_label ... >
</activity>
...
</application>
</manifest>

Trong phn t <application>, thuc tnh android:icon ch ti nhng ti nguyn


ca biu tng nhn din ng dng.

26

Lp trnh Android c bn
Trong phn t <activity>, thuc tnh android:name xc nh tn lp y ca
lp con Activity, cn cc thuc tnh android:label ch nh mt chui s dng
nh l nhn m ngi dung c th thy c (user-visible label) cho activity.
Bn cn khai bo tt c cc thnh phn ca ng dng theo cch sau:

Cc phn t <activity> cho activity.

Cc phn t <service> cho service.

Cc phn t <receiver> cho broadcast receiver.

Cc phn t <provider> cho content provider.

Cc activity, service v Content Provider m bn bao gm trong m ngun nhng


khng khai bo trong file k khai s khng c h thng nhn thy, nn c th s
khng bao gi chy. Tuy nhin, cc broadcast receiver c th c khai bo trong file
k khai hoc c to ng trong m (nh cc i tng BroadcastReceiver)
v c ng k vi h thng bng cch gi phng thc registerReceiver().
bit thm thng tin v cu trc ca file k khai, xem ti liu File AndroidManifest.xml.

Khai bo kh nng ca thnh phn


Nh tho lun t trc, trong mc Kch hot cc thnh phn, bn c th s dng
mt Intent khi ng activity, service v broadcast receiver. Bn c th lm iu
ny bng cch t tn mt cch tng minh cho thnh phn ch (s dng tn lp thnh
phn) trong intent. Tuy nhin, sc mnh thc s ca cc intent nm bn trong khi nim
v nhng action ca chng. Bn ch vic m t loi ca action mnh mun thc hin (v
ty chn d liu khi bn mun thc hin), ng thi cho php h thng tm mt thnh
phn trn thit b c th thc thi action ri khi ng n. Nu c nhiu thnh phn c kh
nng thc hin action do intent m t, ngi dung s chn mt thnh phn cn s dng.
Cch thc m h thng nhn din nhng thnh phn c th phn hi li mt intent l
so snh intent nhn c vi cc b lc intent cung cp trong file k khai ca nhng
ng dng khc trn thit b.
Khi khai bo mt thnh phn trong file k khai ca ng dng, bn c th ty chn bao
gm cc b lc intent nhm khai bo nhng kh nng ca thnh phn n c th
phn hi li cc intent t nhng ng dng khc. Bn c th khai bo mt b lc intent
cho thnh phn bng cch thm vo mt phn t <intent-filter> ng vai tr lm
con ca phn t khai bo thnh phn .
V d, mt ng dng e-mail cha mt activity dng son tho e-mail mi c th khai
bo mt b lc intent trong file k khai ca n phn hi cc intent send (gi) ( gi
e-mail i). Sau , mt activity trong ng dng ca bn c th to ra mt intent vi action
gi (ACTION_SEND), sao cho h thng khp vi activity gi ca ng dng e-mail
v khi ng n khi bn kch hot intent thng qua phng thc startActivity().
bit thm thng tin v cch to cc b lc intent, xem ti liu Intents and Intent
Filters (Intent v b lc intent).

27

Lp trnh Android c bn

Khai bo cc yu cu ca ng dng
C rt nhiu thit b vn hnh bng Android v khng phi tt c trong s chng u
cung cp cc tnh nng v kh nng nh nhau. trnh cho ng dng ca bn khi
b ci t trn cc thit b thiu tnh nng cn thit vn hnh, mt iu quan trng l
bn phi nh ngha r rng mt profile cho nhng loi thit b m ng dng ca mnh
h tr, bng cch khai bo thit b cng cc yu cu phn mm trong file k khai. Hu
ht nhng khai bo ny u ch mang tnh thng tin v h thng khng c chng, song
cc service ngoi nh Google Play li c chng cung cp tnh nng lc tm kim
ng dng t thit b ca h.
V d, nu ng dng ca bn yu cu mt camera v s dng nhng API c gii thiu
trong Android 2.1 (API Cp 7), bn nn khai bo nhng yu cu ny trong file k khai.
Theo cch ny, nhng thit b khng c camera v c phin bn Android thp hn bn
2.1 s khng th ci t ng dng ca bn t Google Play.
Tuy nhin, bn cng c th khai bo rng ng dng ca mnh s dng camera, nhng
iu ny l khng bt buc. Vi trng hp ny, ng dng ca bn phi thc hin mt
thao tc kim tra trong thi gian chy xc nh xem thit b c camera khng v tt
cc tnh nng s dng camera i nu camera khng sn sng.
Sau y l mt s c tnh quan trng ca thit b m bn nn xem xt khi thit k v
pht trin ng dng ca mnh.
Kch thc mn hnh (screen size) v mt (density)
phn loi thit b theo kch thc mn hnh, Android nh ngha hai c tnh
cho mi thit b: Kch thc mn hnh (kch thc vt l ca mn hnh) v mt
mn hnh (mt cc pixel - im nh trn mn hnh, hay cn gi l dpi - dots per
inch). n gin ha tt c cc dng khc nhau ca cu hnh mn hnh, h thng
Android phn chng thnh cc nhm d dng la chn hn.
Cc kch thc mn hnh l: Nh (small), va (normal), ln (large) v rt ln
(extra large).
Cc mt mn hnh l: Thp (low), va (medium), cao (high) v rt cao (extra high).
Theo mc nh, ng dng ca bn s tng thch vi tt c cc kch thc v mt
mn hnh, v h thng Android s thc hin tinh chnh ph hp vi layout ca
giao din ngi dng v ti nguyn nh. Tuy nhin, bn nn to ra cc layout (b
cc) chuyn bit cho mt s kch thc mn hnh nht nh v cung cp cc nh
chuyn dng cho nhng mt nht nh, s dng cc ti nguyn layout thay th,
v bng cch khai bo chnh xc trong file k khai v kch thc mn hnh c
ng dng ca bn h tr vi phn t <supports-screens>.
tham kho thm thng tin, xem ti liu Supporting Multiple Screens (H
tr a mn hnh).
Cu hnh u vo
Nhiu thit b cung cp mt loi c ch nhp u vo khc bit, chng hn nh
bn phm phn cng (hardware keyboard), mt bi ln (trackball), hoc bn di chut
5 chiu (five-way navigation pad). Nu ng dng ca bn i hi mt phn cng
c th dng nhp u vo, bn nn khai bo n trong file k khai vi phn t

28

Lp trnh Android c bn
<uses-configuration>. Tuy nhin, rt him khi mt ng dng yu cu cu hnh
nhp nh vy.

Cc c im ca thit b
C nhiu c im phn cng v phn mm c th hoc khng th tn ti trn
mt thit b chy Android, chng hn camera, cm bin nh sng (light sensor),
bluetooth, mt phin bn nht nh ca OpenGL, hoc mn hnh cm ng trung
thc. Bn khng nn cho rng mt c im nht nh l c sn trn mi thit b
chy Android (ngoi th vin chun ca Android). Do , bn nn khai bo bt k
c im no c ng dng ca mnh s dng vi phn t <uses-feature>.
Phin bn nn tng
Cc thit b chy Android thng chy nhng phin bn khc nhau ca nn
tng Android, chng hn nh Android 1.6 hay Android 2.3. Mi phin bn thnh
cng thng bao gm thm cc API m cha tn ti trong nhng phin bn
trc . ch ra rng tp cc API sn sng, mi phin bn nn tng xc
nh mt Cp API (v d nh Android 1.0 l API Cp 1 (API Level 1) v Android
2.3 l API Cp 9). Nu s dng bt c API no c thm vo nn tng sau
phin bn 1.0, bn nn khai bo Cp API ti thiu c cha nhng API bng
cch s dng phn t <uses-sdk>.
iu quan trng l bn cn khai bo tt c cc yu cu cho ng dng ca mnh,
bi v khi bn phn phi ng dng trn Google Play, ca hng s s dng nhng khai
bo ny lc cc ng dng ph hp cho mi thit b. Nh vy, ng dng ca bn ch
nn hin th sn sng i vi nhng thit b p ng c mi yu cu m n a ra.
bit thm thng tin v cch Google Play lc cc ng dng da trn nhng yu
cu trn (hoc cc yu cu khc), xem ti liu Lc trn Google Play (Filters on
Google Play).

Ti nguyn ca ng dng
Mt ng dng Android khng ch bao gm m ngun - n i hi nhng ti nguyn khc
nm tch bit vi m ngun (source code), chng hn nh hnh nh, file m thanh v
bt c th g lin quan ti hnh thc trnh by trc quan ca ng dng. V d, bn nn
nh ngha cc hot cnh (animation), menu, style, mu sc v layout ca cc giao din
ngi dng activity vi file XML. S dng ti nguyn ca ng dng lm cho vic cp
nht nhiu c im khc nhau trong ng dng ca bn tr nn d dng m khng phi
chnh sa m ngun. Bn cnh , bng cch cung cp tp cc ti nguyn thay th,
bn c th ti u ha ng dng ca mnh cho nhiu loi cu hnh thit b (chng hn
nh nhng ngn ng v kch thc mn hnh khc nhau).
i vi mi ti nguyn bao gm trong d n Android, cc cng c SDK (SDK build toos)
xc nh mt ID duy nht c dng s nguyn (integer), v bn c th dng ID ny
tham chiu ti ti nguyn t m ngun ca ng dng hoc t cc ti nguyn khc c
nh ngha trong XML. V d, nu ng dng ca bn cha mt file nh tn l logo.png
(lu trong th mc res/drawable/directory), cc cng c SDK s to mt ID ti
nguyn c tn l R.drawable.logo, bn c th dng cho vic tham chiu ti file
nh v chn n vo giao din ngi dng ca mnh.

29

Lp trnh Android c bn
Mt trong nhng kha cnh quan trng nht ca vic cung cp ti nguyn tch bit khi ma
ngun l bn c th cung cp cc ti nguyn thay th cho nhng cu hnh thit b khc. V
d, bng vic nh ngha cc chui (t ,cm t, hoc cu) xut hin trn giao din ngi
dng (UI) trong XML, bn c th dch (translate) nhng chui ny sang loi ngn ng khc
v lu chng trong cc file ring bit. Sau , da vo mt b nh x ngn ng (language
qualifier) m bn thm vo tn th mc ti nguyn (chng hn nh res/values-fr/
i vi cc gi tr chui ting Php) v thit lp ngn ng ngi dung, h thng Android s
p dng nhng chui ngn ng ph hp cho giao din ngi dng ca bn.
Android h tr nhiu b nh x khc nhau cho cc ti nguyn thay th ca bn. B nh
x l mt chui ngn c bao gm trong tn ca th mc ti nguyn, xc nh loi
cu hnh thit b m ti , nhng ti nguyn trn nn c s dng. Mt v d khc,
bn nn thng xuyn to cc layout khc nhau cho nhng activity ca mnh, da vo
vo chiu xoay v kch thc mn hnh ca thit b. V d, khi mn hnh thit b ang
dng ng (portrait orientation, cn gi l tall), bn mun mt layout vi nhng button
nm dc. Tuy nhin, khi mn hnh dng nm ngang (landscapte orientation, cn gi
l wide), cc button nn c cn chnh theo chiu ngang. thay i layout da trn
chiu xoay mn hnh, bn c th nh ngha hai layout khc nhau v p dng b nh
x thch hp i vi tng tn th mc ca layout. Sau , h thng s t ng p dng
layout thch hp da vo chiu xoay hin ti ca thit b.
bit thm thng tin v nhng loi ti nguyn khc nhau m bn c th bao gm trong
ng dng ca mnh v cch to cc ti nguyn thay th cho nhiu loi cu hnh thit
b, xem hng dn dnh cho cc nh pht trin ti mc Ti nguyn ca ng dng.

4. File AndroidManifest.xml
Mi ng dng u phi c mt file AndroidManifest.xml (vi chnh xc tn gi )
trong th mc gc ca n. File k khai ny trnh by nhng thng tin cn thit v ng
dng cho h thng Android, l thng tin m h thng bt buc phi c trc khi n
c th chy bt c dng ma ngun no ca ng dng. Mt s nhim v m file k khai
c th thc hin bao gm:

Xc nh tn gi Java cho ng dng. Tn gi ng vai tr l nh mt nh danh


(identifier) duy nht ca ng dng.

M t cc thnh phn ca ng dng - activity, service, broadcast receiver v Content Provider cu thnh nn ng dng. File AndroidManifest.xml ch ra tn
cc lp thc thi mi thnh phn v a ra nhng kh nng ca chng (v d, cc
loi thng ip Intent m chng c th x l). Nhng khai bo nh vy cho h
thng Android bit cc thnh phn no c khi ng v chng c thc thi
di nhng iu kin no.

Quyt nh nhng tin trnh no s x l cc thnh phn ca ng dng.

Khai bo cc quyn m ng dng bt buc phi c c th truy cp vo cc phn


c bo v ca API v tng tc vi nhng ng dng khc.

Khai bo nhng quyn m cc thnh phn khc cn c c th tng tc vi


nhng thnh phn ca ng dng.

30

Lp trnh Android c bn

Lit k cc lp Instrumentation cung cp profile cng cc thng tin khc khi


ng dng ang chy. Nhng khai bo ny ch tn ti trong file k khai trong khi
ng dng ang c pht trin v kim th; chng b loi b trc khi ng dng
c pht hnh.

Khai bo cp API ti thiu m ng dng yu cu.

Lit k nhng th vin m ng dng phi lin kt ti.

Cu trc ca file k khai


Hnh bn di th hin cu trc chung ca file k khai v mi phn t n c th cha.
Mi phn t, cng vi mi thuc tnh ca n, c ghi li y trong mt file ring
bit. xem thng tin chi tit v bt c phn t no, hy nhn chut vo tn phn t
trong biu , trong danh sch cc phn t theo trnh t ABC trn s hoc trn bt
c ch no khc cp n tn phn t.
<?xml version=1.0 encoding=utf-8?>
<manifest>
<uses-permission />
<permission />

<permission-tree />

<permission-group />
<instrumentation />
<uses-sdk />

<uses-configuration />
<uses-feature />

<supports-screens />

<compatible-screens />

<supports-gl-texture />
<application>
<activity>

<intent-filter>
<action />

<category />
<data />

</intent-filter>
<meta-data />
</activity>
<activity-alias>

<intent-filter> . . . </intent-filter>
<meta-data />

</activity-alias>

31

Lp trnh Android c bn
<service>

<intent-filter> . . . </intent-filter>
<meta-data/>

</service>
<receiver>

<intent-filter> . . . </intent-filter>
<meta-data />

</receiver>
<provider>

<grant-uri-permission />
<meta-data />

<path-permission />

</provider>

<uses-library />
</application>
</manifest>

Tt c cc phn t c th xut hin trong file k khai u c lit k trong danh sch
bn di theo trnh t ABC. y ch l nhng phn t hp l; bn khng th t thm
cc phn t hoc thuc tnh ca ring mnh c.
<action>
<activity>
<activity-alias>
<application>
<category>
<data>
<grant-uri-permission>
<instrumentation>
<intent-filter>
<manifest>
<meta-data>
<permission>
<permission-group>
<permission-tree>
<provider>
<receiver>
<service>

32

Lp trnh Android c bn
<supports-screens>
<uses-configuration>
<uses-feature>
<uses-library>
<uses-permission>
<uses-sdk>

Cc quy c v file
Mt s quy c v quy tc p dng chung cho tt c cc phn t cng nh thuc tnh
trong file k khai:
Cc phn t
Ch c cc phn t <manifest> v <application> mi l phn t bt buc,
chng phi tn ti v c th ch duy nht mt ln. Hu ht cc phn t khc u c
th xut hin nhiu ln hoc khng - mc d t nht mt vi trong s chng phi c
mt trong file k khai c ngha.
Nu mt phn t cha bt k th g, n s cha c nhng phn t khc. Mi gi
tr u c thit lp thng qua thuc tnh, ch khng phi di dng d liu trong
mt phn t.
Cc phn t ng cp thng khng c cng th t. V d, cc phn t
<activity>, <provider> v <service> c th c trn ln theo bt c
trt t no. (Phn t <activity-alias> l ngoi l ca nguyn tc ny: N
phi theo sau <activity> m n l b danh (alias)).
Cc thuc tnh
Theo ngha chnh thc th tt c cc thuc tnh l ty chn (khng bt buc). Tuy
nhin, c mt s thuc tnh phi c ch nh cho mt phn t phc v mc
ch no . Hy s dng ti liu ny nh mt hng dn. i vi nhng thuc
tnh thc s khng bt buc, ti liu ny cp ti mt gi tr mc nh hoc trng
thi xy ra khi khng c s n nh gi tr no.
Ngoi tr mt s thuc tnh ca phn t gc <manifest>, cn li
mi tn thuc tnh u bt u vi tin t android: - v d nh
android:alwaysRetainTaskState. Do tin t mang tnh ton cc, nn cc
ti liu thng b qua n khi tham chiu n cc thuc tnh qua tn ca chng.
Khai bo tn lp
Nhiu phn t tng ng vi cc i tng Java, bao gm cc phn t cho bn
thn ng dng (phn t <application>) v nhng thnh phn chnh - activitiy
(<activity>), service (<service>), broadcast receiver (<receiver>),
Content Provider (<provider>).
Nu bn nh ngha mt lp con, hu ht l cho cc lp thnh phn (Activity,
Service, BroadcastReceiver v ContentProvider), lp con s c

33

Lp trnh Android c bn
khai bo thng qua thuc tnh name. Tn phi bao gm tn y ca gi. V d,
mt lp con Service c th c khai bo nh sau:
<manifest . . . >

<application . . . >

<service android:name=com.example.project.SecretService . . . >


. . .

</service>
. . .

</application>

</manifest>

Tuy nhin, c mt cch vit gin lc, nu k t u tin ca chui l mt du


chm, chui s c thm vo tn gi ca ng dng (c ch nh trong thuc tnh
package ca phn t <manifest>). on m di y tng t nh bn trn:
<manifest package=com.example.project . . . >
<application . . . >

<service android:name=.SecretService . . . >


. . .

</service>
. . .

</application>

</manifest>

Khi khi ng mt thnh phn, Android to mt th hin ca lp con c xc


nh tn. Nu khng lp con no c ch nh, Android s to mt th hin ca
lp nn tng (base class).
Nhiu gi tr
Nu c nhiu gi tr c n nh, xu hng ph bin l phn t s c lp li
thay v lit k nhiu gi tr trong mt phn t n. V d, mt b lc intent c th
lit k vi action:
<intent-filter . . . >

<action android:name=android.intent.action.EDIT />

<action android:name=android.intent.action.INSERT />


<action android:name=android.intent.action.DELETE />
. . .

</intent-filter>

Gi tr ti nguyn
Mt s thuc tnh c gi tr c th c hin th i vi ngi dung - v d, label
(nhn) v icon (biu tng) cho mt activity. Cc gi tr ca nhng thuc tnh ny

34

Lp trnh Android c bn
nn c nh v t mt ti nguyn hoc theme. Cc gi tr ti nguyn c th
hin di nh dng sau:
@[package:]type:name

trong , tn package (gi) c th b b qua nu ti nguyn nm cng gi vi ng


dng, type l loi ti nguyn - chng hn nh string hay drawable - v
name l tn nh danh ti nguyn c th. V d:
<activity android:icon=@drawable/smallPic . . . >

Gi tr ly t theme c biu din tng t, nhng bt u vi ? ch khng phi

@:

?[package:]type:name

Gi tr chui
Trong khi mt gi tr thuc tnh l mt chui, hai du cho ngc (\\) phi c dng
cho cc k t thot (escape character) - v d, \\n cho mt dng mi hoc \\uxxxx
cho mt k t Unicode.
Cc tnh nng ca file
Mc di y s m t cch mt s tnh nng ca Android c phn nh trong file
k khai.

B lc intent
Cc thnh phn ct li ca mt ng dng (activity, service v broadcast receiver) u
c intent kch hot. Intent l mt bundle thng tin (i tng Intent) m t mt
action mong mun - bao gm d liu cn gii quyt, hng mc ca thnh phn nn
thc hin action cng nhng ch dn khc. Android nh v mt thnh phn thch hp
phn hi intent, khi ng mt th hin mi ca thnh phn nu cn thit v truyn
cho n mt i tng Intent.
Cc thnh phn ch ra kh nng ca chng - nhng loi intent m chng c th phn
hi - thng qua cc b lc intent. Do h thng Android phi bit nhng intent no m
mt thnh phn c th x l trc khi khi ng mt thnh phn, nn cc b lc intent
s c xc nh trong file k khai di dng cc phn t <intent-filter>. Mt
thnh phn c th c s lng b lc ty , nhng mi b lc li m t mt kh nng
khc nhau.
Mt intent ch nh r rng tn ca thnh phn ch s kch hot thnh phn ; b lc
khng lm vic ny. Tuy nhin, mt intent khng ch nh c th tn thnh phn ch li
c th kch hot mt thnh phn ch khi intent c th vt qua mt trong nhng b lc
ca thnh phn y.
bit thm thng tin v cch cc i tng Intent c kim th qua b lc intent,
xem ti liu Intents and Intent Filters (Intent v b lc intent) .

35

Lp trnh Android c bn

Nhn v biu tng


Mt s phn t c thuc tnh icon v label hin th mt biu tng nh v mt nhn
ch cho ngi dng. Mt s khc cn c thuc tnh description cung cp dng m
t di hn v cng c th c hin th trn mn hnh. V d, phn t <permission>
c tt c ba thuc tnh, nn khi ngi dng c yu cu cp quyn cho mt ng dng
th mt biu tng i din cho quyn, tn ca quyn v mt m t v c hin th
cho ngi dung.
Trong mi trng hp, biu tng v nhn thit lp trong phn t cha n tr thnh
thit lp biu tng v nhn mc nh cho tt c cc phn t con. Do vy, biu
tng v nhn t trong phn t <application> l biu tng v nhn mc nh
cho mi thnh phn ca ng dng. Tng t, biu tng v nhn thit lp cho mt
thnh phn - v d, phn t <activity> - l thit lp mc nh cho tng phn
t <intent-filter> ca thnh phn . Nu phn t <application> t mt
nhn nhng mt activity v b lc intent ca n th khng, nhn ca ng dng s
c coi l nhn chung cho c activity ln b lc intent.
Biu tng v nhn thit lp cho mt b lc intent c dng i din cho mt
thnh phn khi thnh phn th hin ti ngi dng nhm mc ch hon thnh chc
nng c khai bo ca b lc. V d, mt b lc vi thit lp android.intent.
action.MAIN v android.intent.category.LAUNCHER nhn mt activity
nh l nhn t khi to ng dng - tc l, nhn t nn c hin th trong mn hnh
chnh ca ng dng. Do , biu tng v nhn thit lp trong b lc s c hin th
trong mn hnh chnh.

Quyn
Quyn (permission) l kh nng hn ch truy cp vo mt phn m ngun hoc d liu
trn thit b. S hn ch c p t bo v d liu v m ngun quan trng khi
vic b lm dng bp mo hoc gy hu qu ti tri nghim ngi dng.
Mi quyn c xc nh bng mt nhn duy nht. Thng th nhn ch ra action b hn
ch. V d, di y l mt s quyn nh ngha bi Android:
android.permission.CALL_EMERGENCY_NUMBERS
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER

Mt tnh nng c th c nhiu nht mt quyn bo v.


Nu mt ng dng cn truy cp ti tnh nng c mt quyn bo v, ng dng cn phi
khai bo rng n cn quyn bng cch s dng phn t <uses-permission>
trong file k khai. Sau , khi ng dng c ci ln thit b, trnh ci t (installer) s
quyt nh xem c cp quyn m ng dng yu cu hay khng bng cch kim tra c
quan cp chng thc cho ng dng, trong mt s trng hp s hi ngi dng. Nu
quyn c cp, ng dng c th s dng cc tnh nng c bo v. Nu khng,
vic c gng truy cp vo nhng tnh nng ny s tht bi m khng c mt thng bo
no cho ngi dng.

36

Lp trnh Android c bn
Mt ng dng cng c th bo v cc thnh phn ca n (activity, service, broadcast
receiver v Content Provider) vi quyn. ng dng c th s dng bt c quyn no
do Android nh ngha (c lit k trong android.Manifest.permission), hoc
do nhng ng dng khc khai bo, hoc t nh ngha. Mt quyn mi c khai bo
vi phn t <permission>. V d, mt activity c th c bo v nh sau:
<manifest . . . >
<permission android:name=com.example.project.DEBIT_ACCT . . . />
<uses-permission android:name=com.example.project.DEBIT_ACCT />
. . .
<application . . .>
<activity android:name=com.example.project.FreneticActivity
android:permission=com.example.project.DEBIT_ACCT
. . . >
. . .
</activity>
</application>
</manifest>

Lu , trong v d ny, quyn DEBIT_ACCT khng ch c khai bo vi phn t


<permission> m cn c yu cu vi phn t <uses-permission>. L do l
cc thnh phn khc ca ng dng c th khi ng activity c bo v, cho d
s bo v c p dng bi chnh bn thn ng dng.
Trong cng v d trn, nu thuc tnh permission c t cho mt quyn c
khai bo u (chng hn nh android.permission.CALL_EMERGENCY_
NUMBERS), th khng nht thit phi khai bo li vi phn t <permission>. Tuy
nhin, vn cn phi khai bo quyn vi <uses-permission>.
Phn t <permission-tree> khai bo mt namespace cho mt nhm quyn s
c nh ngha trong m ngun. V <permission-group> xc nh mt nhn
cho tp cc quyn (bao gm c nhng quyn c khai bo trong file k khai vi cc
phn t <permission> v nhng quyn c khai bo u khc). Phn t ny
ch nh hng ti cch cc quyn c nhm li khi hin th ti ngi dng. Phn t
<permission-group> khng xc nh quyn no thuc v nhm no m ch cp
cho nhm mt ci tn. Mt quyn c t trong nhm bng cch gn tn nhm vo
thuc tnh permissionGroup ca phn t <permission>.

Cc th vin
Mi ng dng c lin kt ti th vin mc nh ca Android, bao gm cc gi c
bn xy dng ng dng (vi nhng lp thng dng nh Activity, Service,
Intent, View, Button, Application, ContentProvider,).
Tuy nhin, mt s gi li nm trong th vin ring ca chng. Nu ng dng ca bn
dng m t bt k gi no trong s nhng gi ny, ng dng phi c lin kt r rng
ti chng. File k khai phi cha mt phn t <uses-library> ring bit t tn
cho mi th vin. (C th tm thy tn th vin trong ti liu ca gi ).

37

Lp trnh Android c bn

5. Giao din ngi dng trn mobile


Giao din ngi dng (User Interface - UI) ca ng dng l tt c nhng g ngi dung
c th nhn thy v tng tc c. Android cung cp nhiu thnh phn giao din
ngi dng c dng sn (pre-build UI), chng hn nh cc i tng layout c cu
trc v nhng iu khin (control) cho php bn xy dng giao din ha ngi dng
(Graphical User Interface - GUI) cho ng dng ca mnh. Ngoi ra, Android cn cung
cp nhng module UI khc cho cc giao din c bit nh hp thoi (dialog), thng bo
(notification) v menu.

5.1 Tng quan v giao din ngi dng


Mi phn t giao din ngi dng trong ng dng Android u c xy dng bng
cch s dng cc i tng View v ViewGroup. View l i tng v ra th g
trn mn hnh sao cho ngi dng c th tng tc c. ViewGroup l i tng
cha cc i tng View (v ViewGroup) khc nh ngha layout ca giao din.
Android cung cp mt tp hp (collection) gm c cc lp con ca View ln
ViewGroup, nhm cung cp cho ngi dng nhng iu khin u vo thng dng
(chng hn nh cc button v trng vn bn cng nhng dng layout khc nhau (v
d nh layout tuyn tnh hay layout tng i).

Layout ca giao din ngi dng


Giao din ngi dng ca mi thnh phn trong ng dng c nh ngha bng
cch s dng mt cy phn cp cc i tng View v ViewGroup, nh minh ha
Hnh 1. Mi nhm view l mt i tng cha v hnh (invisible container) b tr cc

38

Lp trnh Android c bn
view con, trong khi view con c th l nhng iu khin u vo hoc cc widget(2)
khc to thnh mt s phn ca giao din ngi dng. Cy phn cp c th dng
n gin hoc phc tp, tuy theo nhu cu (nhng s n gin vn l cch tt nht
gia tng hiu nng).

Hnh 1. Minh ha mt cy phn cp view, xc nh mt layout giao din ngi dng.


khai bo layout, bn c th khi to cc i tng View trong m ngun v bt
u xy dng mt cy phn cp, nhng cch d dng cng nh hiu qu nht l nh
ngha layout vi mt file XML. XML cung cp cho layout mt cu trc m con ngi c
kh nng c hiu c, tng t nh HTML.
Tn mt phn t XML cho mt view s tng ng vi lp Android m view ny i
din. Do , mt phn t <TextView> s to widget TextView trong giao din ngi
dng, cn mt phn t <LinearLayout> to mt view group LinearLayout.
V d, mt layout theo chiu dc n gin vi text view (view dng vn bn) v mt
button trng s nh di y:
<?xml version=1.0 encoding=utf-8?>

<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width=fill_parent

android:layout_height=fill_parent
android:orientation=vertical >

<TextView android:id=@+id/text

android:layout_width=wrap_content

android:layout_height=wrap_content

android:text=y l mt TextView />

<Button android:id=@+id/button

android:layout_width=wrap_content

android:layout_height=wrap_content
android:text=y l mt Button />

</LinearLayout>

L cc tin ch nh, thng dng cung cp thng tin hoc tng tc vi user dng n gin khi user khng mun mt thi
gian vo phn mm chnh.
(2)

39

Lp trnh Android c bn
Khi bn np mt ti nguyn layout trong ng dng, Android s khi to mi nt
(node) ca layout thnh mt i tng ang trong thi gian chy, bn c th
dng i tng nh ngha thm cc hnh vi, truy vn trng thi i tng hoc
chnh sa layout.
xem hng dn hon chnh v cch to mt layout giao din ngi dng, mi bn tham
kho XML Layouts.

Cc thnh phn ca giao din ngi dng


Bn khng nht thit phi xy dng tt c giao din bng cc i tng View v
ViewGroup . Android cung cp vi thnh phn ng dng a ra mt chun layout
giao din ngi dng m bn ch cn lm mt vic n gin l nh ngha ni
dung. Mi thnh phn giao din ngi dng nh vy u c mt tp cc API ring
c m t trong ti liu tng ng, chng hn nh Action Bar , Dialogs v
Status Notifications .

5.2 Layout
Layout nh ngha cu trc trc quan cho giao din ngi dng, chng hn nh giao din
ngi dng cho mt activity hoc widget ca ng dng (app widget). Bn c th khai bo
layout theo hai cch:

Khai bo cc phn t giao din ngi dng trong XML. Android cung cp mt
b t vng XML n gin tng ng vi cc lp View v lp con, v d nh cho
widget v layout.

Khi to cc phn t layout trong thi im chy. ng dng ca bn c th


to cc i tng View cng nh ViewGroup (v thao tc vi cc thuc tnh ca
chng) hon ton bng vic lp trnh.

Framework Android cho bn kh nng s dng linh hot mt hoc c hai phng thc
ny khai bo v qun l giao din ngi dng ca ng dng. V d, bn c th khai
bo layout mc nh cho ng dng trong XML, bao gm nhng phn t mn hnh s
xut hin trong v cc thuc tnh ca chng. Sau , bn c th thm m trong ng
dng thay i trng thi ca cc i tng mn hnh, bao gm nhng i tng
c khai bo trong XML ti thi im chy ng dng.
u im ca vic khai bo giao din ngi dng trong XML l cho php bn tch bit
tt hn m trnh by (giao din) ca ng dng khi phn m iu khin hnh vi ca
n. Cc m t giao din ngi dng c t bn ngoi ma ngun, c ngha l bn
c th sa i hoc ty chnh giao din m khng phi sa m ngun v bin dch li
(recompile). V d, bn c th to layout XML cho cc chiu xoay mn hnh khc nhau,
kch thc mn hnh khc nhau v ngn ng khc nhau. Ngoi ra, vic khai bo layout
trong XML gip cho vic hnh dung cu trc ca giao din ngi dng tr nn d dng
hn, dn ti vic g li (debug) cng d hn. Nh vy, ti liu ny tp trung vo vic
hng dn bn cch khai bo layout trong XML. Nu bn quan tm n cch khi to
cc i tng View vo thi im chy, hy tham kho lp ViewGroup v View.

40

Lp trnh Android c bn
Thng thng, b t vng XML khai bo cc phn t cho giao din ngi dng s
tun theo cu trc cng nh cch t tn ca lp v phng thc, trong tn phn t
tng ng vi tn lp v tn thuc tnh tng ng vi phng thc. Thc t, s tng
ng xy ra thng xuyn, nn bn c th on thuc tnh XML no s tng ng vi
phng thc lp no, hoc bit c lp no s ng vi mt phn t XML cho. Tuy
nhin, lu rng khng phi tt c b t vng u ging nhau. Trong vi trng hp,
nhng khc bit nh trong cch t tn vn tn ti. V d, phn t EditText c mt thuc
tnh text tng ng vi EditText.setText().
Mch nh: Tm hiu thm v cc loi layout khc nhau trong mc Common Layout
Objects (Cc i tng layout thng thng). Ngoi ra cn c mt b hng dn v
vic xy dng cc layout khc nhau trong ti liu hng dn Hello Views.

Plugin ADT cho Eclipse h tr bn xem trc layout ca file XML - sau khi m
file XML, chn tab Layout.

Bn nn th dng cng c Hierarchy Viewer g li layout - n hin th nhng


gi tr thuc tnh ca layout, v nhng wireframe (bn phc tho v b tr cc thnh
phn, ch tp trung vo layout, khng tp trung vo giao din ha nh hnh nh,
font ch, mu sc) c du hin ch r phn canh m v canh l, v hin th ton
b view trong khi bn g li trn phn mm gi lp hoc thit b tht.

Cng c layoutopt cho php bn phn tch nhanh layout v cy phn cp tm ra


cc vn v hiu sut hoc nhng vn khc.

Vit file XML


S dng b t vng XML ca Android, bn c th thit k nhanh nhng layout v phn
t mn hnh m chng bao hm, theo cch ging nh khi bn to trang Web trong
HTML - vi mt chui phn t lng nhau (nested element).
Mi file layout phi cha chnh xc mt phn t gc (root element) v phn t phi
l mt i tng View hoc ViewGroup. Sau khi nh ngha phn t gc, bn c
th thm cc i tng layout hoc widget di dng phn t con (child element)
tng bc xy dng mt cy phn cp View nh ngha layout ca bn. V d, sau y
l mt layout XML s dng i tng LinearLayout dng dc cha TextView
v Button:
<?xml version=1.0 encoding=utf-8?>

<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width=fill_parent

android:layout_height=fill_parent
android:orientation=vertical >

<TextView android:id=@+id/text

android:layout_width=wrap_content

android:layout_height=wrap_content

android:text=Xin cho, y l mt TextView />

<Button android:id=@+id/button

41

Lp trnh Android c bn
android:layout_width=wrap_content

android:layout_height=wrap_content

android:text=Xin cho, y l mt Button />

</LinearLayout>

Sau khi khai bo layout ca mnh trong XML, bn lu file li vi ui .xml trong th
mc res/layout/ ca d n Android, layout c bin dch.
bit thm thng tin v c php cho file layout XML, xem ti liu Layout Resources
(Cc ti nguyn layout).

Np ti nguyn XML
Khi bn bin dch ng dng, mi file layout XML c bin dch thnh mt ti nguyn
View. Bn nn np (load) ti nguyn layout t m ngun ca ng dng, trong phn
thc thi callback (gi tr li) Activity.onCreate(). thc hin iu , bn
gi setContentView(), sau truyn cho phng thc ny mt tham chiu ti ti
nguyn layout ca bn theo mu: R.layout.ten_file_layout. V d, nu layout XML
c lu thnh main_layout.xml, bn c th np layout ny cho Activity nh sau:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main_layout);

Framework ca Android s gi phng thc callback onCreate()trong Activity ca


bn khi Activity c khi ng (xem phn tho lun v vng i (lifecycle) trong ti
liu Activities.

Cc thuc tnh
Mi i tng View v ViewGroup h tr cc thuc tnh XML khc nhau ca chng.
Mt s thuc tnh l chuyn bit i vi mt i tng View (v d, TextView h tr
thuc tnh textSize), nhng nhng thuc tnh ny cn c bt c i tng View
no c th m rng t lp ny k tha. Mt s thuc tnh l thuc tnh chung i vi
tt c cc i tng View, bi v chng c k tha t lp View gc (nh thuc tnh
id chng hn). V, cc thuc tnh khc c coi nh l tham s ca layout (layout
parameter), l nhng thuc tnh m t hng layout ca i tng View, nh
c i tng cha l ViewGroup nh ngha.

ID
Bt k i tng View no cng c th s hu mt ID dng s nguyn (integer ID) lin
kt vi n ch xc nh View trong cy phn cp. Khi ng dng c bin dch, ID

42

Lp trnh Android c bn
ny c tham chiu di dng s nguyn, nhng trong file XML ca layout, ID c
gn di dng chui, trong thuc tnh id. y l mt thuc tnh XML thng xut hin
tt c cc i tng View (nh ngha bi lp View) v bn s thng xuyn s
dng n. C php ca ID bn trong th XML l:
android:id=@+id/my_button

Biu tng (@) phn u chui ch ra rng b phn tch XML (XML parser) nn phn
tch, m rng phn cn li ca chui ID v nhn bit n nh l mt ti nguyn ID. Biu
tng du cng (+) c ngha y l mt tn ti nguyn mi c to v thm vo kho
ti nguyn (trong file R.java). C mt s ti nguyn ID khc c cung cp bi framework Android. Khi tham chiu mt ID ca ti nguyn Android, bn khng cn biu tng
du cng, nhng phi thm vo namespace ca gi android nh sau:
android:id=@android:id/empty

Vi namespace gi android, hin chng ta ang tham chiu mt ID t lp ti nguyn


android.R ch khng phi lp ti nguyn ni b.
to cc view v tham chiu ti chng t ng dng, cch thng thng l:
1. nh ngha mt view/widget trong file layout v gn cho n mt ID duy nht:
<Button android:id=@+id/my_button

android:layout_width=wrap_content

android:layout_height=wrap_content

android:text=@string/my_button_text/>

2. Sau , bn to mt th hin ca i tng view v kim sot n t layout (thng


l trong phng thc onCreate()):
Button myButton = (Button) findViewById(R.id.my_button);

Vic xc nh ID cho cc i tng view ng vai tr quan trng khi to mt


RelativeLayout. Trong mt layout tng i (relative layout), nhng view ng
cp (sibling view) c th nh ngha layout ca chng lin quan ti view ng cp khc
bng cch tham chiu ti ID duy nht ca view .
Mt ID khng cn phi l duy nht trong ton b cy phn cp, nhng n nn l duy
nht trong mt phn ca cy m bn ang tm kim (cng c th l ton b cy, do
vy tt nht n nn l duy nht trn ton b cy khi c th).

Cc thng s layout
Cc thuc tnh layout XML c t tn di dng layout_<ten thuoc tinh> nh ngha
cc tham s layout cho View ph hp vi ViewGroup cha n.
Mi lp ViewGroup ci t di dng mt lp lng, m rng t lp ViewGroup.
LayoutParams. Lp con ny cha cc loi thuc tnh xc nh kch c v v tr cho

43

Lp trnh Android c bn
tng view con (child view) sao cho ph hp vi nhm view. Nh bn c th thy Hnh
1, nhm view cha (parent view) xc nh cc thng s layout cho mi view con (bao
gm c nhm view con).

Hnh 1. Minh ha mt cy phn cp view c cc tham s layout lin kt vi tng view.


Lu , mi lp con LayoutParams u c c php ring thit lp cc gi tr. Mi
phn t con phi xc nh LayoutParams thch hp vi phn t cha ca n, mc d
phn t con c th xc nh LayoutParams khc cho con ca mnh.
Mi nhm view u cha mt thng s chiu rng (width) v chiu cao (height)
(layout_width v layout_height), trong mi view u phi xc nh hai thng
s ny. Nhiu LayoutParams cn cha c cc ty chn l (margin) v vin (border).
Bn c th xc nh chiu rng v chiu cao vi cc kch thc chnh xc, mc d c
th bn khng mun lm iu ny thng xuyn. Thng th bn s hay s dng mt
trong nhng hng s di y hn thit lp chiu rng v chiu cao:

wrap_content cho bit view ny c kch thc thay i ph hp vi ni dung.

fill_parent (hay match_parent i tn trong API Cp 8) cho bit view ny c kch


thc ln bng kch thc m view cha cho php.

Nhn chung, vic xc nh mt chiu rng v chiu cao layout s dng cc n v tuyt
i nh pixel (im nh) khng c khuyn khch. Thay vo , s dng cc kch
thc tng i nh l nhng n v pixel c lp vi mt (density-independent
pixel - dp), wrap_content hoc fill_parent, l phng php tt hn, v n m bo rng
ng dng ca bn s hin th ng nhng kch thc mn hnh thit b khc nhau. Cc
loi kch thc c chp nhn c trnh by trong ti liu Available Resources
(Cc ti nguyn c sn).

44

Lp trnh Android c bn

V tr layout
Dng hnh hc ca view l hnh ch nht. Mi view c mt v tr, c th hin bng
mt cp ta left (bn tri), top (bn trn) cng hai thng s kch thc l chiu rng
v chiu cao. n v cho v tr v kch thc l pixel.
Chng ta c th ly thng s v tr ca mt view bng cch kch hot cc phng thc
getLeft() v getTop(). Phng thc getLeft() tr v thng s left, hay ta
X ca hnh ch nht i din cho view. Phng thc getTop() tr v thng s top,
hay ta Y ca hnh ch nht i din cho view. Cc phng thc ny u tr v v
tr tng i ca view so vi cha ca n. V d, khi getLeft() tr v 20, c ngha l
view c v tr cch cnh tri ca view cha ca n 20 pixel.
Ngoi ra, c mt vi phng thc tin li c cung cp trnh cc php tnh khng
cn thit, l getRight() v getBottom(). Nhng phng thc ny tr v
ta ca cnh phi v y ca hnh ch nht i din cho view. Chng hn, gi
getRight() s tng ng vi php tnh sau: getLeft() + getWidth().

Kch thc, vng m v cn l


Kch thc ca view c th hin bng mt thng s chiu rng v chiu cao. Thc
t, mi view lun s hu hai cp gi tr chiu rng v chiu cao.
Cp th nht c bit n vi tn chiu rng o lng (measured width) v chiu cao
o lng (measured height). Nhng di ny xc nh ln ca mt view so vi phn
t cha. C th thu c cc di o lng bng cch gi getMeasuredWidth()
v getMeasuredHeight().
Cp th hai c bit n n gin vi tn chiu rng (width) v chiu cao (height),
hoc i khi l chiu rng hnh hc (drawing width) v chiu cao hnh hc (drawing
height). Nhng di ny xc nh kch thc thc s ca view trn mn hnh, trong
thi gian v hnh v sau layout. Nhng gi tr ny c th (khng nht thit phi) khc
bit vi chiu cao o lng v chiu rng o lng. C th thu c chiu rng v
chiu cao bng cch gi getWidth() v getHeight().
o cc kch thc, mt view tnh c vng m (padding) ca n. Vng m c
th hin bng pixel cho phn bn tri, bn trn, bn phi v bn di ca view. C
th dng vng m thit lp khong cch cho phn ni dung ca view vi cnh
ca view bng mt lng pixel c th. V d, vng m bn tri l 2 s y ni dung
ca view i 2 pixel v bn phi ca cnh tri. C th thit lp vng m bng cch
dng phng thc setPadding(int, int, int, int), ng thi truy vn vng ny
bng cch gi getPaddingLeft(), getPaddingTop(), getPaddingRight()
v getPaddingBottom().
Mc d c th xc nh vng m, song view li khng h tr l (margin). Tuy nhin,
cc nhm view li h tr. Xem ViewGroup v ViewGroup.MarginLayoutParams
bit thm thng tin.
tham kho thng tin v cc di, xem ti liu Dimension Values (Cc gi tr di)

45

Lp trnh Android c bn

Cc layout thng dng


Mi lp con ca lp ViewGroup cung cp mt cch thc duy nht hin th cc view
lng trong n. Di y l mt s loi layout thng dng hn c xy dng cho nn
tng Android.
Ghi ch: Mc d bn c th lng mt hay nhiu layout vo trong layout khc hon
thin thit k giao din ca mnh, song bn vn nn c gng gi cho cy phn cp
layout c t cp nht. Layout ca bn s v nhanh hn nu c t layout lng trong
hn (mt cy phn cp thin v chiu rng s tt hn mt cy phn cp thin v
chiu su).

Layout tuyn tnh

Layout t chc cc con ca n thnh mt hng ngang hoc dc. N to mt thanh cun
dc (scrollbar) nu chiu di ca s vt qu chiu di mn hnh.

Layout tng i

Cho php bn xc nh v tr tng i ca cc i tng con (con A bn tri con


B) hoc tng i vi i tng cha (c cn chnh theo cnh trn cng ca i
tng cha).

46

Lp trnh Android c bn

Web View

Hin th cc trang Web.

Xy dng layout vi mt adapter


Khi ni dung ca layout l ng (dynamic) hoc khng c xc nh trc, bn c
th s dng mt layout l lp con ca AdapterView to ra mt layout bao gm cc
view ti thi im thc thi chng trnh. Lp con ca lp AdapterView dng mt
Adapter lin kt (bind) d liu cho layout ca n. Adapter ng vai tr l thnh
phn trung chuyn gia ngun d liu v layout AdapterView - Adapter ly d
liu (t mt ngun, chng hn nh mt mng hoc truy vn c s d liu) v chuyn
i mi mc thnh mt view c th thm vo layout AdapterView.
Cc layout thng dng c h tr bi mt adapter bao gm:

List View

Hin th mt danh sch cun gm mt ct n.

47

Lp trnh Android c bn

Grid View

Hin th mt li cun gm cc ct v dng.

in d liu vo mt adapter view


Bn c th to mt AdapterView, chng hn nh ListView hoc GridView bng
cch lin kt th hin AdapterView vi mt Adapter, Adapter ly d liu t mt
ngun bn ngoi v to mt View biu din mi mc d liu.
Android cung cp mt s lp con ca Adapter rt hu ch trong vic truy xut nhng
loi d liu khc nhau v xy dng cc view cho mt AdapterView. Hai adapter
thng dng nht l:

ArrayAdapter
S dng adapter ny khi ngun d liu ca bn l mt mng. Mc nh,
ArrayAdapter to mt view cho tng phn t mng bng cch gi phng thc
toString() trn mi thnh vin v t ni dung vo mt TextView.
V d, nu bn c mt mng cc chui mun hin th trong mt ListView, hy
khi to mt ArrayAdapter mi bng cch s dng mt phng thc khi to
(constructor) xc nh layout cho tng chui v mng chui:
ArrayAdapter adapter = new ArrayAdapter<String>(this,

android.R.layout.simple_list_item_1, myStringArray);

Cc tham s cho phng thc khi to trn l:


ng dng Context ca bn.

Layout cha mt TextView cho tng chui trong mng.

Mng cc chui.

Sau , bn ch cn gi setAdapter() trong ListView:


ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);

48

Lp trnh Android c bn
ty chnh hnh thc hin th ca mi mc, bn c th ghi (override) phng
thc toString() cho cc i tng trong mng. Hoc, to mt view cho mi
mc khc TextView (v d nu bn mun mt ImageView cho tng mc), hy
m rng lp ArrayAdapter v ghi phng thc getView() tr v loi ca
view bn mun cho mi mc.

SimpleCursorAdapter
S dng adapter ny khi d liu ca bn ti t mt i tng Cursor (con tr).
Khi s dng SimpleCursorAdapter, bn phi ch nh mt layout s dng
cho mi dng trong Cursor v cc ct trong Cursor nn c chn vo nhng
view tng ng ca layout. V d, nu mun to mt danh sch tn mi ngi
km theo s in thoi, bn c th thc thi mt truy vn tr v mt Cursor cha
mt dng cho tng ngi v cc ct cho tn cng s in thoi. Sau , bn to
mt mng chui xc nh cc ct t Cursor m bn mun trong layout cho tng
kt qu v mt mng s nguyn xc nh nhng view tng ng m mi ct nn
c t vo :
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,

ContactsContract.CommonDataKinds.Phone.NUMBER};

int[] toViews = {R.id.display_name, R.id.phone_number};

Khi bn khi to SimpleCursorAdapter, hy truyn layout s dng cho


tng kt qu, Cursor s cha cc kt qu v hai mng sau:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,

R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);

ListView listView = getListView();


listView.setAdapter(adapter);

Sau , adapter SimpleCursorAdapter s to mt view cho tng dng trong


Cursor, s dng layout thu c t vic chn mi mc fromColumns vo view
toViews tng ng.
Nu trong sut vng i ca ng dng, bn thay i d liu c bn c adapter
ca mnh c, bn nn gi notifyDataSetChanged(). Thao tc ny s thng
bo cho view nh km rng d liu b thay i v n nn t cp nht.

X l cc s kin click
Bn c th phn hi cc s kin Click trn tng mc trong mt AdapterView bng
cch thc thi giao din (interface) AdapterView.OnItemClickListener.
V d:

49

Lp trnh Android c bn
// To mt thng ip x l i tng di dng mt lp n danh
// (anonymous class).
private OnItemClickListener mMessageClickedHandler =
new OnItemClickListener() {

public void onItemClick(AdapterView parent, View v, int position,


long id) {

};

// Lm g phn hi li s kin Click

listView.setOnItemClickListener(mMessageClickedHandler);

5.2.1 Layout tuyn tnh


LinearLayout l mt nhm view c chc nng cn chnh ton b con ca n theo
mt hng duy nht, c th l dc hoc ngang. Bn c th xc nh hng ca layout
nh thuc tnh android:orientation.

Tt c view con ca mt LinearLayout u c xp chng (stack) ln nhau, nn


mt danh sch dc ch c duy nht mt con trn tng dng, bt k chng rng bao
nhiu i na; trong khi , mt danh sch ngang s ch cao mt dng (chiu cao ca
con cao nht, cng thm vng m). Mt LinearLayout b nh hng bi cc l
(margin) gia nhng view con v kiu cn chnh (gravity) (cn phi, cn gia hoc cn
tri) ca tng view con .

Trng s ca layout
LinearLayout cng h tr vic gn mt trng s (weight) cho ring tng view con
vi thuc tnh android:layout_weight. Thuc tnh ny gn mt gi tr tm quan

50

Lp trnh Android c bn
trng (importance) cho mt view theo ngha l n s chim bao nhiu khng gian trn
mn hnh. Mt gi tr trng s ln hn s cho php n m rng lp y bt k khng
gian cn li no trong view cha. Cc view con c th xc nh mt gi tr trng s, sau
bt c khng gian cn li no trong nhm view cng c gn cho cc con theo t
l khai bo. Trng s mc nh l 0.
V d, nu c ba trng vn bn v hai trong s khai bo mt trng s l 1, trong khi
trng khc khng c trng s, trng vn bn th ba khng c trng s s khng
tng di v s ch chim vng khng gian nht nh theo ni dung m n yu cu.
Hai trng kia s cng m rng lp y khng gian cn li sau khi c ba trng
c o lng. Nu, trng th ba c thit lp trng s l 2 (thay v 0), tc hin ti
trng th ba c khai bo l quan trng hn hai trng kia, trng ny s ly mt
na trong tng khng gian cn li, trong khi hai trng kia chia u khong khng gian
tha ra cho nhau.

Cc view con cng trng s


to mt layout tuyn tnh, trong mi view con s dng cng mt khong khng
gian trn mn hnh, hy thit lp gi tr ca android:layout_height ca tng view
thnh 0dp (cho layout dc) hoc android:layout_width ca mi view thnh
0dp (cho layout ngang). Sau , bn t gi tr cho android:layout_weight
ca tng view bng 1.

V d
<?xml version=1.0 encoding=utf-8?>

<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width=fill_parent

android:layout_height=fill_parent
android:paddingLeft=16dp

android:paddingRight=16dp

android:orientation=vertical >
<EditText

android:layout_width=fill_parent

android:layout_height=wrap_content
android:hint=@string/to />

<EditText

android:layout_width=fill_parent

android:layout_height=wrap_content
android:hint=@string/subject />

<EditText

android:layout_width=fill_parent
android:layout_height=0dp
android:layout_weight=1
android:gravity=top

51

Lp trnh Android c bn

<Button

android:hint=@string/message />
android:layout_width=100dp

android:layout_height=wrap_content
android:layout_gravity=right
android:text=@string/send />

</LinearLayout>

bit thm chi tit v cc thuc tnh cho tng view con ca mt LinearLayout,
xem LinearLayout.LayoutParams.

5.2.2 Layout tng i


RelativeLayout l mt nhm view c tnh nng hin th cc view con theo nhng

v tr tng i. V tr ca mi view c th c xc nh l tng i vi cc phn t


ngang cp (chng hn nh so vi cnh tri v cnh di ca view khc), hoc theo v
tr tng i so vi cha RelativeLayout (chng hn nh so vi bn di, bn tri
ca phn gia).

52

Lp trnh Android c bn

RelativeLayout l mt tin ch rt hiu qu trong thit k giao din ngi dng, v


n c th xa b cc nhm view lng nhau v gi cho cy phn cp layout c t cp
nhm gia tng hiu sut. Nu t thy mnh s dng vi nhm LinearLayout lng
nhau, bn c th thay th chng bng mt RelativeLayout.

nh v cc view
RelativeLayout cho php cc view con n nh v tr tng i ca chng so
vi view cha hoc vi mt view khc (c xc nh bng ID). Do vy, bn c th
cn chnh hai phn t bng vin phi, hoc lm cho view n bn di view kia, nm
gia mn hnh, nm gia theo chiu dc v bn tri theo chiu ngang,... Theo
mc nh, tt c view con u c v gc trn bn tri ca layout, nn bn phi
nh ngha v tr ca tng view, s dng nhiu thuc tnh ca layout c sn trong
RelativeLayout.LayoutParams.
Mt s thuc tnh layout dng cho cc view trong mt RelativeLayout bao gm:

android:layout_alignParentTop
Nu true: Lm cho gc trn ca view ny khp vi gc trn ca view cha.

android:layout_centerVertical
Nu true: Cn gia view con ny theo chiu dc trong phm vi view cha.

android:layout_below
Cc v tr cnh trn ca view ny nm di view c ID c ch nh.

android:layout_toRightOf
Cc v tr cnh tri ca view ny nm v bn phi ca view c ID c ch nh.

53

Lp trnh Android c bn
Trn y ch l mt s v d. Tt c thuc tnh ca layout c ghi ti
RelativeLayout.LayoutParams.
Gi tr cho mi thuc tnh layout c th l boolean (true/false) cho php mt v tr
layout tng i vi cha RelativeLayout, hoc mt ID tham chiu ti mt view
khc trong layout, ni view ny c nh v.
Trong layout XML, cc i tng ph thuc vo nhng view khc c th khai bo theo
th t bt k. V d, bn c th khai bo rng view1 nm bn di view2 ngay c
nu khi view2 l view cui cng c khai bo trong cy phn cp. V d di y
minh ha mt trng hp nh vy.

V d
Trong on m di y, mi thuc tnh kim sot v tr tng i ca tng view c
in m.

54

Lp trnh Android c bn
<?xml version=1.0 encoding=utf-8?>

<RelativeLayout xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width=fill_parent

android:layout_height=fill_parent
android:paddingLeft=16dp

android:paddingRight=16dp >
<EditText

android:id=@+id/name

android:layout_width=fill_parent

android:layout_height=wrap_content
android:hint=@string/reminder />

<Spinner

android:id=@+id/dates

android:layout_width=0dp

android:layout_height=wrap_content
android:layout_below=@id/name

android:layout_alignParentLeft=true

android:layout_toLeftOf=@+id/times />

<Spinner

android:id=@id/times

android:layout_width=96dp

android:layout_height=wrap_content
android:layout_below=@id/name

android:layout_alignParentRight=true />

<Button

android:layout_width=96dp

android:layout_height=wrap_content
android:layout_below=@id/times

android:layout_alignParentRight=true
android:text=@string/done />

</RelativeLayout>

bit thm chi tit v tt c cc thuc tnh ca layout cho tng view con ca mt
RelativeLayout, xem RelativeLayout.LayoutParams.

5.2.3 List View


ListView l nhm view c tnh nng hin th danh sch nhng mc c th cun c

(scrollable item). Cc mc ca danh sch c chn t ng vo danh sch bng cch


s dng mt Adapter ly ni dung t mt ngun, nh mt mng hoc truy vn c
s d liu, ng thi chuyn i tng kt qu thnh mt view t bn trong danh sch.
xem hng dn cch chn ng cc view bng cch s dng adapter, mi bn
tham kho mc Xy dng layout vi mt adapter.

55

Lp trnh Android c bn

S dng Loader
S dng CursorLoader l phng php chun truy vn mt Cursor (con
tr) di dng mt tc v khng ng b (asynchronous task) trnh chn lung
(thread) chnh ca ng dng khi truy vn. Khi CursorLoader nhn kt qu Cursor,
LoaderCallbacks nhn mt phng thc callback ti onLoadFinished(),
l ni bn cp nht Adapter vi Cursor mi v list view hin th kt qu v sau.
Mc d cc API CursorLoader c gii thiu ln u trong Android 3.0 (API Cp
11), song chng u c mt trong Support Library (th vin h tr) nn ng dng ca
bn c th s dng chng nu n h tr cc thit b chy Android 1.6 hoc cao hn.
Mun bit thm thng tin v cch s dng Loader np d liu theo cch khng
ng b, hy xem hng dn v Loaders (Cc trnh Loader).

V d
V d sau y s dng ListActivity, l activity cha mt ListView vi t
cch l phn t layout duy nht theo mc nh. N thc thi mt truy vn ti Contacts
Provider yu cu danh sch cc tn v s in thoi.
Activity thi hnh giao din LoaderCallbacks s dng CursorLoader nhm
np ng d liu cho list view.

56

Lp trnh Android c bn
public class ListViewLoader extends ListActivity

implements LoaderManager.LoaderCallbacks<Cursor> {

// y l Adapter c s dng hin th d liu ca danh sch

// y l cc dng danh b m chng ta s nhn c

SimpleCursorAdapter mAdapter;

static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,

ContactsContract.Data.DISPLAY_NAME};

// y l iu kin chn

static final String SELECTION = (( +

ContactsContract.Data.DISPLAY_NAME + NOTNULL) AND ( +


ContactsContract.Data.DISPLAY_NAME + != ));

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// To mt thanh tin trnh (progress bar) hin th khi danh sch np


ProgressBar progressBar = new ProgressBar(this);

progressBar.setLayoutParams(new

LayoutParams(LayoutParams.WRAP_CONTENT,

LayoutParams.WRAP_CONTENT, Gravity.CENTER));

progressBar.setIndeterminate(true);

getListView().setEmptyView(progressBar);
// Phi thm thanh tin trnh vo gc ca layout


ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
root.addView(progressBar);

// i vi adapter con tr, hy xc nh nhng ct no s i


// vi view no

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};


int[] toViews = {android.R.id.text1}; // TextView trong

//simple_list_item_1

//
//
//
//

To mt adapter trng, chng ta s dng n hin th d


liu np.
Chng ta truyn null vo con tr, sau cp nht n trong
onLoadFinished()

mAdapter = new SimpleCursorAdapter(this,

android.R.layout.simple_list_item_1, null,

fromColumns, toViews, 0);

setListAdapter(mAdapter);

// Chun b loader. Hoc kt ni li vi mt loader c sn,


// hoc khi ng mt loader mi.

57

Lp trnh Android c bn

getLoaderManager().initLoader(0, null, this);

// c gi khi mt loader mi phi c to ra

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

// Lc ny, hy to v tr v mt CursorLoader, CursorLoader

// ny s m nhim vic to mt Con tr cho d liu c hin th.


return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
}

PROJECTION, SELECTION, null, null);

// c gi khi mt loader to t trc c np xong

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {


// Tro i (swap) con tr mi vo. (Framework s tin hnh
// vic ng con tr c khi chng ta quay v).

mAdapter.swapCursor(data);
}

// c gi khi mt trnh loader to t trc c phc hi v


// trng thi ban u (reset), lm cho d liu khng kh dng
public void onLoaderReset(Loader<Cursor> loader) {

// c gi khi Con tr cui cng c gi ti onLoadFinished()


// bn trn b ng. Chng ta cn m bo l s khng s dng
// con tr ny na.

mAdapter.swapCursor(null);
}

@Override

public void onListItemClick(ListView l, View v, int position, long id) {

// Lm g khi mt mc danh sch c nhn

Ghi ch: Do v d ny thc thi mt truy vn trn Contacts Provider nn nu bn mun


th on m ny, ng dng ca bn phi yu cu quyn READ_CONTACTS trong file
k khai (manifest file):

<uses-permission android:name=android.permission.READ_CONTACTS />.

5.2.4 Grid View


GridView l mt ViewGroup c tnh nng hin th cc mc trong mt li hai chiu
c th cun c. Cc mc ca li c t ng chn vo layout bng cch s dng
mt ListAdapter.

xem hng dn cch chn ng cc view bng cch s dng mt adapter, mi bn


tham kho mc Xy dng layout vi mt adapter trong cun sch ny.

58

Lp trnh Android c bn

V d
Trong hng dn ny, bn s to mt li gm cc mu nh (image thumbnail - dng
hnh nh thu nh ca mt bc nh). Khi mt mc c chn, mt thng ip tc thi
(toast message) s hin th v tr ca nh.
1. Bt u mt d n mi c tn HelloGridView.
2. Tm mt s tm nh bn mun s dng, hoc ti v cc nh mu ny. Lu cc file
nh vo th mc res/drawable/ ca d n.
3. M file res/layout/main.xml v thm on m sau vo:
<?xml version=1.0 encoding=utf-8?>

<GridView xmlns:android=http://schemas.android.com/apk/res/android
android:id=@+id/gridview

android:layout_width=fill_parent

android:layout_height=fill_parent

android:columnWidth=90dp

android:numColumns=auto_fit

android:verticalSpacing=10dp

android:horizontalSpacing=10dp

android:stretchMode=columnWidth
android:gravity=center
/>

59

Lp trnh Android c bn
GridView ny s lp y ton b mn hnh. Hu ht cc thuc tnh u kh d

hiu. bit thm thng tin v nhng thuc tnh hp l, mi bn xem phn tham
kho GridView.

4. M HelloGridView.java v chn on m sau cho phng thc onCreate():


public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

GridView gridview = (GridView) findViewById(R.id.gridview);

gridview.setOnItemClickListener(new OnItemClickListener() {

gridview.setAdapter(new ImageAdapter(this));

public void onItemClick(AdapterView<?> parent, View v, int


position, long id) {

Toast.makeText(HelloGridView.this, "" + position, Toast.LENGTH_


SHORT).show();

}
});
}

Sau khi layout main.xml c thit lp cho view ni dung, GridView c ly


v t layout thng qua phng thc findViewById(int). Sau , phng thc
setAdapter() thit lp mt adapter ty chn (ImageAdapter) vi t cch l
ngun cho tt c cc mc cn hin th trong li. ImageAdapter c to
bc tip theo.
thc hin mt tc v no khi nhn vo mt mc trong li, phng
thc setOnItemClickListener() c truyn mt AdapterView.
OnItemClickListener mi. Th hin v danh v danh (anonymous instance)
ny xc nh phng thc callback onItemClick() thc thi mt Toast hin
th v tr ch s (index) (bt u t s 0) ca mc c chn (thc t, v tr c th
c dng ly nh kch thc gc cho nhng tc v khc).
5. To mt lp mi c tn ImageAdapter m rng BaseAdapter:
public class ImageAdapter extends BaseAdapter {

private Context mContext;

public ImageAdapter(Context c) {

mContext = c;

public int getCount() {

return mThumbIds.length;
}

public Object getItem(int position) {


return null;

60

Lp trnh Android c bn
}

public long getItemId(int position) {

return 0;

// to mt ImageView mi cho mi mc tham chiu bi Adapter

public View getView(int position, View convertView, ViewGroup parent) {

ImageView imageView;


if (convertView == null) { // nu convertView cha b hy, hy khi

// to mt s thuc tnh

imageView = new ImageView(mContext);

imageView.setLayoutParams(new GridView.LayoutParams(85, 85));

imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

imageView.setPadding(8, 8, 8, 8);

imageView = (ImageView) convertView;

} else {

imageView.setImageResource(mThumbIds[position]);
return imageView;
}

// tham chiu ti cc nh

private Integer[] mThumbIds = {

R.drawable.sample_2, R.drawable.sample_3,

R.drawable.sample_6, R.drawable.sample_7,

};

R.drawable.sample_4, R.drawable.sample_5,
R.drawable.sample_0, R.drawable.sample_1,
R.drawable.sample_2, R.drawable.sample_3,
R.drawable.sample_4, R.drawable.sample_5,
R.drawable.sample_6, R.drawable.sample_7,
R.drawable.sample_0, R.drawable.sample_1,
R.drawable.sample_2, R.drawable.sample_3,
R.drawable.sample_4, R.drawable.sample_5,
R.drawable.sample_6, R.drawable.sample_7

Trc ht, lp ny thc thi mt s phng thc cn thit tha k t BaseAdapter.


Phng thc khi to v getCount() l hai phng thc n gin, khng cn gii
thch thm. Thng thng, getItem(int) nn tr v i tng thc s v tr xc
nh trong adapter nhng trong v d ny, n b b qua. Tng t, getItemId(int)
nn tr v id hng ca mc, song y, vic ny l khng cn thit.

61

Lp trnh Android c bn
Phng thc cn thit u tin l getView(). Phng thc ny to mt View mi
cho mi nh c thm vo ImageAdapter. Khi getView() c gi, mt View
c truyn vo, thng l mt i tng c kh nng b thu hi b nh (t nht l
sau khi phng thc ny c gi mt ln), nn y s c mt bc kim tra xem
i tng ny c bng null khng. Nu i tng l null, mt i tng ImageView
s c khi to v cu hnh vi cc thuc tnh mong mun cho vic trnh by nh:
oo

setLayoutParams(ViewGroup.LayoutParams) thit lp chiu cao v

oo

setScaleType(ImageView.ScaleType) khai bo rng cc bc nh nn

oo

setPadding(int, int, int, int) xc nh vng m (padding) cho tt

chiu rng cho View - iu ny m bo rng, cho d kch c ca drawable l


bao nhiu, mi nh s c thay i kch thc v ct xn (crop) ph hp vi
nhng di ny.
c ct xn quanh trung tm (nu cn).

c cc cnh bn. (Lu , nu cc nh c t l khung hnh khc nhau, nh no c t


vng m hn s b ct xn nhiu hn nu n khng khp vi nhng di c
a ra cho ImageView).

Nu View truyn ti getView() khc null, ImageView cc b c khi to vi


i tng c kh nng c ti s dng l View.
cui phng thc getView(), s nguyn position truyn ti phng thc
c s dng chn mt nh t mng mThumbIds, mng ny c thit lp l
ti nguyn nh cho ImageView.
on m cn li nh ngha mThumbIds nh l mt mng gm cc ti nguyn
drawable.
6. Chy ng dng.
nghim vi nhng hnh vi ca GridView v cc phn t
ImageView bng cch iu chnh thuc tnh ca chng. V d, thay v
dng setLayoutParams(ViewGroup.LayoutParams), hy s dng
setAdjustViewBounds(boolean).
Th

5.3 Cc s kin u vo
Trn Android, c nhiu cch chn (intercept) cc s kin t mt action tng
tc ca ngi dng vi ng dng ca bn. Khi xem xt cc s kin trong giao din
ngi dng, bn nn p dng phng php bt cc s kin t i tng View c
th m ngi dung tng tc cng. Lp View cung cp phng tin thc hin
iu ny.
Trong nhng lp View khc nhau dng to layout, hy lu rng c vi phng
thc callback dng public hu ch cho cc s kin giao din ngi dng. Nhng
phng thc ny c framework Android gi khi action tng ng xy ra trn i
tng . V d, khi nhn vo mt View (chng hn nh mt Button), phng thc
onTouchEvent() s c gi trn i tng . Tuy nhin, ngn chn iu ny,
bn phi m rng lp v ghi ln phng thc . Nhng vic m rng mi i
tng View x l s kin nh vy s khng thit thc. l l do ti sao lp View
cn cha mt tp cc giao din lng nhau vi nhng callback m bn c th d nh

62

Lp trnh Android c bn
ngha hn nhiu. Cc giao din nh vy gi l trnh lng nghe s kin (event listener),
l cha kha bt nhng tng tc ca ngi dng vi giao din.
Trong khi bn s dng trnh lng nghe s kin lng nghe tng tc ca ngi dung,
c th s n lc no bn mun m rng mt lp View xy dng mt thnh phn
ty chnh. C th bn mun m rng lp Button to ra ci g hay hn chng hn.
Trong trng hp ny, bn c th nh ngha cc hnh vi s kin mc nh cho lp
bng cch s dng trnh x l s kin (event handler) cho lp.

Trnh lng nghe s kin


Trnh lng nghe s kin l mt giao din trong lp View cha mt phng thc callback.
Nhng phng thc ny s c framework Android gi khi trnh lng nghe s kin
ng k c kch hot trn view do ngi dng tng tc vi mt mc trn giao din.
Nhng phng thc callback sau c bao hm trong trnh lng nghe s kin:

onClick()
T View.OnClickListener. Phng thc ny c gi khi ngi dung chm
vo mc ( ch cm ng), hoc chuyn focus(3) vo mc bng cch s dng
cc phm iu hng (nevigation key) hay bi ln v nhn phm enter hoc nhn
bi ln xung.

onLongClick()
T View.OnLongClickListener. Phng thc ny c gi khi ngi dung
chm ri gi vo mc ( ch cm ng), hoc focus vo mc vi cc phm
iu hng hay bi ln v nhn gi phm enter ph hp hoc nhn gi bi ln (trong
mt giy).

onFocusChange()
T View.OnFocusChangeListener. Phng thc ny c gi khi ngi
dung di chuyn n hoc ri khi mt mc bng cch s dng cc phm iu
hng hoc bi ln.

onKey()
T View.OnKeyListener. Phng thc ny c gi khi ngi dung focus
vo mt mc v nhn hoc th mt phm cng trn thit b.

onTouch()
T View.OnTouchListener. Phng thc ny c gi khi ngi dung thc
hin mt action, chng hn nh mt s kin chm (touch event), bao gm nhn, th
hay bt c ng tc di chuyn no trn mn hinh (trong phm vi ca mc).

onCreateContextMenu()
T View.OnCreateContextMenuListener. Phng thc ny c gi khi
mt menu ng cnh (context menu) ang c dng (kt qu ca vic nhn lu
(long click). Xem tho lun v menu ng cnh trong phn hng dn cho nh
pht trin Menu ca sch ny.
(3)

Trng thi ca iu khin ang c kch hot hay c chn ngi dng c th thao tc hoc nhp liu vi n.

63

Lp trnh Android c bn
Mi phng thc ny l thnh phn duy nht ca giao din tng ng. nh ngha
mt trong nhng phng thc ny v x l cc s kin, hy thc thi giao din lng
(nested interface) trong Activity hoc nh ngha n nh l mt lp n danh. Sau ,
hy truyn mt th hin ca lp ny ti phng thc View.set...Listener()
tng ng. (V d, hy gi setOnClickListener() v truyn cho n th hin ca
OnClickListener).
V d bn di ch r cch ng k mt trnh lng nghe s kin on-click cho mt Button.
// To mt lp n danh ca OnClickListener

private OnClickListener mCorkyListener = new OnClickListener() {


public void onClick(View v) {

// lm g khi button c nhn

};

protected void onCreate(Bundle savedValues) {


...

// Ly v button t layout

// ng k trnh lng nghe onClick vi lp n danh bn trn

Button button = (Button)findViewById(R.id.corky);

button.setOnClickListener(mCorkyListener);
...
}

Bn c th thy thun tin hn khi thc thi OnClickListener nh l mt phn ca


Activity. iu ny s ngn vic np thm lp v cp pht i tng khng xy ra. V d:
public class ExampleActivity extends Activity implements OnClickListener
{

protected void onCreate(Bundle savedValues) {

...

Button button = (Button)findViewById(R.id.corky);

button.setOnClickListener(this);
}

// Trin khai callback OnClickListener


public void onClick(View v) {

}
}

// lm g khi button c nhn

...

Lu , callback onClick() trong v d bn trn khng c gi tr tr v, nhng mt s


phng thc lng nghe s kin khc phi tr v mt kt qu dng boolean. L do ty
thuc vo s kin. i vi mt s phng thc khc , l do chnh l:

64

Lp trnh Android c bn

onLongClick() - tr v mt boolean cho bit liu bn s dng xong s kin

onKey() - tr v mt boolean cho bit liu bn s dng xong s kin hay cha

onTouch() - tr v mt boolean cho bit liu trnh lng nghe s kin x l xong

hay cha v bn khng cn x l n na. Tc l, tr v true (ng) ch ra rng


bn x l s kin v n nn dng ti y; tr v false (sai) nu bn cha x l
xong s kin v/hoc n nn tip tc lm vic vi bt c trnh lng nghe s kin
on-click no khc.
v bn khng cn x l n na. Tc l, tr v true ch ra rng bn x l xong
s kin v n nn dng ti y; tr v false nu bn cha x l xong s kin v/
hoc n nn tip tc lm vic vi bt c trnh lng nghe s kin on-key no khc.
s kin ny. Vn quan trng l s kin ny c th c nhiu action theo sau nhau.
V vy, nu tr v false khi s kin action nhn chm vo mn hnh c nhn, c
ngha l bn cha dng xong s kin v cng khng quan tm ti cc action theo
sau s kin ny. Do vy, bn s khng c gi cho bt c action no khc trong
s kin, chng hn nh mt c ng ngn tay hoc s kin action cui cng.

Cn nh rng, cc s kin phm cng lun c gi ti View hin ti m bn ang


focus vo. Chng c gi bt u t nh ca cy phn cp View, sau xung dn
ti khi n c ch thch hp. Nu View ca bn (hoc mt con ca View) ang c
focus, bn c th thy s kin truyn qua phng thc dispatchKeyEvent(). Nh
mt gii php thay th cho vic bt cc s kin phm qua View, bn c th nhn tt c
s kin trong Activity vi onKeyDown() v onKeyUp().
ng thi, khi ngh v u vo vn bn cho ng dng ca mnh, bn cn nh rng
nhiu thit b ch c cc phng tin nhp liu (input method) mm. Cc phng n
ny khng i hi phi da trn phm cng; mt s c th s dng cch nhp liu
bng ging ni (voice input), nhp liu bng ch vit (handwriting input) v nhiu
loi khc. Thm ch, nu mt phng tin nhp liu hin th mt giao din ging bn
phm, thng th n s khng kch hot h cc s kin onKeyDown(). Bn khng
nn xy dng mt giao din ngi dng i hi bm vo phm c th kim sot,
tr phi bn mun hn ch ng dng ca mnh ch chy vi nhng thit b c bn phm
cng. C th, bn nn thit k sao cho khng ph thuc vo cc phng thc
kim tra u vo khi ngi dung nhn phm return, thay vo s dng nhng action
nh IME_ACTION_DONE bo cho phng tin nhp liu bit ng dng trng i
cch phn ng nh th no, t c th thay i giao din ngi dng theo hng
tt hn. Hy loi b nhng gi nh khng cn thit v cch hot ng ca phng
tin nhp liu mm v ch vic tin tng n cung cp vn bn nh dng cho ng
dng ca bn.
Ghi ch: Android s gi cc phng thc x l s kin trc, sau l nhng
phng thc x l mc nh ph hp vi nh ngha lp bc th hai. Nh vy,
vic tr v true t nhng trnh lng nghe s kin ny s ngn s kin khng truyn
ti cc trnh lng nghe s kin khc, ng thi chn phng thc callback i vi
phng thc x l s kin mc nh trong View. V vy, hy chc chn rng bn
mun chm dt s kin khi tr v true.

65

Lp trnh Android c bn

Cc phng thc x l s kin


Nu ang xy dng mt thnh phn ty chnh t View, bn c th nh ngha mt vi
phng thc callback nh nhng phng thc x l s kin mc nh. Trong ti liu
Thnh phn ty chnh, bn s bit c mt s callback thng dng dng cho vic
x l s kin, bao gm:

onKeyDown(int, KeyEvent) - c gi khi xy ra mt s kin nhn phm.

onKeyUp(int, KeyEvent) - c gi khi xy ra mt s kin th phm.

onTrackballEvent(MotionEvent) - c gi khi xy ra mt s kin di

onTouchEvent(MotionEvent) - c gi khi xy ra mt s kin di chuyn

onFocusChanged(boolean, int, Rect) - c gi khi mt view c

chuyn bi ln.

trn mn hnh cm ng.


focus hoc mt focus.

C mt s phng thc khc khng phi l mt phn ca lp View, nhng c th trc


tip nh hng ti cch bn x l cc s kin. Do vy, khi qun l nhiu s kin phc
tp hn trong mt layout, hy xem xt cc phng thc sau:

Activity.dispatchTouchEvent(MotionEvent) - Cho php Activity

ViewGroup.onInterceptTouchEvent(MotionEvent) - Cho php ViewGroup

ViewParent.requestDisallowInterceptTouchEvent(boolean) - Gi

ca bn chn tt c cc s kin chm mn hnh trc khi chng c gi n


window (ca s).
theo di cc s kin khi chng c gi ti nhng View con.

phng thc ny trn View cha ch ra rng view cha khng chn cc s kin
chm mn hnh vi onInterceptTouchEvent(MotionEvent).

Ch cm ng
Khi ngi dung thc hin iu hng trn giao din vi cc phm iu hng (directional
key) hoc bi ln, iu cn thit l phi focus vo nhng mc c kh nng tng tc
(nh button), gip ngi dng bit c ci g s tip nhn u vo. Tuy nhin, nu
thit b c tnh nng cm ng v ngi dung bt u tng tc vi giao din bng cch
chm ln mn hnh th khng nht th it phi nh du cc mc hoc focus vo mt
View c th. Do , c mt ch tng tc gi l ch cm ng (touch mode).
i vi mt thit b c kh nng cm ng, mt khi ngi dng chm vo mn hnh,
thit b s chuyn sang ch cm ng. T lc ny tr i, ch nhng View m ti ,
isFocusableInTouchMode() c gi tr true s c focus vo, chng hn nh cc
widget chnh sa vn bn. Nhng View khc cng c kh nng cm ng, nh cc button,
s khng c focus khi ngi dng chm vo; thay v vy chng l kch hot cc trnh
lng nghe s kin on-click khi bn nhn vo.

66

Lp trnh Android c bn
Bt c thi im no ngi dung nhn phm iu hng hoc ln bi ln, thit b s
thot khi ch cm ng v tm mt view focus vo. Lc ny, ngi dng c th
tip tc tng tc vi giao din ngi dng m khng phi chm vo mn hnh.
Ch cm ng c duy tr trn ton h thng (tt c window v activity). truy vn
trng thi hin thi, bn c th gi isInTouchMode() xem thit b c ang ch
cm ng hay khng.

X l s kin focus
Framework s nh k x l thay i v focus p ng thao tc nhp liu t
ngi dng. iu ny bao gm vic thay i focus khi mt s View b xa hoc n
i, hay khi View mi to ra. Cc view cho bit chng sn sng nhn focus
thng qua phng thc isFocusable(). di chuyn focus vo mt View, hy gi
setFocusable(). Khi ch cm ng, bn c th truy vn xem mt View c cho
php focus hay khng vi isFocusableInTouchMode(). Bn c th thay i iu
ny vi setFocusableInTouchMode().
Vic di chuyn focus c da vo thut ton tm hng xm gn nht theo hng
cho. Trong mt s trng hp him gp, thut ton mc nh c th khng khp
vi hnh vi d nh ca lp trnh vin. Trong nhng tnh hung , bn c th cung
cp cc thuc tnh ghi tng minh ln nhng thuc tnh XML trong file layout l
nextFocusDown, nextFocusLeft,nextFocusRight v nextFocusUp. Hy thm mt trong
cc thuc tnh ny vo View s mt focus, ng thi nh ngha gi tr thuc tnh bng
gi tr id ca View s nhn focus. V d:
<LinearLayout

android:orientation=vertical

... >

<Button android:id=@+id/top

android:nextFocusUp=@+id/bottom

... />

<Button android:id=@+id/bottom

android:nextFocusDown=@+id/top

... />

</LinearLayout>

Trong layout dc ny, iu hng ln trn t Button u tin s khng i u c, v


cng khng iu hng tr xung t Button th hai. Lc ny, Button trn cng xc
nh nt di cng l nextFocusUp (v ngc li), mn hnh s focus vo cc i
tng ln lt v tun hon t trn xung di v t di ln trn.
Nu bn mun khai bo mt View c th focus c trong giao din ngi dng (d n c
theo truyn thng hay khng), hy thm thuc tnh XML android:focusable vo View
, trong phn khai bo layout v thit lp gi tr true. Bn cng c th khai bo mt View c
th focus c trong lc ch cm ng vi android:focusableInTouchMode.

67

Lp trnh Android c bn
yu cu mt View nhn focus, gi requestFocus().
lng nghe cc s kin focus (khi mt View c focus hoc mt focus), s dng
onFocusChange(), nh tho lun trong mc Trnh lng nghe s kin trn.

5.4 Menu
Menu l thnh phn giao din ngi dng thng dng trong nhiu loi ng dng.
cung cp tri nghim ngi dung quen thuc v nht qun, bn nn s dng cc API
Menu biu din action ca ngi dng v nhng ty chn khc trong cc activity
ca mnh.
K t Android 3.0 (API Cp 11), cc thit b nn Android khng cn bt buc phi c
mt button Menu na. Vi s thay i ny, cc ng dng Android nn thot khi s
ph thuc vo bng menu 6 mc m thay vo cung cp mt action bar th hin
nhng action thng thng ca ngi dung.
Mc d thit k v tri nghim ngi dng cho cc mc ca menu thay i, nhng
nhng yu t cn bn nh ngha mt tp action v ty chn vn da trn cc API
Menu. Hng dn ny ch ra cch to ba loi menu c bn hoc biu din cc action
trn mi phin bn ca Android:
Menu ty chn v action bar
Menu ty chn (Options menu) l tp cc mc menu chnh cho mt activity. y
l ni bn nn t cc action c nh hng trn ton ng dng, chng hn nh
Search (tm kim), Compose email (son tho e-mail) v Settings (chnh sa
cc thit lp).
Nu bn ang pht trin cho Android 2.3 hay cp thp hn, ngi dng c th hin
th bng menu ty chn ty chn bng cch nhn button Menu.
T phin bn 3.0 tr i, cc mc trn menu ty chn c hin th trn action bar
bao gm cc action trn mn hnh v cc hnh ng n (overflow option - ngi
dng chm vo mt biu tng cui action bar hin th nhng action n ny).
K t Android 3.0, button Menu dn b loi b (mt s thit b khng c button ny).
Do vy, bn nn hng ti s dng action bar cung cp cch thc truy cp ti
nhng action v ty chn khc.
Xem mc To mt menu ty chn.
Menu ng cnh v ch contextual action
Menu ng cnh (context menu) l mt menu ng (floating menu) xut hin khi
ngi dung nhn lu trn trn mt phn t. Menu ny cung cp cc action nh
hng ti ni dung hoc khung ng cnh c chn.
Khi pht trin ng dng cho Android 3.0 v cp cao hn, bn nn s dng ch
contextual action (contextual action mode) kch hot cc action trn phn ni
dung c chn. Ch ny hin th nhng mc action nh hng ti ni dung
c chn trong mt thanh pha trn mn hnh v cho php ngi dung chn
cng lc nhiu mc.
Xem mc To menu ng cnh.

68

Lp trnh Android c bn
Menu popup
Menu popup hin th mt danh sch cc mc theo dng dc ngay trn view kch
hot menu . Menu cung cp dng cung cp nhiu action lin quan ti ni
dung c th hoc cung cp thm ty chn cho mt lnh. Cc action trong mt
menu popup khng nh hng trc tip ti ni dung tng ng - ging nh cc
action trn menu ng cnh. Thay vo , menu popup cung cp nhng action m
rng lin quan ti cc vng ni dung trong activity ca bn.
Xem mc To menu popup.

nh ngha mt menu trong XML


Android cung cp mt nh dng XML chun nh ngha cc mc menu cho tt c
cc loi menu. Thay v xy dng mt menu trong m ngun ca activity, bn nn nh
ngha mt menu v tt c cc mc ca n trong mt file ti nguyn menu XML. Sau ,
bn c th in np file XML ny di dng mt i tng Menu trong activity.
Bn nn s dng ti nguyn menu v nhng l do sau:

Ti nguyn menu gip bn d hnh dung cu trc menu trong XML hn.

Ti nguyn menu gip tch bit phn ni dung ca menu ra khi m x l ca


ng dng.

Ti nguyn menu cho php bn to cc cu hnh menu thay i cho nhng phin
bn nn tng, cc kch thc mn hnh v cu hnh khc nhau bng cch s dng
framework ti nguyn ng dng (app resources).

nh ngha menu, hy to mt file XML bn trong th mc res/menu/ ca d n


v xy dng menu vi cc phn t di y:

<menu>
nh ngha mt Menu l i tng cha cho cc mc menu. Mt phn t <menu>
nn l nt gc cho file, c th cha mt hoc nhiu phn t <item> v <group>.

<item>
To mt MenuItem i din cho mt mc n trong menu. Phn t ny c th
cha mt phn t <menu> lng to mt menu con (submenu).

<group>
L phn t khng bt buc, nh ngha mt vt cha n (v hnh) cho cc phn t
<item>. N cho php bn phn loi cc mc menu chng c th chia s thuc
tnh, chng hn nh trng thi active v trng thi hin th (visibility). tham kho
thm thng tin, xem mc To nhm menu.
y l mt menu v d c tn game_menu.xml:

69

Lp trnh Android c bn
<?xml version=1.0 encoding=utf-8?>

<menu xmlns:android=http://schemas.android.com/apk/res/android>

<item android:id=@+id/new_game

android:icon=@drawable/ic_new_game
android:title=@string/new_game

android:showAsAction=ifRoom/>

<item android:id=@+id/help

android:icon=@drawable/ic_help
android:title=@string/help />

</menu>

Phn t <item> h tr vi thuc tnh m bn c th dng nh ngha giao din v


hnh vi cho mt mc. Cc mc trong menu trn bao gm nhng thuc tnh sau:

android:id
ID ti nguyn duy nht i vi mt mc, cho php ng dng nhn din mc khi
ngi dung chn n.

android:icon
Tham chiu ti mt drawable s dng biu tng cho mc.

android:title
Tham chiu ti mt chui s dng lm tiu cho mc.

android:showAsAction
Xc nh thi im v cch thc m mc ny xut hin di dng mt mc action
trong action bar.
y l nhng thuc tnh quan trng nht m bn nn s dng, nhng ngoi ra cn
c sn nhiu thuc tnh khc. bit thm thng tin v tt c cc thuc tnh c
h tr, xem ti liu Menu Resource (Ti nguyn menu).
Bn c th thm mt menu con vo mt mc trong bt c menu no (ngoi tr trong
mt menu con) bng cch thm mt phn t <menu> di dng l con ca <item>.
Cc menu con rt hu ch khi ng dng c nhiu chc nng c th c t chc theo
ch nh cc mc trong thanh menu ca ng dng my tnh (File, Edit, View,...).
V d:
<?xml version=1.0 encoding=utf-8?>

<menu xmlns:android=http://schemas.android.com/apk/res/android>

<item android:id=@+id/file

android:title=@string/file >

<!-- menu con ca file -->


<menu>

<item android:id=@+id/create_new

70

android:title=@string/create_new />

Lp trnh Android c bn
<item android:id=@+id/open

</menu>

android:title=@string/open />

</item>

</menu>

s dng menu trong activity, bn phi chuyn i ti nguyn XML thnh mt i


tng c th lp trnh c bng cch s dng MenuInflater.inflate(). Trong
cc mc tip theo, bn s thy cch to mt i tng menu da trn file XML cho
tng loi menu.

To mt menu ty chn

Hnh 1. Menu ty chn trong Trnh duyt, trn Android 2.3.


Menu ty chn l ni cha cc action v ty chn khc lin quan ti ng cnh activity
hin ti, chng hn nh Search, Compose email v Settings.
V tr cc mc trong menu ty chn xut hin trn mn hnh ty chn s ph thuc
vo phin bn m bn ang pht trin ng dng:

Nu bn pht trin ng dng cho Android 2.3.x (API Cp 10) hay cp thp hn,
ni dung ca menu ty chn s xut hin phn di mn hnh khi ngi dung
nhn button Menu, nh minh ha Hnh 1. Khi menu ty chn c m ra, u
tin menu cha biu tng ca su mc menu. Nu menu cha qu su mc,

71

Lp trnh Android c bn
Android s t mc th sau v nhng mc menu cn li vo menu trn (overflow
menu) m ti , ngi dng c th m bng cch chn More.

Nu bn pht trin ng dng cho Android 3.0 (API Cp 11) v cp cao hn, cc
mc t menu ty chn u sn c trong action bar. Theo mc nh, h thng t tt
c cc action u b n trong mt biu tng bn phi ca action bar v ngi
dng c th hin th chng bng cch bm vo biu tng ny (hoc bng cch
nhn button Menu ca thit b, nu c). cho php truy cp nhanh vo nhng
action quan trng, bn c th tng cp vi mc xut hin trong action bar bng
cch thm android:showAsAction=ifRoom vo cc phn t <item>
tng ng (xem Hnh 2).
bit thm thng tin v cc mc action v nhng hnh vi khc ca action bar,
xem hng dn Action Bar.
Ghi ch: Ngay c khi khng pht trin ng dng cho Android 3.0 v cp cao hn,
bn cng c th xy dng layout cho action bar ca mnh vi hiu ng tng t.
tm hiu v d v cch bn c th h tr cc phin bn c hn ca Android vi
action bar, xem v d mu trong ti liu mu Action Bar Compatibility (Tng thch
Action Bar).

Hnh 2. Action bar t ng dng Honeycomb Gallery hin th cc tab iu hng v mt


mc action camera (cng vi l biu tng cha cc hnh ng n).
Bn c th khai bo cc mc cho menu ty chn t lp con Activity hoc lp con
Fragment. Nu c activity ln nhng phn vng (c to bi lp Fragment) u
khai bo cc mc cho menu ty chn, chng s c kt hp trong giao din ngi
dng. Cc mc ca activity xut hin trc tin, theo sau l nhng mc thuc tng
phn vng theo th t m mi phn vng c thm vo activity. Nu cn, bn c th
sp xp li cc mc menu vi thuc tnh android:orderInCategory trong tng
<item> bn cn phi di chuyn th t.
n nh menu ty chn cho mt activity, hy ghi phng thc
onCreateOptionsMenu() (cc phn vng t cung cp phng thc callback
onCreateOptionsMenu() ca chng). Trong phng thc ny, bn c th s dng
ti nguyn menu (c nh ngha trong file XML) to Menu. V d:

72

Lp trnh Android c bn
@Override

public boolean onCreateOptionsMenu(Menu menu) {


MenuInflater inflater = getMenuInflater();

return true;

inflater.inflate(R.menu.game_menu, menu);

Bn cng c th thm cc mc menu bng cch s dng add() v truy xut cc mc


menu vi findItem() cp nht thuc tnh ca chng, s dng lp MenuItem.
Nu bn pht trin ng dng cho Android 2.3.x v cp thp hn, h thng s gi
phng thc onCreateOptionsMenu() to menu ty chn khi ngi dng m
menu ln u. Cn nu bn pht trin ng dng cho Android 3.0 v cp cao hn, h
thng s gi onCreateOptionsMenu() khi khi ng activity hin th cc mc
ln action bar.

X l cc s kin click
Khi ngi dung chn mt mc t menu ty chn (gm cc mc action trong action bar),
h thng s gi phng thc onOptionsItemSelected() ca activity. Phng thc
ny truyn MenuItem chn. Bn c th nhn din mc bng cch gi phng thc
getItemId() tr v ID duy nht cho mc menu (xc nh bi thuc tnh android:id
trong ti nguyn menu hoc vi mt s nguyn c truyn cho phng thc add()).
Bn c th khp ID ny vi cc mc menu c thc hin action thch hp. V d:
@Override

public boolean onOptionsItemSelected(MenuItem item) {



// X l vic la chn mc menu


switch (item.getItemId()) {

case R.id.new_game:
newGame();

return true;
case R.id.help:
showHelp();

return true;
default:

return super.onOptionsItemSelected(item);
}
}

Khi bn x l thnh cng mt mc menu, hy tr v true. Nu khng x l mc


menu, bn nn gi phng thc onOptionsItemSelected() ca lp cha (mc
nh phng thc ny tr v false).
Nu activity ca bn bao gm cc phn vng th trc tin, h thng s gi
onOptionsItemSelected() ca activity ri ca tng phn vng (theo th t m

73

Lp trnh Android c bn
mi phn vng c thm vo) ti khi c mt gi tr true c tr v hoc tt c cc
phn vng u c gi.
Mch nh: Android 3.0 b sung kh nng cho php bn nh ngha hnh vi on-click
cho mt mc menu trong XML, s dng thuc tnh android:onClick. Gi tr cho
thuc tnh phi l tn phng thc do activity s dng menu ny nh ngha. Phng
thc phi l public v chp nhn mt tham s MenuItem n - khi h thng gi
phng thc ny, n s truyn mc menu chn. tham kho thm thng tin v
v d, xem ti liu Menu Resource (Ti nguyn menu).
Mch nh: Nu ng dng cha nhiu activity v mt vi trong s chng cung cp menu
ty chn ging nhau, hy cn nhc vic to mt activity khng thc thi g, ngoi tr
cc phng thc onCreateOptionsMenu() v onOptionsItemSelected().
Sau , hy m rng lp ny cho mi activity m c menu ty chn ging nhau .
Bng cch ny, bn c th qun l mt tp m ngun cho vic x l nhng action
menu v mi lp con chu k tha cc hnh vi menu. Nu bn mun thm cc mc
menu vo mt trong nhng activity con chu, hy ghi onCreateOptionsMenu()
trong activity . Gi super.onCreateOptionsMenu(menu) cc mc menu
gc (ca lp cha) c to, ri thm nhng mc menu mi vi menu.add(). Bn
cng c th ghi hnh vi ca lp cha cho tng mc menu ring l.

Thay i mc menu vo thi im thc thi


Sau khi h thng gi onCreateOptionsMenu(), h thng s duy tr mt th
hin ca Menu bn to v khng gi li onCreateOptionsMenu() na, tr
phi menu b mt hiu lc v mt s l do. Tuy nhin, bn ch s dng phng thc
onCreateOptionsMenu() to trng thi menu ban u v khng thay i trong
sut vng i ca activity .
Nu mun chnh sa menu ty chn da trn cc s kin xy ra trong sut
vng i ca activity, bn c th thc hin iu ny bn trong phng thc
onPrepareOptionsMenu(). Phng thc ny truyn i tng Menu ang tn
ti bn c th chnh sa, chng hn nh thm (add), loi b (remove) hay v hiu
ha (disable) cc mc. (Cc phn vng cng cung cp mt phng thc callback
onPrepareOptionsMenu()).
Trn Android 2.3.x v cp thp hn, h thng gi onPrepareOptionsMenu() mi
ln ngi dung m menu ty chn (nhn button Menu).
Trn Android 3.0 v cp cao hn, menu ty chn c xem nh lun m khi cc
mc menu c hin th trong action bar. Khi mt s kin xy ra v bn mun cp
nht menu, bn phi gi invalidateOptionsMenu() yu cu h thng gi
onPrepareOptionsMenu().
Ghi ch: Bn khng nn thay i cc mc trong menu ty chn da trn View hin
ang focus. Ti ch ch cm ng (khi ngi dung ang khng s dng bi ln
hoc bn iu hng D-pad), cc view khng th c focus, do bn khng nn
dng focus lm c s chnh sa cc mc trong menu ty chn. Nu bn mun
cung cp cc mc menu ng cnh cho mt View, hy s dng menu ng cnh
(Context Menu).

74

Lp trnh Android c bn

To menu ng cnh

Hnh 3. nh chp mn hnh ca mt menu ng cnh ng (tri) v mt action bar ng


cnh (phi).
Mt menu ng cnh cung cp cc action nh hng ti mt mc hoc khung ng cnh
c th trong giao din ngi dng. Bn c th cung cp mt menu ng cnh cho bt
c view no, nhng chng thng c s dng cho cc mc trong mt ListView,
GridView hoc nhng tp view khc m ti , ngi dung c th thc hin action
trc tip ln tng mc.
Hai cch cung cp cc action theo ng cnh:

Trong mt menu ng cnh ng (floating context menu). Mt menu xut hin di


dng danh sch ng bao gm cc mc menu (tng t nh hp thoi) khi ngi
dung thc hin mt s kin long-click (nhn v gi) trn view khai bo h tr cho
menu ng cnh. Ngi dng c th thc hin mt action ng cnh trn mt mc
ti mt thi im.

Trong ch action ng cnh (contextual action mode). Ch ny l thc thi h


thng ca ActionMode hin th mt action bar ng cnh pha trn mn hnh vi
cc mc action nh hng ti nhng mc c chn. Khi ch ny hot ng,
ngi dung c th thc hin mt action trn nhiu mc cng lc (nu ng dng
ca bn cho php iu ny).

75

Lp trnh Android c bn
Ghi ch: Ch action ng cnh c trn Android 3.0 (API Cp 11) v cp cao hn.
K thut ny thng c dng hin th cc action ng cnh khi sn sng.
Nu ng dng ca bn h tr cc phin bn cp thp hn 3.0, bn nn quay li vi
menu ng cnh ng trn nhng thit b .

To menu ng cnh ng
to mt menu ng cnh ng:
1. ng k View vi i tng m menu ng cnh nn c lin kt bng cch gi
registerForContextMenu() v truyn View cho phng thc.

Nu activity ca bn s dng mt ListView hoc GridView v bn mun


mi mc cung cp menu ng cnh ging nhau, hy ng k tt c cc mc
cho mt menu ng cnh bng cch truyn ListView hoc GridView cho
registerForContextMenu().

2. Thc thi phng thc onCreateContextMenu() trong Activity hoc trong


Fragment.
Khi view m bn ng k nhn mt s kin long-click, h thng s gi phng thc
onCreateContextMenu(). y l ni bn nh ngha cc mc menu, thng
l bng cch s dng mt ti nguyn menu. V d:

@Override

public void onCreateContextMenu(ContextMenu menu, View v,

ContextMenuInfo menuInfo) {

super.onCreateContextMenu(menu, v, menuInfo);

inflater.inflate(R.menu.context_menu, menu);

MenuInflater inflater = getMenuInflater();

MenuInflater cho php bn to menu ng cnh t mt ti nguyn menu (menu

resource). Cc tham s ca phng thc callback cha View m ngi dung


chn v mt i tng ContextMenu.ContextMenuInfo cung cp thm
thng tin v mc c chn. Nu activity ca bn c vi view m mi view li
cung cp mt menu ng cnh khc nhau, bn c th s dng nhng tham s
quyt nh nn to menu ng cnh no t ti nguyn menu no.
3. Thc thi onContextItemSelected().
Khi ngi dung chn mt mc menu, h thng gi phng thc ny bn c th
thc hin action thch hp. V d:
@Override

public boolean onContextItemSelected(MenuItem item) {


AdapterContextMenuInfo info =

switch (item.getItemId()) {

(AdapterContextMenuInfo) item.getMenuInfo();
case R.id.edit:

76

Lp trnh Android c bn
editNote(info.id);
return true;

case R.id.delete:

deleteNote(info.id);
return true;
default:

return super.onContextItemSelected(item);
}
}

Phng thc getItemId() truy vn ID cho mc menu c chn, y l


th bn nn gn cho tng mc menu trong XML bng cch s dng thuc tnh
android:id, nh trnh by trong mc nh ngha mt menu trong XML
(Defining a Menu in XML).
Khi bn x l thnh cng mt mc menu, hy tr v true. Nu khng x l mc
menu, bn nn truyn mc menu cho phng thc x l ca lp cha. Nu activity
ca bn cha cc phn vng, activity s nhn callback ny trc tin. Bng cch
gi lp cha khi khng x l, h thng truyn s kin cho phng thc callback
tng ng trong tng phn vng, mi thi im mt s kin (theo th t m tng
phn vng c thm vo) cho ti khi tr v true hoc false. (Phng thc
mc nh ca Activity v android.app.Fragment tr v false, do vy li
khuyn l bn nn gi lp cha thng xuyn khi khng x l).

S dng ch action ng cnh


Ch action ng cnh l thc thi h thng ca ActionMode tp trung vo tng
tc ca ngi dng thc hin cc action ng cnh. Khi ngi dung bt ch ny
bng cch chn mt mc, mt action bar ng cnh xut hin phn trn ca mn hnh
hin th nhng action m ngi dng c th thc hin trn mc ang c chn.
Trong khi ch ny c bt, ngi dng c th chn nhiu mc (nu bn cho php),
b chn cc mc, ng thi tip tc iu hng trong phm vi activity (bn c th cho
php s lng mc ty ). Ch action b v hiu ha (disabled) v action bar ng
cnh bin mt khi ngi dung khng chn mt mc no, nhn button BACK, hoc chn
action Done bn tri action bar ng cnh.
Ghi ch: Action bar ng cnh khng nht thit phi lin kt vi action bar. Chng
hot ng c lp, bt k action bar ng cnh chim v tr hin th ca action bar.
Nu pht trin ng dng cho Android 3.0 (API Cp 11) hoc cp cao hn, bn nn
thng xuyn s dng ch action ng cnh biu din cc action theo ng cnh
thay v s dng menu ng cnh ng (floating context menu).
i vi cc view cung cp action ng cnh, bn nn thng xuyn kch hot ch
action ng cnh theo mt trong hai s kin (hoc c hai):

Ngi dng thc hin mt long-click trn view.

Ngi dng chn mt checkbox hoc thnh phn giao din tng t bn
trong view.

77

Lp trnh Android c bn
Cch ng dng kch hot ch action ng cnh v xc nh hnh vi cho mi action
ty thuc vo thit k ca bn. C hai thit k c bn:

Thit k cho nhng action theo ng cnh trong cc view c lp, ty .

Thit k cho tp cc action ng cnh trn nhng nhm mc ca mt ListView


hoc GridView (cho php ngi dung chn nhiu mc v thc hin mt action
trn tt c cc mc).

Cc mc ni dung tip theo s m t thit lp cn thit cho tng kch bn.

Bt ch action ng cnh cho tng view ring bit


Nu mun kch hot ch action ng cnh ch khi ngi dng chn cc view c th,
bn nn:
1. Thc thi giao din ActionMode.Callback. Trong cc phng thc callback,
bn c th xc nh action cho action bar ng cnh, phn hi s kin click trn
cc mc action, ng thi x l nhng s kin lin quan n vng i ca ch
action(Action Mode).
2. Gi startActionMode() nu bn mun hin th action bar (chng hn nh khi
ngi dung nhn lu vo view).
V d:
1. Thc thi giao din ActionMode.Callback:
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback()
{

// c gi khi to ch action; startActionMode() c gi

public boolean onCreateActionMode(ActionMode mode, Menu menu) {

@Override

// S dng ti nguyn menu to cc mc ca menu ng cnh

inflater.inflate(R.menu.context_menu, menu);

MenuInflater inflater = mode.getMenuInflater();

return true;
}


// c gi mi khi hin th ch action. Lun lun c gi


// sau onCreateActionMode nhng c th c gi nhiu ln nu
// ch khng cn hiu lc.

@Override

public boolean onPrepareActionMode(ActionMode mode, Menu menu) {

return false; // Tr v false nu khng lm g

// c gi khi ngi dung chn mt mc menu ng cnh

public boolean onActionItemClicked(ActionMode mode, MenuItem item)

@Override

78

Lp trnh Android c bn
{

switch (item.getItemId()) {

case R.id.menu_share:

shareCurrentItem();

mode.finish(); // Action c chn, sau ng CAB

return true;
default:

return false;
}
}

// c gi khi ngi dung thot khi ch action

public void onDestroyActionMode(ActionMode mode) {

@Override

mActionMode = null;

};

Lu , nhng callback ca s kin ny gn nh ging ht cc callback cho menu


ty chn (options menu), ngoi tr mi callback trong li truyn i tng
ActionMode lin kt vi s kin. Bn c th s dng cc API ActionMode to
nhiu thay i cho action bar ng cnh (CAB), chng hn nh xem li tiu (title)
v ph (subtitle) vi setTitle() v setSubtitle() (rt hu ch trong vic
ch ra s lng mc c chn).
Cng cn lu rng v d trn t bin (variable) mActionMode l null khi ch
action b hy. bc tip theo, bn s thy vic bin ny c khi to v ang lu
bin thnh vin trong activity hoc phn vng em li li ch nh th no.
2. Gi startActionMode() bt ch action ng cnh lc thch hp, chng
hn nh phn hi mt long-click trn mt View:
someView.setOnLongClickListener(new View.OnLongClickListener() {

// c gi khi ngi dung nhn lu trn mt s View


public boolean onLongClick(View view) {

if (mActionMode != null) {

return false;
}

// Khi ng CAB bng cch s dng ActionMode. Callback c


// xc nh trn
mActionMode = getActivity().startActionMode(mActionModeCallback);

view.setSelected(true);
return true;
}
});

79

Lp trnh Android c bn
Khi bn gi phng thc startActionMode(), h thng tr v ActionMode
c to. Bng cch lu n trong mt bin thnh vin (member variable), bn c th
thay i action bar ng cnh phn hi li nhng s kin khc. Trong v d trn,
ActionMode c s dng m bo rng th hin ActionMode khng c ti
to nu n hot ng bng cch kim tra xem bin thnh vin c null khng trc
khi bt u ch action .

Bt mt tp action ng cnh trong mt ListView hoc


GridView
Nu c mt tp cc mc trong ListView hay GridView (hoc m rng khc ca
AbsListView) v mun cho php ngi dung thc hin tp action, bn nn:

Thc thi giao din AbsListView.MultiChoiceModeListener v thit lp


n cho nhm view vi setMultiChoiceModeListener(). Trong cc phng
thc callback ca trnh lng nghe, bn c th xc nh cc action cho action bar
ng cnh, phn hi nhng s kin click trn cc mc action, ng thi x l cc
callback khc tha k t giao din ActionMode.Callback.

Gi setChoiceMode() vi i s (argument) CHOICE_MODE_MULTIPLE_MODAL.

V d:
ListView listView = getListView();

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);

listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
@Override

public void onItemCheckedStateChanged(ActionMode mode, int position,

long id, boolean checked) {

// Ti y, bn c th lm g khi cc mc c chn/b chn,


// chng hn nh cp nht tiu trong CAB (Action bar ng cnh)

@Override

{

public boolean onActionItemClicked(ActionMode mode, MenuItem item)

// Phn hi s kin click trn cc action trong CAB


switch (item.getItemId()) {

case R.id.menu_delete:

deleteSelectedItems();

mode.finish(); // Action c chn, sau ng CAB

return true;
default:

return false;
}
}

@Override

80

Lp trnh Android c bn

public boolean onCreateActionMode(ActionMode mode, Menu menu) {

// To menu cho CAB

inflater.inflate(R.menu.context, menu);

MenuInflater inflater = mode.getMenuInflater();

return true;
}

@Override

public void onDestroyActionMode(ActionMode mode) {

// Ti y, bn c th thc hin cc cp nht cn thit cho


// activity khi CAB b loi b. Theo mc nh, cc mc c
// chn u b b chn cha c chn (unchecked).

@Override

public boolean onPrepareActionMode(ActionMode mode, Menu menu) {

// Ti y, bn c th thc hin cp nht cho CAB nh mt yu


// cu (request) invalidate()

return false;
}
});

Nh vy y! Lc ny, khi ngi dung nhn lu trn mt mc, h thng s gi phng


thc onCreateActionMode() v hin th action bar ng cnh vi nhng action
c th. Trong lc action bar ng cnh cn hin th, ngi dung c th chn thm cc
mc khc.
Trong mt s trng hp m ti , cc action ng cnh cung cp nhng mc action
thng dng, c th bn s mun thm mt checkbox hoc mt phn t giao din tng
t cho php ngi dung la chn cc mc, bi v c th h khng bit n vic s
dng thao tc nhn lu. Khi ngi dung chn checkbox, bn c th kch hot ch
action ng cnh bng cch thit lp mc danh sch tng ng vi trng thi chn
(checked) bng setItemChecked().

To menu popup

Hnh 4. Mt menu popup trong ng dng Gmail, c gn vo mt biu tng pha


bn phi mn hnh (nhn vo hin th cc action n).

81

Lp trnh Android c bn
PopupMenu l menu c neo vo mt View. Loi menu ny xut hin bn di
view neo nu cn ch, hoc bn trn view nu ngc li. PopupMenu rt hu ch
trong vic:

Cung cp mt menu c mc menu n cho cc action lin quan ti ni dung c th


(chng hn nh cc header e-mail ca Gmail, nh minh ha Hnh 4).
Ghi ch: Popup menu khng ging nh mt menu ng cnh thng dng cho cc
action nh hng ti ni dung c chn. i vi nhng action nh hng ti ni dung
c chn, s dng ch action ng cnh hoc menu ng cnh ng.

Cung cp phn th hai ca cu lnh (chng hn nh mt button nh du Add


s to mt menu popup vi cc ty chn Add khc nhau).

Cung cp mt danh sch x xung (drop-down list) tng t vi Spinner khng


lu gi lu la chn ca n.
Ghi ch: PopupMenu lun sn sng i vi API Cp 11 v cp cao hn.

Nu bn nh ngha menu trong file XML, y l cch bn c th hin th menu popup:


1. To mt th hin ca PopupMenu phng thc khi to ca n, phng thc ny
s ly Context (ng cnh) ca ng dng hin ti v View m menu nn neo vo.
2. S dng MenuInflater in ti nguyn menu cho i tng Menu (i tng
ny c tr v bi phng thc PopupMenu.getMenu(). Trn API Cp 14 v
cp cao hn, bn c th dng PopupMenu.inflate() thay th.
3. Gi phng thc PopupMenu.show().
V d, y l mt button vi thuc tnh android:onClick m s hin th mt
menu popup:
<ImageButton

android:layout_width=wrap_content

android:layout_height=wrap_content

android:src=@drawable/ic_overflow_holo_dark

android:onClick=showPopup />

android:contentDescription=@string/descr_overflow_button

Sau , activity c th hin th menu popup nh sau:


public void showPopup(View v) {

PopupMenu popup = new PopupMenu(this, v);

inflater.inflate(R.menu.actions, popup.getMenu());

MenuInflater inflater = popup.getMenuInflater();

popup.show();
}

Trong API Cp 14 v cp cao hn, bn c th kt hp hai dng in menu vi


PopupMenu.inflate().

82

Lp trnh Android c bn
Menu b hy (dismiss) khi ngi dung chn mt mc hoc chm vo bn ngoi khu
vc menu. Bn c th lng nghe s kin hy menu bng cch s dng PopupMenu.
OnDismissListener.

X l cc s kin click
thc hin mt action khi ngi dung chn mt mc menu, bn phi thc thi giao
din PopupMenu.OnMenuItemClickListener v ng k n vi PopupMenu
bng cch gi setOnMenuItemclickListener(). Khi ngi dng chn mt
mc, h thng gi phng thc callback onMenuItemClick() trong giao din
ca bn.
V d:
public void showMenu(View v) {

PopupMenu popup = new PopupMenu(this, v);

// Activity ny thc thi OnMenuItemClickListener

popup.inflate(R.menu.actions);

popup.setOnMenuItemClickListener(this);
popup.show();
}

@Override

public boolean onMenuItemClick(MenuItem item) {


switch (item.getItemId()) {

case R.id.archive:
archive(item);
return true;

case R.id.delete:
delete(item);
return true;
default:

return false;
}
}

To nhm menu
Nhm menu l tp cc mc menu c chung mt s c im nht nh. Vi mt nhm
menu, bn c th:

Hin th hoc n tt c cc mc vi setGroupVisible().

Bt hoc v hiu ha tt c cc mc vi setGroupEnabled().

Cho php/khng cho php ngi dng chn cc mc vi setGroupCheckable().

83

Lp trnh Android c bn
Bn c th to mt nhm bng cch lng cc phn t <item> bn trong mt phn t
<group> trong ti nguyn menu, hoc bng cch n nh mt ID nhm vi phng
thc add().
Di y l v d v ti nguyn menu c cha mt nhm:
<?xml version=1.0 encoding=utf-8?>

<menu xmlns:android=http://schemas.android.com/apk/res/android>
<item android:id=@+id/menu_save

android:icon=@drawable/menu_save

android:title=@string/menu_save />

<!-- nhm menu -->

<group android:id=@+id/group_delete>

<item android:id=@+id/menu_archive
android:title=@string/menu_archive />
<item android:id=@+id/menu_delete

</group>

android:title=@string/menu_delete />

</menu>

Cc mc trong nhm xut hin cng cp vi mc u tin - c ba mc trong menu


u l anh em (sibling) ca nhau. Tuy nhin, bn c th chnh sa cc c trng ca
hai mc trong nhm bng cch tham chiu ID nhm v s dng nhng phng thc
lit k trn. H thng cng khng bao gi chia tch cc mc c nhm. V d,
nu bn khai bo android:showAsAction=ifRoom cho mi mc, chng s xut
hin trong action bar hoc trong biu tng cha cc action n.

S dng cc mc menu c th nh du

Hnh 5. nh chp mn hnh ca mt menu con vi cc mc c th nh du.

84

Lp trnh Android c bn
i khi, vic mt menu c giao din h tr kh nng la chn mc menu bng cch bt
hoc tt s rt hu ch, bn hy s dng checkbox khi mi mc c la chn c lp
vi nhau hoc dng cc radio button khi cc mc thuc mt nhm v ch cho php la
chn mt mc. Hnh 5 minh ha mt menu con vi nhng mc c th nh du c
vi cc radio button.
Ghi ch: Cc mc menu trong Icon Menu (t menu ty chn) khng th hin th mt
checkbox hoc radio button. Nu chn cch to cc mc trong Icon Menu l c th nh
du, bn phi t biu th trng thi chn bng cch hon i biu tng v/hoc vn
bn mi ln trng thi thay i.
Bn c th nh ngha kh nng c th nh du cho tng mc menu ring bng cch
s dng thuc tnh android:checkable trong phn t <item>, hoc cho c nhm
vi thuc tnh android:checkableBehavior trong phn t <group>. V d, tt
c cc mc trong nhm menu ca on m di y u c th nh du c vi
mt radio button:
<?xml version=1.0 encoding=utf-8?>

<menu xmlns:android=http://schemas.android.com/apk/res/android>

<group android:checkableBehavior=single>

<item android:id=@+id/red

android:title=@string/red />

<item android:id=@+id/blue

</group>

android:title=@string/blue />

</menu>

Thuc tnh android:checkableBehavior chp nhn c hai gi tr:

single
Ch mt mc ca nhm c th c chn (button radio).

all
Tt c cc mc c th c chn (checkbox).

none
Khng th chn bt c mc no.
Bn c th p dng trng thi chn mc nh cho mt mc bng cch s dng thuc
tnh android:checked trong phn t <item>, ng thi thay i trng thi ny
trong m ngun vi phng thc setChecked().
Khi mt mc c th nh du c chn, h thng s gi phng thc callback tng
ng vi mc (chng hn nh onOptionsItemSelected()). Phng thc ny
l ni bn phi thit lp trng thi ca checkbox, do checkbox hoc radio button khng
t ng thay i trng thi ca n c. Bn c th truy vn trng thi hin ti ca mc
(nh trc khi ngi dng chn n) vi isChecked() v thit lp trng thi chn
vi setChecked(). V d:

85

Lp trnh Android c bn
@Override

public boolean onOptionsItemSelected(MenuItem item) {


switch (item.getItemId()) {

case R.id.vibrate:

case R.id.dont_vibrate:

if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
return true;
default:

return super.onOptionsItemSelected(item);
}
}

Nu bn khng thit lp trng thi chn bng cch ny th, trng thi hin th ca
mc (checkbox hoc button radio) s khng i khi ngi dung chn n. Khi bn thit
lp trng thi, activity s bo ton trng thi chn ca mc; do , khi ngi dung
m menu ln sau, trng thi chn m bn thit lp s hin th.
Ghi ch: Cc mc menu c th nh du thng c s dng ch da trn c s theo
phin (session) v khng c lu sau khi tt ng dng. Nu c cc thit lp ng dng
mun lu cho ngi dng, bn nn lu tr d liu bng cch dng Cc thit lp chia s
(Shared Preferences).

Thm mc menu da trn mt Intent


i khi, bn mun c mt mc menu khi ng mt activity dng Intent (bt
k l mt activity trong ng dng ca bn hay ng dng khc). Khi bn bit intent
mun dng v mc menu c th s kch hot intenet , bn c th khi ng intent
vi startActivity() trong phng thc callback trn mc c chn thch hp
(chng hn nh callback onOptionsItemSelected()).
Tuy nhin, nu bn khng chc chn rng thit b ca ngi dung cha mt ng dng
c th x l intent, hy thm mt mc menu kch hot n. iu ny s dn ti mt
mc menu khng hot ng, bi intent c th khng x l activity . gii quyt vn
ny, Android cho php bn thm ng cc mc menu khi Android tm kim nhng
activity x l intent trn thit b.
thm cc mc menu da trn nhng activity ang sn sng chp nhn mt intent:
1. nh ngha mt intent vi hng mc CATEGORY_ALTERNATIVE v/hoc
CATEGORY_SELECTED_ALTERNATIVE, cng vi bt c yu cu no khc.
2. Gi Menu.addIntentOptions(). Sau , Android s tm kim bt k ng
dng no c th thc thi intent v thm chng vo menu.
Nu khng ng dng ci t no p ng intent th khng c mc menu no c
thm vo.

86

Lp trnh Android c bn
Ghi ch: CATEGORY_SELECTED_ALTERNATIVE c dng x l phn t ang
c chn trn mn hnh. V vy, ch nn s dng hng mc ny khi to mt Menu trong
onCreateContextMenu().
V d:
@Override

public boolean onCreateOptionsMenu(Menu menu){


super.onCreateOptionsMenu(menu);

// To mt Intent m t nhng yu cu cn thc hin c xut


// hin trong menu ca chng ta. ng dng cung cp phi bao gm

// mt gi tr hng mc ca Intent.CATEGORY_ALTERNATIVE.
Intent intent = new Intent(null, dataUri);

intent.addCategory(Intent.CATEGORY_ALTERNATIVE);

// Tm kim v to menu vi cc ng dng cung cp c chp nhn.

menu.addIntentOptions(

R.id.intent_group, // Nhm menu m cc mc mi s c thm vo

0,

0,

// ID mc menu duy nht (none)


// Sp xp cc mc (none)

this.getComponentName(),

// Tn activity hin ti null,

// Cc mc c th a vo trc (none) intent,

// Intent c to trn, m t cc yu cu ca chng ta 0,


// Thm c (flag) cho cc mc iu khin (none) null);

// Mng cc MenuItem lin quan ti nhng mc c th (none)

return true;

i vi mi activity c tm thy cung cp mt b lc intent khp vi intent nh


ngha, mt mc menu s c thm vo, s dng gi tr trong android:label ca
b lc intent lm tiu cho mc menu, ng thi dng biu tng ca ng dng lm
biu tng cho mc menu. Phng thc addIntentOptions() tr v s lng
mc menu thm vo.
Ghi ch: Khi bn gi addIntentOptions(), phng thc ny ghi ln bt k v tt
c cc mc menu thuc nhm menu c ch nh trong i s th nht.

Cho php activity ca bn c thm vo cc menu khc


Bn cng c th cung cp cc service ca activity cho nhng ng dng khc, vy nn
ng dng ca bn c th c bao gm trong cc menu khc (o ngc vai tr
m t trn).
c bao gm trong cc menu ca ng dng khc, bn cn nh ngha mt b lc
intent nh thng l, nhng lu phi bao gm CATEGORY_ALTERNATIVE v/hoc
cc gi tr CATEGORY_SELECTED_ALTERNATIVE cho hng mc b lc intent. V d:

87

Lp trnh Android c bn
<intent-filter label=@string/resize_image>
...

<category android:name=android.intent.category.ALTERNATIVE />

<category android:name=android.intent.category.SELECTED_ALTERNATIVE />

...

</intent-filter>

tham kho thng tin v cch to cc b lc intent, xem mc Intents and Intent Filters (Intent v b lc intent).
xem mt ng dng mu s dng k thut ny, hy tm trong v d mu Note Pad.

5.5 Thng bo
Thng bo (notification) l mt thng ip m bn c th hin th cho ngi dng
ngoi giao din ngi dung thng thng ca ng dng. Khi bn ra lnh cho h thng
a ra mt thng bo, trc ht thng bo s xut hin di dng mt biu tng trong
vng thng bo (notification area). xem chi tit v thng bo, ngi dung cn m
ngn thng bo (notification drawer). C vng thng bo ln ngn thng bo u l
cc khu vc c h thng kim sot m ngi dung c th xem vo mi thi im.

Hnh 1. Cc thng bo trong vng thng bo.

Hnh 2. Cc thng bo trong ngn thng bo.

88

Lp trnh Android c bn
Thit k ca thng bo
L mt b phn quan trng ca giao din ngi dng Android, thng bo c nhng quy
tc thit k ring ca chng. bit cch thit k thng bo v tng tc vi chng,
hy c ch Hng dn Thit k Notifications ca Android.
Ghi ch: Ngoi tr ni c ghi ch, hng dn ny cp ti lp
NotificationCompat.Builder trong Support Library (th vin h tr) phin bn
4. Lp Notification.Builder c thm vo trong Android 3.0.

Cc phn t hin th thng bo


Thng bo trong ngn thng bo c th xut hin mt trong hai kiu trc quan, ph
thuc vo phin bn v trng thi ca ngn thng bo:
View thng thng
View chun ca thng bo trong ngn thng bo.
View ln (big view)
View hin th khi thng bo c m rng. View ln l mt phn ca tnh nng
thng bo m rng c sn trong Android 4.1.
Cc kiu ny c m t nhng mc sau.

View thng thng


Mt thng bo trong view thng thng s xut hin trong vng thng bo vi chiu
cao ln ti 64 dp. Ngay c khi bn to mt thng bo vi kiu view ln, thng bo vn
s xut hin trong view thng thng cho ti khi c m rng. y l mt v d v
view thng thng:

Hnh 3. Thng bo trong view thng thng.


Cc ch thch trong hnh minh ha trn cp nhng ni dung sau:
1. Tiu ni dung (content title).
2. Biu tng ln (large icon).
3. Vn bn ni dung (content text).
4. Thng tin ni dung (content info).

89

Lp trnh Android c bn
5. Biu tng nh (small icon).
6. Thi gian thng bo xut hin. Bn c th thit lp mt gi tr c th vi setWhen();
nu bn khng lm nh vy th gi tr mc nh s l thi gian h thng nhn c
thng bo.

View ln
Mt thng bo ca view ln ch xut hin khi thng bo c m rng, iu ny xy ra
khi thng bo nm u ngn thng bo, hoc khi ngi dung thao tc m rng ngn
thng bo. Cc thng bo m rng l tnh nng sn c vi Android 4.1.
nh chp mn hnh di y hin th mt thng bo dng hp th n (inbox):

Hnh 4. Thng bo view ln.


Lu , view ln c hu ht cc phn t nh view thng thng. im khc bit duy
nht l ch thch s 7, vng chi tit. Mi kiu view ln u thit lp vng ny theo mt
cch khc nhau. Cc kiu hin c l:
Kiu bc tranh ln (big picture)
Vng chi tit cha mt nh bitmap cao ti 256 dp trong phn chi tit ca n.
Kiu vn bn ln (big text)
Hin th mt khi vn bn ln trong phn chi tit.
Kiu hp th n
Hin th cc dng vn bn trong phn chi tit.
Mi kiu view ln u c cc ty chn ni dung m view thng thng khng c,
bao gm:
Tiu ni dung ln
Cho php bn ghi tiu ni dung ca view thng thng vi mt tiu ch
xut hin trong view m rng.
Vn bn tm lc (summary text)

90

Lp trnh Android c bn
Cho php bn thm mt dng vn bn di vng chi tit.
Vic p dng mt kiu view ln cho mt thng bo c m t trong mc p dng kiu
view ln cho mt thng bo.

5.5.1 To thng bo
Bn c th xc nh thng tin giao din ngi dng v cc action cho mt thng bo
trong mt i tng NotificationCompat.Builder. t to mt thng bo,
bn gi NotificationCompat.Builder.build(), n tr v mt i tng
Notification cha cc thng s k thut cho bn. a ra thng bo, bn truyn
i tng Notification cho h thng bng cch gi NotificationManager.
notify().

Nhng ni dung bt buc ca mt thng bo


Mt i tng Notification phi cha nhng ni dung sau:

Mt biu tng nh, thit lp bi setSmallIcon().

Mt tiu , thit lp bi setContentTitle().

Vn bn chi tit, thit lp bi setContentText().

Cc thit lp v ni dung ty chn ca mt thng bo


Tt c cc thit lp thng bo v ni dung khc u khng bt buc. tm hiu thm
v chng, xem ti liu tham kho v NotificationCompact.Builder.

Cc action ca thng bo
Mc d chng l ty chn, song bn vn nn thm t nht mt action cho thng bo
ca mnh. Mt action cho php ngi dung i trc tip t thng bo ti mt Activity
trong ng dng, y cng l ni h c th nhn vo mt hay nhiu s kin hoc lm
nhng vic khc.
Mt thng bo c th cung cp nhiu action. iu bn nn lm l lun nh ngha
action kch hot khi ngi dung nhn vo thng bo; thng th action ny m mt
Activity trong ng dng ca bn. Bn cng c th thm cc button vo thng bo
thc hin cc action b sung nh tng thi gian cho mt bo thc (alarm) hoc phn
hi lp tc mt tin nhn vn bn (text message); tnh nng ny c sn phin bn
Android 4.1. Nu s dng thm cc button action, bn phi lm cho chc nng ca
chng sn sng trong mt Activity ca ng dng; xem mc Handling compatibility
(X l vn tng thch) bit thm thng tin chi tit.
Trong mt Notification, bn thn action do mt PendingIntent nh ngha cha
mt Intent khi ng Activity ca ng dng. lin kt PendingIntent vi
mt thao tc ca ngi dng, gi phng thc thch hp ca NotificationCompat.
Builder. V d, nu bn mun khi ng Activity khi ngi dung nhn vo
dng thng bo trong ngn thng bo, hy thm PendingIntent bng cch gi
setContentIntent().

91

Lp trnh Android c bn
Khi ng mt Activity khi ngi dung nhn vo thng bo l kch bn action
ph bin nht. Bn cng c th khi ng mt Activity khi ngi dng tt mt
thng bo. Trong Android 4.1 v cc phin bn mi hn, bn c th khi ng mt
Activity t mt button action. tm hiu su hn, hy c hng dn tham kho
cho NotificationCompat.Builder.

To mt thng bo n gin
on m nh di y minh ha mt thng bo n gin, xc nh mt activity s
m khi ngi dng nhn vo thng bo. Ch rng, on m to mt i tng
TaskStackBuilder v dng n to PendingIntent cho action. M hnh ny
c gii thch chi tit hn mc Preserving Navigation when Starting an Activity
(Bo ton iu hng khi khi ng mt Activity):
NotificationCompat.Builder mBuilder =

new NotificationCompat.Builder(this)

.setContentTitle(My notification)

.setSmallIcon(R.drawable.notification_icon)

.setContentText(Hello World!);

// To mt intent tng minh cho Activity trong ng dng

Intent resultIntent = new Intent(this, ResultActivity.class);


// i tng stack builder s cha mt ngn xp li (back stack) cho
// Activity khi ng.

// iu ny m bo rng vic duyt quay tr li (backward) t Activity


// s thot ra khi ng dng v n mn hnh Home.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

// Thm ngn xp li cho Intent (nhng khng phi bn thn Intent)


stackBuilder.addParentStack(ResultActivity.class);

// Thm Intent khi ng Activity vo nh ca ngn xp


stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =

stackBuilder.getPendingIntent(

0,

PendingIntent.FLAG_UPDATE_CURRENT
);

mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// mId cho php bn cp nht thng bo v sau.

mNotificationManager.notify(mId, mBuilder.build());

Mi vic hon tt! Hin ngi dng c thng bo.

92

Lp trnh Android c bn

p dng mt kiu view ln cho thng bo


mt thng bo xut hin trong view ln khi n c m rng, trc ht, hy to mt
i tng NotificationCompat.Builder vi cc ty chn view thng thng m
bn mun. Tip theo, gi Builder.setStyle() bng mt i tng kiu view ln
vi vai tr l i s ca n.
Nh rng, kiu thng bo m rng khng c sn trong cc nn tng trc Android 4.1.
bit cch x l cc thng bo cho Android 4.1 v nhng nn tng trc n, tham
kho mc X l vn tng thch.
V d, on m nh di y cho thy cch thay i thng bo c to trong on m
trc s dng kiu view ln dng hp th n:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)

.setSmallIcon(R.drawable.notification_icon)

.setContentText(Events received)

.setContentTitle(Event tracker)

NotificationCompat.InboxStyle inboxStyle =

new NotificationCompat.InboxStyle();

String[] events = new String[6];

// Thit lp mt tiu cho view ln c kiu hp th n


inboxStyle.setBigContentTitle(Event tracker details:);
...

// Chuyn cc s kin vo view ln

for (int i=0; i < events.length; i++) {


inboxStyle.addLine(events[i]);
}

// Chuyn i tng kiu view ln vo i tng thng bo.


mBuilder.setStyle(inBoxStyle);
...

// a ra thng bo y.

X l vn tng thch
Khng phi mi tnh nng thng bo u sn sng cho phin bn c th trc ,
bt k cc phng thc dng thit lp chng u nm trong lp th vin h tr
NotificationCompat.Builder. V d, button action ph thuc vo thng bo m
rng ch xut hin trn Android 4.1 v cp cao hn, bi bn thn nhng thng bo m
rng u ch sn sng trn Android 4.1 v cp cao hn.
m bo tng thch tt nht, hy to thng bo vi NotificationCompat v cc
lp con ca n, c bit l NotificationCompat.Builder. Ngoi ra, bn hy tun
theo quy trnh sau khi thc thi mt thng bo:
1. Cung cp tt c cc chc nng ca thng bo cho mi ngi dng, bt k h ang
dng phin bn no. lm iu ny, hy m bo rng tt c cc chc nng u

93

Lp trnh Android c bn
c sn t mt Activity trong ng dng ca bn. C th bn s mun thm mt
Activity mi lm vic ny.
V d, nu mun s dng addAction() nhm cung cp mt iu khin dng
v bt u pht a phng tin (media playback), trc ht, hy thc thi iu
khin ny trong mt Activity thuc ng dng ca bn.
2. m bo mi ngi dng u c th s dng tnh nng trong Activity, bng
cch khi ng n khi ngi dung nhn vo thng bo. lm iu ny, hy to
mt PendingIntent cho Activity. Gi setContentIntent() thm
PendingIntent vo thng bo.
3. Lc ny, hy thm cc tnh nng ca thng bo m rng bn mun dng vo
thng bo. Cn nh rng, bt c chc nng no bn thm cng sn sng trong
Activity khi ng khi ngi dung nhn vo thng bo.

5.5.2 Qun l thng bo


Khi cn a ra mt thng bo nhiu ln cho cng mt loi s kin, bn nn trnh vic
to mi hon ton thng bo. Thay v vy, bn cn xem xt vic cp nht thng bo
trc hay thay i mt s gi tr ca n, hoc thm vo gi tr mi, hay c hai cch
u c.
V d, Gmail thng bo cho ngi dung rng cc e-mail mi n ni bng cch
tng s ln m nhng tin nhn cha c v bng cch thm mt on tm lc v
tng e-mail cho thng bo. c gi l k thut thng bo stacking (dng ngn
xp); k thut ny s c m t chi tit hn trong hng dn Notifications
(Cc thng bo).
Ghi ch: Tnh nng ny ca Gmail i hi kiu view ln dng hp th n, l mt
phn trong tnh nng thng bo m rng c sn t phin bn Anroid 4.1.
Mc di y m t cch cp nht v g b thng bo.

Cp nht thng bo
thit lp mt thng bo c kh nng cp nht, hy cp cho n mt ID thng
bo bng cch gi NotificationManager.notify(ID,
notification).
cp nht thng bo khi bn hin th n, hy cp nht hoc to mt i tng
NotificationCompat.Builder, xy dng mt i tng Notification t i
tng v hin th Notification vi cng ID m bn s dng trc . Nu
thng bo trc vn hin hu, h thng s cp nht n t ni dung ca i tng
Notification. Nu thng bo trc b tt, mt thng bo mi s c to
thay th.
on m di y m t mt thng bo c cp nht phn nh s lng s kin
xy ra. N xp chng (stack) thng bo, a ra bn tm lc:

94

Lp trnh Android c bn
mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// Thit lp mt ID cho thng bo n c th cp nht c


int notifyID = 1;

mNotifyBuilder = new NotificationCompat.Builder(this)


.setContentTitle(New Message)

.setContentText(Youve received new messages.)

.setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;

// Khi ng mt vng lp x l d liu ri thng bo cho ngi dung


...

mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);

// Do ID khng i, thng bo ang tn ti s c cp nht.


mNotificationManager.notify(

notifyID,

mNotifyBuilder.build());

...

on m ny to ra mt thng bo trng nh sau:

Hnh 5. Thng bo c cp nht hin th trong ngn thng bo.

G b thng bo
Cc thng bo s cn hin hu cho n khi mt trong nhng iu di y xy ra:

Ngi dng tt tng thng bo hoc s dng Clear All (nu thng bo c th b
xa b).

Ngi dng nhn vo thng bo v bn gi setAutoCancel() khi to thng bo.

Bn gi phng thc cancel() vi mt ID thng bo c th. Phng thc ny


cng xa nhng thng bo ang din ra.

Bn gi cancelAll() xa tt c cc thng bo bn hin th trc .

95

Lp trnh Android c bn

5.5.3 Bo ton tri nghim iu hng khi khi ng Activity


Khi khi ng Activity t thng bo, bn phi bo ton tri nghim iu hng
(navigation experience) ca ngi dng. Nhn button Back a ngi dng tr li qua
lung cng vic (work flow) thng thng ca ng dng ti mn hnh Home, ng thi
nhn Recents hin th Activity di dng mt tc v c lp. bo ton tri
nghim iu hng, bn nn khi ng Activity trong mt tc v mi. Cch bn
thit lp PendingIntent cp cho bn mt tc v mi ph thuc vo bn cht ca
Activity bn ang khi ng. C hai tnh hung chnh:
Activity thng thng
Bn ang khi ng mt Activity vn l mt phn trong lung cng vic thng
thng ca ng dng. tnh hung ny, hy thit lp PendingIntent khi
ng mt tc v mi, ng thi cung cp mt ngn xp li cho PendingIntent.
Ngn xp li ny s ti to hnh vi Back thng thng ca ng dng.
Cc thng bo t ng dng Gmail minh ha iu ny. Khi nhn vo mt thng bo
ca mt tin nhn email, bn s thy c chnh thng ip . Chm vo button
Back s a bn quay li mn hnh Home thng qua Gmail, nhng iu ny ch
xy ra ch khi bn truy cp vo Gmail t mn hnh Home thay v t mt thng bo.
iu ny vn xy ra bt k bn ang trong ng dng no khi ang chm vo
thng bo. V d, nu bn ang trong Gmail v son tho mt e-mail, ng thi
nhn vo mt thng bo ca mt e-mail, lp tc bn s ti e-mail . Chm vo
button Back s a bn v hp th n v k l mn hnh Home, thay v ti
e-mail m bn ang son.
Activity c bit
Ngi dng ch thy Activity ny nu n c khi ng t mt thng bo.
Theo mt ngha no , Activity m rng thng bo bng cch cung cp
thng tin kh c th hin th trong bn thn thng bo. i vi tnh hung ny,
hy thit lp PendingIntent khi ng trong mt tc v mi. D vy, bn
khng cn to mt ngn xp li, bi Activity khi ng khng phi l mt
phn trong lung activity ca ng dng. Nhn button Back s a ngi dung ti
mn hnh Home.

Thit lp mt activity PendingIntent thng thng


thit lp mt PendingIntent khi ng trc tip mc Activity, hy lm theo
cc bc sau:
1. nh ngha cy phn cp Activity ca ng dng trong file k khai (manifest).
a. Thm h tr cho Android 4.0.3 v cc phin bn trc . lm vic ny,
hy xc nh cha ca Activity m bn ang khi ng bng cch thm mt
phn t <meta-data> di dng con ca <activity>.
Vi

phn

ny,

PARENT_ACTIVITY .

96

t android:name=android.support.
Thit lp android:value=<parent_

Lp trnh Android c bn
activity_name>, trong <parent_activity_name> l gi
tr ca android:name i vi phn t <activity> cha. Xem mt v
d file XML sau.

b. ng thi, bn thm h tr cho Android 4.1 v cc phin bn mi hn. thc


hin iu ny, hy thm thuc tnh android:parentActivityName vo
phn t <activity> ca Activity bn ang khi ng.
Ni dung XML cui cng trng s nh sau:
<activity

android:name=.MainActivity

android:label=@string/app_name >
<intent-filter>

<action android:name=android.intent.action.MAIN />

<category android:name=android.intent.category.LAUNCHER />

</intent-filter>

</activity>
<activity

android:name=.ResultActivity

android:parentActivityName=.MainActivity>

<meta-data

android:name=android.support.PARENT_ACTIVITY

android:value=.MainActivity/>

</activity>

2. To mt ngn xp li da trn Intent khi ng Activity:


a. To Intent khi ng Activity.
b. To mt stack builder bng cch gi TaskStackBuilder.create().
c. Thm ngn xp li vo stack builder bng cch gi addParentStack().
i vi tng Activity trong cy phn cp bn xc nh trong file k khai,
ngn xp li cha mt i tng Intent khi ng Activity. Phng
thc ny cng s thm cc c khi ng ngn xp trong mt tc v mi.
Ghi ch: Mc d tham s cho addParentStack() l mt tham chiu n Activity
khi ng, song li gi phng thc ny li khng thm Intent khi ng
Activity. Thay vo , n c lu bc tip theo.
d. Thm Intent khi ng Activity t thng bo bng cch gi
addNextIntent() . Truyn Intent bn to bc u tin di
dng tham s cho addNextIntent() .
e. Nu cn, bn thm tham s cho cc i tng Intent trong ngn xp bng
cch gi TaskStackBuilder.editIntentAt(). i khi, vic ny rt cn
thit m bo i tng Activity hin th d liu c ngha khi ngi
dung duyt ti n bng cch s dng Back.

97

Lp trnh Android c bn
f.

Ly mt PendingIntent cho ngn xp li ny bng cch gi


getPendingIntent(). Sau , bn c th s dng PendingIntent ny
di dng tham s cho setContentIntent().

on m sau minh ha qu trnh ny:


...

Intent resultIntent = new Intent(this, ResultActivity.class);

TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);


// Thm ngn xp li

stackBuilder.addParentStack(ResultActivity.class);
// Thm Intent vo nh ca ngn xp

stackBuilder.addNextIntent(resultIntent);

// Ly mt PendingIntent cha ton b ngn xp li


PendingIntent resultPendingIntent =

...

stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);


builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

mNotificationManager.notify(id, builder.build());

Thit lp mt activity PendingIntent c bit


Phn tip theo m t cch thit lp mt activity PendingIntent c bit.

Activity c bit khng cn ngn xp li, nn bn khng cn xc nh cy phn cp


Activity ca n trong file k khai, bn cng khng phi gi addParentStack()

xy dng mt ngn xp li. Thay vo , hy s dng file k khai thit lp cc ty


chn tc v Activity v to PendingIntent bng cch gi getActivity():
1. Trong file k khai, thm cc thuc tnh sau vo phn t <activity> cho Activity:

android:name=activityclass

Tn lp y ca activity.

android:taskAffinity=

Kt hp vi c FLAG_ACTIVITY_NEW_TASK bn thit lp trong m ngun, iu ny


m bo Activity ny khng i ti tc v mc nh ca ng dng. Bt c tc v
ang tn ti no c mi lin h mc nh vi ng dng u khng b nh hng.

android:excludeFromRecents=true

Loi tr tc v mi ra khi Recents, nn ngi dung khng th v tnh duyt quay li


n c.

98

Lp trnh Android c bn
on m nh di y hin th phn t:
<activity

android:name=.ResultActivity
...

android:launchMode=singleTask

android:taskAffinity=

android:excludeFromRecents=true>

</activity>
...

2. Xy dng v a ra thng bo:


a. To mt Intent khi ng Activity.
b. Thit lp Activity khi ng trong mt tc v mi, trng bng
cch gi setFlags() vi cc c FLAG_ACTIVITY_NEW_TASK v
FLAG_ACTIVITY_CLEAR_TASK .
c. Thit lp bt c ty chn no khc bn cn cho Intent.
d. To mt PendingIntent t Intent bng cch gi getActivity().
Sau , bn c th dng PendingIntent ny lm tham s cho
setContentIntent().
on m sau minh ha qu trnh ny:
// Khi to i tng Builder.

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);


// To mt Intent cho Activity
Intent notifyIntent =

new Intent(new ComponentName(this, ResultActivity.class));

// Thit lp Activity khi ng trong mt tc v mi, trng

notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
// To PendingIntent

PendingIntent notifyIntent =

PendingIntent.getActivity(

this,
0,

notifyIntent

PendingIntent.FLAG_UPDATE_CURRENT
);

// t PendingIntent vo bn trong trnh xy dng thng bo


builder.setContentIntent(notifyIntent);

// Cc thng bo c a ra bng cch gi chng ti


// service NotificationManager ca h thng.

99

Lp trnh Android c bn
NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// Xy dng mt i tng Notification n danh t stack builder, v


// truyn n ti NotificationManager

mNotificationManager.notify(id, builder.build());

5.5.4 Hin th tin trnh trong thng bo


Cc thng bo c th cha mt thanh m t trng thi tin trnh ng (animated progress
indicator) cho ngi dung thy tnh trng ca mt hot ng ang chy. Nu bn c th
c lng hot ng din ra trong bao lu v lng cng vic m n hon thnh vo
bt c thi im no, hy s dng dng xc nh ca thanh m t trng thi (mt dng
xc nh). Nu bn khng th c lng hot ng din ra trong bao lu, hy s dng
dng khng xc nh ca thanh m t trng thi (mt thanh m t trng thi activity).
Cc thanh m t trng thi tin trnh c hin th s dng mt lp thc thi ca lp
ProgressBar.
s dng thanh m t trng thi tin trnh trn cc nn tng t Android 4.0, hy gi
setProgress(). i vi cc phin bn trc, bn phi t to layout thng bo ty
chnh ca mnh, trong cha mt view ProgressBar.
Cc mc di y m t cch hin th tin trnh trong mt thng bo bng cch s dng
setProgress().

Hin th mt thanh m t trng thi tin trnh trong thi gian


c nh
hin th mt progress bar xc nh, hy thm thanh vo thng bo ca bn bng
cch gi setProgress(max, progress, false), sau hin th thng bo. Khi
hot ng din ra, progress tng dn v cp nht thng bo. Vo thi im cui hot
ng, progress nn bng max. Cch thng thng gi setProgress() l t
max c gi tr 100, sau tng progress di dng gi tr phn trm hon thnh
(percent complete value) cho hot ng.
Bn c th ri khi progress bar khi hot ng hon thnh, hoc hy n. Trong c
hai trng hp, hy nh cp nht vn bn ca thng bo cho thy rng hot ng
hon thnh. hy progress bar, gi setProgress(0, 0, false). V d:

100

Lp trnh Android c bn
...

mNotifyManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

mBuilder = new NotificationCompat.Builder(this);


mBuilder.setContentTitle(Picture Download)

.setContentText(Download in progress)

.setSmallIcon(R.drawable.ic_notification);

// Khi ng mt hot ng di trong lung chy nn (background thread)


new Thread(

new Runnable() {

@Override

public void run() {

int incr;

// Chy hot ng di dng ny 20 ln


for (incr = 0; incr <= 100; incr+=5) {

// Thit lp thanh m t trng thi tin trnh ti gi tr cao

mBuilder.setProgress(100, incr, false);

// nht, s phn trm hon thnh hin ti v trng thi xc nh


// Hin th progress bar ln u tin.

mNotifyManager.notify(0, mBuilder.build());

// Cho lung ngh v thc y hot ng chim thi gian

try {

// Ngh trong 5 giy

Thread.sleep(5*1000);

} catch (InterruptedException e) {

Log.d(TAG, sleep failure);

// Khi vng lp c hon thnh, cp nht thng bo

// Hy progress bar

mNotifyManager.notify(ID, mBuilder.build());

mBuilder.setContentText(Download complete)

}

.setProgress(0,0,false);

// Khi ng lung bng cch gi phng thc run() trong Runnable ca n


).start ();

Cc thng bo kt qu c trnh by Hnh 6. Bn tri l nh chp nhanh ca thng


bo trong khi hot ng ang din ra; bn phi l nh chp nhanh ca thng bo sau
khi hot ng hon thnh.

101

Lp trnh Android c bn

Hnh 6. Progress bar trong v sau khi din ra hot ng.

Hin th mt thanh m t trng thi activity lin tc


hin th mt thanh m t trng thi activity khng xc nh, hy thm trnh ny vo
thng bo bng cch s dng setProgress(0, 0, true) (hai tham s u tin
b b qua), sau hin th thng bo. Kt qu nhn c s l mt thanh m t trng
thi cng kiu vi progress bar, ngoi tr hot cnh (animation) ca n ang din ra.
a ra thng bo vo lc bt u hot ng. Hot cnh s chy cho n khi bn
chnh sa thng bo ca mnh. Khi hot ng hon thnh, gi setProgress()
setProgress(0, 0, false), sau cp nht thng bo hy thanh m t
trng thi activity. Hy lun lm iu ny; bng khng, hot cnh s chy ngay c khi
hot ng hon thnh. ng thi, hy nh thay i vn bn ca thng bo ch
ra rng hot ng hon tt.
xem cch thc cc thanh m t trng thi activity hot ng, hy tham chiu n
on m nh trc . Tm n cc dng m sau:
// Thit lp cho thanh m t trng thi tin trnh gi tr cao nht,
// s phn trm hon thnh hin ti v trng thi xc nh
mBuilder.setProgress(100, incr, false);
// Hin th thng bo

mNotifyManager.notify(0, mBuilder.build());

Thay th nhng dng bn va tm thy bng cc dng sau:


// Thit lp mt thanh m t trng thi activity cho hot ng c
// di khng xc nh
mBuilder.setProgress(0, 0, true);
// a ra thng bo

mNotifyManager.notify(0, mBuilder.build());

Thanh m t trng thi kt qu c trnh by Hnh 7:

Hnh 7. Mt Thanh m t trng thi activity ang chy.

102

Lp trnh Android c bn

Cc layout thng bo ty chnh


Framework thng bo cho php bn nh ngha mt layout thng bo ty chnh (custom
notification layout), layout ny nh ngha hnh thc hin th ca thng bo trong mt i
tng RemoteViews. Thng bo c layout ty chnh tng t cc thng bo thng,
ngoi tr chng c da trn mt RemoteViews nh ngha trong file layout XML.
Chiu cao kh dng ca mt layout thng bo ty chnh ph thuc vo view thng
bo. Layout view thng thng b gii hn 64 dp, cn layout view m rng b gii
hn 256 dp.
nh ngha mt layout thng bo ty chnh, hy bt u bng cch khi to mt
i tng RemoteViews c th in (inflate) t file layout XML. Sau , thay v gi
cc phng thc nh setContentTitle(), hy gi setContent(). thit
lp ni dung chi tit trong thng bo ty chnh, hy s dng cc phng thc trong
RemoteViews thit lp gi tr cho con ca view:
1. To mt layout XML cho thng bo trong mt file ring bit. Bn c th s dng bt
c tn file no mnh mun, nhng phi s dng ui m rng .xml.
2. Trong ng dng ca mnh, bn hy s dng cc phng thc RemoteViews
xc nh biu tng v vn bn ca thng bo. t i tng RemoteViews
vo NotificationCompat.Builder ca bn bng cch gi setContent().
ng thit lp mt Drawable nn trn i tng RemoteViews ca bn, bi v
iu ny c th khin mu vn bn tr nn kh c.
Lp RemoteViews cng cha cc phng thc m bn c th d dng s dng
thm mt Chronometer hoc ProgressBar vo layout ca thng bo. bit
thm thng tin v cch to layout ty chnh cho thng bo, mi bn tham kho ti liu
RemoteViews.
Ch : Khi s dng layout thng bo ty chnh, bn phi thc s cn trng m bo
layout ty chnh ca mnh c th lm vic vi cc chiu xoay cng nh phn gii khc
nhau ca thit b. Li khuyn ny p dng cho mi layout View, n cng c bit quan
trng i vi cc thng bo, bi khng gian trong ngn thng bo rt hn ch. ng lm
cho layout ty chnh ca mnh phc tp qu mc, ng thi chc chn rng bn kim
th n vi nhiu cu hnh khc nhau.

S dng ti nguyn style cho vn bn thng bo ty chnh


Hy lun s dng ti nguyn style cho cc phn vn bn trong thng bo ty chnh.
Mu nn ca thng bo c th thay i qua nhng thit b v phin bn khc nhau,
song vic s dng ti nguyn style gip bn gii quyt bi ton ny. Bt u t Android
2.3, h thng xc nh mt style cho vn bn layout thng bo chun. Nu s dng
cng style trong cc ng dng cho Android 2.3 v cp cao hn, bn s m bo rng
vn bn ca mnh ni bt trn nn hin th.

103

Lp trnh Android c bn

5.6 Thnh phn ty chnh


Android a ra mt m hnh phc tp v cu trc mnh m cho vic xy dng giao din
ngi dng, da trn cc lp layout c bn lView vViewGroup. bt u, nn
tng bao gm mt lot View v lp con ViewGroup dng sn - c gi tng ng l
cc widget v layout - m bn c th s dng khi xy dng giao din ngi dng cho
mnh.
Mt phn danh sch widget c sn bao gm Button, TextView, EditText,
ListView, CheckBox, RadioButton, Gallery, Spinner, cng vi l
nhiu widget cho nhng mc ch c bit, gm AutoCompleteTextView,
ImageSwitcher v TextSwitcher.
C mt trong s cc layout c sn l LinearLayout, FrameLayout,
RelativeLayout v nhng i tng khc. tham kho thm v d, xem mc
Common Layout Objects (Cc i tng layout thng thng).
Nu khng c widget v layout c sn no ph hp vi nhu cu ca bn, hy t to lp
con View. Ch cn iu chnh mt cht nhng layout hoc widget c sn l bn c
th to lp con cho chng v ghi cc phng thc ca chng.
Vic t to cc lp con View gip bn iu khin chnh xc giao din v cc chc nng
ca mt phn t mn hnh. a ra tng v iu khin bn c vi cc view ty
chnh, di y cung cp vi v d bn c th thc hin vi vic vi chng:

Bn c th to mt kiu View t thit k hon ton, v d nh mt nt bm volume


control (iu khin m lng) c c t vic s dng ha 2D.

Bn c th kt hp mt nhm thnh phn View vo mt thnh phn n mi to


mt vi th ging nh ComboBox (kt hp danh sch popup v trng vn bn
nhp t do), mt iu khin b chn hai chiu (dual-pane selector control) - y
chnh l mt khung gm hai phn tri v phi, mi phn cha mt danh sch m
ti bn c th gn li (di chuyn) phn t gia hai danh sch,...

Bn c th ghi ln cch m thnh phn EditText c dng trn mn hnh. (Bi


hng dn v Notepad - Notepad Tutorial s dng cch lm ny to hiu ng
p v to mt trang ghi ch dng dng).

Bn c th bt nhng s kin khc nh n phm v x l chng theo cch ring


(chng hn nh cho mt tr chi).

Cc mc di y trnh by cch thc to View ty chnh v dng chng trong ng


dng. c thm thng tin chi tit, xem lpView.

Phng php c bn
Di y l kin thc tng quan mc nng cao v nhng iu bn cn bit bt
u to thnh phn View ca ring mnh:
1. M rng mt lpViewhin c hoc lp con cha lp ca bn.
2. Ghi mt s phng thc t lp cha. Cc phng thc ca lp cha b ghi s
bt u vi on, v d nh onDraw(), onMeasure() v onKeyDown(). Thao

104

Lp trnh Android c bn
tc tng t vi cc s kin on...trong Activityhoc ListActivitym
bn ghi cho ton vng i v cc hm khc.
3. S dng lp m rng mi ca bn. Mt khi hon tt, bn c th s dng lp
m rng mi ny.
Mch nh:Lp m rng c th c nh ngha di dng lp ni b (inner class)
trong activity s dng chng. iu ny thc s hu ch, bi n kim sot cc truy
cp khng cn thit ti lp m rng (c th bn mun to mt View dng public
cho nhng mc ch s dng rng hn trong ng dng ca mnh).

Thnh phn ty chnh hon ton


Thnh phn ty chnh hon ton c th c dng to ra thnh phn ha hin
th theo cch bn mun. C l, mt b o VU (VU meter) ging nh ng h o xng
hoc mt danh sch bi ht theo chiu dc, ti y mt qu bng di chuyn dc theo
cc t bn c th ht cng vi my karaoke. Bt k theo cch no, cng c th g
m nhng thnh phn c sn khng lm c, cho d bn c gng kt hp chng.
Tht may l bn c th d dng to ra cc thnh phn c giao din cng nh hnh
vi mnh mun, c l iu ny ch b hn ch bi kh nng tng tng ca bn, kch
thc mn hnh v hiu nng x l hin ti (cn nh rng, iu hin nhin l ng
dng ca bn phi chy nhng ng dng vi hiu nng km hn my tnh bn
(workstation)).
to mt thnh phn ty chnh hon ton:
1. Thnh phn ph bin nht m bn c th m rng lView, nn thng th bn s
bt u bng cch m rng n to thnh phn cp cao mi cho mnh.
2. Bn c th cung cp mt phng thc khi to c kh nng ly cc thuc tnh v
tham s t XML. Ngoi ra, bn cng c th s dng cc thuc tnh v tham s ca
mnh (c th l mu sc v di ca b o VU, hoc chiu rng v gim ca
kim,).
3. C th bn s mun to cc trnh lng nghe s kin , phng thc truy cp v
chnh sa thuc tnh ring, v cng c th l nhng hnh vi phc tp hn trong
lp thnh phn.
4. Chc hn bn s mun ghi lnonMeasure()vonDraw()nu mun thnh
phn hin th iu g . Trong khi c hai phng thc trn u c hnh vi mc
nh,onDraw()mc nh s khng lm g, cnmc nh onMeasure()lun thit
lp kch thc 100x100 - c th y khng phi l iu bn mun.
5. Cc phng thcon...khc cng c th b ghi theo yu cu.
M rngonDraw()vonMeasure()
Phng thconDraw()mang n cho bn mtkhung v canvas (canvas); trn khung
ny, bn c th thc thi bt c th g mnh mun: ha 2D, cc thnh phn chun
hoc ty chnh khc, vn bn c nh kiu trnh by (styled text), hoc bt k th g
khc bn c th ngh n.

105

Lp trnh Android c bn
Ghi ch:iu ny khng p dng cho ha 3D. Nu mun s dng ha 3D, bn
phi m rngSurfaceView thay v View, ng thi v t mt lung (thread) ring
bit khc. Xem v d v GLSurfaceViewActivity c thm thng tin chi tit.

onMeasure() l phng thc lin quan nhiu hn mt cht. onMeasure()l

phn quan trng trong mi lin h gia thnh phn ca bn v i tng cha ca
n.onMeasure()c ghi bo co mt cch hiu qu v chnh xc kt qu o
ca nhng thnh phn m n cha. Vic ny c thc hin phc tp hn mt cht
bi cc yu cu v gii hn t cha (c truyn vo qua phng thconMeasure())
cng nh bi yu cu gi phng thc setMeasuredDimension()vi chiu di
v chiu cao o lng khi chng c tnh ton. Nu bn khng gi c phng
thc ny t mt phng thc onMeasure()ghi , kt qu s l mt ngoi l ti thi
im .
mc cao, thc thionMeasure()s nh sau:
6. Phng thc onMeasure()b ghi s c gi vi nhng thng s o lng v chiu
rng v chiu cao (cc tham s widthMeasureSpecvheightMeasureSpec,
c hai u l m dng s nguyn biu din di). Cc thng s o lng trn
nn c coi l yu cu v gii hn chiu rng v chiu di o lng m bn nn
a ra. Bn c th tm thy ngun tham kho y v cc loi hn ch m nhng
thng s ny c th i hi trong ti liu tham chiu diView.onMeasure(int,
int)(ti liu ny lm rt tt vic gii thch ton b hot ng o lng).
7. Phng thc onMeasure()trong thnh phn ca bn nn tnh ton mt chiu
rng v chiu cao o lng s c yu cu dng thnh phn . Phng
thc ny nn th lm vic vi cc thng s c truyn vo, mc d n c th la
chn b qua chng (trong trng hp ny, i tng cha c th chn vic lm,
bao gm ct (clipping), cun (scrolling), nm ra (throwing) mt ngoi l (exception),
hoc yu cuonMeasure()th li ln na vi nhng thng s o lng khc).
8. Khi

tnh

xong

chiu

rng

chiu

cao,

phng

thc

setMeasuredDimension(int width, int height)phi c gi vi


cc thng s o lng tnh ton. Nu tht bi, kt qu tr v mt ngoi l c
nm ra.

Sau y l tng quan v mt s phng thc chun khc m framework c th gi trn


cc view:

106

Lp trnh Android c bn
Hng mc

Phng thc

M t

To

Phng thc khi to

Gm c mt dng
phng thc khi
to c gi khi view
c to ra t m
ngun v mt dng
c gi khi view
c to t mt file
layout. Dng th hai
nn phn tch v p
dng bt c thuc
tnh no xc nh
trong file layout.

onFinishInflate()

c gi sau khi
mt view v tt c
con ca n c to
t XML.

onMeasure(int, int)

c gi xc
nh yu cu v
kch thc cho view
ny cng tt c con
ca n.

Layout
(b cc)

onLayout(boolean, int, int, int, c gi khi view


int)
ny cn gn mt kch

thc v v tr cho tt
c con ca n.

onSizeChanged(int, int, int, int) c gi khi kch


thc ca view ny
thay i.

Dng hnh
(drawing)

onDraw(Canvas)

c gi khi view
sp dng ni dung
ca n.

107

Lp trnh Android c bn
Hng mc

Phng thc

M t

X l s kin

onKeyDown(int, KeyEvent)

c gi khi mt s
kin bn phm mi
xy ra.

onKeyUp(int, KeyEvent)

c gi khi mt s
kin th phm xy ra.

onTrackballEvent(MotionEvent)

c gi khi mt s
kin chuyn ng bi
ln xy ra.

onTouchEvent(MotionEvent)

c gi khi mt s
kin chuyn ng
trn mn hnh cm
ng xy ra.

Focus

Gn
(attach)

onFocusChanged(boolean, int, Rect) c gi khi view


c focus
mt focus.

hoc

onWindowFocusChanged(boolean)

c gi khi ca
s cha view c
focus hoc mt focus.

onAttachedToWindow()

c gi khi view
c gn vo mt
ca s.

onDetachedFromWindow()

c gi khi view
c g khi ca
s gn vi n.

onWindowVisibilityChanged(int)

c gi khi trng
thi hin th (visibility)
ca ca s cha view
thay i.

V d v View ty chnh
V d mu CustomView trongti liu API Demos (Cc bn demo API)cung cp v d
v mt View c ty chnh. View ty chnh c nh ngha trong lpLabelView.
LabelView minh ha mt s kha cnh khc nhau ca cc thnh phn ty chnh:

M rng lp View cho mt thnh phn ty chnh hon ton.

Tham s ha (parameterize) phng thc khi to no nhn cc tham s c


nh ngha trong file XML ca view. Mt vi trong s chng c truyn qua lp
View cha, nhng quan trng hn, c mt s thuc tnh ty chnh c nh ngha
v s dng cho LabelView.

108

Lp trnh Android c bn

Cc phng thc public chun ca kiu m bn mun thy cho mt thnh


phn nhn (label component), v d nh setText() , setTextSize() ,
setTextColor()...

Phng thc onMeasure ghi xc nh v thit lp kch thc khi dng ca


thnh phn. (Lu , trong LabelView, cng vic thc s c hon thnh bi mt
phng thc private measureWidth()).

Phng thc onDraw() ghi v nn nhn trn khung canvas c cung cp.

Bn c th thy mt s mu s dng ca View ty chnh LabelView trong custom_view_1.xml


t phn nhng v d mu. C th, bn c th thy s kt hp ca c hai b tham s
namespace android: v b tham s namespace ty chnh app:. Cc tham s app: ny
l nhng tham s ty chnh m LabelView nhn din v lm vic cng, c nh ngha
trong mt lp ni b bn trong cc lp nh ngha ti nguyn R mu.

Cc iu khin hn hp
Nu khng mun to mt thnh phn ty chnh hon ton, bn hy tm cch t mt
thnh phn c th ti s dng cha nhm iu khin tn ti, sau to mt thnh
phn hn hp (Compound Component), hay cn gi l iu khin hn hp (Compound
Control) tha mn yu cu bn a ra. Ni ngn gn, iu ny nhm mt lot iu
khin (hoc view) n nguyn hn thnh mt nhm mc c lin quan lgc vi nhau v
nhm ny c th c coi l mt phn t n l. V d, mt Combo Box c th c
coi nh mt s kt hp ca trng EditText mt dng v mt button iu chnh vi mt
PopupList gn vo. Nu bn nhn button v chn th g t danh sch, n s in
vo trng EditText. Bn cnh , nu mun, ngi dng cng c th g trc tip ci
g vo bn trong trng EditText.
Trong Android, thc ra c hai View khc sn sng lm vic ny: Spinner v
AutoCompleteTextView, nhng d sao th khi nim v Combo Box cng l mt
v d d hiu.
to mt thnh phn hn hp:
1. Xut pht im thng l mt loi layout no ; v vy, hy to mt lp m rng
layout. Trong v d ny v Combo box, chng ta s s dng LinearLayout (layout
tuyn tnh) vi hng thit b xoay theo chiu ngang. Cn nh rng, cc layout
khc c th c lng bn trong, nn thnh phn hn hp c th c cu trc v
mc phc tp ty . Lu , tng t mt Activity, bn c th s dng phng
php khai bo (da trn XML) to cc thnh phn cha trong , hoc bn cng
c th lng chng bng cch lp trnh t m ngun.
2. Trong phng thc khi to ca lp mi, hy cung cp bt c tham s no lp cha
mun, ri truyn chng qua phng thc khi to ca lp cha trc tin. Sau ,
bn c th thit lp cc view khc s dng trong thnh phn mi ca mnh; y
l ni bn s to trng EditText v PopupList. Lu , bn cng c th a cc
thuc tnh v tham s ca mnh vo trong XML, v XML c th c phng thc
khi to ca bn ly ra v s dng.
3. Bn cng c th to nhng trnh lng nghe s kin m cc view cha trong c
th to ra, v d nh mt phng thc lng nghe cho trnh lng nghe s kin click

109

Lp trnh Android c bn
vo mt mc trong danh sch (List Item Click Listener) cp nht ni dung ca
EditText nu ngi dng chn mt mc trong danh sch .
4. Bn cng c th t to thuc tnh cng vi cc phng thc truy cp v chnh sa
chng, v d nh cho php gi tr EditText c khi to trong thnh phn, cng
nh truy vn ni dung ca n khi cn.
5. Trong trng hp m rng mt layout, bn khng cn ghi ln cc phng thc
onDraw() v onMeasure(), v layout s c hnh vi mc nh c kh nng lm
tt vic ny. Tuy nhin, nu cn, bn vn c th ghi chng.
6. Bn c th ghi nhng phng thc on... khc, v d nh onKeyDown(),
chn nhng gi tr mc nh t danh sch popup ca mt combo box khi mt phm
no c nhn.
Tm li, vic s dng mt layout lm c s cho mt iu khin ty chnh em li rt
nhiu li ch, bao gm:

Bn c th xc nh layout bng cch s dng cc file XML khai bo nh vi mn


hnh activity, hoc bn c th to cc view mt cch t ng v lng chng vo
trong layout t m ngun.

Cc phng thc onDraw() v onMeasure() (cng vi hu ht nhng phng


thc on... khc) s c hnh vi ph hp, nn bn khng cn phi ghi chng.

Cui cng, bn c th xy dng cc view hn hp phc tp mt cch ty , nhanh


chng v ti s dng chng nu chng u l thnh phn n.

Cc v d v iu khin hn hp
Trong d n API Demos i km SDK, c hai v d v danh sch - V d 4 (Example
4) v V d 6 (Example 6) bn di Views/Lists biu din mt SpeechView m rng
LinearLayout to mt thnh phn hin th cc trch dn pht biu. Cc lp tng ng
trong m mu l List4.java v List6.java.

Chnh sa mt kiu View c sn


C mt ty chn gip bn to mt View ty chnh d dng hn, ty chn ny cng rt
hu ch trong mt vi trng hp nht nh. Nu tn ti sn mt thnh phn tng
t nh mun, bn c th m rng thnh phn v ch vic ghi hnh vi m mnh
mun thay i. Bn c th lm mi th mnh mun vi mt thnh phn ty chnh hon
ton; tuy nhin, bng cch bt u vi mt lp chuyn bit hn trong cy phn cp
View, bn c th thu c nhiu hnh vi thc hin chnh xc iu bn mun lm.
V d, SDK cha mt ng dng NotePad trong cc v d mu. iu ny l gii cho
nhiu kha cnh ca vic s dng nn tng Android, trong s l vic m rng View
EditText to ghi ch dng dng (lined notepad). y khng phi mt v d hon
ho, v cc hm API thc hin vic ny c th thay i t bn xem (preview) trc
, song n vn a ra nhng l gii thch hp cho cc nguyn l (principle).

110

Lp trnh Android c bn
Nu bn cha hon thnh n, hy nhp m ngun mu ca NotePad vo Eclipse (hoc
xem m ngun trc tip trn lin kt c cung cp). C th l, hy xem nh ngha
ca MyEditText trong file NoteEditor.java ti a ch: http://developer.android.com/
samples/index.html.
y, c mt s im cn lu .
1. nh ngha
Lp c nh ngha vi dng sau:

public static class MyEditText extends EditText


oo

N ng vai tr l lp ni b bn trong activity NoteEditor, song v l public


nn n c th c truy cp di dng NoteEditor.MyEditText t bn
ngoi lp NoteEditor nu mun.

oo

N l static, ngha l khng to cc phng thc tng hp (synthetic


method) m cho php truy cp d liu t lp cha, c ngha rng n c hnh vi
nh mt lp ring bit hn l mt ci g lin quan cht ch vi NoteEditor.
y l cch r rng hn gip to cc lp ni b nu chng khng cn truy cp
ti trng thi t lp bn ngoi, gi cho lp to ra c nh gn, ng thi cho
php n c th c nhng lp khc s dng d dng.

oo

N m rng EditText, l View chng ta chn ty chnh trong


trng hp ny. Khi chng ta hon tt, lp mi c th thay th cho mt view
EditText thng thng.

2. Khi to lp
Nh mi khi, lp cha c gi trc. Hn na, y khng phi phng thc khi
to mc nh m l mt phng thc khi to c tham s ha. EditText c
to vi nhng tham s khi n c to t mt file layout XML; do , phng
thc khi to va phi ly chng v va phi truyn cho phng thc khi to
ca lp cha.
3. Cc phng thc ghi
Trong v d ny, ch c mt phng thc ghi : onDraw() - tuy nhin, c th c
nhiu phng thc khc khi bn to thnh phn ty chnh ca mnh.
i vi v d NotePad, vic ghi ln phng thc onDraw() cho php chng ta
v nhng dng mu xanh ln khung canvas ca view EditText (khung canvas
c truyn ti phng thc onDraw() ghi ). Phng thc cha .onDraw()
c gi trc khi phng thc con kt thc. Phng thc ca lp cha nn c
kch hot, nhng trong trng hp ny, chng ta lm iu bc cui cng sau
khi v cc dng mnh mun bao gm.
4. S dng thnh phn ty chnh
By gi, chng ta c thnh phn ty chnh ca mnh, nhng lm sao c th
s dng n? Trong v d NotePad, thnh phn ty chnh c s dng trc tip
t layout khai bo; vy nn, hy nhn vo note_editor.xml trong th mc
res/layout.

111

Lp trnh Android c bn
<view
class=com.android.notepad.NoteEditor$MyEditText
id=@+id/note

android:layout_width=fill_parent

android:layout_height=fill_parent
android:background=@android:drawable/empty
android:padding=10dip
android:scrollbars=vertical

android:fadingEdge=vertical />

oo

Thnh phn ty chnh c to di dng mt view chung trong XML, cn lp


c xc nh bi gi y . Lu , lp ni b chng ta va nh ngha c
tham chiu bng cch s dng ghi ch (notation) NoteEditor$MyEditText,
y l cch chun tham chiu ti cc lp ni b trong ngn ng lp trinh Java.
Nu thnh phn View ty chnh khng c nh ngha di dng mt lp ni
b th cch thay th l bn c th khai bo thuc tnh View vi tn phn t XML
v loi b thuc tnh class. V d:
<com.android.notepad.MyEditText
id=@+id/note

... />

Lu , lp MyEditText lc ny nm trong mt file ring bit. Khi lp c


lng trong lp NoteEditor, k thut ny s khng hot ng.
oo

Cc thuc tnh v tham s khc trong nh ngha c truyn vo phng


thc khi to thnh phn ty chnh, sau truyn qua phng thc khi to
EditText, nn chng l nhng tham s ging nhau m bn c th s dng cho
mt view EditText. Lu , bn cng c th t thm cc tham s ca mnh,
chng ta s bn li vic ny sau.

V l tt c nhng g bn cn lm. Phi tha nhn rng y l mt trng hp n


gin, song li l cha kha to ra cc thnh phn ty chnh ch va phc tp
mc bn cn.
Mt thnh phn phc tp hn c th ghi ln cc phng thc on... nhiu hn, ng
thi a ra mt s phng thc tr gip ca chng, v cn bn l ty chnh cc
thuc tnh v hnh vi. Gii hn duy nht l tr tng tng ca bn v nhng g bn
mun thnh phn thc hin.

6. X l u vo t bn phm
H thng Android a ra mt bn phm trn mn hnh (on-screen keyboard) - c bit
n nh mt phng tin nhp liu mm (soft input method) - khi mt trng vn bn
trong giao din ngi dng c focus. cung cp tri nghim tt nht cho ngi
dng, bn c th xc nh cc c im v loi u vo mnh mun (chng hn nh
n l s in thoi hay a ch e-mail) v hnh vi ca phng tin nhp liu (chng hn
nh n c thc hin hnh vi t sa li v ng php hay khng).

112

Lp trnh Android c bn
Ngoi cc phng tin nhp liu trn mn hnh, Android cn h tr bn phm cng, nn
iu quan trng l ng dng ca bn phi ti u tri nghim ngi dng tng tc
c th xy ra, cho d l bn phm gn km.
Nhng ch ny c bn lun cc mc di y.

6.1 Xc nh kiu phng tin nhp liu


Mi trng vn bn u phc v cho mt loi vn bn u vo tng ng, chng hn
nh a ch e-mail, s in thoi, hay ch n thun l vn bn dng ch. V vy, iu
quan trng l bn phi xc nh kiu u vo cho tng trng vn bn trong ng dng
ca mnh, nhm gip h thng hin th phng tin nhp liu mm ph hp (chng hn
nh mt bn phm trn mn hnh).
Bn cnh nhng loi button c sn km theo phng tin nhp liu, bn nn xc
nh cc hnh vi, chng hn nh phng tin ny c cung cp gi chnh t (spelling
suggestion) khng, hoc vit hoa u dng cc cu mi v thay th button ngt dng
bng mt button action, chng hn nh Done hoc Next. Mc ny s ch cho bn thy
cch xc nh nhng c im trn.

Xc nh kiu bn phm
Bn hy lun khai bo phng tin nhp liu cho trng vn bn ca mnh bng cch
thm thuc tnh android:inputType vo phn t <EditText>.

Hnh 1. Kiu u vo phone.


V d, nu bn mun c mt phng tin nhp liu cho vic nhp s in thoi, hy
s dng gi tr phone:
<EditText
android:id=@+id/phone

android:layout_width=fill_parent
android:layout_height=wrap_content
android:hint=@string/phone_hint

android:inputType=phone />

113

Lp trnh Android c bn

Hnh 2. Kiu u vo textPassword.


Hoc, nu trng vn bn l dnh cho mt khu, hy s dng gi tr textPassword
trng che (conceal) d liu u vo khi ngi dng nhp:
<EditText
android:id=@+id/password
android:hint=@string/password_hint
android:inputType=textPassword

... />

Mt s gi tr c th c ghi li vi thuc tnh android:inputType v mt s gi


tr c th c kt hp nh ngha giao din cho phng tin nhp liu cng nhng
hnh vi thm vo.

Bt gi chnh t v cc hnh vi khc

Hnh 3. Thm textAutoCorrect s cung cp kh nng t sa cc li chnh t.

114

Lp trnh Android c bn
Thuc tnh android:inputType cho php bn xc nh nhiu hnh vi cho phng
tin nhp liu. Quan trng nht, nu trng vn bn ca bn c dnh cho u vo
dng vn bn c bn (chng hn nh cho mt tin nhn vn bn), bn nn bt tnh nng
t sa chnh t vi gi tr textAutoCorrect.
Bn c th kt hp cc hnh vi v kiu phng tin nhp liu khc nhau vi thuc tnh
android:inputType. V d, y l cch to mt trng vn bn c chc nng
vit hoa t u tin ca mt cu v t sa li chnh t:
<EditText
android:id=@+id/message
android:layout_width=wrap_content
android:layout_height=wrap_content
android:inputType=
textCapSentences|textAutoCorrect
.../>

Xc nh action ca phng tin nhp liu


Hu ht cc phng tin nhp liu mm u cung cp mt button action cho ngi
dng gc di cng, ph hp vi trng vn bn hin ti. Theo mc nh, h
thng s dng button ny cho c action Next (tip theo) hoc Done (hon thnh),
tr phi trng vn bn ca bn cho php c nhiu dng (chng hn nh vi andro
id:inputType=textMultiLine); trong trng hp ny, button action l du
ngt dng. Tuy nhin, bn c th xc nh thm nhng action c kh nng ph hp
vi trng vn bn hn, chng hn nh Send hay Go.
xc nh button action cho bn phm, hy s dng thuc tnh android:imeOptions
vi mt gi tr action nh actionSend hay actionSearch. V d:

Hnh 4. Button Send xut hin khi bn khai bo android:imeOptions=


actionSend .
<EditText
android:id=@+id/search

android:layout_width=fill_parent
android:layout_height=wrap_content
android:hint=@string/search_hint
android:inputType=text

android:imeOptions=actionSend />

Sau , bn c th lng nghe phm c nhn trn button action bng cch xc nh
mt TextView.OnEditorActionListener cho phn t EditText. Trong trnh

115

Lp trnh Android c bn
lng nghe, hy phn hi ID ca action IME (input method editor - trnh chnh sa
phng tin nhp liu) ph hp xc nh trong lp EditorInfo, chng hn nh
IME_ACTION_SEND. V d:
EditText editText = (EditText) findViewById(R.id.search);
editText.setOnEditorActionListener(new OnEditorActionListener() {
@Override

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {


boolean handled = false;

if (actionId == EditorInfo.IME_ACTION_SEND) {



sendMessage();



handled = true;
}


return handled;
}
});

6.2 X l trng thi hin th ca phng tin nhp liu


Khi mt trng vn bn nhn hoc b mt forcus Android hin th hoc n phng tin
nhp liu (chng hn nh bn phm trn mn hnh) mt cch tng ng. H thng
cng ra quyt nh v cch thc giao din ngi dng v trng vn bn xut hin trn
phng tin nhp liu. V d, khi khng gian dc trn mn hnh b rng buc, trng
vn bn s lp y ton b khng gian trn phng tin nhp liu. i vi hu ht ng
dng, cc hnh vi mc nh tha mn nhu cu.
D vy, trong mt s trng hp, bn c th mun iu khin trng thi hin th c
ca phng tin nhp liu trc tip hn v xc nh cch bn mun layout xut hin
khi phng tin nhp liu hin din. Mc ny s gii thch cch iu khin v phn hi
trng thi hin th c ca phng tin nhp liu.

Hin th phng tin nhp liu khi activity khi ng


Mc d t focus vo trng vn bn th nht trong layout khi activity khi ng, song
Android li khng hin th phng tin nhp liu. Hnh vi ny l ph hp, bi vic nhp
vn bn c th khng phi l nhim v chnh trong activity . Tuy nhin, nu vic
nhp vn bn l nhim v chnh (chng hn nh mn hnh ng nhp), bn s mun
phng tin nhp liu xut hin theo mc nh.
hin th phng tin nhp liu khi activity khi ng, hy thm thuc tnh
android:windowSoftInputMode cho phn t <activity> vi gi tr
stateVisible. V d:

116

Lp trnh Android c bn
<application ... >
<activity

android:windowSoftInputMode=stateVisible ... >
...
</activity>
...
</application>

Ghi ch: Nu thit b ca ngi dng c bn phm cng i km, phng tin nhp
liu mm s khng xut hin.

Hin th phng tin nhp liu theo nhu cu


Nu c mt phng tin nhp liu trong vng i ca activity m ti y, bn mun
m bo phng tin nhp liu phi hin din, hy s dng InputMethodManager
hin th n.
V d, phng thc sau ly mt View m ti y, ngi dung cn phi nhp liu vo
View ny, gi requestFocus() focus vo View, sau gi showSoftInput()
m phng tin nhp liu:
public

if





}
}

void showSoftKeyboard(View view) {


(view.requestFocus()) {
InputMethodManager imm = (InputMethodManager)


getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);

Ghi ch: Mt khi phng tin nhp liu hin th, bn khng nn n n bng cch
lp trnh m ngun na. H thng n phng tin nhp liu khi ngi dung hon
thnh tc v trong trng vn bn, hoc ngi dng c th n n vi mt iu khin
ca h thng (chng hn nh vi button Back).

Xc nh cch thc phn hi ca giao din ngi dng


Khi phng tin nhp liu xut hin trn mn hnh, n s lm gim khng gian hin c
ca giao din ngi dng trong ng dng. H thng ra quyt nh l n nn iu chnh
phn hin th ca giao din ngi dng, nhng c th n khng thc hin iu ny
ngay lc . m bo hnh vi tt nht cho ng dng ca mnh, hy ch ra cch bn
mun h thng hin th giao din ngi dng ca mnh trong phn khng gian cn li.
khai bo cch phn hi m bn mong mun trong mt activity, s dng thuc tnh
android:windowSoftInputMode trong phn t <activity> ca file k khai vi
mt trong s nhng gi tr adjust (iu chnh).

117

Lp trnh Android c bn
V d, nhm m bo h thng thay i kch thc layout cho phn khng gian hin
ti - iu ny m bo rng mi ni dung ca layout u c th c truy cp - s dng
adjustResize:
<application ... >
<activity


android:windowSoftInputMode=adjustResize ... >
...
</activity>
...
</application>

Bn c th kt hp thng s iu chnh trn vi thng s v trng thi hin th ca


phng thc nhp liu ban u t bn trn:
<activity


android:windowSoftInputMode=stateVisible|adjustResize ... >
...
</activity>

Xc nh adjustResize l vic thc s quan trng nu giao din ngi dng ca


bn bao gm cc iu khin m ngi dung c th cn truy cp ngay lp tc sau
khi hoc trong khi thc hin nhp vn bn u vo. V d, nu bn s dng mt layout
tng i t mt button bar cui mn hnh, hy dng adjustResize thay
i kch thc layout sao cho bar xut hin trn phng tin nhp liu.

6.3 H tr iu hng qua bn phm


Ngoi cc phng tin nhp liu mm (chng hn nh bn phm trn mn hnh),
Android cn h tr cc bn phm vt l gn vo thit b. Bn phm khng ch em li
mt ch thun tin cho vic nhp liu vn bn m cn cung cp mt cch thc
ngi dung iu hng v tng tc vi ng dng. Mc d hu ht thit b cm tay
nh in thoi u s dng cm ng lm ch tng tc chnh, song my tnh bng
v cc thit b tng t ngy cng tr nn ph bin v nhiu ngi dung thch s dng
ph kin bn phm gn thm vo.
Nh nhiu thit b Android tng cung cp loi tri nghim ny, iu quan trng l bn
phi ti u ng dng ca mnh h tr tng tc qua bn phm. Mc ny m t cch
bn c th h tr tt hn cho vic iu hng vi bn phm.
Ghi ch: Vic h tr iu hng theo hng trong ng dng ca bn rt quan
trng m bo ngi dng c th truy cp c m khng cn dng cc h tr
trc quan. Vic h tr y vic iu hng theo hng trong ng dng cng
gip bn kim th giao din ngi dng vi cc cng c nh uiautomator.

118

Lp trnh Android c bn

Kim th ng dng
Ngi dng c th duyt ng dng ca bn bng bn phm, bi v h thng Android
bt hu ht cc hnh vi cn thit theo mc nh.
Tt c cc widget tng tc cung cp bi framework Android (chng hn nh Button
v EditText) u c th nhn focus. iu ny c ngha rng, ngi dng c th iu
hng vi cc thit b iu khin nh D-pad hoc bn phm v mi widget s sng ln
hoc ngc li, thay i giao din ca n khi n c focus vo.
kim th ng dng ca bn, hy:
1. Ci t ng dng trn mt thit b c sn bn phm phn cng.
Nu thit b phn cng ca bn khng c bn phm, hy kt ni bn phm Bluetooth
hoc mt bn phm USB (mc d khng phi mi thit b u h tr ph kin USB).
Bn cng c th s dng trnh gi lp (emulator) Android:
1. Trong AVD Manager, nhn vo New Device (thit b mi) hoc chn mt profile
c sn v nhn Clone (to bn sao).
2. Trong ca s hin ra, hy m bo rng Keyboard v DPad c bt.
2. kim th ng dng, hy ch dng phm Tab iu hng trn giao din ngi
dng, m bo rng mi iu khin trong u nhn c focus khi cn.
Tm xem c thc th no c focus khng nh bn mun khng.
3. Bt u t khi ng dng khi ng v thay vo , hy dng cc phm iu hng
(phm mi tn trn bn phm) duyt ng dng.
T mi phn t c th c focus trong giao din ngi dng, nhn Up (ln),
Down (xung), Left (tri), Right (phi).
Tm xem c thc th no c focus khng nh bn mun khng.
Nu bn gp bt c thc th no m ti khi bn ang iu hng vi phm Tab hoc
iu khin iu hng khng nh mun, hy xc nh v tr nn c focus trong
layout. iu ny s c bn lun mc sau.

X l vic iu hng dng phm Tab


Khi ngi dng iu hng trn ng dng ca bn bng phm Tab, h thng chuyn
focus gia cc phn t da trn th t m chng xut hin trong layout. V d, nu bn
s dng mt layout tng i (relative layout) v th t cc phn t trn mn hnh khc
vi trong file, bn phi t xc nh th t focus theo cch th cng.
V d, trong layout di y, hai button c sp xp bn phi v mt trng vn bn
c sp xp pha bn tri ca button th hai. truyn focus t button th nht ti
trng vn bn, sau l button th hai, layout phi xc nh r th t focus cho tng
phn t m c th focus vo vi thuc tnh android:nextFocusForward:

119

Lp trnh Android c bn
<RelativeLayout ...>

<Button
android:id=@+id/button1
android:layout_alignParentTop=true


android:layout_alignParentRight=true
android:nextFocusForward=@+id/editText1
... />

<Button
android:id=@+id/button2
android:layout_below=@id/button1
android:nextFocusForward=@+id/button1
... />
<EditText
android:id=@id/editText1


android:layout_alignBottom=@+id/button2
android:layout_toLeftOf=@id/button2
android:nextFocusForward=@+id/button2

... />
...
</RelativeLayout>

Lc ny, thay v chuyn focus t button1 ti button2, sau l editText1, vic


chuyn focus ph hp vi giao din trn mn hnh: T button1 ti editText1 ri
ti button2.

X l vic iu hng theo hng


Ngi dung cng c th iu hng ng dng ca bn bng cch dng cc phm mi
tn trn bn phm (hnh vi tng t nh khi iu hng vi D-pad hoc bi ln). H
thng cung cp mt d on tt nht cho view nn c focus, theo hng xc nh
da trn layout ca cc view trn mn hnh. i khi, h thng c th on sai.
Nu h thng khng truyn focus cho view thch hp khi ngi dng thao tc iu hng
theo hng cho, hy xc nh view no nn c focus vi cc thuc tnh sau:

android:nextFocusUp.

android:nextFocusDown.

android:nextFocusLeft.

android:nextFocusRight.

Mi thuc tnh ch nh view k tip nhn focus khi ngi dung thc hin iu hng
theo hng bng cch s dng ID ca view. V d:

120

Lp trnh Android c bn
<Button
android:id=@+id/button1

android:nextFocusRight=@+id/button2
android:nextFocusDown=@+id/editText1

... />
<Button
android:id=@id/button2
android:nextFocusLeft=@id/button1
android:nextFocusDown=@id/editText1

... />
<EditText
android:id=@id/editText1
android:nextFocusUp=@id/button1

... />

6.4 X l cc action t bn phm


Khi ngi dng focus vo mt view c vn bn chnh sa c, chng hn nh
mt phn t EditText v ngi dung c mt bn phm cng gn vo, tt c u
vo s c h thng x l. Tuy nhin, nu mun chn hoc t x l trc tip
u vo t bn phm, bn c th thc thi cc phng thc callback t giao din
KeyEvent.Callback, chng hn nh onKeyDown() v onKeyMultiple().
C hai lp Activity v View u thc thi giao din KeyEvent.Callback; v vy,
thng th bn nn ghi cc phng thc callback trong phn m rng ca nhng
lp , nu thch hp.
Ghi ch: Khi x l cc s kin t bn phm vi lp KeyEvent v nhng hm API
lin quan, bn nn hy vng rng cc s kin y s ch ti t bn phm phn cng.
ng bao gi trng cy vo cc s kin t bt c phm o no trn phng tin
nhp liu mm (mt bn phm trn mn hnh chng hn).

X l cc s kin phm n
x l mt phm n c nhn, hy thc thi onKeyDown() hoc onKeyUp() nu
thch hp. Thng th bn nn s dng onKeyUp() nu mun m bo ch nhn mt
s kin. Nu ngi dung nhn v gi button, onKeyDown() s c gi nhiu ln.
V d, phng thc sau s phn hi mt s phm iu khin mt tr chi:
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {

switch (keyCode) {
case KeyEvent.KEYCODE_D:



moveShip(MOVE_LEFT);



return true;
case KeyEvent.KEYCODE_F:

121

Lp trnh Android c bn



moveShip(MOVE_RIGHT);



return true;
case KeyEvent.KEYCODE_J:



fireMachineGun();



return true;
case KeyEvent.KEYCODE_K:



fireMissile();



return true;
default:



return super.onKeyUp(keyCode, event);
}
}

X l cc phm b tr
phn hi cc s kin t phm b tr (modifier key), chng hn nh khi mt phm
c kt hp vi Shift hay Ctrl (Control), bn c th truy vn (query) KeyEvent c
truyn ti phng thc callback. Mt vi phng thc cung cp thng tin v phm b
tr, chng hn nh getModifiers() v getMetaState(). Tuy nhin, gii php n
gin nht l kim tra xem liu c ng phm b tr m bn ang quan tm c nhn
hay khng vi cc phng thc nh isShiftPressed() v isCtrlPressed().
V d, sau y l bi tp thc thi onKeyDown() cng vi mt s x l b sung khi phm
Shift c nhn cng vi mt trong s cc phm:
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {

switch (keyCode) {
...
case KeyEvent.KEYCODE_J:
if (event.isShiftPressed()) {




fireLaser();
} else {




fireMachineGun();
}



return true;
case KeyEvent.KEYCODE_K:
if (event.isShiftPressed()) {




fireSeekingMissle();
} else {




fireMissile();
}



return true;
default:

122

return super.onKeyUp(keyCode, event);

Lp trnh Android c bn
}
}

7. Widget ca ng dng
Widget ca ng dng l cc view loi nh trong ng dng , c th c nhng vo
nhng ng dng khc (chng hn nh mn hnh Home) v nhn cp nht theo chu k.
Nhng view ny c gi l cc Widget trong giao din ngi dng, bn c th pht
hnh chng vi mt Widget provider (Widget provider). Thnh phn ng dng c th
cha cc Widget khc c gi l Widget ch cho Widget ca ng dng (App Widget
host). nh chp mn hnh bn di biu din Widget ca ng dng Music.

Ti liu ny m t cch cng b mt Widget ca ng dng bng cch dng mt Widget


provider. Bn c th tham kho phn tho lun v vic t to AppWidgetHost
cha cc Widget ca ng dng ti phn App Widget Host.
Thit k Widget
tham kho thm thng tin v cch thit k Widget cho ng dng, mi bn c
hng dn v Widget.

Kin thc c bn
to Widget cho ng dng, bn cn c:
i tng AppWidgetProviderInfo
M t siu d liu (metadata) cho mt Widget, chng hn nh layout ca Widget,
tn sut cp nht v lp AppWidgetProvider. C th xc nh iu ny trong XML.

Thc thi lp AppWidgetProvider


nh ngha nhng phng thc c bn cho php bn lp trnh giao din vi Widget
ca ng dng da trn cc s kin broadcast. Thng qua , bn s nhn c
cc broadcast khi Widget ca ng dng c cp nht, c bt, b v hiu ha
v b xa.
Layout ca view
nh ngha layout ban u cho Widget ca ng dng, xc nh trong XML.
Ngoi ra, bn c th thc thi mt activity cu hnh cho Widget ca ng dng. y l
mt Activity ty chn c a ra khi ngi dung thm Widget cho ng dng ca bn,

123

Lp trnh Android c bn
cho php ngi chnh sa cc thit lp trong Widget ca ng dng vo thi im
khi to.
Mc di y m t cch thit lp mi thnh phn .

Khai bo Widget ca ng dng trong file k khai


Trc ht, hy khai bo lp AppWidgetProvider trong file k khai AndroidManifest.xml
ca ng dng. V d:
<receiver android:name=ExampleAppWidgetProvider >

<intent-filter>


<action android:name=android.appwidget.action.APPWIDGET_UPDATE />

</intent-filter>

<meta-data android:name=android.appwidget.provider
android:resource=@xml/example_appwidget_info />
</receiver>

Phn t <receiver> yu cu thuc tnh android:name, thuc tnh ny xc nh


AppWidgetProvider c Widget ca ng dng dng.
Phn t <intent-filter> phi cha mt phn t <action> vi thuc tnh
android:name. Thuc tnh ny ch ra rng AppWidgetProvider chp nhn
broadcast ACTION_APPWIDGET_UPDATE. y l broadcast duy nht bn phi
khai bo mt cch tng minh. B AppWidgetManager s t ng gi tt c cc
broadcast khc trong Widget ca ng dng ti AppWidgetProvider, nu cn.
Phn t <meta-data> xc nh ti nguyn AppWidgetProviderInfo v yu cu
cc thuc tnh sau:

android:name- Xc nh tn siu d liu. S dngandroid.appwidget.provider


nhn din d liu di dng trnh m t (descriptor) AppWidgetProviderInfo.

android:resource - Xc nh v tr ti nguyn AppWidgetProviderInfo.

Thm siu d liu AppWidgetProviderInfo


AppWidgetProviderInfo xc nh cc c im cn thit ca mt Widget cho ng
dng, chng hn nh di ti thiu ca layout, ti nguyn layout ban u, tn sut
cp nht Widget ng dng v mt activity cu hnh (ty chn) khi ng lc to.
nh ngha i tng AppWidgetProviderInfo trong ti nguyn XML bng cch s dng
mt phn t n <appwidget-provider> v lu n trong th mc res/xml/ ca
d n.

124

Lp trnh Android c bn
V d:
<appwidget-provider xmlns:android=http://schemas.android.com/apk/
res/android
android:minWidth=40dp
android:minHeight=40dp
android:updatePeriodMillis=86400000
android:previewImage=@drawable/preview
android:initialLayout=@layout/example_appwidget

android:configure=com.example.android.ExampleAppWidgetConfigure
android:resizeMode=horizontal|vertical
android:widgetCategory=home_screen|keyguard
android:initialKeyguardLayout=@layout/example_keyguard>
</appwidget-provider>

Di y l tng quan v cc thuc tnh <appwidget-provider>:


Gi tr cho cc thuc tnh minWidth v minHeight xc nh khong khng gian


ti thiu m Widget ca ng dng chim theo mc nh. Mn hnh Home nh v
cc Widget ng dng trong ca s ca n da trn mt khung li gm nhng
c chiu rng v chiu cao xc nh. Nu gi tr chiu rng hoc chiu cao ti thiu
ca Widget trong ng dng khng khp vi kch thc cc , kch thc Widget
trong ng dng s c lm trn ln bng kch thc ca gn nht.

Xem mc App Widget Design Guidelines (Hng dn thit k Widget cho ng dng)
bit thm thng tin v vic thay i kch thc ca Widget trong ng dng.
Ghi ch: gip cho Widget trong ng dng ca bn c th dng vi nhiu loi thit
b, kch thc ti thiu ca n khng nn ln hn 4 x 4 .

Cc thuc tnh minResizeWidth v minResizeHeight xc nh kch thc


ti thiu tuyt i cho Widget ca ng dng. Nhng gi tr ny nn xc nh kch
thc m ti , Widget ca ng dng c chp nhn hoc ngc li, khng
s dng c. S dng nhng thuc tnh ny cho php ngi dung thay i kch
thc Widget ti mt c c th nh hn kch thc mc nh ca Widget c
cc thuc tnh minWidth v minHeight nh ngha. Ni dung ny c gii thiu
trong Android 3.1.

Xem phn Hng dn thit k Widget cho ng dng (App Widget Design Guidelines)
bit thm thng tin v vic thay i kch thc Widget trong ng dng.
Thuc tnh updatePeriodMillis xc nh tn sut framework Widget trong ng
dng nn yu cu mt cp nht (update) t AppWidgetProvider bng cch gi
phng thc callback onUpdate(). Cp nht thc s khng m bo xy ra chnh
xc ti thi im c gi tr ny; do , chng ti khuyn bn nn cp nht t thng
xuyn nht nu c th - c th l khng qu mt gi mi ln tit kim pin. Bn cng
c th cho php ngi dung iu chnh tn sut bng cch cu hnh - mt s ngi
mun b m thi gian cho c phiu (stock ticker) phi cp nht 15 pht mt ln, hoc
c th ch l bn ln mi ngy.

125

Lp trnh Android c bn
Ghi ch: Nu thit b ang ch ng khi n thi im cp nht (c xc
nh bi updatePeriodMillis), thit b s thc dy thc hin cp nht. Nu
bn cp nht khng qu mt ln mi gi, iu ny s khng gy vn ng k i
vi thi lng pin. Tuy nhin, nu cn cp nht vi tn sut cao hn v/hoc khng
cn cp nht khi thit b ch ng, bn c th thc hin cp nht da trn bo
thc (alarm), n s khng nh thc thit b. lm vic ny, hy t bo thc vi
mt Intent m AppWidgetProvider s nhn, bng cch s dng AlarmManager.
Thit lp loi bo thc thnh ELAPSED_REALTIME hoc RTC, tc l n s ch gi
bo thc khi thit b ang ch thc. Sau , thit lp updatePeriodMillis
thnh 0.

Thuc tnh initialLayout ch ti ti nguyn layout xc nh layout ca Widget


trong ng dng.

Thuc tnh configure xc nh Activity chy khi ngi dung thm Widget
ng dng, nhm gip h cu hnh cc thuc tnh ca Widget. Vic ny l ty chn
(c mc To activity cu hnh cho Widget trong ng dng bn di).

Thuc tnh previewImage xc nh mt nh xem trc (preview) ca Widget trong


ng dng sau khi n c cu hnh, l th ngi dng nhn thy khi chn Widget
ng dng. Nu khng c nh xem trc, thay vo ngi dung s nhn thy biu
tng ng dng. Trng ny tng ng vi thuc tnh android:previewImage
trong phn t <receiver> ti file AndroidManifest.xml. Tham kho phn
tho lun v vic s dng previewImage mc Thit lp nh xem trc. Thuc
tnh ny c gii thiu trong Android 3.0.

Thuc tnh autoAdvanceViewId xc nh view ID cho view con ca Widget


trong ng dng. View ny nn c host ca Widget t ng cp nht. Thuc tnh
ny c gii thiu trong Android 3.0.

Thuc tnh resizeMode xc nh cc quy tc m ti , mt Widget c th c


thay i kch thc. Bn dng thuc tnh ny to cc Widget c kh nng thay
i kch thc cho mn hnh Home - theo chiu ngang, chiu dc hoc c hai.
Ngi dung chm v gi vo mt Widget hin th b thay i kch thc (resize
handle), sau ko n theo chiu ngang hoc/v dc thay i kch thc trn
khung li. Cc gi tr cho thuc tnh resizeMode bao gm horizontal (ngang),
vertical (dc) v none (khng chn gi tr no). khai bo mt Widget c
kh nng thay i kch thc theo chiu ngang v dc, hy thit lp gi tr l
horizontal|vertical. Thuc tnh ny c gii thiu trong Android 3.1.

Thuc tnh minResizeHeight xc nh chiu cao ti thiu (theo dp) m Widget


c th c thay i kch thc. Trng ny khng c tc dng nu ln hn
minHeight, hoc nu vic thay i kch thc theo chiu dc b v hiu ha (xem
resizeMode). Thuc tnh ny c gii thiu trong Android 4.0.

Thuc tnh minResizeWidth xc nh chiu rng ti thiu (theo dp) m idget


c th c thay i kch thc. Trng ny khng c tc dng nu ln hn
minWidth, hoc nu vic thay i kch thc theo chiu ngang b v hiu ha
(xem resizeMode). Thuc tnh ny c gii thiu trong Android 4.0.

126

Lp trnh Android c bn

Thuc tnh widgetCategory khai bo xem Widget trong ng dng ca bn c


th c hin th trn mn hnh Home, mn hnh kha (lock screen) - cn gi l
bo v bn phm, hoc c hai hay khng. Cc gi tr cho thuc tnh ny bao gm
home_screen v keyguard. Mt Widget c hin th trn c hai mn hnh trn
cn m bo theo hng dn thit k cho c hai lp Widget. tham kho thm
thng tin, xem mc Bt Widget ca ng dng trn mn hnh kha. Gi tr mc nh
l home_screen. Thuc tnh ny c gii thiu trong Android 4.2.

Thuc tnh initialKeyguardLayout ch ti ti nguyn layout nh ngha


mn hnh kha cho layout Widget ca ng dng. N hot ng tng t
android:initialLayout, ng thi cung cp mt layout c th xut hin ngay
lp tc cho ti khi Widget c khi to v c th cp nht layout. Thuc tnh ny
c gii thiu trong Android 4.2.

Xem lp AppWidgetProviderInfo bit thm thng tin v cc thuc tnh c


phn t <appwidget-provider> chp nhn.

To layout cho Widget ca ng dng


Bn phi nh ngha mt layout ban u cho Widget trong ng dng ca mnh trong file
XML v lu file vo th mc res/layout/ ca d n. Bn c th thit k Widget cho ng
dng bng cch s dng cc i tng View c lit k bn di, nhng trc khi
bt u, hy tm hiu mc Hng dn thit k Widget cho ng dng.
Nu bn quen vi Layout, vic to layout cho Widget ca ng dng rt n gin. Tuy
nhin, bn phi nhn thc c rng cc layout Widget ca ng dng c da trn
RemoteViews vn khng h tr bt c loi layout hay Widget ca view no.
Mt i tng RemoteViews (mt Widget ca ng dng) c th h tr nhng lp
layout sau:

FrameLayout.

LinearLayout.

RelativeLayout.

GridLayout.

v cc lp Widget di y:

AnalogClock.

Button.

Chronometer.

ImageButton.

ImageView.

ProgressBar.

TextView.

ViewFlipper.

ListView.

127

Lp trnh Android c bn

GridView.

StackView.

AdapterViewFlipper.

Con chu ca nhng lp ny khng c h tr.


RemoteViews cng h tr ViewStub, l mt View v hnh, kch thc bng khng
m bn c th dng in dn cc ti nguyn layout vo thi im chy.

Thm l cho Widget ca ng dng


Nhn chung, cc Widget thng khng nn m rng ti cnh bn mn hnh v khng
nn trn sang (flush) nhng Widget khc; v vy, bn nn thm l (margin) trn cc
cnh xung quanh khung (frame) Widget.
Nh Android 4.0, cc Widget ca ng dng c t ng thm vng m (padding)
gia khung Widget v khung vin (bounding box) ca Widget a ra phng n
cn chnh tt hn so vi nhng Widget khc cng cc biu tng trn mn hnh
Home ca ngi dung. tn dng hnh vi rt c khuyn khch ny, hy thit lp
targetSdkVersion trong ng dng ca bn thnh 14 hoc cao hn.
Rt d vit mt layout n c cc l ty chnh p dng cho nhng phin bn trc
ca nn tng; v khng c cc l thm vo cho Anroid 4.0 v cp cao hn:
1. Thit lp targetSdkVersion ca ng dng thnh 14 hoc cao hn.
2. to mt layout ging nh bn di, hy tham kho ti nguyn s o (dimension
resource) thy c cc l ca n:
<FrameLayout
android:layout_width=match_parent
android:layout_height=match_parent
android:padding=@dimen/widget_margin>
<LinearLayout
android:layout_width=match_parent
android:layout_height=match_parent
android:orientation=horizontal
android:background=@drawable/my_widget_background>

</LinearLayout>
</FrameLayout>

3. To hai ti nguyn s o, mt trong res/values/ cung cp l ty chnh cho


Widget ca Android phin bn trc 4.0, v mt res/values-v14/ khng
cung cp thm vng m cho Widget ca Anroid 4.0:
res/values/dimens.xml:
<dimen name=widget_margin>8dp</dimen>

128

Lp trnh Android c bn
res/values-v14/dimens.xml:
<dimen name=widget_margin>0dp</dimen>

Ty chn khc n gin hn l xy dng l ph cho cc tp nn (background asset)


dng nine-patch (mt dng nh bitmap m rng) theo mc nh, ng thi cung cp
nhng nine-patch (b 9 bn v) khc khng c l cho cc hm API Cp 14 hoc cp
cao hn.

S dng lp AppWidgetProvider
Lp AppWidgetProvider m rng BroadcastReceiver di dng mt lp thch hp
x l cc broadcast ca Widget trong ng dng. AppWidgetProvider ch nhn cc s
kin broadcast c lin quan ti Widget trong ng dng, chng hn nh khi Widget c
cp nht, b xa, c bt v b v hiu ha. Khi nhng s kin broadcast ny xy ra,
AppWidgetProvider nhn cc li gi phng thc sau:
Bn phi khai bo thc thi lp AppWidgetProvider di dng mt broadcast receiver
s dng phn t <receiver> trong AndroidManifest (xem mc Khai bo Widget ca
ng dng trong file k khai bn trn).
onUpdate()

c gi cp nht Widget trong ng dng theo chu k xc nh bi thuc tnh


updatePeriodMillis trong AppWidgetProviderInfo (xem mc Thm siu d
liu AppWidgetProviderInfo bn trn). Phng thc ny cng c gi khi ngi
dung thm Widget trong ng dng, v vy n nn thc hin cc ci t cn thit,
chng hn nh xc nh nhng trnh x l s kin cho cc View v khi ng mt
Service tm thi, nu cn. Tuy nhin, nu bn khai bo mt cu hnh cho
activity, phng thc ny s khng c gi khi ngi dung thm Widget ng
dng, nhng s c gi cho nhng ln cp nht sau. Cu hnh activity c trch
nhim thc hin cp nht u tin khi vic cu hnh hon tt. (Xem mc To
activity cu hnh cho Widget ca ng dng bn di).
onAppWidgetOptionsChanged()

c gi khi Widget c t ln u tin v ti bt c thi im no Widget b


thay i kch thc. Bn c th s dng callback ny hin th hoc n ni dung
da trn phm vi kch thc ca Widget. Bn ly phm vi kch thc bng cch
gi getAppWidgetOptions(), n s tr v mt Bundle cha:

OPTION_APPWIDGET_MIN_WIDTH - Cha rng buc (bound) di ca chiu

OPTION_APPWIDGET_MIN_HEIGHT - Cha rng buc di ca chiu cao hin

OPTION_APPWIDGET_MAX_WIDTH - Cha rng buc trn ca chiu rng hin

OPTION_APPWIDGET_MAX_HEIGHT - Cha rng buc trn ca chiu cao hin

rng hin ti, tnh theo n v dp, ca mt thc th Widget.


ti, tnh theo n v dp, ca mt thc th Widget.
ti, tnh theo n v dp, ca mt thc th Widget.
ti, tnh theo n v dp, ca mt thc th Widget.

129

Lp trnh Android c bn
Callback ny c gii thiu trong API Cp 16 (Android 4.1). Nu bn thc thi callback
ny, hy chc chn rng ng dng ca bn khng ph thuc vo n, bi callback s
khng c gi trn nhng thit b c hn.

onDeleted(Context, int[])
c gi mi khi mt Widget trong ng dng b xa t host Widget ca ng dng.

onEnabled(Context)
c gi khi mt th hin Widget trong ng dng c to ln u tin.
V d, nu ngi dung thm hai th hin ca Widget trong ng dng,
onEnabled(Context) ch c gi vo ln u tin. Nu bn cn m mt c
s d liu mi hoc thc hin ci t khc ch cn xy ra mt ln trn tt c cc
th hin Widget ca ng dng, y l ni thch hp lm iu ny.

onDisabled(Context)
c gi khi th hin cui cng ca Widget ng dng b xa t host Widget ng
dng. y l ni bn nn dn dp bt c cng vic no hon thnh trong
onEnabled(Context), chng hn nh xa mt c s d liu tm thi.

onReceive(Context, Intent)
c gi cho mi broadcast v trc mi phng thc callback bn trn.
Thng thng, bn khng phi thc thi phng thc ny bi khi thc thi,
AppWidgetProvider s mc nh lc tt c cc broadcast Widget trong ng dng
v gi nhng phng thc trn nu ph hp.
AppWidgetProvider quan trng nht l onUpdate(), v callback ny c gi khi
mi Widget trong ng dng c thm vo mt host (tr phi bn s dng mt activity
cu hnh). Nu Widget trong ng dng ca bn chp nhn bt c s kin tng tc
vi ngi dng no, bn phi ng k cc trnh x l s kin trong callback ny. Nu
Widget trong ng dng khng to cc file hoc c s d liu tm thi hoc thc hin
cng vic khc i hi phi dn dp (clean-up), onUpdate() c th l phng thc
callback duy nht bn cn xc nh. V d, nu mun mt Widget trong ng dng vi
mt button khi ng activity khi nhn vo, bn c th s dng thc thi di y ca
AppWidgetProvider:
public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {

final int N = appWidgetIds.length;

for (int i=0; i<N; i++) {


int appWidgetId = appWidgetIds[i];

// To mt Intent khi ng ExampleActivity

// Thc hin quy trnh vng lp ny i vi mi Widget ca ng dng


// thuc v provider ny

130

Intent intent = new Intent(context, ExampleActivity.class);

Lp trnh Android c bn
PendingIntent pendingIntent =

PendingIntent.getActivity(context, 0, intent, 0);

// Ly layout cho Widget ca ng dng v gn mt trnh lng


// nghe s kin on-click cho button

views.setOnClickPendingIntent(R.id.button, pendingIntent);

// Ra lnh cho AppWidgetManager thc hin mt cp nht trn

appWidgetManager.updateAppWidget(appWidgetId, views);

RemoteViews views = new RemoteViews(context.getPackageName(),


R.layout.appwidget_provider_layout);

// widget ca ng dng hin ti

}
}

AppWidgetProvider ny ch nh ngha phng thc onUpdate() cho mc ch xc


nh mt PendingIntent khi ng Activity v gn n vi button ca Widget
trong ng dng bng setOnClickPendingIntent(int, PendingIntent). Lu
, callback ny bao gm mt vng lp qua tng mc trong appWidgetIds, l
mt mng cc ID xc nh mi Widget trong ng dng do provider ny to ra. Bng
cch ny, nu ngi dng to nhiu th hin ca Widget trong ng dng, tt c cc
th hin ny s c cp nht cng lc. Tuy nhin, ch c mt lch trnh (schedule)
updatePeriodMillis c qun l cho tt c cc th hin ca Widget trong ng
dng. V d, nu lch trnh cp nht c xc nh c hai gi mt ln, v th hin th hai
ca Widget trong ng dng c thm vo mt gi sau th hin th nht, th chng u
c cp nht vo thi im do th hin th nht xc nh cn thi im cp nht th
hai s b b qua (chng u c cp nht c hai gi mt ln thay v mt gi mt ln).
Ghi ch: Do AppWidgetProvider l m rng ca BroadcastReceiver, nn
tin trnh ca bn khng c m bo s tip tc chy sau khi cc phng thc
callback tr v kt qu (xem BroadcastReceiver bit thm thng tin v vng
i broadcast). Nu tin trnh ci t Widget trong ng dng ca bn c th ko di
trong vi giy (v d nh vo lc thc hin cc yu cu Web) v bn yu cu tin trnh
tip tc, bn nn khi ng mt Service trong phng thc onUpdate(). Trong
phm vi Service ny, bn c th thc hin cp nht ca ring mnh cho Widget trong
ng dng m khng phi lo AppWidgetProvider s b ng do li ng dng khng
phn hi (ANR - Application Not Responding). Tham kho AppWidgetProvider
trong Wiktionary xem xt v d v mt Widget ng dng chy vi mt Service.
Ngoi ra, bn cng cn xem xt lp mu ExampleAppWidgetProvider.java.

Nhn cc Intent broadcast ca Widget trong ng dng


AppWidgetProvider khng ch l mt lp thun tin. Nu mun nhn trc tip cc
broadcast ca Widget trong ng dng, bn c th thc thi BroadcastReceiver ca mnh
hoc ghi callback onReceive(Context, Intent). Cc Intent bn cn quan tm:

131

Lp trnh Android c bn
ACTION_APPWIDGET_UPDATE.

ACTION_APPWIDGET_DELETED.

ACTION_APPWIDGET_ENABLED.

ACTION_APPWIDGET_DISABLED.

ACTION_APPWIDGET_OPTIONS_CHANGED.

To activity cu hnh cho Widget ca ng dng


Nu mun ngi dung cu hnh cc thit lp khi h thm mt Widget ng dng mi,
bn c th to mt activity cu hnh cho Widget ng dng. Activity ny s c t
ng kch hot bi host Widget ng dng (App Widget host), ng thi cho php ngi
dung cu hnh cc thit lp c sn cho Widget ng dng vo thi im to, chng hn
nh mu sc, kch thc, tn sut cp nht v nhng thit lp chc nng khc cho
Widget ca ng dng.
Activity cu hnh nn c khai bo di dng mt activity thng thng trong file k
khai ca Android. Tuy nhin, activity cu hnh s c host Widget ca ng dng khi
ng bng action ACTION_APPWIDGET_CONFIGURE, do activity phi chp nhn
Intent ny. V d:
<activity android:name=.ExampleAppWidgetConfigure>

<intent-filter>


<action android:name=android.appwidget.action.APPWIDGET_CONFIGURE/>

</intent-filter>
</activity>

ng thi, activity phi c khai bo trong file XML AppWidgetProviderInfo vi thuc


tnh android:configure (xem mc Thm siu d liu cho AppWidgetProviderInfo
bn trn). V d, activity cu hnh c th c khai bo nh sau:
<appwidget-provider
xmlns:android=http://schemas.android.com/apk/res/android
...

android:configure=com.example.android.ExampleAppWidgetConfigure

... >
</appwidget-provider>

Lu , activity c khai bo vi namespace y , bi activity ny s c tham


chiu t bn ngoi phm vi ca gi.
l tt c nhng g bn cn khi ng vi mt activity cu hnh. By gi, th bn
cn chnh l mt activity thc th. Tuy nhin, c hai iu quan trng bn cn ghi nh
khi thc thi activity:

132

Host Widget ca ng dng gi activity cu hnh v activity nn lun tr v mt


kt qu. Kt qu nn bao gm ID Widget ca ng dng truyn bi Intent khi ng
activity (c lu trong phn ph ca Intent nh EXTRA_APPWIDGET_ID).

Lp trnh Android c bn

Phng thc onUpdate() s khng c gi khi Widget ca ng dng c


to (h thng s khng gi broadcast ACTION_APPWIDGET_UPDATE khi mt
activity cu hnh c kch hot). Trch nhim ca activity cu hnh l yu cu mt
cp nht t AppWidgetManager khi Widget ca ng dng c to ln u. Tuy
nhin, onUpdate() s c gi cho nhng cp nht ln sau v ch b qua vo
ln u tin.

Xem cc on m nh mc di y thy v d v cch tr v kt qu t cu hnh


v cp nht Widget ca ng dng.

Cp nht Widget ca ng dng t activity cu hnh


Khi mt Widget ng dng dng mt activity cu hnh, trch nhim ca activity l cp
nht Widget ng dng khi vic cu hnh hon tt. Bn c th lm iu ny bng cch
yu cu mt cp nht trc tip t AppWidgetManager.
Sau y l tng quan v quy trnh cp nht cho Widget trong ng dng v ng activity
cu hnh:
1. Trc ht, ly ID ca Widget trong ng dng t Intent khi ng activity:
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {

mAppWidgetId = extras.getInt(


AppWidgetManager.EXTRA_APPWIDGET_ID,


AppWidgetManager.INVALID_APPWIDGET_ID);
}

2. Thc hin vic cu hnh Widget trong ng dng ca bn.


3. Khi vic cu hnh hon tt, ly mt th hin ca AppWidgetManager bng cch gi
getInstance(Context):
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

4. Cp nht Widget ng dng vi mt layout RemoteViews bng cch gi


updateAppWidget(int, RemoteViews):
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);

5. Cui cng, to Intent tr v, thit lp Intent ny vi kt qu ca activity, sau kt


thc activity:

133

Lp trnh Android c bn
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();

Mch nh: Khi activity cu hnh m ln u, hy thit lp kt qu activity l


RESULT_CANCELED. Bng cch ny, nu ngi dng thot khi activity trc khi
i n bc cui, host Widget ng dng s c thng bo rng vic cu hnh b hy
v Widget ng dng s khng c thm vo.
Xem lp mu ExampleAppWidgetConfigure.java trong ApiDemos.

Thit lp nh xem trc


Android 3.0 gii thiu trng previewImage xc nh mt bn xem trc cho Widget
ca ng dng. Bn xem trc ny c hin th ti ngi dung t b chn Widget
(Widget picker). Nu trng ny khng c cung cp gi tr, biu tng ca Widget
trong ng dng s c dng lm bn xem trc.
y l cch bn xc nh thit lp ny trong XML:
<appwidget-provider

xmlns:android=http://schemas.android.com/apk/res/android
...
android:previewImage=@drawable/preview>
</appwidget-provider>

Nhm h tr vic to mt nh xem trc cho Widget ng dng ca bn ( xc nh


trong trng previewImage), trnh gi lp Android bao gm mt ng dng c tn
Widget Preview. to nh xem trc, hy khi ng ng dng ny, chn Widget
cho ng dng ca bn v thit lp Widget theo cch bn mun nh xem trc xut
hin, sau lu n li ri t vo ti nguyn drawable trong ng dng ca bn.

Bt Widget ca ng dng trn mn hnh kha


Android 4.2 gii thiu ti ngi dng kh nng thm cc Widget vo mn hnh kha.
cho thy Widget trong ng dng ca bn sn sng dng trn mn hnh
kha, hy khai bo thuc tnh android:widgetCategory trong file XML xc nh
AppWidgetProviderInfo ca bn. Thuc tnh ny h tr hai gi tr, l home_
screen v keyguard. Mt Widget ca ng dng c th khai bo h tr cho mt trong
hai, hoc c hai gi tr trn.
Theo mc nh, mi Widget ng dng u h tr vic t trn mn hnh Home, v
vy home_screen l gi tr mc nh cho thuc tnh android:widgetCategory.
Nu bn mun Widget ng dng ca mnh sn sng cho mn hnh kha, hy thm
gi tr keyguard:

134

Lp trnh Android c bn
<appwidget-provider
xmlns:android=http://schemas.android.com/apk/res/android
...
android:widgetCategory=keyguard|home_screen>
</appwidget-provider>

Nu bn khai bo mt Widget c th hin th c trn c mn hnh kha ln mn hnh Home,


kh nng l bn s mun ty chnh Widget ty theo v tr m Widget c hin th. V d, bn
c th to mt file layout ring cho mn hnh bo v bn phm (mn hnh kha) v mn hnh
Home. Bc tip theo l pht hin hng mc Widget vo thi im chy v phn hi ph hp.
Bn c th pht hin ng dng ca mnh ang mn hnh kha hay mn hnh Home bng
cch gi getAppWidgetOptions() ly cc ty chn Widget di dng mt Bundle.
Bundle tr v s bao gm kha OPTION_APPWIDGET_HOST_CATEGORY, m gi tr ca n
s l WIDGET_CATEGORY_HOME_SCREEN hoc WIDGET_CATEGORY_KEYGUARD. Gi tr
ny c xc nh bi host m ti , Widget c gn vo. Trong AppWidgetProvider,
bn c th kim tra hng mc ca Widget, v d nh:
AppWidgetManager appWidgetManager;
int widgetId;
Bundle myOptions = appWidgetManager.getAppWidgetOptions (widgetId);
// Ly gi tr ca OPTION_APPWIDGET_HOST_CATEGORY
int category = myOptions.getInt
(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
// Nu gi tr l WIDGET_CATEGORY_KEYGUARD, y s l Widget mn hnh kha
boolean isKeyguard = category ==
AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;

Khi bit hng mc ca Widget, bn c th ty chn ti mt layout nn khc hoc thit


lp cc thuc tnh khc,... V d:
int baseLayout = isKeyguard ? R.layout.keyguard_widget_layout :
R.layout.widget_layout;

Bn cng nn xc nh mt layout khi to cho Widget ng dng khi nm trn mn hnh


kha vi thuc tnh android:initialKeyguardLayout. y cng tng t
nh android:initialLayout, trong cung cp mt layout c th xut hin ngay
tc th cho ti khi Widget c khi to v c th cp nht layout.

Cc hng dn thay i kch thc


Khi mt Widget c host trn mn hnh kha, framework s b qua cc trng
minWidth, minHeight, minResizeWidth v minResizeHeight. Nu mt
Widget ng thi l Widget ca mn hnh Home, nhng tham s ny vn cho thy
chng rt cn thit khi c s dng mn hnh Home; tuy nhin, chng s b b qua
cho nhiu mc ch mn hnh kha.

135

Lp trnh Android c bn
Chiu rng ca mt Widget cho mn hnh kha lun lp y khng gian c cp. i
vi chiu cao ca mt Widget cho mn hnh kha, bn c cc ty chn sau:

Nu Widget khng t nh du (mark) n di dng c th thay i kch thc


theo chiu dc (android:resizeMode=vertical), chiu cao ca n lun
l small:
oo

Trn thit b ch dc, small c xc nh l phn khng gian cn li khi


mt giao din ngi dng m kha (unlock) c hin th.

oo

Trn my tnh bng v in thoi ch ngang, small c thit lp ty


theo c s ca tng thit b.

Nu Widget t nh du n di dng c th thay i kch thc chiu dc, chiu


cao ca Widget s l small trn in thoi ch dc v giao din ngi dng
m kha. Trong tt c cc trng hp khc, Widget s iu chnh kch thc
lp y chiu cao c th.

S dng Widget ca ng dng vi cc collection


Android 3.0 gii thiu cc Widget ca ng dng cng vi cc collection. Nhng dng
Widget ng dng ny dng RemoteViewsService hin th cc collection c
ly t d liu t xa (remote data), chng hn nh t content provider. D liu do
RemoteViewsService cung cp c biu din trong Widget ng dng dng mt
trong nhng kiu view di y, chng ta gi l cc collection view:
ListView
View hin th cc mc trong mt danh sch cun dc (vertically scrolling list). V d,
Widget ca ng dng Gmail.
GridView
View hin th cc mc trong mt li cun hai chiu (two-dimensional scrolling
grid). V d, Widget ca ng dng Bookmarks.
StackView
View dng xp chng (stacked card view), ti y ngi dng c th vut y
View ln hoc xung v s nhn thy View trc hoc sau View ny. V d, cc
Widget ca ng dng YouTube v Books.
AdapterViewFlipper
Mt ViewAnimator n gin h tr adapter, to hiu ng ng gia hai hay
nhiu view. Ch c mt view con c hin th ti mt thi im.
Nh cp trn, nhng collection view ny hin th cc collection do d
liu t xa ly v. iu ny c ngha l chng s dng mt Adapter gn giao
din ngi dng vi d liu. Mt Adapter gn cc mc n ca mt tp d
liu thnh nhng i tng View n. Do cc collection view ny c adapter
ly v, nn framework Android phi bao gm kin trc ph h tr s dng
chng trong cc Widget. Trong trng hp ca mt Widget, Adapter c

136

Lp trnh Android c bn
thay th bi RemoteViewsFactory, y n gin l i tng bao mt lp
mng quanh giao din Adapter. Khi yu cu mt mc c th trong collection,
RemoteViewsFactory to v tr v mc cho collection di dng mt i tng
RemoteViews. bao gm mt collection view trong Widget ng dng ca mnh,
bn phi thc thi RemoteViewsService v RemoteViewsFactory.
RemoteViewsService l mt service cho php mt adapter t xa yu cu cc i
tng RemoteViews. RemoteViewsFactory l mt giao din cho adapter
gia mt collection view (chng hn nh ListView, GridView,) v d liu
bn di view . T mu Widget StackView, sau y l mt v d v on m mu
c sn m bn dng thc thi service v giao din ny:
public class StackWidgetService extends RemoteViewsService {

@Override

public RemoteViewsFactory onGetViewFactory(Intent intent)
{
return new

StackRemoteViewsFactory(this.getApplicationContext(), intent);
}
}

class StackRemoteViewsFactory implements


RemoteViewsService.RemoteViewsFactory {
// ... bao gm cc phng thc tng t adapter y.
// Xem mu StackView Widget.
}

ng dng mu
M ngun trch on trong mc ny c ly t ng dng mu Widget StackView:

Mu ny cha mt ngn xp gm 10 view, hin th cc gi tr t 0! ti 9!. Widget ca


ng dng mu c nhng hnh vi chnh sau:

Ngi dng c th lt dc view trn cng ca wiget ng dng hin th view


tip theo hoc sau . y l mt hnh vi ca StackView dng sn.

137

Lp trnh Android c bn

Nu khng c bt c tng tc no vi ngi dung, Widget ca ng dng t ng


duyt qua cc view ca n theo trnh t, ging nh mt show trnh chiu (slide show).
l do thit lp android:autoAdvanceViewId=@id/stack_view trong
file res/xml/stackwidgetinfo.xml. Thit lp ny p dng cho ID ca view,
trong trng hp ny l ID ca view ngn xp.

Nu ngi dng chm vo view trn cng, Widget ca ng dng s hin th thng
ip Toast Touched view n ( chm view n), trong n l ch s (v tr) ca
view c chm. tham kho thm phn tho lun v cch thc thi iu ny,
xem mc Thm hnh vi cho cc mc ring.

Thc thi Widget ca ng dng vi cc collection


thc thi mt Widget ca ng dng vi cc collection, bn phi tun th mt s
bc c bn. Mc di y m t thm nhng bc bn cn thc hin thc thi mt
Widget ca ng dng vi cc collection.

K khai Widget ca ng dng vi cc collection


Ngoi nhng iu kin c lit k trong mc Khai bo Widget ca ng dng
trong file k khai, c th gn cc Widget ca ng dng vi cc collection vo
RemoteViewsService ca mnh, bn phi khai bo service trong file k khai
vi quyn BIND_REMOTEVIEWS. iu ny s gip ngn cc ng dng khc t do
truy cp vo d liu trong Widget ng dng ca bn. V d, khi to mt Widget ng
dng dng RemoteViewsService to mt collection view, mc k khai trng
s nh sau:
<service android:name=MyWidgetService
...

android:permission=android.permission.BIND_REMOTEVIEWS />

Dng android:name=MyWidgetService tham chiu ti lp con ca


RemoteViewsService.

Layout cho Widget ca ng dng vi cc collection


Yu cu chnh i vi file XML layout cho Widget trong ng dng ca bn l phi
cha mt trong nhng collection view sau: ListView, GridView, StackView hoc
AdapterViewFlipper. y l widget_layout.xml cho ng dng mu Widget StackView:
<?xml version=1.0 encoding=utf-8?>
<FrameLayout
xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width=match_parent

android:layout_height=match_parent>

<StackView xmlns:android=http://schemas.android.com/apk/res/android

android:id=@+id/stack_view

138

Lp trnh Android c bn
android:layout_width=match_parent

android:layout_height=match_parent
android:gravity=center

android:loopViews=true />

<TextView xmlns:android=http://schemas.android.com/apk/res/android
android:id=@+id/empty_view

android:layout_width=match_parent

android:layout_height=match_parent
android:gravity=center

android:background=@drawable/widget_item_background
android:textColor=#ffffff
android:textStyle=bold

android:text=@string/empty_view_text
android:textSize=20sp />
</FrameLayout>

Lu , cc view trng phi l anh em ca collection view nhng view trng ny c


th biu din trng thi trng.
Ngoi file layout cho ton b Widget ng dng ca mnh, bn phi to file layout
khc xc nh layout cho tng mc trong collection (v d, mt layout cho mi
quyn sch trong collection sch). V d, ng dng mu Widget StackView ch
c mt file layout l widget_item.xml , do tt c cc mc u s dng layout
ging nhau. Tuy nhin, ng dng mu Widget StackView c hai file layout l
dark_widget_item.xml v light_widget_item.xml .

Lp AppWidgetProvider cho Widget ca ng dng vi cc


collection
Ging nh vi mt Widget ca ng dng thng thng, phn ln m trong lp
con AppWidgetProvider ca bn thng nm trong onUpdate(). Khc bit
ln trong vic thc thi cho onUpdate() khi to mt Widget ca ng dng vi cc
collection l bn phi gi setRemoteAdapter(). iu ny cho bit collection view,
ni ly d liu ca n. Sau , RemoteViewsService c th tr v thc thi ca
RemoteViewsFactory, v Widget c th a ra d liu ph hp. Khi gi phng
thc ny, bn phi truyn mt Intent ch ti thc thi ca RemoteViewsService v ID
ca Widget ng dng s xc nh Widget ng dng cn cp nht.
V d, y l cch mu Widget StackView thc thi phng thc callback onUpdate()
thit lp RemoteViewsService thnh adapter t xa cho collection Widget ca
ng dng:

139

Lp trnh Android c bn
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {

// cp nht mi Widget ca ng dng vi mt adapter t xa

for (int i = 0; i < appWidgetIds.length; ++i) {

// Thit lp Intent khi ng StackViewService


// cung cp cc view cho collection ny.

Intent intent = new Intent(context, StackWidgetService.class);


// Thm ID cho Widget ca ng dng vo phn ph ca Intent.

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetIds[i]);

intent.setData(Uri.parse(intent.toUri
(Intent.URI_INTENT_SCHEME)));

// Khi to i tng RemoteViews cho layout


// ca Widget trong ng dng.

// Thit lp i tng RemoteViews s dng adapter RemoteViews.

// Adapter ny kt ni ti mt RemoteViewsService thng qua


// Intent c th. y l cch bn to d liu.

// View trng c hin th khi collection khng c mc no.

// N nn nm trong cng layout c dng khi to


// i tng RemoteViews trn.

rv.setEmptyView(R.id.stack_view, R.id.empty_view);

RemoteViews rv = new RemoteViews


(context.getPackageName(), R.layout.widget_layout);

rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);

//

// Thc hin thm cc x l c th cho Widget ng dng ny...

appWidgetManager.updateAppWidget(appWidgetIds[i], rv);

super.onUpdate(context, appWidgetManager, appWidgetIds);

//
}

Lp RemoteViewsService
D liu lu tr lu di
V lu di, bn khng th trng cy vo mt th hin ca service hoc bt c d
liu no m th hin ny cha. V vy, bn ng nn cha bt k d liu no trong
RemoteViewsService (tr phi n dng tnh). Nu bn mun d liu trong Widget
ca ng dng c lu tr lu di, cch tt nht l dng mt ContentProvider m
d liu ca n c lu tr trong ton b vng i ca tin trnh.

140

Lp trnh Android c bn
Nh m t trn, lp con RemoteViewsService cung cp RemoteViewsFactory
c dng to collection view t xa.
C th, bn cn thc hin nhng bc sau:
To lp con RemoteViewsService. RemoteViewsService l service m qua ,
mt adapter t xa c th yu cu RemoteViews.
Trong lp con RemoteViewsService ca bn, hy bao gm mt lp c th thc
thi giao din RemoteViewsFactory. RemoteViewsFactory l mt giao din cho
adapter gia mt collection view t xa (chng hn nh ListView, GridView,)
v d liu bn di view . Vic thc thi ca bn c trch nhim phi to ra mt i
tng RemoteViews cho tng mc trong tp d liu. Giao din ny l mt lp mng
bao bn ngoi Adapter.
Ni dung chnh ca vic thc thi RemoteViewsService l RemoteViewsFactory
ca n, nh m t di y.

Giao din RemoteViewsFactory


Lp ty chnh thc thi giao din RemoteViewsFactory ca bn cung cp cho
Widget ng dng nhng d liu cha trong cc mc trong collection ca n. lm
vic ny, n kt hp file XML layout ca Widget ng dng vi mt ngun d liu. Ngun
d liu ny c th l bt k, t mt c s d liu ti mt mng n gin. Trong ng
dng mu Widget StackView, ngun d liu l mt mng ca WidgetItems. Cc hm
RemoteViewsFactory ng vai tr l adapter dn d liu vo collection view t xa.
Hai phng thc quan trng nht bn cn thc thi cho lp con RemoteViewsFactory
l onCreate() v getViewAt().
H thng gi onCreate() khi to i tng factory ln u. y l ni bn thit
lp bt k kt ni v/hoc con tr no ti ngun d liu ca bn. V d, ng dng
mu Widget StackView dng onCreate() khi to mt mng cc i tng
WidgetItem. Khi Widget ca ng dng hot ng, h thng truy cp vo nhng i
tng ny bng cch s dng ch s v tr ca chng trong mng v vn bn chng
cha c hin th.
y l mt on trch t ng dng mu Widget StackView, phn phng thc
OnCreate() ca lp thc thi RemoteViewsFactory:
class StackRemoteViewsFactory implements
RemoteViewsService.RemoteViewsFactory {

private static final int mCount = 10;

private Context mContext;

public StackRemoteViewsFactory(Context context, Intent intent) {

private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();

private int mAppWidgetId;


mContext = context;

mAppWidgetId =

intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,

141

Lp trnh Android c bn

AppWidgetManager.INVALID_APPWIDGET_ID);

public void onCreate() {

// Trong onCreate(), bn thit lp bt k

// kt ni/con tr no cho ngun d liu ca mnh.

// Hot ng nng v d nh ti v hoc to ni dung,


// nn c truyn ti onDataSetChanged()

// hoc getViewAt(). Nu chy qu 20 giy,

// li gi ny s tr v trong mt ANR.
for (int i = 0; i < mCount; i++) {

mWidgetItems.add(new WidgetItem(i + !));

...
}
...

Trong RemoteViewsFactory, phng thc getViewAt() tr v mt i tng


RemoteViews tng ng vi position c th trong tp d liu. y l mt on
trch t ng dng mu Widget StackView ca lp thc thi RemoteViewsFactory:
public RemoteViews getViewAt(int position) {

// Xy dng mt mc cc view t xa da trn mc Widget ca ng dng


// trong file XML, v thit lp vn bn da trn v tr.

rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);


RemoteViews rv = new RemoteViews(mContext.getPackageName(),
R.layout.widget_item);
...


}

// Tr v i tng cc view t xa.


return rv;

Thm hnh vi cho cc mc ring


Cc mc trn cho bn bit cch gn d liu vo collection ca Widget trong ng
dng ca bn. Nhng nu bn mun thm ng mt hnh vi vo tng mc ring l
trong collection view th sao?
Nh trnh by mc S dng lp AppWidgetProvider, thng th bn dng
setOnClickPendingIntent() thit lp mt hnh vi click cho i tng - chng
hn nh khin mt button c th kch hot mt Activity. Tuy nhin, phng
php ny khng c cho php i vi cc view con trong mt mc collection ring l
( lm r iu ny, bn c th dng setOnClickPendingIntent() thit lp
mt button ton cc (global button) trong Widget ng dng ca Gmail, button ny s
khi ng ng dng, nhng khng phi trn tng mc n l trong danh sch). Thay
vo , thm hnh vi click cho cc mc n l trong mt collection, bn s dng

142

Lp trnh Android c bn
setOnClickFillInIntent(). iu ny s thit lp mt Intent mu cho Intent

trng thi ch (pending Intent) cho collection view ca bn, sau thit lp mt Intent
trn mi mc trong collection thng qua RemoteViewsFactory.
Mc ny s dng ng dng mu Widget StackView m t cch thm hnh vi cho
tng mc n l. Trong mu Widget StackView, nu ngi dung chm vo view trn
cng, Widget ca ng dng s hin th thng ip Toast nh sau Touched view n,
trong n l ch s (v tr) ca view c chm . y l cch n lm vic:

StackWidgetProvider (mt lp con AppWidgetProvider) to mt Intent


trng thi ch c mt action ty chnh gi l TOAST_ACTION.

Khi ngi dung chm vo mt view, Intent s c truyn i v s truyn TOAST_ACTION.

Broadcast ny b StackWidgetProvider ca phng thc onReceive()


chn li, cn Widget trong ng dng hin th thng ip Toast cho view . D liu
cho cc mc ca collection c RemoteViewsFactory cung cp, thng qua
RemoteViewsService.
Ghi ch: ng dng mu Widget StackView s dng mt broadcast. Tuy nhin, thng
th mt Widget ca ng dng s kch hot mt activity trong tnh hung nh vy.

Thit lp mu Intent trng thi ch


StackWidgetProvider (lp con AppWidgetProvider) thit lp mt Intent
trng thi ch. Cc mc ring l ca mt collection khng th t thit lp cc Intent
trng thi ch ca chng. Thay vo , collection ng vai tr thit lp mt mu Intent
trng thi ch, cn cc mc ring l thit lp mt Intent to hnh vi duy nht trn
c s tng mc mt (item-by-item).
Lp ny cng nhn broadcast c gi khi ngi dung chm vo mt view. N x l
s kin ny trong phng thc onReceive(). Nu hnh ng ca Intent l TOAST_
ACTION, Widget trong ng dng hin th mt thng ip Toast cho view hin ti.
public class StackWidgetProvider extends AppWidgetProvider {

public static final String TOAST_ACTION =


com.example.android.stackwidget.TOAST_ACTION;
public static final String EXTRA_ITEM =
com.example.android.stackwidget.EXTRA_ITEM;

...



//
//
//
//

c gi khi BroadcastReceiver nhn mt Intent broadcast.


Kim tra xem action ca Intent c phi l TOAST_ACTION
hay khng. Nu ng, Widget trong ng dng hin th mt thng
ip Toast cho mc hin ti.

public void onReceive(Context context, Intent intent) {

@Override

AppWidgetManager mgr = AppWidgetManager.getInstance(context);

if (intent.getAction().equals(TOAST_ACTION)) {

143

Lp trnh Android c bn
int appWidgetId =
intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,

AppWidgetManager.INVALID_APPWIDGET_ID);

int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);

Toast.makeText(context, Touched view + viewIndex,


Toast.LENGTH_SHORT).show();

super.onReceive(context, intent);

@Override


public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {

// cp nht tng Widget ca ng dng vi adapter t xa

for (int i = 0; i < appWidgetIds.length; ++i) {


// Thit lp Intent tr ti StackViewService cung cp


// cc view cho collection ny.

Intent intent = new Intent(context, StackWidgetService.class);

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetIds[i]);


// View trng c hin th khi collection khng c mc no
// N nn l anh em ca collection view.

// Khi cc Intent c so snh, phn ph b b qua, nn


// chng ta cn nhng phn ph vo d liu chng khng
// b b qua na.

intent.setData(Uri.parse(intent.toUri
(Intent.URI_INTENT_SCHEME)));

RemoteViews rv = new RemoteViews(context.getPackageName(),


R.layout.widget_layout);
rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);

rv.setEmptyView(R.id.stack_view, R.id.empty_view);
// Phn ny cho php cc mc c hnh vi c lp. N lm vic
// ny bng cch thit lp mt mu Intent trng thi ch.
// Cc mc c lp ca mt collection khng th t thit
// lp cc Intent trng thi ch ca chng. Thay vo ,
// collection s thit lp mt mu Intent trng thi ch,
// v cc mu c lp s thit lp mt fillInIntent to
// hnh vi duy nht trn c s tng mc mt.
Intent toastIntent = new Intent(context, StackWidgetProvider.class);


// Thit lp action cho Intent. Khi ngi dung chm vo
// mt view c th, n s c hiu ng ca

// TOAST_ACTION broadcast.

144

toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);

Lp trnh Android c bn

toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetIds[i]);

intent.setData(Uri.parse(intent.toUri
(Intent.URI_INTENT_SCHEME)));
PendingIntent toastPendingIntent =

PendingIntent.getBroadcast(context, 0, toastIntent,

PendingIntent.FLAG_UPDATE_CURRENT);

rv.setPendingIntentTemplate

(R.id.stack_view, toastPendingIntent);

super.onUpdate(context, appWidgetManager, appWidgetIds);

appWidgetManager.updatesAppWidget(appWidgetIds[i], rv);

}
}

Thit lp cc Intent thay th


RemoteViewsFactory phi thit lp mt Intent thay th (fill-in Intent) trn mi

mc trong collection. iu ny gip chng ta c th phn bit action on-click ring l


ca mt mc c chn. Sau , Intent thay th c kt hp vi template (mu)
PendingIntent xc nh Intent cui cng c thc thi khi mc c nhn.
public class StackWidgetService extends RemoteViewsService {
@Override

public RemoteViewsFactory onGetViewFactory(Intent intent) {


return new StackRemoteViewsFactory(this.getApplicationContext(),


intent);

class StackRemoteViewsFactory implements


RemoteViewsService.RemoteViewsFactory {

private static final int mCount = 10;

private Context mContext;

public StackRemoteViewsFactory(Context context, Intent intent) {

private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();

private int mAppWidgetId;


mContext = context;

// Khi to tp d liu.

mAppWidgetId =
intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
}

AppWidgetManager.INVALID_APPWIDGET_ID);

public void onCreate() {

145

Lp trnh Android c bn

//
//
//
//
//

Trong onCreate(), bn thit lp bt k kt ni con


tr no cho ngun d liu ca mnh. Hot ng nng ,
v d nh ti v hoc to ni dung, nn c truyn
ti onDataSetChanged() hoc getViewAt(). Nu chy qu
20 giy, li gi ny s tr v trong mt ANR.

mWidgetItems.add(new WidgetItem(i + !));

for (int i = 0; i < mCount; i++) {

...
}

...

// V tr (ch s) ca mt WidgetItem trong mng, s dng gi


// tr vn bn ca mc trong phn kt hp vi mc Widget ca ng
// dng trong file XML khi to mt i tng RemoteViews.
public RemoteViews getViewAt(int position) {

// v tr lun chy t 0 n getCount() - 1.

// Khi to mt mc RemoteViews da trn mc Widget ca ng dng


// trong file XML, v thit lp vn bn da trn v tr.

RemoteViews rv = new RemoteViews


(mContext.getPackageName(), R.layout.widget_item);
rv.setTextViewText(R.id.widget_item,
mWidgetItems.get(position).text);
// Tip theo, thit lp mt fill-intent s c s dng
// trong template Intent trng thi ch

// c thit lp trn collection view trong StackWidgetProvider.

Bundle extras = new Bundle();

Intent fillInIntent = new Intent();

extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
fillInIntent.putExtras(extras);

// Cho php phn bit action on-click n ca mt


// mc cho

rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);

...

}
...
}

146

// Tr v i tng RemoteViews.
return rv;

Lp trnh Android c bn

Gi cho d liu ca collection lun cp nht


Minh ha bn di cho thy lung (flow) xy ra trong mt Widget ca ng dng dng
cc collection khi cp nht xy ra. N ch ra cch thc m ngun ca Widget ng dng
tng tc vi RemoteViewsFactory v cch bn c th kch hot cc cp nht:

Mt tnh nng ca nhng Widget ng dng dng cc collection l cung cp cho ngi
dng ni dung mi nht. V d, hy xem xt Widget ng dng ca Gmail trong Android
3.0, cung cp cho ngi dng mt nh chp nhanh ca hp th n. lm iu ny,
bn cn kch hot RemoteViewsFactory v collection view ly v cng nh
hin th d liu mi. Bn thc hin iu ny vi AppWidgetManager bng cch
gi notifyAppWidgetViewDataChanged(). Li gi ny tr v kt qu trong mt
callback ti phng thc onDataSetChanged()ca RemoteViewsFactory, cho
php bn ly bt k d liu mi no. Lu , bn c th thc hin cc hot ng
x l phc tp (processing-intensive operation) mt cch ng b trong callback
onDataSetChanged(). Bn c bo m rng li gi ny s hon tt trc

147

Lp trnh Android c bn
khi siu d liu hoc d liu ca view c ly t RemoteViewsFactory. Ngoi
ra, bn c th thc hin nhng hot ng c x l c bit trong phng thc
getViewAt(). Nu li gi ny tn nhiu thi gian, view ang np (xc nh bi
phng thc getLoadingView()ca RemoteViewsFactory) s c hin th ti
v tr tng ng ca collection view cho ti khi n tr v.

8. Activity
Activity l thnh phn ca ng dng cung cp mt mn hnh cho ngi dng c th

tng tc cng lm vic g , chng hn nh gi in thoi, chp nh, gi e-mail


hoc xem bn . Mi activity c cp mt ca s v giao din ngi dng trn
. Ca s thng chim ton b mn hnh, song cng c th nh hn mn hnh v
ni (float) ln pha trn cc ca s khc.
Mt ng dng thng cha nhiu activity gn vi nhau kh lng lo. Thng thng,
mt activity trong ng dng c xc nh l activity chnh (main activity), c
hin th cho ngi dng khi khi ng ng dng ln u. Sau , mi activity c th
khi ng mt activity khc thc hin nhng action khc. Mi khi mt activity mi
khi ng, activity trc s dng li, nhng h thng vn bo lu activity ny
trong mt ngn xp - l ngn xp li (back stack). Khi mt activity mi khi
ng, n c y vo ngn xp li v khin ngi dng tp trung vo . Ngn xp
li tun th c ch last in, first out (cn gi l LIFO, tc vo sau, ra trc) c
bn ca ngn xp. Do vy, khi ngi dung lm vic xong vi activity hin ti v nhn
button Back, activity ny s c ly khi ngn xp (v b hy), cn activity trc
s phc hi. (Ngn xp li c tho lun k hn trong ti liu Tc v v ngn xp
li (Tasks and Back Stack).
Khi mt activity b dng do mt activity mi khi ng, n c thng bo v s thay
i trng thi ny thng qua cc phng thc callback trong vng i ca activity. C
vi phng thc callback m mt activity c th nhn, l kt qu t s thay i trng
thi ca activity ny - h thng to, dng, phc hi hay ph hy n - v mi callback
em n cho bn c hi thc hin cng vic c th thch hp vi s thay i trng thi
. V d, khi dng, activity ca bn nn gii phng bt k i tng ln no, chng
hn nh mng hoc cc kt ni c s d liu. Khi activity phc hi, bn c th ly li
nhng ti nguyn cn thit v phc hi cc action b ngt trc . Nhng chuyn dch
trng thi ny l tt c cc phn ca vng i (lifecycle) activity.
Phn cn li ca ti liu ny tho lun v cch xy dng v s dng mt activity mc
c bn, trong bao gm mt tho lun hon chnh v cch lm vic ca vng i
activity. Do , bn c th qun l st sao vic chuyn i gia nhiu trng thi khc
nhau ca activity.

To activity
to mt activity, bn phi to mt lp con mi (hoc mt lp con tn ti) ca
Activity . Trong lp con ca mnh, bn cn thc thi nhng phng thc callback do
h thng gi trong khi chuyn i gia cc trng thi ca vng i activity , chng
hn nh khi activity c to, b dng, phc hi hoc b ph hy. Hai phng thc
callback quan trng nht l:

148

Lp trnh Android c bn
onCreate()
Bn phi thc thi phng thc ny. H thng gi n khi to activity. Trong lc thc
thi, bn nn khi to nhng thnh phn cn thit ca activity. Quan trng nht, y
chnh l ni bn phi gi setContentView() xc nh layout cho giao din
ngi dng ca activity.

onPause()
H thng gi phng thc ny di dng du hiu u tin cho thy ngi dng
ang ri khi activity ca bn (d khng phi lc no n cng truyn ti ngha l
hot ng b hy). y thng l ni bn nn xc nhn (commit) bt c thay i
no l ra nn c lu tr lu di ngoi phin hin ti ca ngi dung (bi ngi
dng c th s khng tr li).
Bn nn s dng vi phng thc callback khc cung cp mt tri nghim ngi
dng a dng gia cc activity, ng thi x l cc ln ngt (interuption) bt thng
khin activity b dng li, thm ch b hy b. Tt c cc phng thc callback trn
ton vng i ca activity u c tho lun mc Qun l vng i ca activity
bn di.

Thc thi mt giao din ngi dng


Giao din ngi dng cho mt activity c cung cp bi mt cy phn cp cc view
- i tng c k tha t lp View. Mi view iu khin mt khng gian hnh ch
nht c th trong ca s ca activity v c th phn hi tng tc t ngi dung. V d,
mt view c th l button khi to action khi ngi dng chm vo n.
Android cung cp mt s view c lm sn m bn c th dng thit k v t chc
layout ca mnh. Widget l cc view cung cp mt b phn t trc quan (v c tnh
tng tc) cho mn hnh, chng hn nh mt button, trng vn bn, checkbox, hay
n gin ch l mt bc nh. Cc layout l nhng view ly t ViewGroup ng vai tr
cung cp mt m hnh layout duy nht cho cc view con ca n, chng hn nh layout
tuyn tnh (linear layout), layout dng li (grid layout), hoc layout tng i (relative
layout). Bn cng c th dng cc lp con ca View v cc lp ViewGroup (hoc
nhng lp con c sn) t to widget v layout cho mnh, sau p dng chng cho
layout activity ca bn.
Cch thng dng nht xc nh mt layout s dng cc view l vi mt file layout
XML c lu trong ti nguyn ng dng ca bn. Bng cch ny, bn c th duy tr
thit k ca giao din ngi dng tch khi ma ngun xc nh hnh vi ca activity.
Bn c th thit lp layout vi vai tr giao din ngi dng cho activity ca mnh vi
setContentView(), sau truyn ID ti nguyn cho layout. Tuy nhin, bn cng c
th to nhng View mi trong m ngun ca activity v xy dng mt cy phn cp
view bng cch chn cc View mi vo mt ViewGroup, sau s dng layout
bng cch truyn ViewGroup gc cho setContentView().
bit thm thng tin v vic to mt giao din ngi dng, tham kho ti liu Giao

149

Lp trnh Android c bn
din ngi dng.

Khai bo activity trong file k khai


Bn phi khai bo activity ca mnh trong file k khai h thng c th truy cp n.
khai bo activity, hy m file k khai v thm phn t <activity> di dng con
ca phn t <application>. V d:
<manifest ... >

<application ... >

<activity android:name=.ExampleActivity />

...

</application ... >

...
</manifest >

C vi thuc tnh khc m bn c th bao gm trong phn t ny, nhm xc nh cc


thuc tnh hn nh: Nhn (label) cho activity, biu tng (icon) cho activity, hoc mt
theme thay i style cho giao din ngi dng ca activity. Trong , android:name
l thuc tnh duy nht cn thit - y l thuc tnh xc nh tn lp ca activity. Khi pht
hnh ng dng, bn khng nn i tn ny bi nu lm vy, bn c th ph hng mt
s chc nng, chng hn nh cc shortcut ca ng dng (c bi blog Things That
Cannot Change (Mt s th khng th thay i)).
Xem phn tham kho v phn t <activity> bit thm thng tin v cch khai bo
activity trong file k khai.

S dng b lc intent
Mt phn t <activity> cng c th xc nh nhiu b lc intent - bng cch dng
phn t <intent-filter> - khai bo cch m cc thnh phn ca ng dng khc
c th kch hot n.
Khi bn to mt ng dng mi s dng cc cng c SDK ca Android, activity gc c
to t ng bao gm mt b lc intent khai bo activity tng ng vi action chnh v
nn t hng mc l launcher (mn hnh chnh). B lc intent trng nh sau:
<activity android:name=.ExampleActivity android:icon=@drawable/app_icon>

<intent-filter>

<action android:name=android.intent.action.MAIN />

<category android:name=android.intent.category.LAUNCHER />

</intent-filter>

</activity>

Phn t <action> xc nh y l im bt u main cho ng dng. Phn t


<category> cho thy rng activity ny nn c lit k trong b khi ng ng dng

150

Lp trnh Android c bn
ca h thng ( cho php ngi dng kch hot activity ny).
Nu d nh cho ng dng ca mnh c th t kim sot v khng cho php cc ng
dng khc kch hot activity ca n, bn khng cn bt k b lc intent no khc. Ch
duy nht mt activity nn c action main v hng mc launcher, nh v d trc.
Nhng activity bn khng mun c mt trong cc ng dng khc th khng nn c b
lc intent v bn c th t khi ng chng bng cch dng cc intent tng minh
(explicit intent), nh tho lun mc di y.
Tuy nhin, nu mun activity ca mnh phn hi cc intent ngm nh (implicit intent)
c gi t nhng ng dng khc (v c ng dng ca bn), bn phi xc nh thm
cc b lc intent cho activity ca mnh. i vi mi loi intent bn mun phn hi ti,
bn phi bao gm mt <intent-filter> cha mt phn t <action>, ng thi c
th ty chn thm mt phn t <category> v/hoc <data>. Nhng phn t ny xc
nh kiu intent m activity ca bn c th phn hi ti.
bit thm thng tin v cch activity ca bn phn hi li intent, tham kho ti liu
Intent v b lc Intent ti a ch:
http://developer.android.com/guide/components/intents-filters.html.

Khi ng activity
Bn c th khi ng mt activity khc bng cch gi startActivity(), truyn cho
n mt Intent m t activity m bn mun khi ng. Intent hoc xc nh chnh xc
activity bn mun khi ng, hoc m t kiu action bn mun thc hin (v h thng
s chn activity ph hp cho bn, activity c th ti t ng dng khc). Mi intent
cng c th cha mt lng nh d liu c activity s dng khi n khi ng.
Khi lm vic trong ng dng ca mnh, bn s phi thng xuyn kch hot mt activity
bit. Bn c th lm vy bng cch to mt intent xc nh r rng activity mnh
mun khi ng qua vic s dng tn lp. V d, y l cch mt activity khi ng
activity khc c tn SignInActivity:
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

Tuy nhin, ng dng ca bn c th mun thc hin mt s action, chng hn nh gi


e-mail, tin nhn vn bn, hoc cp nht trng thi, bng cch s dng d liu t activity ca bn. Trong trng hp ny, ng dng c th khng c cc activity ca mnh
thc hin nhng action y. Do vy, bn c th dng cc activity do nhng ng dng
khc cung cp trn thit b, chng c th thc hin action cho bn. y l ni cc intent
tht s c gi tr - bn c th to mt intent m t action mnh mun thc hin v h
thng s khi ng activity ph hp t ng dng khc. Nu c nhiu activity c th x
l intent , ngi dung c th chn mt activity no s dng. V d, nu mun
cho php ngi dung gi mt e-mail, bn c th to intent sau:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

151

Lp trnh Android c bn
Phn ph EXTRA_EMAIL c thm vo intent l mt mng cc chui a ch e-mail
m mail ny s c gi ti. Khi mt ng dng e-mail phn hi intent ny, n c mng
chui cung cp trong phn ph trn v t chng trong trng to (gi n) ca form
son tho e-mail. Trong trng hp ny, activity ca ng dng e-mail khi ng v khi
ngi dung hon tt, activity s phc hi.

Khi ng activity tr v kt qu
i khi, bn mun nhn mt kt qu t activity m mnh khi ng. Trong trng
hp , hy khi ng activity bng cch gi startActivityForResult() (thay
v startActivity()). Sau , nhn kt qu t activity tip theo, hy thc thi
phng thc callback onActivityResult(). Khi activity tip theo hon tt, n tr
v kt qu trong mt Intent ti phng thc onActivityResult().
V d, c th bn mun ngi dung chn mt trong cc thng tin lin lc ca mnh; t
, activity ca bn c th lm vic g vi thng tin y. y l cch bn c th to
intent nh vy v x l kt qu:
private void pickContact() {



}

// To mt intent chn thng tin lin lc,


// nh nh ngha bi content provider URI

Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);


startActivityForResult(intent, PICK_CONTACT_REQUEST);

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data)


{

// Nu yu cu thnh cng (OK) v l PICK_CONTACT_REQUEST

if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST)


{

// Thc hin mt truy vn ti content provider


// ca danh b cho tn danh b

Cursor cursor = getContentResolver().query(data.getData(),


new String[] {Contacts.DISPLAY_NAME}, null, null, null);

if (cursor.moveToFirst()) { // True nu con tr khng trng


int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);

// Lm g vi tn danh b chn...

String name = cursor.getString(columnIndex);

}
}

V d ny cho thy lgc c bn m bn nn s dng trong phng thc


onActivityResult() x l kt qu ca activity. iu kin u tin kim tra xem
yu cu c thnh cng hay khng - nu c, resultCode s c gi tr RESULT_OK
- v yu cu ti kt qu ny c ang phn hi hay khng - trong trng hp ny,

152

Lp trnh Android c bn
requestCode khp vi tham s th hai gi bi startActivityForResult().
T y, m ngun x l kt qu activity bng cch truy vn d liu tr v trong mt
Intent (tham s data).

iu xy ra l, mt ContentResolver thc hin mt truy vn ti mt content provider,


provider ny tr v mt Cursor cho php d liu truy vn c th c c. bit
thm thng tin, tham kho ti liu Content providers.
tham kho thng tin v cch s dng intent, xem ti liu Intents and Intent Filters
(Intent v b lc intent.

Tt activity
Bn c th tt mt activity bng cch gi phng thc finish() ca activity
ny. Bn cng c th tt mt activity ring khi ng trc bng cch gi
finishActivity().
Ghi ch: Trong hu ht trng hp, bn khng nn tt mt activity mt cch tng
minh bng cch s dng cc phng thc trn. Nh ni dung tho lun mc sau
v vng i ca activity, h thng Android qun l vng i ca mt activity cho bn,
do bn khng cn tt cc activity. Vic gi cc phng thc trn c th nh hng
khng tt n tri nghim ngi dung d kin v ch nn c s dng khi bn hon
ton khng mun ngi dng quay v th hin ny ca activity.

Qun l vng i ca activity


Qun l vng i ca activity bng cch thc thi phng thc callback l vn quan
trng trong vic pht trin mt ng dng mnh m, linh hot. Vng i ca mt activity
b nh hng trc tip bi mi lin h gia n vi nhng activity khc, vi tc v v
ngn xp li ca n.
Mt activity c th tn ti ba trng thi chnh:
Resumed (c khi phc li)
Activity ang mn hnh chnh v ngi dng ang focus vo . (Trng thi ny
i khi cn c gi l running (ang chy)).
Paused (B tm dng)
Mt activity khc trong tin cnh mn hnh v c focus, song activity ny vn
ang hin th. Ngha l, mt activity khc ang hin th trn cng ca activity ny
v activity trong sut mt phn hoc khng che ton b mn hnh. Mt activity b
tm dng l hon ton ang tn ti (i tng Activity ang nm trong b nh,
duy tr tt c trng thi cng nh thng tin thnh vin, ng thi vn c gn vi
trnh qun l ca s (window manager)), nhng li c th b h thng hy trong cc
trng hp b nh mc rt thp.
Stopped (B dng)
Activity b activity khc che hon ton (hin activity ny ang hu cnh
(background). Mt activity b dng cng ang tn ti (i tng Activity c
gi trong b nh, duy tr tt c trng thi v thng tin thnh vin, nhng khng

153

Lp trnh Android c bn
c gn vi trnh qun l ca s). Tuy nhin, activity b dng khng cn hin th
i vi ngi dng v c th b h thng hy khi b nh cn cho vic khc.
Nu mt activity b tm dng hoc dng, h thng c th loi b activity ny khi b
nh bng cch yu cu activity kt thc (gi phng thc finish() ca activity), hoc
n gin l hy tin trnh ca n. Khi activity c m li (sau khi b kt thc hoc hy),
n phi c to t u.

Thc thi cc callback trong vng i ca activity


Khi mt activity chuyn i thnh hoc thot khi cc trng thi khc nhau nh m t
trn, activity s c thng bo qua nhiu phng thc callback khc nhau. Bn
c th ghi tt c cc phng thc callback lm vic ph hp khi trng thi ca
activity thay i. Activity khung sau bao gm nhng phng thc c bn trong vng
i activity:
public class ExampleActivity extends Activity {
@Override

public void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


// Activity ang c to.
}
@Override

protected void onStart() {


super.onStart();


// Activity chun b hin th.
}
@Override

protected void onResume() {


super.onResume();


// Activity n (gi c phc hi).
}
@Override

protected void onPause() {


super.onPause();


// Activity khc ang c focus (activity sp b tm dng).
}

@Override


protected void onStop() {

super.onStop();

// Activity khng cn hin th (hin n ang b dng)

@Override


154

protected void onDestroy() {

super.onDestroy();

// Activity sp b hy b.

Lp trnh Android c bn
}
}

Ghi ch: Thc thi ca cc phng thc vng i ny phi lun gi phng thc ca
lp cha trc khi lm bt c vic g, nh nu trong v d trn.
Cc phng thc cng nhau xc nh ton b vng i ca mt activity. Bng vic
thc thi nhng phng thc ny, bn c th theo di ba vng lp lng nhau trong vng
i activity:

Ton b vng i (entire lifetime) ca mt activity c tnh gia li gi ti


phng thc onCreate() v li gi ti phng thc onDestroy(). Activity
ca bn nn thc hin ci t trng thi global (chng hn nh nh ngha
layout) trong onCreate(), ng thi gii phng tt c ti nguyn cn li trong
onDestroy(). V d, nu activity c mt lung chy ngm ti v d liu t
mng, n c th to lung trong onCreate(), sau dng lung ny trong
onDestroy().

Vng i thy c (visible lifetime) ca mt activity c tnh gia li gi ti


onStart() v li gi ti onStop(). Trong sut thi gian ny, ngi dung c
th thy activity trn mn hnh v tng tc vi n. V d, onStop() c gi
lm cho mt activity mi khi ng khng cn hin th na. Gia hai phng thc
ny, bn c th duy tr ti nguyn cn thit hin th activity cho ngi dng. V
d, bn c th ng k mt BroadcastReceiver trong onStart() theo di
cc thay i nh hng ti giao din ngi dung, ng thi hy ng k n trong
onStop() khi ngi dng khng cn thy ci m bn ang hin th. H thng c
th gi onStart() v onStop() nhiu ln trong ton b vng i ca activity,
dn ti vic activity hin th v n i vi ngi dung.

Vng i nn trc (foreground lifetime) ca mt activity c tnh gia li gi


ti onResume() v li gi ti onPause(). Trong sut thi gian ny, activity
pha trc ca tt c cc activity khc trn mn hnh v c focus. Mt activity c
th thng xuyn chuyn tip vo v ra khi tin cnh - v d, onPause() c
gi khi thit b i vo ch ng hoc khi hp thoi xut hin. V trng thi ny c
th chuyn i thng xuyn, m ngun trong hai phng thc nn gn nh
nhm trnh trnh trng chm tr khi chuyn i lm ngi dng phi i.

Hnh 1 minh ha cc vng lp ny v nhng ng chuyn trng thi khc nhau m


mt activity c th c. Hnh ch nht i din cho phng thc callback m bn c th
thc thi thc hin hot ng khi chuyn tip activity gia cc trng thi.

155

Lp trnh Android c bn
Activity c
khi ng

onCreate()

onStart()
Ngi dng
duyt ti activity

onResume()

Tin trnh ca ng
dng b hy

Activity
ang chy
Activity khc
chuyn v chy
tin cnh

Cc ng dng c
u tin cao hn cn
ti b nh

onRestart()

Ngi dng
quay v activity

onPause()
Activity khng
cn hin th na

Ngi dng
duyt ti activity

onSop()
Activity ang hon
thnh hoc b h
thng hy
onDestroy()

Activity b tt
Hnh 1. Vng i activity.
Cc phng thc callback ca vng i activity ging nhau c lit k Bng 1, m

156

Lp trnh Android c bn
t chi tit hn v tng phng thc callback v xc nh v tr ca chng trong ton b
vng i ca activity, bao gm h thng c th hy activity hay khng sau khi phng
thc callback hon tt.
Bng 1. Tng quan v cc phng thc callback ca vng i activity.

C th
b hy
sau
khng?

Phng thc

M t

onCreate()

c gi khi activity c to ln Khng


u. y l ni bn nn thc hin tt
c cc ci t tnh thng thng - to
view, gn d liu cho danh sch,
Phng thc ny c truyn mt
i tng Bundle cha trng thi
trc ca activity, nu trng thi
c lu gi (xem mc Lu trng
thi ca Activity phn sau).

Phng
thc c
gi tip
theo

onStart()

Lun c onStart() theo sau.

onRestart()

c gi sau khi activity b dng, Khng


ngay trc khi c khi ng li.

onStart()

Lun c onStart() theo sau.

onStart()

c gi ngay trc khi activity hin Khng


th i vi ngi dng.
c onResume() theo sau nu
activity chuyn n tin cnh, hoc
c onStop() theo sau nu n b
n.

onResume() c gi ngay trc khi activity bt Khng


u tng tc vi ngi dng. Ti
thi im ny, activity trn cng ca
ngn xp activity, cng vi u vo t
ngi dng ti .

onResume()
hoc
onStop()

onPause()

Lun c onPause() theo sau.

157

Lp trnh Android c bn

Phng thc

M t

C th
b hy
sau
khng?

onPause() c gi khi h thng bt u phc C


hi activity khc. Phng thc ny
thng c dng commit nhng
thay i cha c lu lu tr
d liu lu di, dng cc hot cnh
v nhng th khc c th chim ti
nguyn CPU,... Phng thc ny s
thc thi nhanh chng, bi activity k
tip s khng c phc hi cho ti
khi phng thc tr v.

Tip theo

onResume()
hoc

onStop()

Phng thc OnPause() c theo


sau bi onResume() nu activity tr
li mn hnh chnh, hoc onStop()
nu activity khng hin th vi ngi
dung.

onStop()

c gi khi activity khng cn hin C


th vi ngi dng. iu ny c th
xy ra bi activity sp b hy, hoc do
activity khc (hay mt activity c sn
hoc activity mi) c phc hi
v ang che ph n.

onRestart()
hoc

onDestroy()

c onRestart() theo sau


nu mun activity tr li tng
tc vi ngi dng, hoc c
onDestroy() theo sau nu activity
ny sp b hy.

onDestroy()

158

c gi trc khi activity b hy. C


y l li gi cui cng m activity
nhn c. N c th c gi,
hoc do activity ang chun b kt
thc (mt s ngi gi finish() cho
n), hoc do h thng s tm thi
hy Activity ny tit kim khng
gian. Bn c th phn bit gia hai
tnh hung ny bng phng thc
isFinishing().

khng c g

Lp trnh Android c bn
Ct c nhn "C th b hy sau khng?" cho ta thy h thng c th hy tin trnh
qun l activity vo bt c thi im nosau khi phng thc tr v, m khng cn
thc thi dng m no khc ca activity hay khng. Ba phng thc c nh du
"C" l (onPause(), onStop() v onDestroy()). Do onPause()ng u tin
trong ba phng thc ny, nn sau khi activity c to, onPause()s l phng
thc cui cng bo m c gi trc khi tin trnhc thb hy - nu h thng phi
phc hi b nh trong trng hp khn cp, onStop() v onDestroy() c th
khng c gi. Do , bn nn s dng onPause() ghi d liu quan trng cn
lu tr lu di (chng hn nh cc chnh sa ca ngi dung) thc hin vic lu.
Tuy nhin, bn nn la chn thng tin phi gi li trongonPause(), bi bt c th tc
chn no trong phng thc ny cng ngn chn vic chuyn tip ti activity tip theo
v lm chm tri nghim ngi dung.
Cc phng thc c nh du "Khng" trong ct C th b hy sau khngbo
v tin trnh host activity khi b hy t thi im chng c gi. V vy, mt activity
c th b hy t lconPause()tr v cho ti lc onResume()c gi. N s khng
th b hy ln na cho ti khionPause()c gi v tr v ln na.
Ghi ch: Mt activity khng th b hy theo nh ngha Bng 1 vn c th b h
thng loi b - tuy nhin, iu ny ch xy ra trong cc hon cnh khng cn ti
nguyn no khc. Thi im mt activity c th b hy c tho lun k hn trong ti
liuProcesses and Threads (Tin trnh v lung).

Lu trng thi ca activity


McQun l vng i ca Activity cp ngn gn rng khi mt activity b dng
hoc tm dng, trng thi ca activity c bo lu. iu ny l ng, bi i
tng Activity vn c gi trong b nh khi n b dng hoc tm dng - mi
thng tin v cc thnh vin v trng thi hin ti ca n vn tn ti. V vy, bt c thay
i no do ngi dng to ra trong activity u c lu gi, nn khi activity quay
v mn hnh chnh (khi n phc hi), nhng thay i ny vn .
Tuy nhin, khi h thng hy mt activity phc hi b nh, i tng Activityb
loi b, nn h thng khng th ch n gin phc hi n v trng thi nguyn vn.
Thay vo , h thng phi to li i tngActivitynu ngi dng iu hng t
activity ny. Tuy nhin, ngi dng khng bit c rng h thng hy activity v
to li n, nn h lm tng l activity tr li nh lc trc. Trong trng hp ny, bn
c th chc chn rng thng tin quan trng v trng thi ca activity c bo v bng
vic thc thi thm mt phng thc callback c tnonSaveInstanceState(), cho
php bn lu thng tin v trng thi ca activity.
H thng gionSaveInstanceState()trc khi lm cho activity ny c th b hy.
H thng truyn cho phng thc ny mt Bundle, trong bn c th lu thng
tin trng thi v activity nh cc cp tn-gi tr bng cch s dng nhng phng
thc nh putString() v putInt(). Sau , nu h thng hy tin trnh ca
ng dng v ngi dung duyt tr li activity ca bn, h thng s to li activity v
truynBundlecho c onCreate()lnonRestoreInstanceState(). S dng
cc phng thc ny, bn c th ly trng thi lu tBundlev phc hi trng thi
ca activity. Nu khng c thng tin trng thi phc hi, Bundlec truyn cho
phng thc s l null ( l trng hp khi activity c to ln u tin).

159

Lp trnh Android c bn
Activity
ang chy
Activity khc chuyn v
chy mn hnh chnh

onCreate()
onRestoreInstanceState()
Phc hi trng thi activity

onSaveInstanceState()
Lu trng thi activity

onRestart()

Ngi dng
duyt ti activity

Ngi dng
duyt ti activity

Tin trnh ca ng
dng b hy

Th hin ca
activity cn nguyn
vn; khng cn
phc hi trng thi

Nhng ng
dng c u
tin cao hn
cn ti b nh

Activity
khng hin th

Th hin ca activity b hy, nhng


trng thi t
onSaveInstanceState() c lu li
Ghi ch: Khng c g bo m rng onSaveInstanceState() s c gi
trc khi activity b hy, bi c nhiu trng hp khng cn thit phi lu trng
thi (chng hn nh khi ngi dung ri khi activity bng cch nhn buttonBack,
do ngi dng mun ng activity mt cch tng minh). H thng s gi
onSaveInstanceState() trc khi gi onStop() v c th c onPause().
Tuy nhin, ngay c khi bn khng lm g v khng thc thi onSaveInstanceState(),
mt s trng thi ca activity s c phng thc onSaveInstanceState()
mc nh ca lp Activity phc hi. C th, phng thc mc nh s gi phng
thc onSaveInstanceState()tng ng i vi tng Viewtrong layout, cho
php mi view cung cp thng tin s c lu v bn thn view . Hu ht mi
widget trong framework ca Android u thc thi phng thc ny khi thch hp, nh
l bt c thay i c th thy c no ti giao din ngi dng u c t ng
lu v phc hi khi activity ca bn c to li. V d, widget EditTextlu bt
c vn bn no do ngi dng nhp vo v widget CheckBoxlu tnh trng c
nh du ca n. iu duy nht cn bn lm l cung cp mt ID duy nht (vi thuc
tnhandroid:id) cho mi widget m bn mun lu trng thi. Nu widget khng c
ID, h thng khng th lu trng thi ca widget c.
Bn cng c th ngn khng cho mt view trong layout khi vic b lu trng thi bng
cch thit lp thuc tnh android:saveEnabled thnh false, hoc bng cch

160

Lp trnh Android c bn
gi phng thc setSaveEnabled(). Thng thng, bn khng nn v hiu ha
n, song bn c th lm vy nu mun phc hi trng thi ca giao din ngi dng
activity theo cch khc.
Mc d thc thi mc nh caonSaveInstanceState() lu thng tin hu ch v
giao din ngi dng ca activity, song bn vn phi ghi n lu thm thng tin.
V d, bn c th phi lu cc gi tr thnh vin c thay i trong sut vng i
ca activity (iu ny c th lin quan ti nhng gi tr c phc hi trong giao din
ngi dng; tuy nhin, theo mc nh th cc thnh vin nm gi gi tr u khng
c phc hi).
Do thc thi mc nh caonSaveInstanceState() gip lu trng thi ca giao din
ngi dng, nn nu mun ghi phng thc ny lu thm thng tin th bn nn lun
gi phng thc onSaveInstanceState()ca lp cha trc khi lm bt c vic
g. Tng t, bn cng nn gi phng thc onRestoreInstanceState()ca
lp cha nu bn ghi phng thc ny; v vy, thc thi mc nh c th phc hi cc
trng thi view.
Ghi ch:VonSaveInstanceState()khng bo m c gi, bn ch nn dng
n ghi li nhng s chuyn i trng thi ca activity (trng thi ca giao din ngi
dng) - ng bao gi dng phng thc ny lu tr d liu lu di. Thay vo ,
hy s dng onPause() lm vic ny (chng hn nh d liu nn c lu vo
c s d liu) khi ngi dung ri khi activity.
Mt cch hay kim th tnh nng ca ng dng trong vic phc hi trng thi ca
n l bn ch cn xoay thit b sao cho hng ca mn hnh thay i. Khi hng mn
hnh thay i, h thng s hy v to li activity p dng ti nguyn thay th sn
sng c mt cho cu hnh mn hnh mi. Do vy, iu quan trng l activity ca bn
phc hi hon ton trng thi khi activity c to li, v ngi dng thng xoay mn
hnh khi dng cc ng dng.

X l cc thay i cu hnh
Mt s cu hnh thit b c th thay i trong lc chy (chng hn nh chiu xoay mn
hnh, bn phm c sn, ngn ng). Khi thay i xy ra, Android s to li activity
ang chy (h thng gi onDestroy(), sau lp tc gi onCreate()). Hnh vi
ny c thit k nhm gip ng dng ca bn thch nghi vi cc cu hnh mi bng
cch t ng np li ng dng vi nhng ti nguyn thay th m bn cung cp
(chng hn nh cc layout khc nhau i vi nhng chiu xoay v kch thc mn
hnh khc nhau).
Nu bn thng thit k activity x l vic khi ng li do chiu xoay mn hnh thay
i v phc hi trng thi ca activity nh m t trn, ng dng ca bn s vng hn
trc cc s kin ngoi mong mun trong sut vng i ca activity.
Cch tt nht x l vic khi ng li l lu, sau phc hi trng thi ca activity
bng cch s dng onSaveInstanceState() v onRestoreInstanceState() (hoc
onCreate()), nh tho lun mc trc.
bit thm thng tin v cu hnh thay i xy ra vo thi im chy v cch x l
chng, hy c hng dnHandling Runtime Changes (X l cc thay i khi chy).

161

Lp trnh Android c bn

Phi hp cc activity
Khi mt activity khi ng activity khc, chng u tri qua cc chuyn tip vng i.
Activity u tin tm dng v dng (d n s khng dng nu vn hin th trong hu
cnh), trong khi activity khc c to. Trong trng hp cc activity chia s d liu
lu vo a hoc ni no , iu quan trng l activity th nht khng hon ton b
dng khi activity th hai c to. Thay vo , tin trnh khi ng activity th hai s
xy ra cng lc dng activity th nht.
Th t ca cc phng thc callback trong vng i c xc nh, c bit l khi
hai activity u trong cng tin trnh v mt ci khi ng ci cn li. Di y l th
t ca cc hot ng xy ra khi Activity A khi ng Activity B:
Phng thconPause()ca Activity A c thc thi.
Cc phng thconCreate(),onStart() vonResume()ca Activity B thc thi
theo th t. (Activity B gi c ngi dng focus vo).
Sau , nu Activity A khng cn hin th trn mn hnh, phng thconStop()ca
n s thc thi.
Vic tin on trnh t ca cc callback cho php bn qun l vic chuyn i thng tin
t activity ny sang activity khc. V d, nu phi ghi vo mt c s d liu khi activity
th nht dng li activity sau c th c n, bn nn ghi vo c s d liu trong sut
thi im chyonPause()thay v onStop().

9. Ty chn lu tr
Android cung cp mt s ty chn bn c th lu tr d liu lu di cho ng dng.
Gii php bn chn ph thuc vo tng nhu cu c th, chng hn nh d liu l ca
ring ng dng ny hay cn cho php ng dng (v ngi dng) khc truy cp vo,
dung lng cn dng l bao nhiu.
Bn c th chn mt trong nhng ty chn lu tr d liu sau:
Ty chnh chia s (Shared Preferences)
Lu d liu ring kiu c s di dng cp kha-gi tr.
B nh trong (Internal Storage)
Lu d liu ring trn b nh thit b.
B nh ngoi (External Storage)
Lu d liu cng cng (public data) trn b nh ngoi cng chia s.
C s d liu SQLite (SQLite Databases)
Lu d liu c cu trc (structured data) trong c s d liu ring.
Kt ni mng (Network Connection)
Lu d liu trn Web bng network server ca bn.

162

Lp trnh Android c bn
Android cung cp cho bn mt cch hin th d liu ring cho cc ng dng khc vi mt Content Provider. Content provider l mt thnh phn ty chn, dng cung
cp quyn c/ghi (read/write) i vi d liu ca ng dng, ty thuc vo gii hn
quyn bn mun cp. tm hiu thm v cch s dng content provider, hy tham
kho ti liu Content Providers.

S dng ty chnh chia s


Lp SharedPreferences cung cp mt framework lm vic chung cho php bn
lu tr v truy xut cc cp kha-gi tr c nh ca cc kiu d liu c s. Bn c th
s dng lp SharedPreferences lu cc d liu c s nh: Boolean, float, int,
long v string. D liu ny s tn ti qua cc phin lm vic (session) ca ngi dng
(thm ch ngay c khi ng dng kt thc).

Ty chnh c nhn
Ty chnh chia s khng ch dng lu ty chnh c nhn (user preference), chng
hn nh nhc chung (ringtone) m ngi dng la chn. Nu bn mun to phn ty
chnh c nhn cho ng dng, hy tm hiu thm v PreferenceActivity, lp ny
s cung cp mt framework Activity bn to phn ty chnh c nhn, phn ny s t
ng c lu li (bng cch s dng ty chnh chia s).
to mt i tng SharedPreferences trong ng dng, hy dng mt trong hai
phng thc sau:

getSharedPreferences() - S dng phng thc ny nu bn cn nhiu

getPreferences() - S dng phng thc ny nu bn ch cn mt file ty

file ty chnh xc nh bng tn; bn c th xc nh tn ny thng qua tham s


u tin.

chnh cho Activity ca mnh. Do phng thc ny ch to mt file ty chnh, nn bn


khng cn cung cp tn.

lu cc gi tr:
1. Gi edit() ly mt i tng SharedPreferences.Editor.
2. Thm cc gi tr vi nhng phng thc nh putBoolean() v
putString().
3. Gi commit() cp nht cc chnh sa .
c gi tr, s dng phng thc SharedPreferences, chng hn nh
getBoolean() v getString().
Sau y l mt v d v vic lu ty chn cho ch nhn phm im lng trong ng dng
my tnh c nhn (calculator):

163

Lp trnh Android c bn
public class Calc extends Activity{

public static final String PREFS_NAME =MyPrefsFile;

@Override

protectedvoid onCreate(Bundle state){

super.onCreate(state);

// Lu ty chnh

boolean silent = settings.getBoolean(silentMode,false);


...

SharedPreferences settings = getSharedPreferences(PREFS_NAME,0);


setSilent(silent);

@Override

protected void onStop(){

super.onStop();

// Chng ta cn mt i tng Editor thay i ty chnh.

// Tt c cc i tng ny u nm trong gi android.context.Context

SharedPreferences.Editor editor = settings.edit();

}
}

SharedPreferences settings = getSharedPreferences(PREFS_NAME,0);


editor.putBoolean(silentMode, mSilentMode);
// Xc nhn cc thay i!
editor.commit();

S dng b nh trong
Bn c th trc tip lu file vo b nh trong ca thit b. Mc nh, cc file c lu
vo b nh trong l ca ring ng dng , nn cc ng dng (hay ngi dng) khc
khng th truy cp vo. Khi ngi dng g ng dng, nhng file ny s b xa b.
to v ghi mt file ring vo b nh trong:
1. Gi phng thc openFileOutput() vi tn file v ch hot ng. Kt qu
tr v s l mt FileOutputStream.
2. Ghi vo file vi phng thc write().
3. ng lung d liu bng phng thc close().

164

Lp trnh Android c bn
V d:
String FILENAME =hello_file;
Stringstring=hello world!;

FileOutputStream fos = openFileOutput(FILENAME,Context.MODE_PRIVATE);


fos.write(string.getBytes());
fos.close();

Ch MODE_PRIVATE s to file mi (hoc thay th mt file cng tn) v t file


ny l ca ring ng dng. Bn c th dng cc ch khc nh: MODE_APPEND,
MODE_WORLD_READABLE v MODE_WORLD_WRITEABLE.
c file t b nh trong:
1. Gi phng thc openFileInput() v truyn tn file cn c cho hm ny. Kt
qu tr v l mt FileInputStream.
2. c tng byte ca file ny bng phng thc read().
3. Sau , ng lung ny bng lnh close().
Mch nh: Nu bn mun lu mt file tnh (static) trong ng dng vo thi im bin
dch chng trnh, hy lu file ny vo th mc res/raw/ trong d n ca bn.
Bn c th m file ny bng phng thc openRawResource(), truyn vo ID ti
nguyn R.raw.<tn file>. Phng thc ny s tr v mt InputStream bn c
th c file (nhng bn khng th ghi vo file gc).

Lu file cache
Nu ch mun lu cache (nh tm) thay v lu lu di mt vi d liu, bn nn dng
phng thc getCacheDir() m mt File i din cho th mc ni b, y
chnh l ni ng dng ca bn tm lu cc file cache.
Khi thiu dung lng b nh trong ca thit b, Android c th xa nhng file cache ny
khi phc khng gian b nh. Tuy nhin, bn khng nn cho h thng t ng
xa cc file ca bn. Hy qun l cc file cache ca mnh v t vo mt khng gian
nh c dung lng hp l, chng hn nh 1MB. Khi ngi dng g ng dng ca bn,
nhng file ny s b xa b.

Cc phng thc hu dng khc


getFilesDir()
Ly ng dn tuyt i ca th mc cha file h thng, cng l ni lu file ni b
trong ng dng ca bn.

getDir()
To th mc mi (hoc m th mc c) nm trong b nh trong.

deleteFile()
Xa mt file lu b nh trong.

165

Lp trnh Android c bn
fileList()
Tr v mt mng cc file ang c lu trong ng dng ca bn.

S dng b nh ngoi
Mi thit b tng thch vi Android u h tr mt b nh ngoi (external storage)
cng chia s cho bn lu file. B nh ngoi ny c th l mt thit b lu tr c th tho
ri (removable storage media) (chng hn nh mt th nh SD) hoc mt b nh trong
(khng th tho ri). Ngi dng c th c c v c th chnh sa cc file c
lu vo b nh ngoi khi s dng ch lu tr b nh USB (USB mass storage)
a file vo mt my tnh.
Mt thit b c th dng mt phn vng ca b nh trong lm b nh ngoi c th vn
cung cp mt khe cm th SD (SD card slot). Trong trng hp ny, th SD khng phi
l mt phn ca b nh ngoi v ng dng ca bn khng th truy cp vo (phn
lu tr b sung ny ch dnh cho cc file a phng tin m ngi dng cung cp v
h thng c th qut c).
Lu : B nh ngoi c th mt tc dng nu ngi dng gn (mount) b nh ny vo
mt my tnh hoc tho ri th nh; bi khi , nhng file bn lu vo b nh ngoi
s khng c bo mt. Tt c cc ng dng c th c v ghi file t trong b nh
ngoi v ngi dng c th xa chng.

Kim tra s sn sng ca cc th nh


Trc khi lm vic vi b nh ngoi, bn nn gi hm getExternalStorageState()
kim tra xem th nh c sn sng hay khng. Th nh c th ang c gn vo
my tnh, b li, ch cho php c, hoc ang trong mt vi tnh trng khc. Sau y l
v d v cch kim tra s sn sng ca th nh:
boolean mExternalStorageAvailable =false;
boolean mExternalStorageWriteable =false;

String state =Environment.getExternalStorageState();


if(Environment.MEDIA_MOUNTED.equals(state)){

// Chng ta c th c v ghi th nh

mExternalStorageAvailable = mExternalStorageWriteable =true;

} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){

// Chng ta ch c th c th nh

mExternalStorageWriteable =false;

mExternalStorageAvailable =true;

} else {

// C mt s li xy ra. Thit b c th trong mt trang thi

// khng th c hoc ghi vo b nh ngoi

// no khc, nhng tt c nhng g chng ta cn bit l



}

166

mExternalStorageAvailable = mExternalStorageWriteable =false;

Lp trnh Android c bn
V d trn nhm kim tra xem b nh ngoi c sn sng c v ghi hay khng.
Phng thc getExternalStorageState() tr v mt s trng thi m bn c
th mun kim tra, chng hn nh th nh c ang b chia s hay khng (ang c
kt ni vi my tnh), ang b li, hoc b tho ri,... Bn c th s dng nhng
thng tin ny thng bo chi tit cho ngi dng bit khi ng dng ca bn cn truy
cp th nh.

Truy cp file trn b nh ngoi


Nu bn s dng API (Application programming interface - Giao din lp trnh ng
dng) Cp 8 hoc cp cao hn, hy s dng phng thc getExternalFileDir()
m mt File i din cho th mc b nh ngoi - l ni bn nn dng lu cc
file ca mnh. Phng thc ny cn truyn vo mt tham s type xc nh kiu
th mc con (subdirectory) bn mun dng, chng hn nh DIRECTORY_MUSIC v
DIRECTORY_RINGTONES (nu truyn vo null s nhn c th mc gc cha
cc file trong ng dng ca bn). Phng thc ny cng s to ra mt th mc ph
hp, nu cn thit. Bng vic xc nh kiu th mc, bn c th m bo rng media
scanner (trnh qut a phng tin) ca Android c th phn loi ng cc file ca bn
trong h thng (v d, chung in thoi c nhn din ng l chung in thoi v
khc vi m nhc). Nu ngi dng g ng dng ra, th mc ny cng vi ni dung
bn trong s b xa.
Nu bn s dng API Cp 7 hoc cp thp hn, hy dng phng thc
getExternalStorageDirectory(), m File i din cho th mc gc ca
b nh ngoi. Sau , bn nn ghi d liu vo th mc sau:
/Android/data/<package_name>/files/

Trong , <package_name> l tn gi theo nh dng Java, chng hn nh com.


example.android.app. Nu thit b ca ngi dng ang chy API Cp 8 hoc
cp cao hn, khi g ng dng, th mc ny cng vi ni dung bn trong s b xa.

Vic lu file chia s


n file khi media scanner
Thm mt file trng c tn l .nomedia vo th mc cha cc file lu trong b nh
ngoi (lu tin t du chm trong tn file). Vic ny s ngn khng cho media scanner c file a phng tin ca bn hoc a chng vo nhng ng dng nh Gallery
hoc Music.
Nu bn mun lu file khng ch dnh ring cho ng dng ca bn v khng b xa khi
ngi dng g ng dng , hy lu cc file ny vo mt trong nhng th mc public
(cng khai) ca b nh ngoi. Cc th mc ny nm th mc gc ca b nh ngoi,
chng hn nh Music/, Pictures/, Ringtones/,
Trong API Cp 8 hoc cp cao hn, hy s dng

getExternalStoragePublicDirectory(), truyn cho phng thc ny kiu


th mc public mun dng, chng hn nh DIRECTORY_MUSIC, DIRECTORY_
PICTURES, DIRECTORY_RINGTONES,... Phng thc ny s to ra mt th mc
ph hp, nu cn.

167

Lp trnh Android c bn
Nu bn s dng API Cp 7 hoc cp thp hn, hy dng phng thc
getExternalStorageDirectory() m file i din cho th mc gc ca
b nh ngoi, sau lu cc file chia s ny vo mt trong nhng th mc di y:

Music/ - Media scanner xc nh tt c cc file a phng tin trong th mc ny

Podcasts/ - Media scanner xc nh tt c cc file a phng tin trong th mc

Ringtones/ - Media scanner xc nh cc file a phng tin y l nhc

Alarms/ - Media scanner xc nh cc file y l m bo thc (alarm sound).

Notifications/ - Media scanner xc nh cc file y l m nhc nh (notifica-

Pictures/ - Cha tt c cc nh (ngoi tr nhng nh chp bng chc nng

Movies/ - Tt c cc on phim (ngoi tr nhng on video t chc nng quay

Download/ - Cc file hn hp ti v.

l m nhc ca ngi dng.

ny l podcast (file m thanh).


chung.

tion sound).
chp nh).

phim ca thit b).

Lu file cache
Nu bn s dng API Cp 8 hoc cp cao hn, hy dng getExternalCacheDir()
m mt File i din cho th mc b nh ngoi - l ni dng lu cc file cache.
Nu ngi dng g b ng dng ca bn, nhng file ny s t ng b xa. Tuy nhin,
trong sut vng i ca ng dng, bn nn qun l cc file cache ny v loi b nhng
file khng cn thit tit kim khng gian nh.
Nu bn dng API Cp 7 hoc cp thp hn, hy s dng phng thc
getExternalStorageDirectory() m mt File i din cho th mc gc
ca b nh ngoi, sau ghi d liu cache vo th mc di y:
/Android/data/<package_name>/cache/

Trong , <package_name>/ l tn gi theo nh dng Java, chng hn nh


com.example.android.app.

S dng c s d liu
H iu hnh Android h tr y cho c s d liu SQLite. Bt c c s d liu no
bn to u c th truy cp c theo tn t bt k lp no trong ng dng, nhng
khng th truy cp c t bn ngoi ng dng.
Phng php c khuyn dng to c s d liu SQLite mi l to mt lp con
ca SQLiteOpenHelper v ghi ln phng thc onCreate(), ti y bn c
th thc thi lnh SQLite to bng cho c s d liu. V d:

168

Lp trnh Android c bn
public class DictionaryOpenHelper extends SQLiteOpenHelper {

private static final int DATABASE_VERSION =2;

private static final String DICTIONARY_TABLE_CREATE =

private static final String DICTIONARY_TABLE_NAME =dictionary;


CREATE TABLE + DICTIONARY_TABLE_NAME + (+

KEY_DEFINITION + TEXT);;

KEY_WORD + TEXT, +

DictionaryOpenHelper(Context context){

super(context, DATABASE_NAME,null, DATABASE_VERSION);

@Override

public void onCreate(SQLiteDatabase db){

db.execSQL(DICTIONARY_TABLE_CREATE);

Sau , bn c th ly mt th hin ca SQLiteOpenHelper ci t bng cch


s dng phng thc khi to nh ngha. ghi v c t c s d liu, gi cc
phng thc getWritableDatabase() v getReadableDatabase() tng
ng. C hai phng thc ny u tr v mt i tng SQLiteDatabase i din
cho c s d liu, ng thi cung cp cc phng thc thao tc vi SQLite.
H iu hnh Android h tr khng gii hn i vi nhng khi nim SQLite chun.
Chng ta c khuyn ngh nn thm mt trng kha gi tr tng t ng (autoincrement value key field) c th s dng lm trng nh danh duy nht nhm tng kh
nng tm kim nhanh mt bn ghi (record). iu ny khng bt buc i vi d liu
ring, nhng nu ci t mt content provider, bn phi thm vo mt trng nh danh
duy nht bng cch s dng hng (constant) BaseColumns._ID.
Bn c th thc thi truy vn SQLite nh s dng phng thc SQLiteDatabase.
query(). Phng thc ny c th nhn nhiu tham s truy vn khc nhau, chng
hn nh bng truy vn, php chiu (projection), php chn (selection), ct (column),
nhm (grouping), i vi nhng truy vn phc tp, chng hn nh truy vn cn nh
danh ct, bn nn s dng SQLiteQueryBuilder, v trnh ny cung cp mt s
phng thc thun tin xy dng truy vn.
Mi truy vn SQLite s tr v mt con tr (cursor) tr ti ton b hng do truy vn tm
c. Con tr lun lun l mt c ch gip bn c th duyt kt qu t mt truy vn c
s d liu cng nh c d liu trn hng v ct.
xem xt ng dng mu minh ha cho cch s dng c s d liu SQLite trong
Android, mi bn tham kho ng dng Note Pad v Searchable Dictionary (T in c
th tra cu c).

169

Lp trnh Android c bn

G li c s d liu
Android SDK bao gm cng c c s d liu sqlite3 cho php bn tm duyt ni
dung bng, chy lnh SQL v thc hin mt s chc nng hu ch khc trn c s
d liu SQLite. Xem mc Examining sqlite3 databases from a remote shell (Tm
hiu v c s d liu sqlite3 t chng trnh dng lnh xa) hc thm v cch
chy cng c ny.

S dng kt ni mng
Bn c th s dng mng (khi mng sn sng) lu tr v truy xut d liu trn
cc dch v da trn Web ca ring bn. thao tc trn mng, s dng cc lp trong
cc gi sau y:

java.net.*

android.net.*

10. Content Provider


Content provider qun l vic truy cp tp d liu c cu trc. Content provider ng gi
d liu, ng thi cung cp c ch quy nh vic bo mt d liu. Content provider
l giao din chun gip kt ni d liu trong mt tin trnh vi m chy trong tin trnh
khc.
Nu mun truy cp d liu trong content provider, bn s dng i tng ContentResolver
trong Context (ng cnh) ca ng dng kt ni content provider nh mt client. i
tng ContentResolver trao i vi i tng provider, mt th hin ca lp thc thi
lp ContentProvider. i tng provider ny nhn d liu yu cu t client, thc hin
cc hot ng c yu cu v tr v kt qu.
Nu khng c nh chia s d liu vi cc ng dng khc, bn khng nht thit phi
pht trin provider ring. Tuy nhin, nu mun cung cp gi cho khch hng tm
kim trong ng dng, bn bt buc phi to content provider. Hoc, nu mun sao
chp v dn file hoc d liu phc tp t ng dng ca mnh sang ng dng khc, bn
cng cn ti provider ny.
Bn thn h iu hnh Android bao gm cc content provider qun l d liu nh
nhc, video, hnh nh v thng tin lin lc c nhn. Bn c th thy mt s provider ny
c lit k trong ti liu tham kho ca gi android.provider. Bt c ng dng
Android no cng c th truy cp vo cc content provider ny.

10.1 C bn v content provider


Content provider qun l vic truy cp ti kho cha d liu trung tm. Content provider
l mt phn ca ng dng Android, thng cung cp giao din ngi dng ring
lm vic vi d liu. Tuy nhin, d nh ban u l content provider s c ng dng
khc dng, ng dng ny truy cp vo provider bng cch s dng mt i tng client
provider. Content provider v i tng client cung cp ng thi h tr mt giao din

170

Lp trnh Android c bn
chun, nht qun cho d liu cng nh qu trnh giao tip ca cc tin trnh bn trong
(inter-process) v bo mt vic truy cp d liu.
Mc ny s gii thiu nhng khi nim c bn sau y:

Content Provider hot ng nh th no.

API bn dng truy xut d liu trong content provider.

API bn dng chn, cp nht hoc xa d liu trong content provider.

Cc tnh nng API khc khin vic thao tc vi content provider tr nn d dng hn.

Tng quan
Content provider biu din d liu vi cc ng dng bn ngoi di dng mt hoc
mt vi bng tng t vi bng thng thy trong c s d liu quan h (relational
database - RDB). Mi hng i din cho mt th hin ca mt kiu d liu bt k m
content provider thu thp; mi ct trong hng th hin mt phn d liu thu thp c
ca th hin.
V d, mt content provider c sn trong nn tng Android l user dictionary (t in
ngi dng), ni lu tr cch vit ca mt s t c bit m ngi dng mun lu li.
Bng 1 gii thiu cch biu din d liu trong content provider ny.
Bng 1: V d v bng t in ca ngi dng
word
Mapreduce
Precompiler
Applet
Const
Int

app id
user1
user14
user2
user1
user5

frequency
100
200
225
255
100

locale
en_US
fr_FR
fr_CA
pt_BR
en_UK

_ID
1
2
3
4
5

Trong Bng 1, mi hng tng ng vi mt th hin ca mt t khng c trong t in


chun. Mi ct i din cho mt d liu no y ca t, chng hn nh m a im
(locale) - ni t xut hin ln u tin . Tiu ct l tn ct c lu trong content
provider. Mun tham chiu ti m a im trong mt hng, bn c th ch ti ct locale
ca hng . Vi content provider ny, ct _ID ng vai tr l kha chnh (primary
key) c content provider qun l t ng.
Ghi ch: Content provider khng yu cu phi c trng kha chnh, content
provider cng khng yu cu phi s dng _ID lm tn ct ca trng kha chnh
nu nh c mt trng khc. Tuy nhin, nu mun rng buc (bind) d liu ca
mt content provider vi mt ListView, bn nht nh phi c tn ct l _ID. Yu cu
ny c gii thch c th trong mc Hin th kt qu ca truy vn bn di.

171

Lp trnh Android c bn

Truy cp content provider


Mt ng dng c th truy cp vo d liu ca content provider bng i tng client ContentResolver. i tng ny c nhng phng thc c tn ging y ht
i tng trong i tng provider, mt th hin ca mt trong nhng lp con ca
ContentProvider. Cc phng thc ca ContentResolver cung cp cc chc
nng CRUD c bn ca b nh lu tr lu di; trong , CRUD bao gm: Create
(to), retrieve (truy xut), update (cp nht) v delete (xa).
i tng ContentResolver trong tin trnh ca ng dng v i tng
ContentProvider trong ng dng c nhim v qun l provider, t ng iu khin
vic giao tip ca tin trnh bn trong. ContentProvider cng hot ng ging nh
mt tng tru tng (abstraction layer) nm gia kho cha d liu v vic hin th d
liu ra bn ngoi di dng bng.
Ghi ch: truy cp mt provider, ng dng thng phi yu cu cc quyn c th
trong file k khai ca n. Hng dn chi tit cho vn ny c trnh by trong mc
Quyn i vi content provider bn di.
V d, ly ra mt danh sch cc t (word) v m a im (locale) ca chng t
content provider user dictionary, bn gi phng thc ContentResolver.query().
Phng thc query() gi phng thc ContentProvider.query() c
content provider user dictionary nh ngha. Cc dng m sau minh ha li gi ca
phng thc ContentResolver.query():
// Truy vn user dictionary v tr v kt qu
mCursor = getContentResolver().query(

UserDictionary.Words.CONTENT_URI, // URI ca bng lu cc t

mSelectionClause // iu kin chn

mProjection, // Cc ct trong hng kt qu


mSelectionArgs, // iu kin chn

mSortOrder); // Trnh t sp xp ca cc hng kt qu tr v

Bng 2 gii thch cc i s ca lnh query(Uri, projection, selection, selectionArgs,


sortOrder) tng ng vi cu lnh SELECT trong SQL:

172

Lp trnh Android c bn
Bng 2: So snh lnh Query() vi truy vn trong SQL.
i s ca lnh
query()

T kha/tham s ca cu lnh
SELECT

Ghi ch

Uri

FROMten_bang

Projection

cot,cot,cot,...

Uri tng ng vi bng


trong content provider, c tn
l ten_bang.

Selection

WHEREcot=gia_tri

selectionArgs

Khng c tng ng. Tham


s la chn thay th ? trong
mnh select.

sortOrder

ORDER BY cot,cot,...

projection l mt mng
cc ct nn c bao gm
trong mi hng kt qu
truy vn.

selection xc nh iu
kin chn hng.

sortOrderxc nh th t
cc hng xut hin trong con
tr (cursor) c tr v.

Content URI
Content URI l nh danh ti nguyn thng nht (uniform resource identifier - URI) xc
nh d liu trong content provider. Content URI bao gm chui nh danh (tn tng
trng cho ton b provider) v mt ng dn (mt tn tr ti mt bng). Khi bn gi
mt phng thc client truy cp vo bng trong content provider, content URI ca
bng chnh l mt trong cc i s.
cc dng m trn, hng CONTENT_URI cha content URI ca bng words trong
t user dictionary. i tng ContentResolver phn tch ly ra chui nh danh
(authority) ca URI, ng thi s dng chui ny phn gii content provider bng
cch so snh chui nh danh vi bng ca h thng cha nhng content provider
khai bo. Sau , ContentResolver c th gi cc i s ca truy vn n ng
provider.

ContentProvider s dng phn ng dn (path) ca content URI chn bng

cn truy cp. Mi content provider thng c mt ng dn cho mi bng m n


qun l.
Trong cc dng m trn, mt URI y ca bng words l:
content://user_dictionary/words

173

Lp trnh Android c bn
Trong , chui user_dictionary l chui nh danh ca provider, cn chui words
l ng dn ca bng. Chui content:// l scheme (thng tin cung cp cho
Content Provider) lun tn ti, xc nh y l mt content URI.
Nhiu content provider cho php bn truy cp vo mt hng n ca mt bng bng
cch gn thm mt gi tr ID vo cui URI. V d, truy xut mt hng c _ID l 4
trong user dictionary, bn c th s dng content URI sau:
Uri singleUri =ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

Thng thng, bn s dng gi tr id khi truy xut mt tp gm nhiu hng, sau


mun cp nht hoc xa mt trong nhng hng .
Ghi ch: Lp Uri v Uri.Builder cha nhiu phng thc thut tin cho vic
khi to ng cc i tng Uri t chui mt cch d dng. ContentUri cha
cc phng thc c th d dng gn thm gi tr id vo URI. on m trn s dng
phng thc withAppendedId() gn mt id vo content URI ca content
provider user dictionary.

Truy xut d liu t content provider


Mc ny miu t cch truy xut d liu t content provider, ly content provider user
dictionary lm v d.
r rng, cc on m nh trong mc ny u gi phng thc ContentResolver.
query() trong lung UI, hay lung giao din ngi dng (UI thread). Tuy
nhin, khi vit m chng trnh thc, bn nn thc hin truy xut khng ng b
trong mt lung ring. lm iu ny, bn s dng lp CursorLoader, s c
miu t chi tit trong ti liu hng dn Loaders. Mt khc, cc dng m y ch
l nhng on m nh; chng khng th hin mt ng dng hon chnh.
truy xut d liu t mt content provider, bn thc hin theo cc bc c bn sau:
1. Yu cu quyn truy cp c i vi content provider.
2. nh ngha on m gi truy vn n content provider.

Yu cu quyn truy cp c
truy xut d liu trong mt trnh cung cp, ng dng ca bn cn quyn truy cp
c (read) cho content provider. Bn khng th yu cu quyn ny trong lc chy
chng trnh; thay vo , bn phi ch ra l cn quyn ny trong file k khai bng cch
s dng phn t <uses-permission> v tn chnh xc ca quyn c nh ngha
trong content provider. Khi s dng phn t ny trong file k khai, c ngha l bn ang
yu cu quyn ny cho ng dng ca mnh. Nu ngi dng ci ng dng ca bn,
ngm hiu l h ng vi yu cu ny.
tm ng tn ca quyn truy cp c cho content provider bn dng cng nh
cc tn quyn truy cp khc, hy tm trong ti liu hng dn s dng ca content
provider .

174

Lp trnh Android c bn
Cc vai tr (role) ca quyn truy cp content provider c miu t chi tit trong mc
Quyn i vi content provider bn di.
Content provider user dictionary nh ngha quyn android.permission.READ_
USER_DICTIONARY trong file k khai; do , nu mun c content provider ny, ng
dng phi yu cu vi tn quyn nh vy.

Xy dng truy vn
Bc tip theo trong vic truy xut d liu t mt content provider l xy dng truy
vn. on m nh u tin nh ngha mt s bin dng truy cp content provider
user dictionary:
// Mt mng chui nh ngha cc ct s c tr v cho mi hng (hay
// Projection)
String[] mProjection =
{


UserDictionary.Words._ID, // Hng thuc lp Contract tng
// ng vi tn ct _ID

UserDictionary.Words.WORD, // Hng thuc lp Contract vi tn
// ct word

};

UserDictionary.Words.LOCALE // Hng thuc lp Contract tng ng


// vi tn ct locale

// nh ngha chui cha mnh chn


String mSelectionClause =null;

// Khi to mt mng cha cc i s chn


String[] mSelectionArgs ={};

on m nh tip theo gii thiu cch s dng hm ContentResolver.query(),


dng content provider user dictionary lm v d. Mt truy vn client ti content provider
tng t mt truy vn SQL, truy vn ny cng cha mt tp ct tr v, mt tp iu
kin chn v th t sp xp.
Mt tp ct m truy vn tr v c gi l mt php chiu (projection) (tng ng vi
bin mProjection).
Biu thc xc nh cc hng truy vn c chia lm mnh chn v i s chn
(selection argument).
Mnh chn l s kt hp ca biu thc Boolean v biu thc lgc (biu thc lgc
c gi tr true/false), tn ct v gi tr (tng ng vi bin mSelectionClause). Liu
c th xc nh tham s c th thay th c khng? Thay v mt gi tr, phng thc
query truy xut gi tr t mng i s chn (tng ng vi bin mSelectionArgs).
Trong on m nh tip theo, nu ngi dng khng nhp vo mt t, mnh
chn c thit lp gi tr l null , truy vn s tr v tt c cc t trong
content provider. Nu ngi dng nhp vo mt t, mnh chn c t l

175

Lp trnh Android c bn
UserDictionary.Words.WORD + = ? v phn t u tin ca mng
i s chn c thit lp bng t m ngi dng nhp vo.
/*

* Lnh sau y nh ngha mt mng chui gm mt phn t cha i


s chn.
*/

String[] mSelectionArgs ={};


// Ly mt t trong giao din ngi dng

mSearchString = mSearchWord.getText().toString();
// Hy nh chn thm m vo y kim tra u vo khng hp l v
// m c (malicious) lm hng chng trnh.
// Nu t do ngi dng nhp vo l chui rng, ly ra ton b t in
if(TextUtils.isEmpty(mSearchString)){


// Vic thit lp mnh chn l null s tr v ton b t trong
// t in

mSelectionClause = null;
mSelectionArgs[0]= ;

} else {

// Khi to mt mnh chn ph hp vi t m ngi dng nhp vo.

mSelectionClause =UserDictionary.Words.WORD + = ?;

// Gn chui ngi dng nhp vo cho i s chn.

mSelectionArgs[0]= mSearchString;

}
// Thc hin truy vn trn bng d liu v tr v mt i tng
// Cursor (con tr)
mCursor = getContentResolver().query(

UserDictionary.Words.CONTENT_URI, // content URI ca bng words

mSelectionClause // Hoc null, hoc l t m ngi dng nhp vo

mProjection, // Cc ct tr v trong tng hng kt qu

mSelectionArgs, // Hoc rng, hoc l chui ngi dng nhp vo

mSortOrder); // Th t sp xp ca cc hng c tr v

// Mt s content provider tr v null nu c li xy ra, mt // s


khc s nm (throw) ra mt ngoi l (exception)
if(null== mCursor){
/*

* Chn thm m vo y x l li. Hy nh, ng s dng con


* tr! C th bn mun gi phng thc android.util.Log.e()
* ghi li li xy ra.

176

Lp trnh Android c bn
*/

// Nu con tr rng, content provider khng tm c t ph hp


} else if (mCursor.getCount()<1){
/*
*
*
*
*

Chn thm m vo y thng bo vi ngi dng rng vic tm


kim khng thnh cng. Vic ny khng nht thit l do li. C
th y, bn mun cung cp cho ngi dng ty chn chn
thm hng mi, hoc nhp li t mun tm.

*/

} else {

// Chn thm m vo y thc hin mt s thao tc vi kt qu tr v

Truy vn trn tng t cu lnh SQL sau:


SELECT _ID, word, locale FROM words WHERE word = <d liu ngi dng
nhp> ORDER BY word ASC;

Cu lnh SQL ny s dng trc tip tn ct thc th thay v cc hng nh ngha trong
lp contract.

Bo v ng dng khi vic nhp m c


Nu d liu c content provider qun l l mt c s d liu SQL, cha c nhng
d liu khng ng tin bn ngoi a vo cu lnh SQL th, c th dn n tnh trng
lm hng c s d liu.
Hy xem mnh chn di y:
// To mt mnh chn bng cch ghp d liu ngi dng nhp vo
// vi tn ct
String mSelectionClause = var = + mUserInput;

Nu thc hin iu ny, v hnh trung bn ang cho php ngi dng ghp m SQL
c vo cu lnh SQL. V d, ngi dng c th nhp nothing; DROP TABLE *; cho
mUserInput, kt qu c mnh chn var = nothing; DROP TABLE *;. Nu mnh
chn ny c coi nh mt cu lnh SQL, n c th khin content provider xa ton
b bng trong c s d liu do SQLite qun l, tr phi content provider c thit lp
bt cc cu lnh SQL gy hi (SQL injection).
trnh vn ny, s dng mnh chn c dng du ? lm tham s thay th v mt
mng ring bao gm cc i s chn. Khi thc hin iu ny, d liu ngi dng nhp
vo c gn trc tip vi truy vn thay v c bin dch di dng cu lnh SQL.
Do khng c x l di dng cu lnh SQL, nn d liu ngi dng nhp khng th
a m SQL c vo. Thay v ghp trc tip d liu ngi dng nhp vo, c th s
dng mnh chn sau:

177

Lp trnh Android c bn
// To mnh chn vi i s c th thay th
String mSelectionClause = var = ?;

To mt mng i s chn nh sau:


// nh ngha mt mng cha cc i s chn
String[] selectionArgs ={};

a mt gi tr vo mng cc i s chn nh sau:


// Thit lp i s chn l d liu ngi dng nhp vo
selectionArgs[0]= mUserInput;

Mt mnh chn s dng du ? lm tham s c th thay th v mt mng cc i s


chn l cch c a dng hn khi xy dng mt php chn, ngay c vi trng hp
content provider khng da trn c s d liu SQL.

Hin th kt qu truy vn
Mt phng thc client ContentResolver.query() lun tr v i tng Cursor
cha cc hng ph hp vi iu kin chn ca truy vn, v mi hng li bao gm cc
ct do i s projection ch nh. Mt i tng Cursor cung cp kh nng truy cp
ngu nhin ti hng v ct n cha. Bng cch s dng cc phng thc ca Cursor,
bn c th duyt qua cc hng kt qu, xc nh kiu d liu ca tng ct, ly d liu
ra khi mt ct, ng thi kim tra cc thuc tnh khc ca kt qu. Mt s Cursor
c ci t t ng cp nht i tng khi d liu ca content provider thay i,
hoc s dng phng thc trigger bn trong mt i tng gim st (observer) mi khi
Cursor thay i, hoc c hai.
Ghi ch: Mt s content provider c th hn ch vic truy cp ti cc ct da trn
c tnh t nhin ca i tng thc hin truy vn. V d, Provider Contacts gii hn
vic truy cp trn mt s ct ng b cc adapter; do , provider ny s khng
tr v nhng ct b gii hn cho mt activity hay service.
Nu khng c hng no ph hp vi iu kin chn, content provider s tr v mt i
tng Cursor vi phng thc Cursor.getCount() cho kt qu l 0 (mt con tr
rng).
Nu xy ra li ni b, kt qu ca truy vn s ty thuc vo tng provider c th: C th
tr v null, hoc nm ra mt ngoi l (Exception).
V i tng Cursor l mt danh sch cc hng, nn cch tt nht hin th
ni dung ca Cursor l lin kt n vi mt ListView thng qua mt i tng
SimpleCursorAdapter.
on m nh di y l phn tip theo ca on m nh trc. Phn ny s to mt
i tng SimpleCursorAdapter cha Cursor l kt qu ca truy vn, ng thi
t i tng SimpleCursorAdapter ny lm adapter ca ListView:

178

Lp trnh Android c bn
// nh ngha mt danh sch ct truy xut d liu t Cursor v a
// vo mt hng u ra
String[] mWordListColumns =
{

};

UserDictionary.Words.WORD, // Hng ca lp contract cha tn ct word


UserDictionary.Words.LOCALE // Hng ca lp contract cha tn ct locale

// nh ngha mt danh sch gm cc View ID s nhn cc ct ca mi hng

int[] mWordListItems ={ R.id.dictWord, R.id.locale};


// To mt i tng SimpleCursorAdapter mi
mCursorAdapter =newSimpleCursorAdapter(

getApplicationContext(), // i tng Context ca ng dng

mCursor, // Kt qu ca truy vn

R.layout.wordlistrow, // Cch biu din trong XML cho mi hng ListView


mWordListColumns, // Mt mng chui cha cc tn ct ca con tr


mWordListItems, // Mt mng s nguyn cha cc ID hin th trong
// layout hng

0); // C (thng khng dng ti)

// Gn adapter cho ListView

mWordList.setAdapter(mCursorAdapter);

Ghi ch: a Cursor v dng ListView, con tr phi cha mt ct c tn


l _ID. Do , truy vn trn mi ly ra ct _ID ca bng words, ngay c khi
ListView khng hin th ct ny. Hn ch ny cng l gii ti sao hu ht content
provider u c ct _ID trong mi bng.

Ly d liu t kt qu truy vn
Thay v ch hin th kt qu truy vn, bn c th s dng kt qu ny cho cc mc ch
khc. V d, bn c th truy xut spelling (cch vit t/nh vn) trong user dictionary,
sau tm kim chng trong content provider khc. thc hin iu ny, bn duyt
qua cc hng trong Cursor:
// Xc nh ch s ct cho ct c tn word

int index = mCursor.getColumnIndex(UserDictionary.Words.WORD);


/*

* Ch tin hnh duyt khi con tr tr v hp l. Content provider user


* dictionary tr v null nu c li bn trong xy ra. Cc trnh cung
* cp ni dung khc c th s nm ra mt ngoi l thay v tr v null.
*/

if(mCursor != null){
/*

* Di chuyn ti hng tip theo trong con tr. Trc ln di chuyn

179

Lp trnh Android c bn
* u tin, con tr ch hng l -1, v nu c gng truy xut d
* liu ti v tr ny, bn s nhn c mt ngoi l.

*/

while(mCursor.moveToNext()){

// Ly gi tr t ct.

// Chn thm m vo y thao tc vi t truy vn c.

newWord = mCursor.getString(index);

...

// kt thc vng lp while

} else {

// Chn thm m vo y bo co li khi con tr null hoc


// content provider nm ra mt ngoi l.

i tng Cursor thc thi cha mt s phng thc get dng cho vi kiu truy xut
d liu khc nhau. V d, on m nh trc s dng getString(). Chng ta cng
c th dng phng thc getType() tr v gi tr cho bit kiu d liu ca ct.

Quyn i vi content provider


Mt ng dng ca content provider c th quy nh quyn m nhng ng dng khc
phi ng k truy cp d liu ca content provider ny. Cc quyn ny m bo
ngi dng bit c mt ng dng s truy cp vo d liu no. Da trn yu cu ca
tng content provider, cc ng dng khc yu cu quyn m chng cn theo quy nh
truy cp vo provider. Ngi dng cui (end user) s thy cc quyn yu cu ny
khi ci t ng dng.
Nu ng dng ca content provider khng xc nh bt c quyn no, ng dng khc
s khng c quyn truy cp vo d liu ca provider ny. Tuy nhin, cc thnh phn
trong ng dng ca content provider lun c quyn c v ghi, m khng phi ng
k nhng quyn c xc nh ny.
Nh lu t trc, content provider user dictionary yu cu quyn android.
permission.READ_USER_DICTIONARY truy xut d liu trong provider ny.
Content provider user dictionary cng nh ngha quyn android.permisstion.
WRITE_USER_DICTIONARY ring cho vic chn, cp nht hoc xa d liu.
nhn c cc quyn cn thit khi truy cp content provider, ng dng yu cu
quyn ny bng phn t <uses-permission> trong file k khai ca ng dng . Khi
trnh qun l gi ng dng Android (Android Package Manager) ci t ng dng,
ngi dng phi chp thun tt c quyn m ng dng yu cu. Nu ngi dng chp
thun tt c nhng quyn ny, trnh qun l gi ng dng mi tip tc ci t; nu
ngi dng khng ng , trnh qun l gi ng dng s hy qu trnh ci t.

180

Lp trnh Android c bn
Phn t <uses-permission> di y yu cu quyn c i vi content provider user
dictionary:
<uses-permissionandroid:name=android.permission.READ_USER_DICTIONARY>

Tc dng ca quyn i vi vic truy cp content provider c gii thch chi tit hn
trong ti liu hng dn Security and Permissions (Quyn v bo mt).

Chn, cp nht v xa d liu


Tng t nh cch truy xut d liu trong provider, bn cng c th s dng s tng
tc gia mt provider client v ContentProvider ca provider chnh sa d liu.
Bn gi mt phng thc ca ContentResolver vi cc i s truyn tng ng
vi phng thc ca ContentProvider. Content provider v provider client s t
ng x l vic bo mt cng nh giao tip bn trong tin trnh.

Chn d liu
chn d liu vo mt content provider, bn gi phng thc ContentResolver.
insert(). Phng thc ny s chn mt hng mi vo content provider v tr v
mt content URI (nh danh ti nguyn thng nht ca ni dung) ca hng . on m
nh di y minh ha cch chn mt hng mi vo content provider user dictionary:
// nh ngha mt i tng Uri mi s nhn kt qu tr v khi chn
// d liu
Uri mNewUri;
...
// nh ngha mt i tng cha gi tr mi s c chn thm
ContentValues mNewValues = new ContentValues();
/*

* Thit lp gi tr cho tng ct v chn t vo t in. i s ca


* phng thc put l tn ct v gi tr
*/

mNewValues.put(UserDictionary.Words.APP_ID,example.user);
mNewValues.put(UserDictionary.Words.LOCALE,en_US);
mNewValues.put(UserDictionary.Words.WORD,insert);

mNewValues.put(UserDictionary.Words.FREQUENCY,100);
mNewUri = getContentResolver().insert(

UserDictionary.Word.CONTENT_URI, // content URI ca user dictionary

mNewValues // cc gi tr chn
);

D liu ca hng mi c a vo mt i tng ContentValues, i tng ny


c dng tng t nh mt con tr mt hng. Cc ct trong i tng ny khng nht

181

Lp trnh Android c bn
thit phi cng kiu d liu; nu khng mun xc nh gi tr no, bn c th thit lp
ct l null bng cch s dng phng thc ContentValues.putNull().
on m nh trn khng thm ct _ID, bi ct ny c duy tr t ng. Content
provider gn mt gi tr ID duy nht cho mi hng mi c thm vo. Cc content
provider thng dng gi tr ny lm kha chnh ca bng.
Content URI tr v mt URI mi xc nh hng mi thm vo, di dng sau:
content://user_dictionary/words/<id_value>

Trong , <id_value> l ni dung ct _ID ca hng mi. a s content provider u


c th t ng nhn din dng content URI ny, sau thc hin cc thao tc c
yu cu trn hng c th .
ly gi tr ca ct _ID t Uri c tr v, gi phng thc ContentUris.
parseId().

Cp nht d liu
cp nht mt hng, bn s dng i tng ContentValues() vi cc gi tr cp nht
nh lm vi thao tc chn, v iu kin chn ging nh khi bn thc hin mt truy
vn. Phng thc client nn dng l ContentResolver.update(). Bn ch cn thm cc
gi tr vo i tng ContentValues cho nhng ct cn cp nht. Nu mun xa ni
dung mt ct, hy thit lp gi tr l null.
on m nh di y s thay i tt c cc hng c ct locale l en thnh locale l
null. Gi tr tr v l s lng hng c cp nht:
// To mt i tng cha cc gi tr c cp nht
ContentValues mUpdateValues = new ContentValues();

// Xc nh iu kin chn cho nhng hng mun cp nht

String mSelectionClause = UserDictionary.Words.LOCALE + LIKE ?;


String[] mSelectionArgs ={en_%};

// To mt bin cha s lng hng c cp nht


int mRowsUpdated =0;
...
/*

* Thit lp gi tr c cp nht v cp nht nhng t c chn.


*/

mUpdateValues.putNull(UserDictionary.Words.LOCALE);
mRowsUpdated = getContentResolver().update(

UserDictionary.Words.CONTENT_URI, // content URI ca user dictionary

mUpdateValues // Cc ct cp nht
mSelectionClause // ct c chn

182

Lp trnh Android c bn
mSelectionArgs // gi tr so snh
);

Bn cng nn x l d liu ngi dng nhp vo trc khi gi phng thc


ContentResolver.update(). tm hiu thm v cch x l, tham kho mc
Bo v ng dng khi vic nhp m c bn trn.

Xa d liu
Xa hng tng t nh vic truy xut hng d liu: Bn xc nh iu kin chn cho
cc hng mun xa v phng thc client s tr v s lng hng xa. on m
nh di y s xa nhng hng c ct app id bng user. Phng thc xa tr v
s lng hng c xa.
// Xc nh iu kin chn cho cc hng mun xa

String mSelectionClause = UserDictionary.Words.APP_ID + LIKE ?;


String[] mSelectionArgs ={user};

// To mt bin lu s lng hng c xa


int mRowsDeleted =0;
...
// Xa cc t ph hp vi iu kin chn

mRowsDeleted = getContentResolver().delete(

UserDictionary.Words.CONTENT_URI, // content URI ca user dictionary

mSelectionArgs // gi tr so snh


);

mSelectionClause // ct chn

Bn cng nn x l trc d liu ngi dng nhp vo khi gi phng thc


ContentResolver.delete(). tm hiu thm v cch x l, tham kho mc
Bo v ng dng khi vic nhp m c bn trn.

Kiu d liu ca provider


Content provider c th lu nhiu kiu d liu khc nhau. Content provider user dictionary ch x l d liu dng vn bn, nhng content provider c th lu cc nh dng
di y:

integer.

long integer (long).

floating point.

long floating point (double).

Mt kiu d liu khc m content provider thng s dng l i tng nh phn ln


(Binary Large Object - BLOB), c ci t nh mt mng byte 64 KB. Bn c th bit
nhng kiu d liu c sn bng cch xem cc phng thc get ca lp Cursor.

183

Lp trnh Android c bn
Kiu d liu ca mi ct trong content provider thng c lit k trong ti liu hng
dn ca trnh . Cc kiu d liu ca content provider user dictionary c lit k
trong ti liu tham kho v lp contract UserDictionary.Words ca trnh ny (cc
lp contract s c gii thiu trong mc Lp contract bn di). Bn cng c th
xc nh kiu d liu bng cch gi phng thc Cursor.getType().
Content provider cng lu gi thng tin v kiu d liu MIME cho mi content URI m
trnh nh ngha. Bn c th s dng thng tin v kiu MIME khm ph xem liu
ng dng ca bn c th x l d liu m content provider dng hay khng, hoc
chn mt kiu x l da trn kiu MIME. Bn thng cn kiu MIME khi lm vic vi
content provider cha cu trc hoc file d liu phc tp. V d, bng ContactsContract.
Data trong Content Provider Contacts s dng kiu MIME dn nhn kiu d liu
lin lc c lu mi hng. ly kiu MIME tng ng vi tng content URI, gi
phng thc ContentResolver.getType().
Mc Ti liu tham kho v kiu MIME bn di s gii thiu c php ca c kiu
MIME chun ln kiu MIME ty chnh.

Cc dng truy cp content provider khc


Ba cch truy cp content provider quan trng khc rt cn thit cho vic pht trin ng
dng l:

Truy cp hng lot (batch access): Bn c th to mt nhm cc li gi truy cp vi


nhng phng thc nm trong lp ContentProviderOperation, sau
p dng nhm ny vo chng trnh bng phng thc ContentResolver.
applyBatch().

Truy vn khng ng b: Bn nn thc hin truy vn trong mt lung ring.


Mt cch thc hin iu ny nh s dng i tng CursorLoader. Cc
v d trong ti liu hng dn Loaders s minh ha cch lm ny.

Truy cp d liu thng qua intent: Mc d khng th gi trc tip mt intent ti


content provider, song bn c th gi intent ti ng dng ca content provider
- y chnh l cng c chnh sa d liu tt nht trong content provider.

Hai cch truy cp v chnh sa hng lot v thng qua intent s c miu t trong
cc mc di y.

Truy cp hng lot


Truy cp content provider hng lot l mt cch hu dng chn mt s lng hng
ln, hoc chn hng trong nhiu bng cng s dng li gi phng thc nh nhau,
hoc thng l thc hin mt chui thao tc ging nh mt giao dch (mt thao tc
n l).
truy cp vo content provider theo ch hng lot, bn to mt mng cc i
tng ContentProviderOperation, sau a chng vo content provider bng
phng thc ContentResolver.applyBatch(). Bn truyn cho phng thc
ny chui nh danh ca chnh provider, thay v mt content URI c th. iu ny cho
php mi i tng ContentProviderOperation trong mng lm vic trn cc

184

Lp trnh Android c bn
bng khc nhau. Mt li gi ti phng thc ContentResolver.applyBatch()
tr v mt mng cha cc kt qu.
Phn gii thiu v lp contract ContactsContract.RawContacts cha mt on
m nh minh ha cho vic chn hng lot. ng dng mu Contact Manager cha mt
v d v vic truy cp hng lot trong file ngun ContactAdder.java.

Hin th d liu s dng ng dng tr gip


Nu ng dng ca bn c quyn truy cp, bn vn mun s dng mt intent hin
th d liu trong ng dng khc. V d, ng dng Calendar (lch ngy thng) cho php
nhn intent ACTION_VIEW hin th mt ngy thng hoc mt s kin c th. iu ny
cho php bn hin th thng tin v lch m khng phi to giao din ngi dng ring.
tm hiu thm v tnh nng ny, xem ti liu hng dn Calendar Provider(Provider Calendar).
ng dng c gi intent ti khng cn phi l ng dng c lin kt vi content
provider. V d, bn c th truy xut mt lin lc t Content Provider Contacts, sau
gi mt intent ACTION_VIEW cha content URI ca hnh nh lin lc ti mt trnh hin
th hnh nh (image viewer).

Truy cp d liu thng qua intent


Intent c th gip bn gin tip truy cp ti content provider. Bn cho php ngi
dng truy cp vo d liu ca content provider ngay c khi ng dng ca bn khng
c quyn ny, hoc bng cch ly intent kt qu tr cho mt ng dng c quyn, hoc
bng vic kch hot mt ng dng c quyn truy cp v cho php ngi dng lm vic
vi ng dng .

Thc hin truy cp bng quyn tm


Ngay c khi khng c quyn truy cp d liu trong content provider, bn vn c th lm
iu ny bng cch gi mt intent ti ng dng c quyn v nhn v intent kt qu
cha quyn URI. y l cc quyn i vi mt content URI nht nh s tn ti cho
n khi activity nhn intent ny kt thc. ng dng c quyn c nh cp quyn tm
bng cch thit lp mt c (flag) trong intent kt qu:

Quyn c: FLAG_GRANT_READ_URI_PERMISSION

Quyn ghi: FLAG_GRANT_WRITE_URI_PERMISSION


Ghi ch: Cc c ny khng cp quyn c v ghi chung ti content provider c chui
nh danh nm trong content URI. Cc quyn truy cp ch c tc dng trn chnh URI
.

Content provider nh ngha cc quyn URI cho content URI trong file k khai ca
n, s dng thuc tnh android:grantUriPermission ca phn t <provider>,
c chc nng tng t nh phn t con <grant-uri-permission> ca phn
t <provider>. C ch quyn URI c gii thch chi tit hn ti ti liu hng
dn Security and Permissions (Quyn v bo mt), trong mc URI permissions
(Quyn URI).

185

Lp trnh Android c bn
V d, ngay c khi khng c quyn READ_CONTACTS, bn vn c th truy xut d liu
mt lin lc trong Content Provider Contacts. C th bn mun thc hin iu ny trong
mt ng dng gi li chc in t ti ngi bn mun lin lc trong ngy sinh nht ca
anh/c y. Thay v yu cu quyn READ_CONTACTS, c th truy cp vo tt c cc
lin lc ca ngi dng v ton b thng tin ca h, bn mun ngi dng qun l
nhng lin lc c ng dng ca bn dng. thc hin iu ny, bn s dng tin
trnh x l sau:
1. ng dng ca bn gi i mt intent cha action ACTION_PICK v
kiu MIME cha lin lc CONTENT_ITEM_TYPE, dng phng thc
startActivityForResult().
2. Do intent trn ph hp vi b lc intent ca activity la chn (selection) trong ng
dng ca ngi dng (People), nn activity ny s hin th mn hnh chnh.
3. Trong activity la chn (selection) ny, ngi dng chn mt lin lc cp
nht. Khi , activity la chn s gi phng thc setResult(resultcode,
intent) to mt intent tr v cho ng dng ca bn. Intent mi ny cha
content URI ca lin lc m ngi dng chn, ng thi thm c FLAG_GRANT_
READ_URI_PERMISSION. Cc c ny s gn quyn URI cho ng dng ca bn
c d liu trong lin lc c content URI tr ti. Sau , activity la chn s
gi phng thc finish() tr iu khin v cho ng dng ca bn.
4. Activity ca bn tr li mn hnh chnh, v h thng gi phng thc
onActivityResult() trong activity ca bn. Phng thc ny s nhn intent
kt qu c activity la chn to ra trong ng dng People.
5. Vi content URI trong intent kt qu, bn c th c d liu lin lc ca Content
Provider Contacts, ngay c khi khng yu cu quyn c lu di trong file k khai.
Sau , bn c th ly thng tin v sinh nht ca lin lc hoc a ch e-mail ca
ngi mun lin lc gi li chc in t.

S dng ng dng khc


Mt cch n gin ngi dng c th chnh sa trn d liu m bn khng c quyn
truy cp l kch hot mt ng dng c quyn v ngi dng thc hin chnh sa
trn .
V d, ng dng Calendar (lch ngy thng) cho php intent ACTION_INSERT, l intent
cho php bn kch hot giao din ngi dng chn ca ng dng ny. Bn c th
truyn d liu mi vo intent ny, y l ni ng dng dng giao din hin th. Do
vic lp li s kin c c php phc tp, nn cch tt hn chn s kin vo Provider
Calendar l kch hot ng dng Calendar vi mt ACTION_INSERT, sau ngi
dng chn s kin vo .

Lp contract
Lp contract nh ngha cc hng s gip ng dng lm vic vi content URI, tn ct,
action ca intent v nhng tnh nng khc ca content provider. Lp contract khng
t ng c trong content provider, nn nh pht trin content provider phi nh ngha
chng, sau x l nhng nh pht trin chng trnh khc c th s dng c.

186

Lp trnh Android c bn
Nhiu nh pht trin tch hp vi nn tng Android c cc lp contract tng ng trong
gi android.provider.
V d, content provider user dictionary c lp contract UserDictionary cha cc
hng content URI v tn ct. Content URI ca bng words c nh ngha trong
hng UserDictionary.Words.CONTENT_URI. Lp UserDictionary.Words
cng cha hng tn ct, c s dng trong on m nh minh ha di y. Chng
hn, chng ta c th nh ngha mt php chiu truy vn nh sau:
String[] mProjection =
{

UserDictionary.Words._ID,

UserDictionary.Words.WORD,

UserDictionary.Words.LOCALE
};

Mt lp contract khc l ContactsContract ca Provider Contacts. Ti liu


tham kho ca lp ny c bao gm v d v cc on m nh. Mt lp con ca n,
ContactsContract.Intents.Insert, l mt lp contract cha cc hng intent
v d liu intent.

Gii thiu thm v kiu MIME


Content provider c th tr v kiu a phng tin MIME chun, hay kiu MIME ty
chnh, hoc c hai.
Kiu MIME c nh dng nh sau:
kiu/kiu con
V d, kiu MIME thng c bit n l text/html c kiu l text v kiu con l
html. Nu Provider tr kiu ny v cho mt URI, c ngha l truy vn s dng URI ny
s tr v text cha cc th HTML.
Chui kiu MIME ty chnh, cn gi l kiu MIME c c trng ca nh cung cp
(vendor-specific MIME type), c thm nhiu gi tr kiu v kiu con phc tp.
Gi tr kiu thng l
vnd.android.cursor.dir
cho nhiu hng, hoc
vnd.android.cursor.item
cho mt hng n.
Kiu con ph thuc vo tng content provider c th. Cc content provider kiu con
trong Android thng c kiu con n gin. V d, khi ng dng Contacts to mt hng

187

Lp trnh Android c bn
mi cho mt s in thoi, ng dng ny s thit lp kiu MIME di y cho hng
mi :
vnd.android.cursor.item/phone_v2
kiu con, gi tr subtype ch n gin l phone_v2.
Cc nh pht trin content provider khc c th to nhng mu kiu con ca ring
h da vo chui nh danh v tn bng. V d, gi s mt content provider c bng
lu thng tin thi gian cc chuyn tu (train time). Chui nh danh ca trnh ny l
com.example.trains, ng thi cha cc bng Line1, Line2 v Line3.
p ng content URI
content://com.example.trains/Line1
cho bng Line1, content provider tr v kiu MIME
vnd.android.cursor.dir/vnd.example.line1
p ng content URI
content://com.example.trains/Line2/5
cho hng 5 trong bng Line2, content provider tr v kiu MIME
vnd.android.cursor.item/vnd.example.line2
Hu ht content provider u nh ngha hng cho cc kiu MIME m trnh ny s dng
trong lp contract. V d, lp contract ca Provider Contacts l ContactsContract.
RawContacts, nh ngha hng CONTENT_ITEM_TYPE cho kiu MIME ca mt
hng lin lc n.
Content URI ca hng n c miu t trong mc Content URIs.

10.2 To content provider


Content Provider qun l vic truy cp ti kho lu tr d liu trung tm. Bn c th
ci t content provider thnh mt hoc nhiu lp trong ng dng Android, cng
vi l cc thnh phn trong file k khai . Mt trong cc lp s thc thi lp con
ContentProvider, y chnh l giao din gia provider ca bn v cc ng dng
khc. Mc d content provider ng ngha vi vic qun l d liu nhng ng dng
khc c th truy cp c, nhng hin nhin l ng dng ca bn cng c cc chc
nng ngi dng truy vn v chnh sa d liu c content provider ca bn qun
l.
Phn ny s gii thiu cc bc c bn xy dng content provider v lit k cc
API cn dng.

188

Lp trnh Android c bn

Chun b trc khi xy dng content provider


Trc khi bt u xy dng content provider, bn thc hin cc bc sau:
1. Quyt nh xem liu bn c cn content provider hay khng. Bn cn xy
dng mt content provider nu mun cung cp mt hoc nhiu tnh nng sau:
oo

Mun cp d liu hoc file phc tp cho cc ng dng khc.

oo

Mun cho php ngi dng sao chp d liu phc tp t ng dng ca bn
vo nhng ng dng khc.

oo

Mun cung cp cc gi tm kim ty chnh bng cch s dng framework


tm kim.

Bn khng cn ti provider dng c s d liu SQLite, nu vic s dng ny


hon ton xy ra trong ng dng ca bn.
2. Nu vn cha xc nh c yu t trn, bn c th tm hiu thm phn 10.1:
C bn v content provider.
Tip theo, thc hin cc bc sau y xy dng content provider:
1. Thit k khng gian lu tr th (raw storage) cho d liu. Content provider cung
cp d liu di hai dng:
D liu di dng file
L nhng d liu thng c tn ti di dng, chng hn nh nh, m
thanh hoc video. Lu cc file ny vo khng gian lu tr ring trong ng dng
ca bn. phn hi yu cu file t ng dng khc, content provider bn xy
dng c th cung cp vic x l file ny.
D liu c cu trc (structured data)
L nhng d liu thng c a vo c s d liu, mng hoc cu trc
tng t. Lu tr d liu ny di dng tng ng vi cc bng cha hng
v ct. Mi hng i din cho mt thc th (entity), chng hn nh mt ngi
hoc mt mc trong bn kim k hng ha. Mi ct i din cho mt s d
liu ca thc th ny, chng hn nh tn ngi hoc gi hng ha. Cch ph
bin lu kiu d liu ny l trong mt c s d liu SQLite, nhng bn c
th s dng bt c kiu b nh lu di no. tm hiu thm v cc kiu b
nh m h thng Android cung cp, xem mc Thit k b nh lu tr d liu.
2. nh ngha bn ci t c th ca lp ContentProvider v cc phng thc
cn thit ca lp ny. Lp ContentProvider l giao din gia d liu ca bn
v cc phn cn li trong h thng Android. tm hiu thm v lp ny, tham kho
mc Ci t lp ContentProvider.
3. nh ngha chui nh danh (authority string) v content URI ca provider, cng vi
tn cc ct. Nu mun ng dng ca provider c th x l c intent, bn cng
phi nh ngha nhng action ca intent, d liu b sung v cc c. ng thi, bn
nh ngha nhng quyn s yu cu ng dng phi ng k khi mun truy cp d
liu. Bn nn tnh n vic nh ngha tt c cc gi tr ny di dng hng nm
trong mt llp contract ring bit; v sau, bn c th cung cp lp ny cho cc

189

Lp trnh Android c bn
nh pht trin ng dng khc. tm hiu thm v content URI, xem mc Thit
k content URI. tm hiu thm v intent, xem mc Intent v truy cp d liu.
4. Thm vo cc ty chn khc, chng hn nh d liu mu hoc phn ci t ca
lp AbstractThreadedSyncAdapter c th ng b d liu gia content
provider v d liu trn m my (cloud-based data).

Thit k b lu tr d liu
Content provider l giao din lu d liu di nh dng c cu trc. Trc khi to
giao din ny, bn phi quyt nh cch lu tr d liu. Bn c th lu d liu di
bt k dng no mnh mun, sau thit k giao din c v ghi d liu, nu cn.
Trong Android c sn mt s k thut lu tr d liu:

H thng Android cha b API ca c s d liu SQLite m cc content provider


ca chnh Android dng lu tr d liu dng bng. Lp SQLiteOpenHelper
gip bn to c s d liu, cn SQLiteDatabase l lp c s truy cp c
s d liu.
Hy nh rng, bn khng nht thit phi s dng c s d liu ci t kho lu
tr d liu. Mt content provider c th hin ra bn ngoi di dng tp bng,
tng t nh c s d liu quan h, nhng bng khng phi l yu cu bt buc
cho vic ci t bn trong ca provider.

lu tr d liu dng file, h iu hnh Android c nhiu API hng file (fileoriented data). tm hiu thm v vic lu tr file, tham kho mc Lu tr
d liu. Nu ang thit k content provider chia s d liu lin quan n a
phng tin (media-related data) nh m nhc hoc video, bn c th xy dng
content provider kt hp gia d liu bng v file.

lm vic vi d liu lu trn mng, s dng cc lp trong java.net v


android.net. Bn cng c th ng b d liu c lu trn mng vi b lu
tr d liu cc b (local data store) nh c s d liu, sau cung cp d liu
di dng bng hoc file. ng dng mu Sample Sync Adapter(V d v adapter
c chc nng ng b) minh ha kiu ng b ny.

Li khuyn khi thit k d liu


Sau y l mt s mo thit k cu trc d liu ca provider:

190

D liu bng phi lun c mt ct kha chnh l trng m content provider duy
tr nh mt gi tr s duy nht cho mi hng. Bn c th dng gi tr trn lin
kt hng ny vi cc hng c lin quan trong bng khc (ly trng ny lm kha
ngoi - foreign key). Mc d bn c th t mt tn bt k cho ct ny, nhng
s dng tn BaseColumns._ID l la chn tt nht, bi v vic lin kt kt qu
ca mt truy vn trn provider vi ListView yu cu mt trong cc ct c truy
xut phi c tn l _ID.

Lp trnh Android c bn

Nu bn mun cung cp nh bitmap hoc cc d liu dung lng ln khc ca


d liu dng file, hy lu d liu ny trong mt file, sau gin tip cung cp
chng thay v lu tr trc tip trong mt bng. Nu lm theo cch ny, bn cn
thng bo vi ngi dng content provider rng h phi s dng phng thc file
ContentResolver truy cp d liu.

S dng kiu d liu BLOB lu d liu c kch thc bin i hoc c cu trc
bin i. V d, bn c th s dng mt ct BLOB lu JSON structure (cu trc
JSON).
Bn cng c th s dng kiu d liu BLOB ci t bng schema-independent
(khng ph thuc cu trc). Trong kiu bng ny, bn xc nh mt ct kha chnh,
mt ct c kiu MIME v mt hoc nhiu ct thng kiu BLOB. ngha ca
d liu trong cc ct BLOB ph thuc vo gi tr trong ct kiu MIME. iu ny
cho php bn lu cc kiu hng khc nhau trong cng mt bng. Bng d liu
ContactsContract.Data ca Provider Contacts l mt v d v bng khng
ph thuc cu trc.

Thit k content URI


Content URI l mt URI xc nh d liu trong content provider. Content URI bao gm
chui nh danh (tn c tnh tng trng cho ton b provider) v mt ng dn
(tn tr ti bng hoc file). C th c hoc khng c phn id tr ti mt hng c th
trong bng. Mi phng thc truy cp d liu ca ContentProvider ly content
URI lm mt i s; vic ny cho php bn xc nh bng, hng hoc file truy cp.
Cc khi nim c bn ca content URI c gii thiu trong mc C bn v
content provider.

Thit k chui nh danh


Mi content provider thng c chui nh danh ring, ng vai tr nh tn s dng
ni b trong Android. trnh xung t vi cc content provider khc, bn nn s
dng quyn s hu min Internet (Internet domain ownership) (theo th t ngc li)
lm c s cho chui nh danh ca provider. V cch lm ny cng c p dng cho
tn gi Android, nn bn c th nh ngha chui nh danh ca provider lm phn m
rng ca tn gi cha trnh ny. V d, nu gi Android c tn l com.example.<tn
ng dng>, bn nn chui nh danh ca provider l com.example.<tn ng

dng>.provider.

Thit k cu trc ng dn
Cc nh pht trin thng to content URI t chui nh danh bng cch gn thm
ng dn tr ti nhng bng c th. Chng hn, nu c hai bng l table1 v table2,
bn kt hp vi chui nh danh trong v d trc to thnh content URI l com.
example.<tn ng dng>.provider/table1 v com.example.<tn
ng dng>.provider/table2. Cc ng dn ny khng hn ch trong mt
phn on (segment) n, khng bt buc phi l bng tng ng vi mi mc ca
ng dn.

191

Lp trnh Android c bn

X l cc ID ca content URI
Theo quy c, content provider cung cp truy cp ti mt hng n trong bng bng
cch chp nhn mt content URI vi mt gi tr ID tng ng cho mi hng nm cui
URI. Cng theo quy c, content provider i chiu gi tr ID vi ct _ID ca bng ,
ng thi thc hin truy cp c yu cu trn hng tng ng.
Cc quy c ny to iu kin thun li cho kiu mu thit k chung truy cp vo
content provider. ng dng thc hin truy vn trn provider v hin th Cursor kt
qu qua ListView bng cch s dng CursorAdapter. Trong nh ngha ca lp
CursorAdapter yu cu mt trong cc ct ca Cursor l _ID.
Sau , ngi dng ly ra mt trong cc hng hin th t giao din ngi dng theo th
t sp xp xem hoc chnh sa d liu. ng dng ly hng tng ng t Cursor
quay tr li ListView, ly ra gi tr _ID cho hng , gn gi tr ny vo content URI,
ri gi yu cu truy cp ti content provider. T , content provider c th thc hin
truy vn hoc chnh sa trn ng hng m ngi dng chn.

Kiu mu content URI


h tr bn chn action dnh cho content URI ti, API ca content provider cha
lp tin dng UriMatcher, s i chiu cc mu content URI vi gi tr s nguyn.
Bn c th s dng nhng gi tr s nguyn ny trong cu lnh switch chn action
mong mun cho content URI hoc cc URI tha mn mt mu c th.
Mt mu content URI tng ng vi nhiu content URI bng cch s dng cc k t
i din (wildcard character) sau:

*: Tng ng vi mt chui c kch thc ty cha bt c k t no hp l.

#: Tng ng vi mt chui c kch thc ty cha cc k t s (numeric


character).

Sau y l v d v thit k v vit m x l content URI, s dng mt Provider vi


chui nh danh com.example.app.provider nhn din nhng content URI sau
tr n cc bng tng ng:

content://com.example.app.provider/table1: Mt bng
ltable1.

content://com.example.app.provider/table2/dataset1: Mt bng
c tn ldataset1.

content://com.example.app.provider/table2/dataset2: Mt bng
c tn l dataset2.

content://com.example.app.provider/table3: Mt bng c tn l
table3.

c tn

Provider trn cng nhn din c cc content URI ny nu chng c gn thm


ID hng, chng hn nh content://com.example.app.provider/table3/1
tng ng vi hng 1 trong bng table3.

192

Lp trnh Android c bn
Cc mu content URI di y c th kh thi:
content://com.example.app.provider/*:

Tng ng vi bt k content URI no ca provider.


content://com.example.app.provider/table2/*:

Tng ng vi content URI ca cc bng dataset1 v dataset2, nhng khng ph


hp vi content URI ca bng table1 hay table3.

content://com.example.app.provider/table3/#: Tng ng vi content


URI ca cc hng n trong bng table3, chng hn nh content://com.
example.app.provider/table3/6 l hng th 6.
on m nh di y m t cch cc phng thc trong UriMatcher lm vic. M
ny s x l cc URI ca ton b bng khc vi cc URI ca mt hng n, s dng mu
content URI content://<chui nh danh>/<ng dn> cho nhiu bng v
content://<chui nh danh>/<ng dn>/<id> cho tng hng n.
Phng thc addURI() nh x (map) gia chui nh danh v ng dn vi mt gi
tr s nguyn. Phng thc match() tr v gi tr s nguyn ca URI. Cu lnh switch
chn gia truy vn trn ton b bng v truy vn trn bn ghi n:
public class ExampleProvider extends ContentProvider{
...

...

// To i tng UriMatcher.

private static final UriMatcher sUriMatcher;

/*

* t li gi phng thc addURI() y, xc nh tt c cc

* ny, c th li gi ti table (bng) 3.

* mu content URI m provider s nhn din. i vi on m

*/
...

/*

* Gn gi tr s nguyn 1 cho nhiu hng ca table 3. Lu , ng

* dn ny khng s dng k t thay th

sUriMatcher.addURI(com.example.app.provider,table3,1);

*/

/*

*
*
*
*

Thit lp m cho mt hng n l 2. Trng hp ny c s dng k


t thay th #. Content URI content://com.example.app.provider/
table3/3 ph hp, nhng content://com.example.app.provider/
table3 th khng.

*/

193

Lp trnh Android c bn

sUriMatcher.addURI(com.example.app.provider,table3/#,2);

// Ci t phng thc ContentProvider.query()

Uri uri,

String selection,

...



publicCursor query(

String[] projection,
String[] selectionArgs,

String sortOrder){
...

/*

* Chn bng truy vn v th t sp xp da trn m m URI


tr v. y, ch gii thiu cc cu lnh dnh cho table 3.

*/

switch(sUriMatcher.match(uri)){

// Nu URI ti l ca ton b table3

// Nu URI ti l ca mt hng n

case1:

if(TextUtils.isEmpty(sortOrder)) sortOrder =_ID ASC;


break;

case2:
/*
*
*
*
*

Do y l URI ca mt hng n, nn phn gi tr _ID


tn ti. Ly phn cui ca ng dn t URI; y l
gi _ID. Sau , gn gi tr vi mnh WHERE ca
truy vn

*/

selection = selection + _ID = uri.getLastPathSegment();


break;

default:
...

// Nu khng nhn din c URI, bn nn thc hin mt


// s x l li y.

// gi m thc hin truy vn

Mt lp khc l ContentUris cung cp cc phng thc hu dng lm vic vi


phn id ca content URI. Cc lp Uri v Uri.Builder cha nhng phng thc
c th d dng phn tch i tng Uri hin c v xy dng cc Uri mi.

194

Lp trnh Android c bn

Ci t lp ContentProvider
Th hin ca lp ContentProvider qun l vic truy cp ti b d liu c cu trc
bng cch x l yu cu t cc ng dng khc. Cui cng th tt c cc dng truy cp
u gi n i tng ContentResolver, sau i tng ny gi ti mt phng
thc c th ca content provider thc hin truy cp.

Phng thc yu cu
Lp tru tng (abstract class) ContentProvider nh ngha su phng thc tru
tng m bn phi ci t thnh mt phn trong cc lp con c th ca chnh bn. Tt
c cc phng thc ny, ngoi tr phng thc onCreate(), c gi bi ng dng
client ang truy cp vo content provider ca bn:
query()

Truy xut d liu t content provider. S dng cc i s chn bng truy vn,
cc hng v ct tr v, cng nh th t sp xp ca kt qu. Tr v d liu di
dng i tng Cursor.
insert()

Chn mt hng mi vo provider. S dng cc i s chn bng ch v ly gi


tr ct s dng. Tr v content URI ca hng mi chn vo.
update()

Cp nht cc hng c trong content provider. S dng cc i s chn bng


cng nh hng mun cp nht v ly gi tr ct c cp nht. Tr v s lng
hng c cp nht.
delete()

Xa hng trong content provider. S dng cc i s chn bng v hng mun


xa. Tr v s lng hng c xa.
getType()

Tr v kiu MIME tng ng vi content URI. Phng thc ny c miu t chi


tit trong mc Ci t kiu MIME ca content provider.
onCreate()

Khi to content provider. H thng Android gi phng thc ny ngay sau khi
Android to content provider ca bn. Lu , content provider ca bn khng c
to ra cho n khi i tng ContentResolver c gng truy cp vo trnh ny.
Lu , cc phng thc ny c cng ch k (signature) vi nhng phng thc
ContentResolver c tn tng t.
Vic ci t cc phng thc ny nn tun theo nhng phn tch di y:

Tt c cc phng thc, ngoi tr onCreate(), c th c nhiu lung (thread)


gi cng lc, nn nhng phng thc ny phi c ci t sao cho an ton
gia nhiu lung. tm hiu thm v a lung, tham kho mc Processes and
Threads (Tin trnh v lung).

195

Lp trnh Android c bn

Trnh cc thao tc di tn ti nguyn trong phng thc onCreate(). Khng


x l cc tc v khi to cho n khi thc s cn. Mc Ci t phng thc
onCreate() bn di s tho lun chi tit hn v iu ny.

Mc d phi ci t cc phng thc ny, song bn khng cn vit m thc


hin thm bt c iu g, ngoi tr tr v kiu d liu mong mun. V d, c th bn
mun trnh khng cho cc ng dng khc chn d liu vo mt s bng. thc
hin iu ny, bn cn b qua li gi hm insert() v tr v 0.

Ci t phng thc query()


Phng thc ContentProvider.query() phi tr v i tng Cursor; hoc
nu li, phng thc ny s nm ra mt ngoi l Exception. Nu ang s dng
c s d liu SQLite lm ni lu tr d liu, bn ch cn tr v i tng Cursor t
mt trong cc phng thc query() ca lp SQLiteDatabase. Nu truy vn ny
khng tm c hng ph hp, bn nn tr v mt th hin ca Cursor c phng
thc getCount() tr v 0. Bn ch nn tr v null nu xy ra li bn trong trong qu
trnh thc hin truy vn.
Nu bn khng s dng c s d liu SQLite lm ni lu tr d liu, hy dng mt
trong cc lp con c th ca Cursor. V d, lp MatrixCursor ci t mt con
tr, trong mi hng l mt mng ca i tng Object. Vi lp ny, hy s dng
phng thc addRow() thm mt hng mi.
Cn nh rng, h thng Android phi c kh nng giao tip vi ngoi l Exception
thng qua cc bin tin trnh. Android c th lm iu ny cho cc ngoi l sau, cng l
nhng ngoi l rt c ch trong vic x l li truy vn:

IllegalArgumentException (bn c th chn nm ra ngoi l ny nu

NullPointerException.

provider ca bn nhn c content URI khng hp l).

Ci t phng thc insert()


Phng thc insert() thm mt hng mi vo bng thch hp, s dng cc gi tr
trong i s ContentValues. Nu tn ct khng nm trong i s ContentValues,
c th bn mun cung cp mt gi tr mc nh cho phng thc ny trong m m ca
content provider hoc trong lc (schema) c s d liu ca bn.
Phng thc ny nn tr v content URI ca hng mi. thc hin iu ny, hy
thm gi tr _ID ca hng mi (hoc mt kha chnh khc) vo content URI ca bng,
s dng withAppendedId().

Ci t phng thc delete()


Phng thc delete() khng nht thit phi xa hon ton hng v mt vt l
khi ni lu tr d liu. Nu ang s dng mt adapter c chc nng ng b (sync
adapter) vi content provider ca mnh, bn phi tnh n vic to mt c xa cho
hng xa thay v xa ton b hng . Adapter c chc nng ng b c th kim tra
nhng hng b xa v xa chng khi server trc khi xa chng khi content provider.

196

Lp trnh Android c bn

Ci t phng thc update()


Phng thc update() s dng cc i s ContentValues tng t nh
phng thc insert(). Phng thc ny cng dng cc i s selection v
selectionArgs tng t nh phng thc delete() v ContentProvider.
query(). Thng tin ny cho php bn ti s dng m gia cc phng thc.

Ci t phng thc onCreate()


H thng Andorid gi phng thc onCreate() khi khi ng content provider. Bn
ch nn thc hin tc v khi to nhanh trong phng thc ny, ng thi tr hon
vic to c s d liu v np (load) d liu cho n khi provider thc s nhn c
yu cu v d liu. Nu thc hin cc tc v gy tn thi gian trong phng thc
onCreate(), bn s lm chm vic khi ng ca content provider; t , lm chm
qu trnh phn hi ca content provider vi cc ng dng khc.
V d, nu s dng c s d liu SQLite, bn c th to mt i tng
SQLiteOpenHelper mi trong ContentProvider.onCreate(), sau to
bng SQL trong ln u m c s d liu. thc hin iu ny theo cch n gin,
trc tin, bn gi phng thc getWritableDatabase(). Phng thc ny s
t ng gi phng thc SQLiteOpenHelper.onCreate().
Hai on m nh di y minh ha s tng tc gia hai phng thc
ContentProvider.onCreate() v SQLiteOpenHelper.onCreate(). on
m nh u tin ci t phng thc ContentProvider.onCreate():
public class Example Provider extends ContentProvider
/*

* nh ngha mt i tng h tr vic x l trn c s d liu.


* Lp MainDatabaseHelper c nh ngha trong on m nh di y.

*/

private MainDatabaseHelper mOpenHelper;

// nh ngha tn c s d liu

// Bin cha i tng c s d liu

public boolean onCreate(){

private static final String DBNAME =mydb;


private SQLiteDatabase db;

/*

* To mt i tng tr gip mi. Phng thc ny lun c


* x l nhanh. Lu , c s d liu khng c to v m
* cho n khi phng thc SQLiteOpenHelper.getWritableDatabase
* c gi

*/

mOpenHelper = new MainDatabaseHelper (

197

Lp trnh Android c bn

getContext(), // context ca ng dng

null, // s dng con tr SQLite mc nh

);

DBNAME, // tn c s d liu

1 // s phin bn (version number)

return true;

...

// Ci t phng thc chn ca content provider

// Chn thm m vo y xc nh bng cn m, x l vic kim

public Cursor insert(Uri uri,ContentValues values){


// tra li, v nhiu x l khc
...
/*

* Ly c s d liu cho php ghi. Lnh ny s bt u qu trnh


* to ca c s d liu nu c s ny cha thc s tn ti.

*/

db = mOpenHelper.getWritableDatabase();

on m nh tip theo l phn ci t ca phng thc SQLiteOpenHelper.


onCreate(), bao gm mt lp tr gip (helper class):
...

// Mt chui nh ngha cu lnh SQL to bng

private static final String SQL_CREATE_MAIN =CREATE TABLE +


main + // Tn bng

_ID INTEGER PRIMARY KEY, +

...

(+ // Cc ct ca bng
WORD TEXT

FREQUENCY INTEGER +
LOCALE TEXT );

/**

* Lp tr gip thc s to v qun l kho lu tr d liu bn di ca


* content provider.
*/

protected static final class MainDatabaseHelper extends SQLiteOpenHelper{

198

Lp trnh Android c bn
/*

* To mt i tng h tr cho kho lu tr d liu SQLite ca


* provider. Khng to c s d liu v nng cp ti y.

*/

MainDatabaseHelper(Context context){

super(context, DBNAME,null,1);

/*

* To kho lu tr d liu. Phng thc ny c gi khi content


* provider ni dung th m kho lu tr v SQLite bo co rng kho
* lu tr ny cha tn ti.

*/

public void onCreate(SQLiteDatabase db){

// To bng chnh

db.execSQL(SQL_CREATE_MAIN);

Ci t cc kiu MIME cho content provider


Lp ContentProvider c hai phng thc tr v kiu MIME:
getType()

Mt trong cc phng thc bt buc m bn phi ci t cho bt c content


provider no.
getStreamTypes()

Mt phng thc bn nn ci t nu content provider ca bn cung cp file.

Kiu MIME ca bng


Phng thc getType() tr v mt String trong nh dng kiu MIME m t kiu
d liu tr v bng i s content URI. i s Uri c th l mt mu ch khng phi
mt URI c th no; trong trng hp ny, bn nn tr v kiu d liu c lin h vi
cc content URI ph hp vi mu.
i vi cc kiu d liu ph bin, chng hn nh vn bn (text), HTML hoc JPEG,
phng thc getType() s tr v kiu MIME chun cho d liu . Danh sch y
ca cc kiu chun ny c lit k trn trang IANA MIME Media Types.
Vi content URI tr ti mt hoc nhiu hng ca d liu dng bng, getType() s tr
v mt kiu MIME theo kiu MIME ty chnh ca Android:

199

Lp trnh Android c bn

Phn type (kiu): vnd

Phn subtype (kiu con):

oo

Nu mu URI cho mt hng n l: android.cursor.item/

oo

Nu mu URI cho nhiu hn mt hng: android.cursor.dir/

Phn xc nh provider: vnd.<tn>.<kiu>


Bn cung cp <tn> v <kiu>. Gi tr <tn> nn l ton cc duy nht, cn
<kiu> nn c gi tr duy nht tng ng vi mu URI. Mt la chn tt cho
<tn> l tn cng ty bn hoc mt s phn trong tn gi Android ca ng
dng m bn pht trin. Mt la chn tt cho <kiu> l mt chui xc nh
bng c lin h vi URI.

V d, nu chui nh danh ca provider l com.example.app.provider v cha


mt bng c tn table1, kiu MIME cho nhiu hng trong table1 l:
vnd.android.cursor.dir/vnd.com.example.provider.table1

Kiu MIME cho mt hng n ca bng table1 l:


vnd.android.cursor.item/vnd.com.example.provider.table1

Kiu MIME cho file


Nu provider ca bn cung cp file, hy ci t phng thc getStreamTypes().
Phng thc ny tr v mt mng String bao gm cc kiu MIME cho nhng file m
provider c th tr v khi nhn c mt content URI xc nh. Bn nn lc cc kiu
MIME bn cung cp bng i s b lc kiu MIME; t , bn ch cn tr v nhng kiu
MIME m client mun x l.
V d, gi s mt provider cung cp cc nh chp c nh dng .jpg, .png v .gif.
Nu mt ng dng gi phng thc ContentResolver.getStreamTypes()
vi chui lc image/* (lc ly bt k th g l nh), th phng thc
ContentProvider.getStreamTypes() s tr v mng:
{image/jpeg,image/png,image/gif}

Nu ng dng ny ch quan tm ti cc file .jpg, n c th gi phng thc


ContentResolver.getStreamTypes() vi chui lc *\/jpeg, cn phng
thc ContentProvider.getStreamTypes() s tr v:
{image/jpeg}

Nu provider bn pht trin khng chia s kiu MIME no do chui lc yu cu, phng
thc getStreamTypes() nn tr v null.

200

Lp trnh Android c bn

Ci t lp contract
Lp contract l lp c khai bo public final cha cc nh ngha hng cho URI,
tn ct, kiu MIME v siu d liu (meta-data) khc gn lin vi provider. Lp ny thit
lp mt giao kt (contract) gia provider v cc ng dng khc bng cch m bo
rng provider c th c truy cp ng, ngay c khi cc gi tr thc s ca URI, tn
ct, thay i.
Lp contract cng gip ch cho nh pht trin ng dng, bi chng thng c cc tn
hng d nh; do , nh pht trin t dng tn ct hoc URI khng chnh xc. V l mt
lp, nn Lp contract c th cung cp ti liu Javadoc. Cc mi trng pht trin tch
hp (integrated development environment- IDE) nh Eclipse c th a ra danh sch
gi cho php ngi dng chn t ng in cc tn hng ny t Lp contract v
hin th Javadoc ca hng .
Nh pht trin ng dng khng cn truy cp vo file lp ca Lp contract t ng dng
ca bn, nhng h c th bin dch tnh lp ny trong ng dng ca mnh t file .jar
bn cung cp.
Lp ContactsContract v cc lp lng (nested class) ca n l nhng v d v
Lp contract.

Ci t quyn ca content provider


Quyn v truy cp v mi phng din trong h thng Android c m t chi tit trong
ch Security and Permissions (Quyn v bo mt). Ch Data Storage (B
lu tr d liu) cng m t quyn v bo mt c tc dng vi nhiu kiu b nh
khc nhau. Tm li, bn cn lu mt s im quan trng sau:

Mc nh, file d liu c lu ti b nh trong ca thit b l ca ring ng


dng v provider do bn pht trin.

C s d liu SQLiteDatabase bn to l ca ring ng dng v provider


do bn pht trin.

Mc nh, cc file d liu bn lu ti b nh ngoi l cng cng (public) v bn


ngoi c th c c (world-readable). Bn khng th dng content provider
gii hn truy cp ti cc file lu trong b nh ngoi, bi cc ng dng khc
c th dng API khc c v ghi chng.

Phng thc gi m hay to file hoc c s d liu SQLite trn b nh


trong ca thit b c th trao c quyn c ln ghi cho tt c cc ng dng
khc. Nu bn s dng mt file hoc c s d liu bn trong lm ni lu tr
d liu cho mnh, ng thi trao quyn truy cp bn ngoi c th c c
(world-readable) v bn ngoi c th ghi c (world-writeable), th cc
quyn bn thit lp cho provider ca mnh trong file k khai s khng cn tc
dng bo v d liu ca bn na. Quyn truy cp mc nh ca file v c
s d liu ti b nh trong l ring t (private) v bn khng nn thay i
quyn mc nh ny i vi kho lu tr d liu provider ca mnh.

Nu mun dng quyn content provider iu khin truy cp ti d liu ca mnh,


bn nn lu d liu trong cc file bn trong, c s d liu SQLite hoc m my (v

201

Lp trnh Android c bn
d nh trn mt server xa), ng thi nn gi cho cc file v c s d liu l dnh
ring cho ng dng ca bn.

Ci t quyn
Mi ng dng u c th c hoc ghi vo provider ca bn, ngay c khi d liu bn
di l ring t, bi theo mc nh th provider ca bn khng c tp cc quyn truy
cp. thay i iu ny, hy thit lp quyn cho provider ca bn trong file k khai,
s dng thuc tnh hoc phn t con ca phn t <provider>. Bn c th thit lp
quyn p dng cho ton b provider, cho bng c th, hay thm ch cho mt s bn
ghi nht nh, hoc c ba.
Bn nh ngha cc quyn cho content provider ang pht trin vi mt hoc nhiu
phn t <permission> trong file k khai. m bo nhng quyn ny l duy
nht i vi ng dng ca bn, s dng kiu phm vi theo nh dng Java cho thuc
tnh android:name. V d, tn ca quyn c l com.example.app.provider.
permission.READ_PROVIDER.
Danh sch di y m t phm vi ca cc quyn ca provider, bt u vi quyn p
dng cho ton b provider, sau i vo cc quyn chi tit hn. Quyn cng chi tit
cng c u tin cao hn quyn c phm vi cao hn:
Quyn c-ghi kt hp mc provider
Mt quyn kim sot c quyn c ln quyn ghi trn ton provider, c xc nh
vi thuc tnh android:permission ca phn t <provider>.
Quyn c v ghi ring mc provider
Mt quyn c v mt quyn ghi cho ton provider. Bn xc nh nhng quyn ny bng
cc thuc tnh android:readPermission v android:writePermission
ca phn t <provider>. Cc quyn ny c u tin hn quyn c thuc tnh
android:permission xc nh.
Quyn ti mc ng dn (path-level)
Quyn c, ghi hoc c/ghi cho mt content URI trong provider m bn pht trin.
Bn ch r mi URI mnh mun qun l vi mt phn t con <path-permission>
ca phn t <provider>. Vi mi content URI bn ch ra, bn c th xc nh
quyn c/ghi, mt quyn c, hay mt quyn ghi, hoc c ba. Quyn c v ghi
ny c quyn u tin hn quyn c/ghi. Quyn ti mc ng dn cng c u
tin hn quyn mc provider.
Quyn tm (temporary permission)
Mt mc quyn m s trao quyn truy cp tm thi cho mt ng dng, ngay c khi
ng dng khng yu cu cc quyn thng thng. c tnh ca quyn tm l lm
gim s quyn m mt ng dng phi yu cu trong file k khai ca n. Khi bn bt
quyn tm, ch nhng ng dng cn quyn lu di trn provider mi c th lin
tc truy cp ton b d liu ca bn.
Gi s c cc quyn bn cn ci t mt ng dng v email provider (trnh cung
cp e-mail), khi mun cho php ng dng hin th nh bn ngoi (outside image
viewer) hin th cc nh nh km trong provider. cp cho ng dng hin th nh

202

Lp trnh Android c bn
cc quyn truy cp cn thit m khng phi yu cu quyn, hy thit lp quyn tm
cho cc content URI ca nh. Thit k ng dng e-mail ca bn khi ngi dng
mun hin th nh, ng dng s gi mt intent cha content URI ca nh v cc
c quyn ti ng dng hin th nh. Sau , ng dng hin th nh c th truy vn
email provider bn pht trin ly nh ra, ngay c khi ng dng hin th khng c
quyn c thng thng trn provider .
bt quyn tm, hoc l thit lp thuc tnh
android:grantUriPermissions ca phn t <provider> , hoc
thm mt hoc nhiu phn t con <grant-uri-permission> vo
phn t <provider> . Nu dng quyn tm, bn phi gi phng thc
Context.revokeUriPermission() mi khi xa s h tr trn mt
content URI khi provider v content URI c gn vi quyn tm.
Gi tr ca thuc tnh xc nh mc truy cp c ca provider do bn pht trin.
Nu thuc tnh ny c thit lp l true, h thng ca bn s gn quyn tm cho
ton b provider, che khut cc quyn c yu cu ti mc ng dn v mc
provider.
N u c n y c t hit lp l f alse, b n p h i th m p h n t co n
<grant-uri-permission> cho phn t <provider> . Mi phn t
con xc nh content URI hoc cc URI c gn quyn truy cp tm.
gn quyn tm cho mt ng dng, mt intent phi cha c FLAG_GRANT_
READ_URI_PERMISSION hoc FLAG_GRANT_WRITE_URI_PERMISSION,
hay c hai. Nhng quyn ny c thit lp bng phng thc setFlags().
Nu khng c thuc tnh android:grantUriPermissions, thuc tnh ny
c coi l false.

Phn t <provider>
Tng t phn t Activity v Service, lp con ca ContentProvider phi
c nh ngha trong file k khai ca ng dng provider, bng cch s dng phn t
<provider>. H iu hnh Android ly cc thng tin sau t phn t ny:
Chui nh danh (android:authorities)
Tn c tnh biu tng xc nh ton b provider bn trong h thng. Thuc tnh
ny c m t chi tit mc Thit k Content URI.
Tn lp provider (android:name)
L lp ci t ContentProvider. Lp ny c m t chi tit mc
Ci t lp ContentProvider.
Quyn
Cc thuc tnh xc nh quyn m nhng ng dng khc phi c truy cp vo
d liu ca provider:

android:grantUriPermssions: C quyn tm.

android:permission: Quyn c ghi kt hp trn ton b provider.

203

Lp trnh Android c bn

android:readPermission: Quyn c trn ton b provider.

android:writePermission: Quyn ghi trn ton b provider.

Quyn v cc thuc tnh tng ng c m t chi tit hn trong mc Ci t


quyn ca content provider.
Cc thuc tnh iu khin v khi ng
Cc thuc tnh ny xc nh cch thc v thi im h thng Android khi
ng provider, nhng c tnh x l ca provider v cc thit lp trong thi
gian chy khc:

android:enabled: C cho php h thng khi ng provider.

android:exported: C cho php cc ng dng khc s dng provider ny.

android:initOrder: Th t khi ng ca provider, lin quan n cc

android:multiProcess: C cho php h thng khi ng provider trong

android:process: Tn ca tin trnh m ti , provider nn chy.

android:syncable: C cho bit d liu provider c ng b vi d liu

provider khc trong cng tin trnh.


cng tin trnh vi client gi.

trn server hay khng.

Cc thuc tnh ny c gii thiu y trong ch hng dn lp trnh ca


phn t <provider>.
Cc thuc tnh thng tin
Nhn v biu tng ty chn cho provider:

android:icon: Ti nguyn drawable cha mt biu tng ca provider.

android:label: Nhn thng tin m t provider hay d liu ca provider ny,

Biu tng ny xut hin bn cnh nhn ca provider trong danh sch cc
ng dng nm Settings > Apps > All.

hoc c hai. Nhn ny xut hin trong danh sch cc ng dng nm Settings
> Apps > All.

Cc thuc tnh ny c gii thiu y trong phn hng dn lp trnh ca


phn t <provider>.

Intent v truy cp d liu


Cc ng dng c th gin tip truy cp content provider thng qua Intent. ng dng
khng gi phng thc bt c no ca ContentResolver hay ContentProvider.
Thay vo , n gi mt intent khi ng mt activity, y l activity thng nm
trong chnh ng dng ca provider ny. Activity ch chu trch nhim truy xut v hin
th d liu trong giao din ngi dng ca activity ny. Ty vo hot ng ca intent,
activity ch cng c th a ra nhc nh ngi dng thc hin thay i trn d liu
ca provider. Mt intent cng c th cha d liu b sung m activity ch hin th trn
giao din ngi dng; sau , ngi dng c th chn thay i d liu ny trc khi s
dng d liu b sung chnh sa d liu trong content provider.

204

Lp trnh Android c bn
C th bn mun s dng vic truy cp thng qua intent m bo tnh ton vn
(integrity) ca d liu. Content provider ca bn c th ph thuc vo vic d liu c
chn thm, cp nht v xa theo cc lgc nghip v c nh ngha cht ch. Nu
gp trng hp nh vy, hy cho php ng dng khc c sa trc tip trn d liu
ca bn, iu ny c th dn n d liu khng hp l. Nu mun cc nh pht trin
s dng truy cp thng qua intent, bn cn m bo rng vic ny phi c hng
dn mt cch r rng. Hy gii thch vi cc nh pht trin ng dng rng ti sao vic
truy cp thng qua intent bng cch dng giao din ngi dng ca ng dng bn pht
trin li tt hn vic c gng chnh sa d liu bng m do h pht trin.
Vic x l cc intent n, tc intent mun chnh sa d liu ca provider do bn pht
trin, khng khc bit so vi vic x l nhng intent khc. Bn c th tm hiu thm
v vic s dng intent qua ch Intents and Intent Filters (Intent v b lc intent).

10.3 Provider Calendar


Provider Calendar l kho lu tr cc s kin lp lch ca ngi dng. API ca Provider
Calendar cho php bn thc hin cc hot ng truy vn, chn, cp nht v xa trn
lch ngy thng (calendar), s kin (event), thnh phn tham d (attendee), li nhc
nh (reminder),
API ca Provider Calendar c th c cc ng dng v adapter c chc nng ng
b (sync adapter) s dng. Cc quy tc ny thay i da vo loi chng trnh thc
hin li gi. Mc ny tp trung ch yu vo cch thc mt ng dng dng API ca
Provider Calendar. Phn tho lun v cch s dng ca adapter c chc nng ng b
s c gii thiu trong mc Adapter c chc nng ng b.
Thng thng, c hoc ghi d liu lch ngy thng, file k khai ca ng dng phi
c cc quyn hp l, nh m t mc Quyn ngi dng. h tr vic thc hin
cc thao tc c d dng, Provider Calendar cung cp tp cc intent, nh m t trong
mc Cc intent ca Calendar. Thng qua ng dng Calendar, cc intent ny gip
ngi dng chn, hin th v chnh sa s kin. Ngi dng tng tc vi ng dng
Calendar, sau tr v ng dng ban u. Do , ng dng ca bn khng cn yu
cu quyn, hoc cn cung cp thm mt giao din ngi dng hin th hoc to s
kin na.

Cc khi nim c bn
Content provider lu tr d liu v gip cc ng dng khc c th truy cp c vo
nhng d liu ny. Cc content provider c nn tng Android cung cp (bao gm
Provider Calendar) thng xut d liu di dng tp bng da trn m hnh c s
d liu quan h; trong , mi hng l mt bn ghi v mi ct l d liu ca mt kiu
v ngha c th. Thng qua API ca Provider Calendar, ng dng v adapter c chc
nng ng b c th c/ghi trn cc bng c s d liu lu tr d liu lp lch ca
ngi dng.
Mi content provider cung cp ra bn ngoi mt URI cng khai (nm trong mt i
tng Uri), y l nh danh duy nht cho mi tp d liu ca provider. Content
provider qun l nhiu tp d liu (nhiu bng) xut ra mt URI cho mi tp. Tt c
cc URI ca provider bt u bng chui content://. nh dng ny nh danh

205

Lp trnh Android c bn
d liu do provider qun l. Provider Calendar nh ngha hng cho URI ca mi lp
(bng) trong trnh ny. Cc URI ny c nh dng l <class>.CONTENT_URI. V d,
Events.CONTENT_URI.
Hnh 1 minh ha mt m hnh d liu ca Provider Calendar. M hnh ny ch biu din
cc bng chnh v nhng trng c chc nng lin kt bng.

Calendars

Lch ngy thng

Events

S kin

Attendee

Thnh phn tham d

Reminder

Li nhc nh

Instances

Th hin

Hnh 1.M hnh d liu ca Provider Calendar.


Mt ngi dng c th c nhiu lch (Calendar), cc lch khc nhau tng ng vi
nhng loi ti khon (account) khc nhau (Lch trn Google, Exchange,).

CalendarContract nh ngha m hnh d liu ca lch v cc s kin cha thng


tin. D liu ny c lu vo mt s bng, nh sau:

206

Lp trnh Android c bn
Bng (Lp)

M t

CalendarContract.Calendars

Bng ny lu thng tin v cc lch c th.


Mi hng ca bng cha thng tin chi tit
v tng lch, chng hn nh tn, mu sc,
thng tin ng b,

CalendarContract.Events

Bng ny lu thng tin v cc s kin c


th. Mi hng ca bng cha thng tin v
mt s kin - v d nh tiu s kin, v
tr, thi im bt u, kt thc, S kin
c th xy ra mt ln hoc lp li nhiu ln.
Thnh phn tham d, li nhc nh v cc
thuc tnh m rng c lu trong tng
bng ring. Mi bng u c mt trng
EVENT_ID tham chiu ti trng _ID ca
bng Events.

CalendarContract.Instances

Bng ny lu thi im bt u v kt thc


ca mi ln xy ra s kin. Mi hng ca
bng i din cho mt ln s kin xy ra.
i vi cc s kin ch xy ra mt ln, th
hin (instance) v s kin l nh x 1:1.
Vi cc s kin xy ra nhiu ln, nhiu
hng c t ng sinh ra tng ng vi
nhiu ln xut hin ca s kin .

CalendarContract.Attendees

Bng ny qun l thng tin v thnh phn


tham d (khch mi). Mi hng i din
cho mt khch mi ca mt s kin. Bng
ny xc nh loi khch mi v phn hi
kh nng tham d ca khch mi i vi
mi s kin.

CalendarContract.Reminders

Bng ny qun l d liu thng bo/nhc


nh (alert/notification data). Mi hng i
din cho mt li nhc nh ca mt s kin.
Mi s kin c th c nhiu li nhc. S
ln nhc ti a cho mi s kin c xc
nh trong bin MAX_REMINDERS, c
thit lp bi adapter c chc nng ng
b qun l lch xc nh. Cc li nhc
c xc nh theo s pht trc mi s
kin v c mt phng thc xc nh
ngi dng no s c nhc.

API ca Provider Calendar c thit k linh hot v mnh m. Cng lc, trnh ny
c th cung cp nhng tri nghim tt cho ngi dng cui cng nh m bo tnh
ton vn ca lch v d liu bn trong. Phn cui s tm tt mt s lu khi s dng
API ny:

207

Lp trnh Android c bn

Chn, cp nht v hin th cc s kin ca lch. trc tip chn, chnh sa v


c s kin trn Provider Calendar, bn cn cc quyn thch hp. Tuy nhin, nu
khng cn xy dng mt ng dng lch chnh thc hoc dng n adapter c chc
nng ng b, th bn khng phi yu cu nhng quyn ny. Thay vo , bn c
th dng cc intent c ng dng Calendar ca Android h tr thc hin cc
hot ng c v ghi trn ng dng. Khi dng intent, ng dng ca bn gi ngi
dng ti ng dng Calendar thc hin cc thao tc cn thit di dng form
cha d liu in sn. Sau khi cc thao tc ny c thc hin, chng c tr v
ng dng m bn pht trin. Bng cch thit k ng dng thc hin cc thao tc
chung thng qua Calendar, bn c th cung cp giao din ngi dng thch hp v
thit thc cho ngi dng. y l cch tip cn c khuyn ngh. tham kho
thm thng tin, xem mc Cc intent ca Calendar.

Adapter c chc nng ng b. Adapter c chc nng ng b tin hnh ng


b d liu ca lch trn thit b ngi dng vi server hoc ngun d liu khc.
Bng CalendarContract.Calendars v CalendarContract.Events
cha cc ct dnh cho adapter c chc nng ng b s dng. Provider ny
v cc ng dng s khng chnh sa nhng ct trn. Thc t, cng l cc ct
khng c hin th, tr phi chng c adapter c chc nng ng b truy cp.
tm hiu thm v adapter c chc nng ng b, xem mc Adapter c chc
nng ng b.

Quyn ngi dng


c d liu lch, ng dng phi c quyn READ_CALENDAR trong file k khai ca
n. Ngoi ra, xa, chn hoc cp nht d liu ca lch, ng dng phi c quyn
WRITE_CALENDAR:
<?xml version=1.0 encoding=utf-8?>

<manifest xmlns:android=http://schemas.android.com/apk/res/android...>

<uses-sdkandroid:minSdkVersion=14/>

<uses-permissionandroid:name=android.permission.WRITE_CALENDAR/>

<uses-permissionandroid:name=android.permission.READ_CALENDAR/>

...

</manifest>

Bng Calendars
Bng CalendarContract.Calendars cha thng tin chi tit v cc lch c nhn.
Cc ct ca bng Calendars di y cung cp quyn ghi cho ng dng hoc adapter
c chc nng ng b. xem danh sch y cc trng c h tr, tham kho
CalendarContract.Calendars.

208

Lp trnh Android c bn
Hng

M t

NAME

Tn lch.

CALENDAR_DISPLAY_NAME

Tn lch s c hin th cho ngi dng.

VISIBLE

Mt gi tr kiu boolean cho bit lch c c


chn hin th hay khng. Gi tr 0 c ngha l
cc s kin tng ng vi lch ny khng c
hin th. Gi tr 1 cho bit cc s kin tng
ng vi lch ny c hin th. y l gi tr
c tc ng ln vic to cc hng trong bng

CalendarContract.Instances.
SYNC_EVENTS

Mt gi tr kiu boolean cho bit xem lch c


c ng b v c cc s kin c lu trn
thit b hay khng. Gi tr 0 cho bit khng ng
b lch ny, hoc khng lu s kin ca lch trn
thit b. Gi tr 1 cho bit c ng b s kin ca
lch ny v lu s kin ca lch trn thit b.

Truy vn lch
Sau y l mt v d minh ha cch ly lch do mt ngi dng c th qun l. n
gin, trong v d ny, hot ng truy vn c hin th trong lung giao din ngi dng
(lung chnh - main thread). Trong thc t, cc truy vn ny nn c thc hin
trong lung khng ng b (asynchronous thread) thay v trn lung chnh. tho
lun thm v iu ny, xem mc Loaders (Cc trnh loader). Nu bn ch c d liu
m khng chnh sa, xem phn AsyncQueryHandler.
// Mng i s projection. To ch s cho mng ny thay v thc hin
// tm kim ng (dynamic lookup) nng cao hiu sut.

public static final String [] EVENT_PROJECTION = newString[]{


Calendars._ID, // 0

Calendars.CALENDAR_DISPLAY_NAME, // 2

};

Calendars.ACCOUNT_NAME, // 1
Calendars.OWNER_ACCOUNT // 3

// Ch s ca mng i s projection bn trn.


privatestaticfinalint PROJECTION_ID_INDEX =0;

privatestaticfinalint PROJECTION_ACCOUNT_NAME_INDEX =1;


privatestaticfinalint PROJECTION_DISPLAY_NAME_INDEX =2;

privatestaticfinalint PROJECTION_OWNER_ACCOUNT_INDEX =3;

209

Lp trnh Android c bn

Ti sao phi a thm trng ACCOUNT_TYPE vo mnh


chn?
Nu truy vn trn Calendars.ACCOUNT_NAME, bn phi a thm trng
Calendars.ACCOUNT_TYPE vo mnh chn. l v mt ti khon ch c xc
nh l duy nht khi xt c ACCOUNT_NAME ln ACCOUNT_TYPE.ACCOUNT_TYPE l
mt chui tng ng vi trnh xc thc ti khon (account authenticator) c s dng
khi ng k ti khon vi AccountManager (trnh qun l ti khon). Mt kiu ti
khon c bit gi l ACCOUNT_TYPE_LOCAL ca lch khng tng ng vi ti khon
thit b. Cc ti khon ACCOUNT_TYPE_LOCAL khng c ng b.
phn tip theo ca v d, bn s to truy vn ca mnh. Mnh chn xc nh iu
kin thc hin truy vn. Trong v d ny, truy vn tm kim lch c ACCOUNT_NAME l
sampleuser@google.com, ACCOUNT_TYPE l com.google, v OWNER_
ACCOUNT l sampleuser@google.com. Nu bn mun xem ton b lch m
ngi dng xem ch khng ch l cc lch ca ngi dng , hy b qua OWNER_
ACCOUNT. Truy vn tr v i tng Cursor m bn c th dng duyt qua tp kt
qu m truy vn c s d liu tr v. xem thm phn tho lun v s dng truy vn
trong content provider, tham kho Content Providers (Content provider).
// Chy truy vn

Cursor cur = null;

ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;

String selection =((+Calendars.ACCOUNT_NAME + = ?) AND (

+Calendars.ACCOUNT_TYPE + = ?) AND (
+Calendars.OWNER_ACCOUNT + = ?));

String[] selectionArgs = new String[] {sampleuser@gmail.com,com.google,


sampleuser@gmail.com};

// Gi truy vn v nhn i tng Cursor tr v.

cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs,null);

Phn tip theo s dng con tr duyt qua tp kt qu. Phn ny s dng cc hng
thit lp u v d tr v gi tr ca mi trng.
// S dng con tr duyt qua cc bn ghi kt qu c tr li
while (cur.moveToNext()) {

long calID =0;

String accountName = null;

String displayName = null;


String ownerName = null;

// Ly ra gi tr ca cc trng

displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);

210

calID = cur.getLong(PROJECTION_ID_INDEX);

accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);

Lp trnh Android c bn

ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);

// Thc hin mt s thao tc vi cc gi tr ny...


...
}

Chnh sa lch
thc hin cp nht trn lch, bn c th cung cp _ID ca lch bng cch gn thm
ID vo Uri (vi phng thc withAppendedId()), hoc ly mc chn u tin.
Mnh chn s bt u vi _id=?, v selectionArg (i s chn) u tin s
l _ID ca lch. Bn cng c th cp nht bng cch m ha (encode) ID trong URI. V
d ny s thay i tn hin th ca lch, s dng phng thc withAppendedId():
private static final String DEBUG_TAG =MyActivity;
...

long calID =2;

ContentValues values = new ContentValues();


// Tn hin th mi ca lch

values.put(Calendars.CALENDAR_DISPLAY_NAME,Trevors Calendar);

Uri updateUri =ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);


int rows = getContentResolver().update(updateUri, values,null,null);
Log.i(DEBUG_TAG,Rows updated: + rows);

Chn lch
Lch c thit k c qun l ch yu bi adapter c chc nng ng b. Do
, bn ch nn thm cc lch mi di dng adapter c chc nng ng b. im
quan trng nht l ng dng ch c th thc hin cc thay i b ngoi, chng
hn nh thay i tn hin th. Nu mt ng dng cn to mt lch cc b (local
calendar), bn c th chn lch di dng mt adapter ng b, s dng ACCOUNT_TYPE l ACCOUNT_TYPE_LOCAL .ACCOUNT_TYPE_LOCAL l mt loi
ti khon c bit ca lch, khng c mi lin kt vi ti khon trn thit b. Lch
ca ti khon ny khng c ng b vi server. tho lun thm v adapter
c chc nng ng b, xem mc Adapter c chc nng ng b.

Bng Events
Bng CalendarContract.Events bao gm thng tin chi tit cho tng s
kin ring. thm, cp nht hoc xa s kin, mt ng dng phi thm quyn
WRITE_CALENDAR vo file file k khai ca n.
Cc ct di y ca bng Events c th c ng dng v adapter c chc nng
ng b chnh sa. c danh sch y cc trng c h tr ny, xem phn
tham kho ca CalendarContract.Events.

211

Lp trnh Android c bn
Hng

M t

CALENDAR_ID

_ID ca lch cha s kin.

ORGANIZER

a ch e-mail ca t chc (hoc ch) ca s


kin.

TITLE

Tiu ca s kin.

EVENT_LOCATION

a im din ra s kin.

DESCRIPTION

Phn m t s kin.

DTSTART

Thi gian bt u s kin, tnh bng n v ms


(mili giy), theo chun UTC, tnh t epoch (k
nguyn Android, tc thi im 1/1/1970).

DTEND

Thi gian kt thc s kin, tnh bng ms, theo


chun UTC, tnh t epoch.

EVENT_TIMEZONE

Mi gi ca s kin.

EVENT_END_TIMEZONE

Mi gi ca thi gian kt thc s kin.

DURATION

Khong thi gian din ra s kin theo nh


dng RFC5545. V d, gi tr ca trng thi
PT1H cho bit s kin s ko di trong mt
gi, v gi tr P2W tng ng vi khong
thi gian l 2 tun.

ALL_DAY

Gi tr 1 cho bit s kin din ra c ngy, ti


mi gi khu vc . Gi tr 0 cho bit y l s
kin nh k c th bt u v kt thc vo bt
c thi im no trong mt ngy.

RRULE

Quy nh v tn sut ca dng s kin ny. V d,

"FREQ=WEEKLY;COUNT=10;WKST=SU".
Bn c th tham kho thm v d ti y.

RDATE

Cc ngy lp li s kin. Bn thng s dng


RDATE kt hp vi RRULE xc nh tp
hp cc s kin lp li. tho lun thm
v iu ny, xem mc RFC5545 spec (Gii
thch cc quy c RFC5545).

AVAILABILITY

S kin ny c tnh l din ra trong thi


gian bn rn hay rnh ri. y l c im c
th ln lch trc.

GUESTS_CAN_MODIFY

Xc nh xem liu ngi tham d c c


chnh sa thng tin s kin hay khng.

GUESTS_CAN_INVITE_OTHERS

Xc nh xem liu ngi tham d c c


mi thm ngi khc khng.

212

Lp trnh Android c bn
Hng

M t

GUESTS_CAN_SEE_GUESTS

Xc nh xem liu ngi tham d c th xem


danh sch ton b khch mi hay khng.

Thm s kin
Khi ng dng ca bn chn thm s kin mi, chng ti khuyn ngh bn nn s dng
Intent INSERT, nh m t trong mc S dng intent chn thm s kin. Tuy nhin,
nu cn, bn c th trc tip chn s kin. Phn ny s hng dn cch lm.
Sau y l cc quy tc chn thm s kin mi:

Bn phi chn thm trng CALENDAR_ID v DTSTART.

Bn cng phi thm trng EVENT_TIMEZONE. ly ra danh sch cc


ID cho mi gi (time zone) c ci t ca h thng, s dng phng thc
getAvailableIDs(). Lu , lut ny khng c p dng khi bn chn mt s
kin bng intent INSERT, nh m t trong mc S dng intent chn thm s
kin - theo cch ny, s kin ca bn s c cung cp mi gi mc nh.

i vi cc s kin khng lp li, bn phi thm trng DTEND.

Vi s kin lp li, bn phi thm trng DURATION, ng thi b sung thm


RRULE hay RDATE. Lu , khng p dng quy tc ny khi chn s kin bng intent
INSERT, nh m t trong mc S dng intent chn thm s kin - theo cch
ny, bn c th s dng mt RRULE kt hp vi DTSTART v DTEND, sau ng
dng Calendar s t ng chuyn i chng thnh khong thi gian.

Di y l v d chn thm mt s kin. n gin, cc cu lnh sau c thc


hin trong lung giao din ngi dng (lung chnh). Thc t, thao tc chn v cp nht
nn c thc hin trong mt lung khng ng b chuyn hot ng vo lung
chy ngm. tm hiu thm, xem phn AsyncQueryHandler.
long calID =3;

long startMillis =0;

long endMillis =0;

Calendar beginTime =Calendar.getInstance();


beginTime.set(2012, 9, 14, 7, 30);

startMillis = beginTime.getTimeInMillis();
Calendar endTime =Calendar.getInstance();
endTime.set(2012, 9, 14, 8, 45);

endMillis = endTime.getTimeInMillis();
...

ContentResolver cr = getContentResolver();

ContentValues values = new ContentValues();


values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);

213

Lp trnh Android c bn
values.put(Events.TITLE,Jazzercise);

values.put(Events.DESCRIPTION,Group workout);
values.put(Events.CALENDAR_ID, calID);

values.put(Events.EVENT_TIMEZONE,America/Los_Angeles);
Uri uri = cr.insert(Events.CONTENT_URI, values);

// ly ra ID ca s kin l phn t cui cng trong Uri


long eventID =Long.parseLong(uri.getLastPathSegment());
//

// ... thc hin mt s thao tc vi ID ca s kin ny ti y


//
//

Ghi ch: Hy xem xt cch v d ny ly ID ca s kin sau khi to xong s kin.


y l cch d nht ly ra ID ca mt s kin. Bn thng cn ID ca s kin
thc hin cc thao tc khc trn lch - v d, thm khch mi hoc li nhc nh
vo s kin.

Cp nht s kin
Khi ng dng ca bn mun cho php ngi dng chnh sa mt s kin, chng ti
khuyn ngh bn nn dng intent EDIT, nh m t trong mc S dng intent chnh
sa s kin. Tuy nhin, nu cn, bn c th trc tip chnh sa s kin. thc hin
cp nht trn mt s kin, bn c th cung cp _ID ca s kin thng qua vic ghp
thm ID vo Uri (bng phng thc withAppendedId()), hoc ly mc chn u
tin. Mnh chn phi bt u vi _id=?, cn i s chn selectionArg u
tin phi l _ID ca s kin. Bn cng c th cp nht bng cch s dng mnh
chn khng c ID. Sau y l mt v d v cp nht s kin. V d ny s thay i tiu
(title) ca s kin, s dng withAppendedId():
private static final String DEBUG_TAG = MyActivity;
...
long eventID =188;
...
ContentResolver cr = getContentResolver();
ContentValues values =newContentValues();
Uri updateUri = null;
// Tiu mi ca s kin
values.put(Events.TITLE,Kickboxing);
updateUri =ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG,Rows updated: + rows);

214

Lp trnh Android c bn

Xa s kin
Bn c th xa s kin bng _ID ca s kin ny di dng ghp thm ID vo URI,
hoc bng cch s dng mnh chn chun. Nu s dng cch gn thm ID, bn
khng phi thc hin php chn. C hai kiu xa: Dng ng dng v dng adapter c
chc nng cp nht. ng dng xa cc bn ghi c ct deleted bng 1. C ny bo vi
adapter c chc nng ng b l hng b xa v vic xa ny phi c p dng
vo server. Adapter c chc nng ng b loi b hon ton s kin khi c s d liu
cng vi nhng d liu lin quan ti s kin ny. Sau y l v d dng ng dng
xa mt s kin thng qua _ID ca s kin :
private static final String DEBUG_TAG = MyActivity;
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri deleteUri = null;
deleteUri =ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().delete(deleteUri,null,null);
Log.i(DEBUG_TAG,Rows deleted: + rows);

Bng Attendees
Mi hng ca bng CalendarContract.Attendees i din cho mt ngi tham
d hoc khch mi ca s kin. Gi phng thc query() tr v danh sch khch
tham d s kin vi EVENT_ID cho trc. EVENT_ID ny phi ph hp vi _ID ca
mt s kin c th.
Bng di y lit k cc trng c th ghi c. Khi chn thm khch mi mi, bn
phi cung cp gi tr cho tt c cc trng ny, ngoi tr ATTENDEE_NAME.
Hng

M t

EVENT_ID

ID s kin.

ATTENDEE_NAME

Tn ngi tham d.

ATTENDEE_EMAIL

a ch e-mail ca ngi tham d.

215

Lp trnh Android c bn
Hng

M t

ATTENDEE_RELATIONSHIP

Mi quan h ca ngi tham d vi s kin. Nhn


mt trong cc mi quan h sau:
RELATIONSHIP_ATTENDEE
(Ngi tham d)
RELATIONSHIP_NONE
(Cha xc nh)
RELATIONSHIP_ORGANIZER
Ngi trong t chc)
RELATIONSHIP_PERFORMER
(Ngi biu din)
RELATIONSHIP_SPEAKER
(Ngi din thuyt)

ATTENDEE_TYPE

Kiu ngi tham d. Thuc mt trong cc kiu


sau:
TYPE_REQUIRED
(Bt buc)
TYPE_OPTIONAL
(C th tham d hoc khng)

ATTENDEE_STATUS

Trng thi tham gia ca ngi tham d. Nhn mt


trong cc trng thi sau:
ATTENDEE_STATUS_ACCEPTED
(Chp nhn)
ATTENDEE_STATUS_DECLINED
(T chi)
ATTENDEE_STATUS_INVITED
(c mi)
ATTENDEE_STATUS_NONE
(Khng xc nh)
ATTENDEE_STATUS_TENTATIVE
(Cha quyt nh)

Thm ngi tham d


Sau y l v d v vic thm mt ngi tham d vo s kin. Lu , gi tr EVENT_ID
l bt buc:
long eventID = 202;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Attendees.ATTENDEE_NAME,Trevor);

216

Lp trnh Android c bn
values.put(Attendees.ATTENDEE_EMAIL,trevor@example.com);
values.put(Attendees.ATTENDEE_RELATIONSHIP,Attendees.RELATIONSHIP_ATTENDEE);
values.put(Attendees.ATTENDEE_TYPE,Attendees.TYPE_OPTIONAL);
values.put(Attendees.ATTENDEE_STATUS,Attendees.ATTENDEE_STATUS_INVITED);
values.put(Attendees.EVENT_ID, eventID);
Uri uri = cr.insert(Attendees.CONTENT_URI, values);

Bng Reminders
Mi hng ca bng CalendarContract.Reminders tng ng vi mt li nhc
nh ca s kin. Li gi phng thc query() tr v danh sch cc li nhc nh ca
s kin c EVENT_ID cho trc.
Bng di y lit k cc trng c th ghi c ca bng nhc nh. Khi thm
mt li nhc mi, bn phi cung cp gi tr cho tt c cc trng ny. Lu , cc
adapter c chc nng ng b xc nh kiu nhc nh m chng h tr trong bng
CalendarContract.Calendars. Xem mc ALLOWED REMINDERS (Cc kiu
nhc nh c cho php) bit thm chi tit.
Hng

M t

EVENT_ID

ID ca s kin.

MINUTES

S pht khi ng li nhc nh trc khi s kin


xy ra.

METHOD

Phng thc cnh bo, khi ci t trn server. Nhn


mt trong cc gi tr sau:
METHOD_ALERT
(Cnh bo)
METHOD_DEFAULT
(Mc nh)
METHOD_EMAIL
(E-mail)
METHOD_SMS
(Tin nhn SMS)

Thm li nhc nh
V d sau thm mt li nhc nh vo s kin. Li nhc nh c khi ng trc s
kin 15 pht.

217

Lp trnh Android c bn
long eventID = 221;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Reminders.MINUTES,15);
values.put(Reminders.EVENT_ID, eventID);
values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
Uri uri = cr.insert(Reminders.CONTENT_URI, values);

Bng Instances
Bng CalendarContract.Instances qun l thi im bt u v kt thc mi
ln din ra mt s kin. Mi hng trong bng i din cho mt ln s kin din ra. Bng
Instances khng cho quyn ghi v ch cung cp mt cch truy vn cc ln din ra
s kin.
Bng sau lit k mt s trng bn c th dng truy vn cho mt th hin. Lu ,
mi gi l do KEY_TIMEZONE_TYPE v KEY_TIMEZONE_INSTANCES xc nh.
Hng

M t

BEGIN

Thi im bt u ca mt th hin, tnh n mili giy


theo chun UTC.

END

Thi im kt thc ca mt th hin, tnh n mili giy


theo chun UTC.

END_DAY

Ngy kt thc theo lch Julian ca th hin, c lin h vi


mi gi ca Calendar.

END_MINUTE

Thi im kt thc theo pht ca th hin, c tnh t


gia m theo mi gi ca Calendar.

EVENT_ID

_ID ca s kin tng ng vi th hin ny.

START_DAY

Ngy bt u theo lch Julian ca th hin, c lin h vi


mi gi ca Calendar.

START_MINUTE

Thi im bt u theo pht ca th hin, c tnh t


gia m, c lin h vi mi gi ca Calendar.

Thc hin truy vn trn bng Instances


truy vn trn bng Instances, bn cn xc nh khong thi gian cho truy vn trong
URI. Trong v d ny, CalendarContract.Instances ly truy cp ti trng TITLE
thng qua bn ci t giao din CalendarContract.EventsColumns. Ni cch
khc, trng TITLE c tr v thng qua mt view ca c s d liu, ch khng qua
truy vn trn bng CalendarContract.Instances th.

218

Lp trnh Android c bn
private static final String DEBUG_TAG = MyActivity;

public static final String[] INSTANCE_PROJECTION = new String[] {


Instances.EVENT_ID, // 0

Instances.TITLE // 2


};

Instances.BEGIN, // 1

// Cc ch s ca mng i s pojection trn.

private static final int PROJECTION_ID_INDEX =0;

private static final int PROJECTION_BEGIN_INDEX =1;


private static final int PROJECTION_TITLE_INDEX =2;
...

// Xc nh phm vi ngy thng bn mun thc hin tm kim cc th


// hin ca s kin
Calendar beginTime = Calendar.getInstance();
beginTime.set(2011, 9, 23, 8, 0);

long startMillis = beginTime.getTimeInMillis();


Calendar endTime = Calendar.getInstance();
endTime.set(2011, 10, 24, 8, 0);

long endMillis = endTime.getTimeInMillis();


Cursor cur = null;

ContentResolver cr = getContentResolver();
// ID ca s kin m bn ang tm kim cc th hin ca n trn bng
// Instances

String selection = Instances.EVENT_ID + = ?;


String[] selectionArgs = new String[] {207};

// Xy dng truy vn vi phm vi ngy thng mun thc hin tm kim.


Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMillis);
ContentUris.appendId(builder, endMillis);
// Thc hin truy vn

cur = cr.query(builder.build(),

INSTANCE_PROJECTION,

selectionArgs,

selection,
null);

while(cur.moveToNext()){

String title =null;

long beginVal =0;

long eventID =0;

219

Lp trnh Android c bn

// Ly gi tr ca cc trng

eventID = cur.getLong(PROJECTION_ID_INDEX);

beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
title = cur.getString(PROJECTION_TITLE_INDEX);

// Thc hin mt s thao tc vi cc gi tr ny.

Calendar calendar = Calendar.getInstance();

Log.i(DEBUG_TAG,Event: + title);

calendar.setTimeInMillis(beginVal);

DateFormat formatter = new SimpleDateFormat(MM/dd/yyyy);

Log.i(DEBUG_TAG,Date: + formatter.format(calendar.getTime()));

}
}

Cc intent ca Calendar
ng dng ca bn khng cn phi c quyn c v ghi d liu lch. Thay vo
, ng dng do bn pht trin c th dng cc intent c ng dng Calendar ca
Android h tr thc hin nhng thao tc c v ghi vi ng dng ny. Bng sau y
lit k cc intent c Provider Calendar h tr:
Cc trng ph h tr
(extra)

Action

URI

M t

VIEW

content://com.
android.calendar/
time/<ms_since_
epoch>

M
lch
vi Khng c.
thi gian c
xc nh bi

<ms_since_
epoch>.
Bn cng c th tr ti
URI ny thng qua hng

CalendarContract.
CONTENT_URI. V v d
s dng intent, xem mc
S dng intent hin th
d liu lch.

VIEW

c o n t e n t : / / c o m . Hin th s kin
android.calendar/ c xc nh
events/<event_id>
bi
<event_id>
.
Bn cng c th tr ti URI

ny bng hng Events.


CONTENT_URI. V v d
s dng intent ny, xem
mc S dng intent
chnh sa s kin.

220

CalendarContract.
EXTRA_EVENT_BEGIN_
TIME
CalendarContract.
EXTRA_EVENT_END_
TIME

Lp trnh Android c bn
Action

URI

M t

EDIT

c o n t e n t : / / c o m . Chnh sa s
android.calendar/ kin c xc
events/<event_id>
nh bi
<event_id>.
Bn cng c th tr ti URI

ny bng hng Events.


CONTENT_URI. V v d
s dng intent ny, xem
mc S dng intent
chnh sa s kin.

EDIT

c o n t e n t : / / c o m . To mt
android.calendar/ s kin.
INSERT
events

Cc trng ph h tr
(extra)

CalendarContract.
EXTRA_EVENT_BEGIN_
TIME
CalendarContract.
EXTRA_EVENT_END_
TIME

Bt c trng ph h tr
no c lit k bng bn
di.

Bn c th tr ti URI
ny bng hng Events.
CONTENT_URI. V v d
s dng intent ny, xem
mc S dng intent
chn thm s kin.
Bng sau lit k mt s trng ph h tr intent (extra) c Provider Calendar
cung cp:
Trng ph h tr intent (extra)

M t

Events.TITLE

Tn s kin.

CalendarContract.EXTRA_
EVENT_BEGIN_TIME

Thi im bt u ca s kin, tnh theo


mili giy t epoch.

CalendarContract.EXTRA_
EVENT_END_TIME

Thi im kt thc s kin, tnh theo mili


giy t epoch.

CalendarContract.EXTRA_
EVENT_ALL_DAY

Mt gi tr kiu boolean cho bit s kin


c din ra c ngy hay khng. Gi tr c
th l true hoc false.

Events.EVENT_LOCATION

a im t chc s kin.

Events.DESCRIPTION

M t v s kin.

Intent.EXTRA_EMAIL

Cc a ch e-mail ca khch mi di
dng mt danh sch phn cch nhau bi
du phy.

Events.RRULE

Quy tc lp s kin.

Events.ACCESS_LEVEL

Xc nh xem s kin l ring t (private)


hay cng cng (public).

221

Lp trnh Android c bn
Trng ph h tr intent (extra)

M t

Events.AVAILABILITY

S kin ny c tnh l din ra trong


thi gian bn rn hay rnh ri. y l
c im c th ln lch trc.

Cc mc di y m t cch s dng nhng intent ny.

S dng intent chn thm s kin


S dng intent INSERT cho php ng dng m bn pht trin chuyn tc v chn s
kin sang Calendar. Vi cch tip cn ny, ng dng ca bn khng cn phi c quyn
WRITE_CALENDAR trong file k khai.
Khi ngi dng chy ng dng theo cch tip cn ny, ng dng s gi h ti Calendar
hon thnh thao tc thm s kin. Intent INSERT s dng cc trng ph lu
trc mt form cha nhng thng tin chi tit ca s kin trong Calendar. Sau , ngi
dng c th hy s kin, chnh sa form (nu cn), hoc lu s kin vo lch ca h.
Sau y l on m nh ln lch cho mt s kin c t chc vo ngy 19 thng 1
nm 2012, din ra t 7 gi 30 pht sng n 8 gi 30 pht sng. Hy lu cc c
im di y ca on m nh ny:

on m xc nh hng Events.CONTENT_URI lm Uri.

on m s dng cc trng ph CalendarContract.EXTRA_EVENT_


BEGIN_TIME v CalendarContract.EXTRA_EVENT_END_TIME lu
trc mt form cha thi gian ca s kin. Cc gi tr thi gian ny c tnh theo
mili giy, theo chun UTC, tnh t epoch.

on m s dng trng ph Intent.EXTRA_EMAIL cung cp mt danh


sch khch mi phn cch nhau bi du phy. Khch mi c xc nh bng a
ch e-mail.
Calendar beginTime =Calendar.getInstance();
beginTime.set(2012,0,19,7,30);

Calendar endTime =Calendar.getInstance();


endTime.set(2012,0,19,8,30);

Intent intent =new Intent(Intent.ACTION_INSERT)


.setData(Events.CONTENT_URI)

.putExtra(CalendarContract.EXTRA_EVENT_END_TIME,

222

.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME,

beginTime.getTimeInMillis())

endTime.getTimeInMillis())

.putExtra(Events.TITLE,Yoga)

.putExtra(Events.DESCRIPTION,Group class)
.putExtra(Events.EVENT_LOCATION,The gym)

.putExtra(Events.AVAILABILITY,Events.AVAILABILITY_BUSY)

Lp trnh Android c bn

.putExtra(Intent.EXTRA_EMAIL,rowan@example.com,

trevor@example.com);

startActivity(intent);

S dng intent chnh sa s kin


Bn c th trc tip cp nht s kin, nh m t trong mc Cp nht s kin. Tuy
nhin, khi bn s dng intent EDIT s cho php mt ng dng khng c cp quyn
c th chuyn thao tc chnh sa ti ng dng Calendar. Khi ngi dng hon thnh
vic chnh sa s kin trn Calendar, h s c a tr li ng dng ban u.
Sau y l v d v mt intent thit lp tiu mi cho mt s kin xc nh, cho php
ngi dng chnh sa s kin trong Calendar.
long eventID =208;

Uri uri =ContentUris.withAppendedId(Events.CONTENT_URI, eventID);


Intent intent =new Intent(Intent.ACTION_EDIT)
.setData(uri)

.putExtra(Events.TITLE,My New Title);

startActivity(intent);

S dng intent hin th d liu lch


Provider Calendar em li hai cch khc nhau s dng intent VIEW:

M lch ca mt ngy c th.

Xem mt s kin.

Sau y l v d minh ha cch m lch ca mt ngy c th:


// Ngy gi tnh theo mili giy t epoch.
long startMillis;
...

Uri.Builder builder =CalendarContract.CONTENT_URI.buildUpon();


builder.appendPath(time);

ContentUris.appendId(builder, startMillis);

Intent intent =new Intent(Intent.ACTION_VIEW)


.setData(builder.build());

startActivity(intent);

223

Lp trnh Android c bn
Sau y l v d minh ha cch m mt s kin xem:
long eventID =208;
...

Uri uri =ContentUris.withAppendedId(Events.CONTENT_URI, eventID);


Intent intent =new Intent(Intent.ACTION_VIEW)

.setData(uri);

startActivity(intent);

Adapter c chc nng ng b


C mt s khc bit nh trong cch mt ng dng v mt adapter c chc nng ng
b truy cp Provider Calendar:

Adapter c chc nng ng b cn xc nh rng n chnh l adapter c chc nng


ng b bng vic thit lp CALLER_IS_SYNCADAPTER l true.

Adapter c chc nng ng b cn cung cp ACCOUNT_NAME v ACCOUNT_TYPE


lm tham s truy vn trong URI.

Adapter c chc nng ng b c quyn truy cp ghi vo nhiu ct hn so vi ng


dng hoc widget. V d, mt ng dng ch c th chnh sa mt s c im ca
lch, chng hn nh tn, tn hin th, ci t hin th v xc nh xem lch c c
ng b hay khng. Khi so snh, adapter c chc nng ng b khng ch c
truy cp vo nhng ct ny m cn nhiu ct khc, nh mu ca lch, mi gi, mc
truy cp, ni din ra, Tuy nhin, adapter c chc nng ng b b gii hn quyn
tng ng vi ACCOUNT_NAME v ACCOUNT_TYPE m n xc nh.

Sau y l phng thc tr gip m bn c th dng tr v URI s dng vi mt


adapter c chc nng ng b:
static Uri asSyncAdapter(Uri uri,String account,String accountType){

return uri.buildUpon()

.appendQueryParameter(Calendars.ACCOUNT_NAME, account)

.appendQueryParameter(android.provider.CalendarContract.
CALLER_IS_SYNCADAPTER,true)

.appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();

tham kho v d ci t mu ca adapter c chc nng ng b (khng ch lin quan


ti Calendar), xem SampleSyncAdapter.

10.4 Provider Contacts


Provider Contacts nm trong h iu hnh Android, l mt thnh phn linh hot, mnh
m, qun l kho lu tr trung tm cha d liu thng tin v con ngi trn thit b.
Provider Contacts l ngun ca d liu bn thy trong ng dng contacts (thng tin lin
lc); trong ng dng ca mnh, bn cn c th truy cp d liu ny, cng nh chuyn

224

Lp trnh Android c bn
d liu gia thit b v cc service trc tuyn. Provider ny ly thng tin t nhiu ngun
d liu v c gng qun l nhiu d liu nht c th cho tng c nhn (contact), nn kt
qu kh phc tp. Do vy, API ca provider ny cha mt tp lp contract ln, cng vi
l nhng giao din h tr c lc cho vic truy xut v chnh sa d liu.
Phn ny s gii thiu cc ni dung sau:

Cu trc c bn ca provider.

Hng dn cch truy xut d liu t provider.

Hng dn cch chnh sa d liu trong provider.

Hng dn cch vit mt adapter c chc nng ng b ng b ha d liu


t server ti Provider Contacts.

Phn ny gi s bn nm c cc khi nim c bn v content provider Android.


tm hiu thm v provider ny, tham kho mc C bn v content provider. ng
dng mu Sample Sync Adapter (Adapter c chc nng ng b mu) l mt v d
v s dng adapter c chc nng ng b (sync adapter) chuyn d liu gia
Provider Contacts v ng dng mu nm trn Google Web Services (Cc service
Web ca Google).

T chc bn trong Provider Contacts


Provider Contacts l mt thnh phn cung cp ni dung ca Android. Trnh ny qun
l ba kiu d liu v mt ngi, mi kiu tng ng vi mt bng trong provider, nh
minh ha Hnh 1:
Contact
(Thng tin
lin lc)

Raw Contact
(Thng tin lin
lc th)

Data
(D liu)

Raw Contact
(Thng tin lin
lc th)

Data
(D liu)

Raw Contact
(Thng tin lin
lc th)

Data
(D liu)

Hnh 1. Cu trc bng ca Provider Contacts.

225

Lp trnh Android c bn
Ba bng ny thng c tham chiu bng tn cc lp contract ca chng. Nhng lp
ny nh ngha cc hng cho cc content URI, tn ct v gi tr ca ct c s dng
trong bng:
Bng ContactsContract.Contacts
Mi hng i din cho mt ngi, da trn s kt hp ca cc hng d liu lin
lc th.
Bng ContactsContract.RawContacts
Cc hng ny lu bn tm tt d liu ca mt ngi, c trng cho loi v ti
khon ca ngi dng.
Bng ContactsContract.Data
Hng cha thng tin chi tit v d liu lin lc th, chng hn nh a ch e-mail
hoc s in thoi.
Nhng bng cn li c i din bng cc lp contract trong ContactsContract
l nhng bng b tr m Provider Contacts dng qun l cc thao tc v h tr
nhng chc nng c th trong thng tin lin lc ca thit b hoc ng dng in thoi.

Thng tin lin lc th


Mt thng tin lin lc th (raw contact) i din cho d liu ca mi ngi tng ng
vi mt tn ti khon (account name) v mt loi ti khon (account type). Do Provider
Contacts cho php nhiu hn mt service trc tuyn lm ngun d liu cho mt ngi
dng, nn provider ny cho php tn ti nhiu d liu lin lc th ca cng mt ngi.
Nhiu d liu lin lc th cng cho php ngi dng kt hp d liu ca mt ngi t
nhiu ti khon thuc cng mt loi ti khon.
Hu ht d liu ca thng tin lin lc th khng c lu trong bng
ContactsContract.RawContacts. Thay vo , chng c lu trong mt
hoc nhiu hng ca bng ContactsContract.Data. Mi hng d liu c
mt ct l Data.RAW_CONTACT_ID cha gi tr RawContacts._ID ca hng
ContactsContract.RawContacts cha.

Cc ct d liu lin lc th quan trng


Cc ct quan trng trong bng ContactsContract.RawContacts c lit k
Bng 1. Hy c k phn Ghi ch bn di bng ny:

226

Lp trnh Android c bn
Bng 1. Cc ct d liu th quan trng.
Tn ct

Mc ch s dng

Ch thch

ACCOUNT_NAME

Tn ti khon ca loi ti
khon lm ngun cho thng tin
lin lc th ny. V d, tn ti
khon ca ti khon Google
l mt trong cc a ch Gmail
ca ch thit b. Xem mc tip
theo v ACCOUNT_TYPE
tm hiu thm.

nh dng ca tn ny c
trng cho loi ti khon ca n.
Khng nht thit phi l a ch
e-mail.

ACCOUNT_TYPE

Loi ti khon lm ngun cho


thng tin lin lc th ny. V
d, loi ti khon ca ti khon
Google l com.google. Lun
lun xc nh loi ti khon ca
bn bng mt nh danh min
(domain identifier) ca min
bn lm ch hoc qun l. iu
ny m bo rng loi ti khon
ca bn l duy nht.

Loi ti khon cung cp thng


tin lin lc thng c mt
adapter c chc nng ng
b tng ng ng b vi
Provider Contacts.

DELETED

C xa ca mt lin lc th.

C ny cho php Provider


Contacts vn gi hng trong
bng cho n khi adapter c chc
nng ng b c th xa hng t
server, sau hon thnh vic
xa hng ti kho lu tr.

Ghi ch
Sau y l mt s lu quan trng v bng ContactsContract.RawContacts:

Tn thng tin lin lc th khng lu trong hng ca bng ContactsContract.


RawContacts. Thay vo , cc thng tin ny c lu trong bng
ContactsContract.Data,
trong
hng
ContactsContract.
CommonDataKinds.StructuredName. Mi thng tin lin lc th ch c mt
hng kiu ny trong bng ContactsContract.Data.

Lu : s dng d liu ti khon ca chnh bn trong mt hng thng tin lin


lc th, trc tin, d liu ny phi c ng k vi AccountManager (trnh
qun l ti khon). thc hin iu ny, hy nhc nh ngi dng thm loi ti
khon v tn ti khon ca h vo danh sch cc ti khon. Nu bn khng thc
hin, Provider Contacts s t ng xa hng thng tin lin lc th ca bn.
V d, nu bn mun ng dng ca mnh lu li d liu lin lc ca mt service trn
nn Web c tn min l com.example.dataservice, v ti khon ngi dng
trn service ca bn l becky.sharp@dataservice.example.com, trc
tin, ngi dng phi thm loi ti khon (com.example.dataservice) v

227

Lp trnh Android c bn
tn ti khon (becky.sharp@dataservice.example.com) ng dng
ca bn c th thm cc hng thng tin lin lc th. Bn c th gii thch yu cu
ny vi ngi dng trong ti liu hng dn, hoc c th nhc nh h thm loi v
tn, hay c hai. Mc tip theo m t chi tit hn v loi ti khon v tn ti khon.

Ngun ca d liu lin lc th


hiu v cch lm vic ca d liu lin lc th, gi s rng ngi dng Emily
Dickinson c ba ti khon ngi dng sau c xc nh trn thit b ca c y:

emily.dickinson@gmail.com.

emilyd@gmail.com.

Ti khon Twitter belle_of_amherst.

Ngi dng ny bt chc nng Sync Contacts (ng b thng tin lin lc) cho c ba ti
khon trong phn ci t Accounts (ti khon).
Gi s Emily Dickinson m mt ca s trnh duyt, ng nhp vo Gmail bng
ti khon emily.dickinson@gmail.com, m phn Contacts v thm vo
lin lc Thomas Higginson. Sau , c y ng nhp vo Gmail bng ti khon
emilyd@gmail.com v gi e-mail cho Thomas Higginson, vic ny s t ng
thm Thomas thnh mt lin lc. Emily cng a ti khon colonel_tom (ID
Twitter ca Thomas Higginson) vo Twitter.
Sau cc thao tc trn, Provider Contacts to ra ba d liu lin lc dng th:
1. Mt d liu lin lc dng th ca Thomas Higginson lin kt vi ti khon
emily.dickinson@gmail.com. Loi ti khon ca ngi dng l Google.
2. D liu lin lc th th hai ca Thomas Higginson lin kt vi ti khon emilyd@
gmail.com. Loi ti khon ca ngi dng ny cng l Google. Thm ch, c d
liu lin lc th th hai ging ht tn trong d liu lin lc th th nht, bi v ngi
ny c thm vo trong mt ti khon ngi dng khc.
3. D liu lin lc th th ba ca Thomas Higginson lin kt vi ti khon
belle_of_amherst. Ti khon ngi dng loi ny l Twitter.

D liu
Nh ghi ch mc trc, d liu ca lin lc th ban u c lu trong hng
ContactsContract.Data lin kt vi gi tr _ID ca d liu lin lc th. iu ny
cho php mt d liu th c nhiu th hin thuc cng mt loi d liu nh a ch
e-mail hoc s in thoi. V d, nu Thomas Higginson ca ti khon emilyd@
gmail.com (hng d liu lin lc th ca Thomas Higginson lin kt vi ti khon
Google emilyd@gmail.com) c mt a ch e-mail nh thigg@gmail.com v
mt e-mail cng vic thomas.higginson@gmail.com, Provider Contacts s lu
hai hng a ch e-mail v lin kt c hai vi d liu lin lc th.
Lu , cc loi d liu khc nhau u c lu trong bng ny. Tn hin th, s in
thoi, e-mail, a ch bu in, nh v cc hng chi tit v Website u c lu
trong bng ContactsContract.Data. gip qun l cc thng tin ny, bng
ContactsContract.Data cha vi ct c tn m t (descriptive name) v nhng

228

Lp trnh Android c bn
ct khc c tn chung chung (generic name). Ni dung ca ct tn m t c cng
ngha vi kiu d liu trong hng, trong khi ni dung ca ct tn chung chung c cc
ngha khc nhau ty theo kiu d liu.

Tn ct m t
Mt s v d v tn ct m t l:

RAW_CONTACT_ID
L gi tr ct _ID cho thng tin lin lc th ca d liu ny.

MIMETYPE
Loi d liu c lu trong hng ny l kiu MIME ty chnh. Provider
Contacts s dng nhng kiu MIME c nh ngha trong cc lp con ca
ContactsContract.CommonDataKinds. Nhng kiu MIME ny l m ngun
m (open source), c th c bt c ng dng hay adapter c chc nng ng
b no lm vic vi Provider Contacts s dng.

IS_PRIMARY
Nu c nhiu kiu hng d liu ny trong bng d liu cho mt thng tin lin lc
th, ct IS_PRIMARY t c vo hng d liu cha d liu chnh ca loi ny. V
d, nu ngi dng nhp s in thoi cho mt lin lc v chn Set default (thit
lp mc nh), hng ContactsContract.Data cha s in thoi ny c ct
IS_PRIMARY c t mt gi tr khc 0 (non-zero value).

Tn ct chung chung
C 15 ct chung chung c tn t DATA1 n DATA15 lun sn sng s dng v
bn ct chung chung b sung t SYNC1 n SYNC4 s c cc adapter c chc nng
ng b s dng. Cc hng tn ct chung chung lun c tc dng, bt k kiu d liu
trong hng l g.
Ct DATA1 l ct c nh ch mc. Provider Contacts lun s dng ct DATA1 cho
d liu m trnh ny mong mun cc truy vn s thng xuyn hng ti nht. V d,
trong hng e-mail, ct ny s cha a ch e-mail thc.
Theo quy c, ct DATA15 c dnh lu tr d liu BLOB, chng hn nh hnh
phc tho nh ca nh chp.

Tn ct c kiu xc nh
d lm vic vi cc ct c kiu d liu c th trn hng, Provider Contacts cng
cung cp hng tn ct c kiu xc nh (type-specific name), c nh ngha trong
lp con ContactsContract.CommonDataKinds. Nhng hng ny ch cung cp
cc tn hng khc nhau cho cng tn ct, gip bn truy cp d liu trong mt hng ca
mt kiu c th.
V d, lp ContactsContract.CommonDataKinds.Email nh ngha cc hng
tn ct c kiu xc nh cho mt hng ContactsContract.Data c kiu MIME l

229

Lp trnh Android c bn
Email.CONTENT_ITEM_TYPE. Lp ny c hng ADDRESS tng ng vi ct a ch
e-mail. Gi tr thc s ca ADDRESS l data1, chnh l tn chung chung ca ct.
Lu : Khng a thm d liu ty chnh ca bn vo bng ContactsContract.
Data bng cch s dng mt hng c mt trong cc kiu MIME nh ngha trc
ca content provider. Nu thc hin iu ny, bn c th lm mt d liu hoc khin
content provider b li. V d, bn khng nn thm hng vi kiu MIME l Email.
CONTENT_ITEM_TYPE cha tn ngi dng thay v a ch e-mail trong ct DATA1.
Nu s dng kiu MIME ty chnh ca mnh cho hng ny, bn c th thoi mi nh
ngha tn ct c kiu xc nh v s dng cc ct ny theo mun.
Hnh 2 minh ha cch b tr cc ct miu t v ct d liu trong hng
ContactsContract.Data, cng vi l cch tn ct c kiu xc nh ph ln
tn ct chung chung.

Address

a ch

Type

Loi

Lable

Nhn

Hnh 2. tn ct c kiu xc nh v tn ct chung chung.

Lp tn ct c kiu xc nh
Bng 2 di y lit k cc lp tn ct c kiu xc nh thng dng:

230

Lp trnh Android c bn
Bng 2. Cc lp tn ct c kiu xc nh.
Lp nh x

Kiu d liu

Ch thch

ContactsContract.
CommonDataKinds.
StructuredName

D liu tn ca lin lc
th c lin kt vi hng
d liu ny.

Mi d liu lin lc th
ch c duy nht mt
hng ny.

ContactsContract.
CommonDataKinds.
Photo

nh chnh ca d liu
lin lc th c lin kt vi
hng d liu ny.

Mi d liu lin lc th
ch c duy nht mt
hng ny.

ContactsContract.
CommonDataKinds.
Email

a ch e-mail ca d liu
lin lc th c lin kt vi
hng d liu ny.

Mt d liu th c th c
nhiu a ch e-mail.

ContactsContract.
CommonDataKinds.
StructuredPostal

a ch bu in ca d
liu th c lin kt vi
hng d liu ny.

Mt d liu th c th c
nhiu a ch bu in.

ContactsContract.
CommonDataKinds.
GroupMembership

Mt nh danh lin kt
d liu lin lc th vi
mt trong cc nhm ca
Provider Contacts.

Nhm l mt tnh nng


ty chn ca mt loi ti
khon v tn ti khon.
Khi nim v nhm c
miu t chi tit trong mc
Nhm lin lc.

Lin lc
Provider Contacts kt hp cc hng d liu lin lc th thng qua tt c cc loi ti
khon v tn ti khon to thnh mt lin lc (contact). iu ny gip hin th
v chnh sa d dng mi d liu m ngi dng c th thu thp cho mt ngi.
Provider Contacts qun l vic to cc hng lin lc mi, ng thi tng hp nhng
d liu lin lc th vi hng lin lc c. C ng dng ln adapter c chc nng
ng b u khng c php thm lin lc, v mt s ct ch c c (read-only)
trong hng lin lc.
Ghi ch: Nu c gng thm mt lin lc vo Provider Contacts bng phng thc
insert(), bn s nhn c ngoi l UnsupportedOperationException.
Nu bn c gng cp nht mt ct c thit lp l ch c, thao tc cp nht s
b b qua.
Provider Contacts to mt lin lc mi phn hi vic thm mt d liu lin lc th
mi khng trng vi bt k lin lc no hin c. Provider cng thc hin iu ny nu
d liu lin lc th c thay i da trn vic d liu ny khng cn khp vi lin lc
c thm vo trc . Nu mt ng dng hoc adapter c chc nng ng b
to mt d liu lin lc th mi trng vi lin lc hin c, d liu lin lc mi s c
kt hp vi lin lc hin c.
Provider Contacts lin kt mt hng lin lc vi cc hng d liu lin lc th ca n
bng ct _ID ca hng lin lc trong bng Contacts. Ct CONTACT_ID ca bng

231

Lp trnh Android c bn
d liu th ContactsContract.RawContacts cha gi tr _ID ca hng lin lc
c lin kt vi mi hng d liu lin lc th.
Bng ContactsContract.Contacts cng c ct LOOKUP_KEY l ct lin kt lu
di vi hng lin lc. Do Provider Contacts t ng qun l cc lin lc, nn trnh ny
c th thay i gi tr _ID ca mt hng lin lc phn hi mt s kt hp hoc ng
b. Thm ch, nu nhng thay i ny xy ra, content URI CONTENT_LOOKUP_URI
kt hp vi LOOKUP_KEY ca lin lc vn tr ti hng lin lc ny, nn bn c th s
dng gi tr LOOKUP_KEY duy tr lin kt ti nhng lin lc a thch, Ct ny c
nh dng ring khng lin quan ti nh dng ca ct _ID.
Hnh 3 minh ha cch ba bng chnh lin kt vi nhau.

Contacts

Lin lc

Rawcontacts

Lin lc th

StructuredName

Tn c cu trc

Data

D liu

Hnh 3. Mi quan h gia cc bng Contacts, Raw Contacts v Details.

232

Lp trnh Android c bn

D liu t Adapter c chc nng ng b


Ngi dng nhp d liu lin lc trc tip vo thit b, nhng trong Provider Contacts,
d liu vn i theo lung t Web service thng qua adapter c chc nng ng b
(sync adapter), nhng adapter ny s t ng chuyn d liu gia thit b v cc
service. Adapter c chc nng ng b chy ngm di s iu khin ca h thng,
v cc phn ny gi phng thc ContentResolver qun l d liu.
Trong Android, Web service m adapter c chc nng ng b lm vic cng s c
mt loi ti khon xc nh. Mi adapter c chc nng ng b lm vic vi mt loi
ti khon, nhng adapter ny c th h tr nhiu tn ti khon thuc loi trn. Loi
ti khon v tn ti khon c m t tm lc trong mc Ngun d liu lin lc
th. Cc nh ngha di y s cung cp thm thng tin chi tit, ng thi m t
cch thc m loi ti khon cng nh tn ti khon lin h vi adapter c chc nng
ng b v service.
Loi ti khon
Xc nh service m ngi dng lu tr d liu vo . Trong hu ht trng
hp, ngi dng phi xc thc (authenticate) bn thn vi service. V d,
Google Contacts (Cc ti khon lin lc ca Google) l mt loi ti khon,
so m google.com xc nh. Gi tr ny tng ng vi loi ti khon m
AccountManager s dng.
Tn ti khon
Xc nh ti khon c th hoc ti khon ng nhp (login) cho mt loi ti khon.
Ti khon Google Contacts ging vi ti khon Google, ly a ch e-mail lm tn
ti khon. Cc service khc c th s dng tn ngi dng dng t n hoc
nh danh bng s khng cha du cch.
Loi ti khon khng phi l duy nht. Ngi dng c th cu hnh nhiu ti khon
Google Contacts v ti (download) d liu ca h v Provider Contacts; iu ny c
th xy ra nu ngi dng c mt tp lin lc ca mt ti khon c nhn, cng vi mt
tp lin lc khc cho cng vic. Cc tn ti khon thng l duy nht. Cng lc, tn ti
khon v loi ti khon nhn din mt lung d liu xc nh gia Provider Contacts
v mt service bn ngoi.
Nu mun chuyn d liu trn service bn s dng v Provider Contacts, bn cn vit
adapter c chc nng ng b ca chnh mnh. iu ny s c m t chi tit trong
mc Adapter c chc nng ng b ca Provider Contacts.
Hnh 4 minh ha cch b tr Provider Contacts trong lung d liu v con ngi. Trong
cc khung ch nht c nh du l sync adapters (adapter c chc nng ng b),
mi adapter c gn nhn bng loi ti khon ca n.

233

Lp trnh Android c bn

People app

ng dng ca mi ngi

App

ng dng

Contacts provider

Provider Contacts

Sync adapters

adapter c chc nng ng b

Hnh 4. Lung d liu ca Provider Contacts.

Cc quyn bt buc
ng dng mun truy cp Provider Contacts phi yu cu cc quyn sau:
Quyn c ti mt hoc nhiu bng
Quyn READ_CONTACTS, c xc nh trong file AndroidManifest.
xml vi phn t <use-permission> v d <uses-permission
android:name=android.permission.READ_CONTACTS>.
Quyn ghi ti mt hoc nhiu bng
Quyn WRITE_CONTACTS, c xc nh trong file AndroidManifest.
xml bng phn t <uses-permission> nh l <uses-permission
android:name=android.permission.WRITE_CONTACTS>.
Nhng quyn ny khng p dng cho user profile (h s thng tin ngi dng).
User profile v cc quyn bt buc ca n c miu t chi tit mc bn di,
User Profile.
Hy nh rng, d liu lin lc ca ngi dng l thng tin c nhn, c tnh cht nhy
cm. Ngi dng lo ngi v tnh ring t, nn h khng mun cc ng dng thu thp
d liu v nhng thng tin ny hay cc lin lc ca h. Nu khng a ra l do r rng
v vic ti sao bn cn quyn truy cp vo d liu lin lc ca ngi dng, h s nh
gi thp ng dng ca bn hoc n gin l t chi ci t ng dng ny.

234

Lp trnh Android c bn

User Profile
Bng ContactsContract.Contacts c mt hng cha d liu v profile cho
ngi dng thit b. D liu ny m t ngi dng thit b, ch khng phi l mt trong
nhng lin lc ca h. Hng profile c lin kt vi hng d liu th tng ng ca
tng h thng s dng profile. Mi profile th c th cha nhiu hng d liu. Cc hng
truy cp user profile nm trong lp ContactsContract.Profile.
Truy cp vo user profile cn cc quyn c bit. Ngoi quyn READ_CONTACTS
v WRITE_CONTACTS c v ghi, bn cn cn thm quyn READ_PROFILE v
WRITE_PROFILE truy cp c v ghi vo user profile.
Hy nh rng, bn phi tnh n thc t rng user profile l d liu nhy cm. Quyn
READ_PROFILE cho php bn truy cp d liu c nhn ca ngi dng thit b. Hy
m bo bn thng bo y ti ngi dng v l do bn cn quyn truy cp vo
user profile trong phn m t ca ng dng m bn pht trin.
truy xut vo hng cha user profile trong bng ContactsContract.
Contacts, gi phng thc ContentResolver.query(). Thit lp content URI
l CONTENT_URI v khng cung cp bt c iu kin chn no. Bn cng c th s
dng content URI lm URI c s truy xut d liu lin lc th hoc d liu cho user
profile. V d, on m nh di y truy xut d liu profile:
// Thit lp cc ct truy xut ly user profile
mProjection =newString[]
{

Profile._ID,

Profile.LOOKUP_KEY,

};

Profile.DISPLAY_NAME_PRIMARY,
Profile.PHOTO_THUMBNAIL_URI

// Truy xut profile trong Provider Contacts


mProfileCursor =

getContentResolver().query(

Profile.CONTENT_URI,

null,

mProjection ,
null,

null);

Ghi ch: Nu bn truy xut nhiu hng t bng ContactsContract.Contacts,


ng thi mun xc nh xem mt trong nhng hng ny c cha user profile hay
khng, hy kim th ct IS_USER_PROFILE ca hng. Nu ct ny c thit lp
l 1, lin lc ny chnh l user profile.

235

Lp trnh Android c bn

Siu d liu ca Provider Contacts


Provider Contacts qun l d liu ln theo vt (track) trng thi d liu lin lc kho
lu tr. Siu d liu v kho lu tr c lu nhiu v tr khc nhau, bao gm cc
hng ca bng Raw Contacts, Data, Contacts, bng ContactsContract.
Settings v bng ContactsContract.SyncState. Bng di y minh ha
tc dng ca mi phn siu d liu ny:
Bng 3. Siu d liu trong Provider Contacts.
Bng

Ct

ContactsContract. DIRTY
RawContacts

Gi tr

ngha

0 - khng
thay i k
t ln ng
b cui.

nh du d liu lin lc th c
thay i trn thit b v cn c
ng b tr li server. Gi tr ny
c Provider Contacts thit lp t
ng khi ng dng Android cp nht
mt hng.
Adapter c chc nng ng b
chnh sa d liu lin lc th hoc
bng d liu lun phi gn chui
CALLER_IS_SYNCADAPTER vo
content URI m adapter ny s
dng. iu ny trnh cho provider
khi vic nh du hng l dirty
(cha c cp nht). Nu khng,
vic chnh sa ca adapter c chc
nng ng b ch mang ngha l
thay i cc b v c gi ti
server, ngay c khi server l ngun
chnh sa.

1 - thay
i k t
ln ng b
cui,
cn
c ng
b tr li
server.

ContactsContract. VERSION
RawContacts

S ch phin Provider Contacts t ng tng gi


bn
ca tr ny mi khi c thay i trn hng,
hng ny.
hoc d liu lin quan n hng ny
thay i.

ContactsContract. D A T A _ S ch phin Provider Contacts t ng tng gi


Data
VERSION
bn
ca tr ny vo bt c thi im no c
hng ny.

236

thay i trn hng d liu.

Lp trnh Android c bn
Bng

Ct

Gi tr

ngha

ContactsContract. S O U R C E _ Gi tr chui Khi mt adapter c chc nng ng


RawContacts
ID
nh danh b to ra mt hng lin lc th mi,
duy
nht
cho mt d
liu lin lc
th vi ti
khon to ra
d liu ny.

ct ny s c thit lp ID duy nht


ca server cho hng ny. Khi mt
ng dng Android to mt d liu
lin lc th mi, ng dng s
trng ct ny. y chnh l du hiu
bo cho adapter c chc nng ng
b bit rng adapter ny nn to mt
d liu lin lc th mi trn server,
v ly mt gi tr cho SOURCE_ID.
C th, id ngun phi l duy nht
i vi mi loi ti khon v nn c
nh qua cc ln ng b:
Duy nht (unique): Mi d liu
lin lc th ca mt ti khon
phi c id ngun cho d liu
. Nu khng tun theo tnh
cht ny, bn s li vn
trong ng dng lin lc. Lu ,
hai d liu lin lc th ca cng
loi ti khon c th c cng id
ngun. V d, d liu lin lc
th Thomas Higginson ca ti
khon
emily.dickinson@
gmail.com c php c cng
id ngun vi d liu lin lc
th Thomas Higginson ca ti
khon emilyd@gmail.com.

n nh (stable): Cc id ngun
l phn bn vng ca d liu
service trc tuyn cho d liu lin
lc th. V d, nu ngi dng
xa b nh lu tr thng tin lin
lc (Contacts Storage) t ni ci
t ng dng, sau ti ng b,
d liu lin lc th c khi phc
li s c cng id ngun nh trc
. Nu bn khng tun theo tnh
cht ny, biu tng shortcut s
ngng hot ng.

237

Lp trnh Android c bn
Bng

Ct

Gi tr

ngha

ContactsContract. G R O U P _ Gi tr 0 - Ct ny l tng thch vi server,


Groups
VISIBLE
Cc lin lc cho php ngi dng n cc lin lc
trong nhm trong nhm c th.
ny khng
c hin
th (visible)
trong giao
din ngi
dng
ca
ng
dng
Android.
1 - Cc
lin lc trong
nhm ny
c hin
th
trong
giao
din
ngi dng
ca
ng
dng.

ContactsContract. U
N
- 0 - Vi Mc nh, cc lin lc b n nu
Settings
GROUPED_ ti
khon khng c lin lc th no ca
VISIBLE
v loi ti chng thuc v mt nhm (thng
khon ny,
cc lin lc
khng nm
trong nhm
s ch
n (invisible)
vi giao din
ngi dng
ng
dng
Android.
1 - Vi
ti
khon
v loi ti
khon ny,
cc lin lc
khng nm
trong nhm
c hin
th
trong
giao
din
ngi dng
ng dng.

238

tin thnh vin nhm ca mt d liu


lin lc th c mt hoc nhiu
hng
ContactsContract.

CommonDataKinds.
GroupMembership trong bng
ContactsContract.Data ch ra).
Bng cch thit lp c ny trong hng
ca bng ContactsContract.
Settings cho mt ti khon v mt
loi ti khon, bn c th quy c
nhng lin lc khng cn nhm c
hin th. Mt tc dng ca c ny l
hin th lin lc t server m khng
cn s dng nhm.

Lp trnh Android c bn
Bng

Ct

ContactsContract. (tt c
SyncState
cc
ct)

Gi tr

ngha

S
dng
bng
ny
lu siu
d liu cho
adapter c
chc nng
ng b.

Vi bng ny, bn c th lu li
trng thi ng b v cc d liu lin
quan n ng b khc mt cch
lu di trn thit b.

Truy cp Provider Contacts


Mc ny gii thiu cc bc truy cp d liu t Provider Contacts, nh sau:

Truy vn thc th.

Chnh sa hng lot.

Tm kim v chnh sa bng intent.

Thc hin ton vn d liu.

Vic thc hin chnh sa t adapter c chc nng ng b s c gii thiu chi tit
hn trong mc Adapter c chc nng ng b ca Provider Contacts.

Cc thc th truy vn
Do cc bng ca Provider Contacts c t chc trong mt h thng phn cp,
nn vic truy vn mt hng v tt c cc hng con c lin kt vi n rt thun
li. V d, hin th ton b thng tin v mt ngi, bn c th mun truy xut
tt c cc hng ca bng ContactsContract.RawContacts c lin quan n
mt hng trong bng ContactsContract.Contacts, hoc tt c cc hng trong bng
ContactsContract.CommonDataKinds.Email c lin quan n mt hng
trong bng ContactsContract.RawContacts. thc hin iu ny mt cch
d dng, Provider Contacts cung cp cu trc thc th (entity), ng vai tr tng t
nhng lin kt c s d liu gia cc bng.
Mt thc th ging nh mt bng cha cc ct c chn t bng cha v bng con ca n.
Khi truy vn mt thc th, bn cung cp mt php chiu v iu kin chn da trn nhng
ct c sn trong thc th. Kt qu s l mt Cursor cha mt hng cho mi hng ca bng
con c truy xut. V d, nu truy vn ContactsContract.Contacts.Entity
ly mt tn lin lc v tt c hng ContactsContract.CommonDataKinds.Email
ca ton b d liu lin lc th c tn ny, bn s nhn v mt Cursor cha mt hng cho
mi hng trong bng ContactsContract.CommonDataKinds.Email.
Cc thc th gip n gin ha truy vn. S dng mt thc th, bn c th cng lc
truy xut tt c d liu lin lc ca mt lin lc hoc d liu lin lc th, thay v phi truy
vn trn bng cha trc ly ID, sau thc hin truy vn bng con bng ID ny.
Ngoi ra, Provider Contacts thc hin truy vn trn mt thc th trong mt giao dch
(transaction) n, iu ny m bo d liu truy xut c cu trc n nh.

239

Lp trnh Android c bn
Ghi ch: Mt thc th thng khng cha tt c cc ct ca bng cha v bng con.
Nu th lm vic vi mt tn ct khng nm trong danh sch hng tn ct ca thc
th, bn s nhn v mt Exception (ngoi l).
on m nh sau minh ha cch truy xut tt c cc hng d liu th ca mt lin lc.
on m nh ny l mt phn trong mt ng dng ln hn, ng dng gm hai activity
l activity chnh v activity chi tit. Activity chnh hin th danh sch cc hng lin lc;
khi ngi dng chn mt hng, activity ny s gi li ID ca hng ti activity chi tit.
Activity chi tit s dng ContactsContract.Contacts.Entity hin th tt c
cc hng d liu t nhng lin lc th tng ng vi lin lc chn.
on m nh di y minh ha activity chi tit:
...

/*

* Thm ng dn thc th vo URI. Trong trng hp ca


* Provider Contacts, URI c khuyn dng l

* content://com.google.contacts/#/entity (# l gi tr ID).

*/

mContactUri =Uri.withAppendedPath(

mContactUri,

ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);

// Khi to loader c LOADER_ID xc nh.


getLoaderManager().initLoader(

LOADER_ID,

null,

this);

// ID ca loader dng khi to

// Cc i s ca loader (trong trng hp


// ny l khng c i s)

// Ng cnh (context) ca activity

// To mt con tr adapter mi gn vo list view


mCursorAdapter == new SimpleCursorAdapter(

this,

// ng cnh ca activity

mCursor,

// chi tit con tr c tr v

R.layout.detail_list_item, // mc hin th cha widget


mFromColumns,


mToViews,


0);

240

// cc ct trong con tr s
// cung cp d liu

// cc view ca mc view
// hin th d liu
// c

// Thit lp adapter tr v cho ListView.

mRawContactList.setAdapter(mCursorAdapter);

Lp trnh Android c bn
...

@Override

public Loader<Cursor> onCreateLoader(int id, Bundle args) {


/*

* Thit lp ct ly d liu.

* RAW_CONTACT_ID c a vo xc nh d liu
* lin lc th lin kt vi hng d liu.
* DATA1 cha ct u tin ca hng d liu
* (thng l ct quan trng nht).

* MIMETYPE ch ra loi d liu ca hng d liu.

*/

String[] projection =

ContactsContract.Contacts.Entity.RAW_CONTACT_ID,

ContactsContract.Contacts.Entity.MIMETYPE

};

ContactsContract.Contacts.Entity.DATA1,

/*

* Sp xp trn con tr truy xut c theo id ca d liu lin lc


* th sao cho tt c cc hng d liu ca mt d liu lin lc th
* c xp li cng nhau.

*/

String sortOrder =

ContactsContract.Contacts.Entity.RAW_CONTACT_ID +
ASC;

/*

* Tr v CursorLoader mi. i s tng t i s ca phng thc


* ContentResolver.query(), ngoi tr i s Context (ng cnh),
* cung cp v tr s dng ca ContentResolver.

*/

return new CursorLoader(

getApplicationContext(), // Ng cnh ca activity


mContactUri,

// Content URI thc th ca mt

projection,

// Cc ct ly gi tr

null,

null,

sortOrder);

// lin lc n

// Truy xut tt c cc lin lc

// th v cc hng d liu ca chng.


//

// Sp xp theo ID ca d liu
// lin lc th.

241

Lp trnh Android c bn
Khi hon thnh vic np d liu, LoaderManager (trnh qun l vic np) gi
phng thc callback onLoadFinished(). Mt trong nhng i s ca phng
thc ny l mt Cursor kt qu ca truy vn. Trong ng dng ca mnh, bn c th
ly d liu t Cursor ny hin th n hoc thc hin cc thao tc khc.

Chnh sa hng lot


Bt c khi no c th, bn nn chn, cp nht v xa d liu ca Provider Contacts
trong ch chnh sa hng lot, bng cch to mt ArrayList cho cc i tng
ContentProviderOperation v gi applyBatch(). Do Provider Contacts thc
hin ton b cc thao tc ca mt applyBatch() trong mt giao dch, nn vic chnh
sa s khng bao gi lm kho lu tr lin lc ri vo tnh trng thiu ng nht. Chnh
sa hng lot cng gip chn cng lc d liu th v d liu chi tit mt cch d dng.
Ghi ch: chnh sa d liu lin lc th dng n, cn tnh n vic gi mt intent
ti ng dng Contacts (lin lc) ca thit b thay v x l chnh sa trong ng dng ca
bn. Cch lm ny c miu t chi tit trong mc Truy vn v chnh sa bng intent.

Cc im trung chuyn
Chnh sa hng lot cha s lng thao tc ln c th chn cc tin trnh khc, v ton
cc s khin ngi dng khng thoi mi. t chc tt c cc chnh sa bn mun
thnh mt vi danh sch tch bit, ng thi trnh lm chm h thng, bn nn t mt
vi im trung chuyn (yield point) cho mt hoc nhiu thao tc. im trung chuyn
l i tng ContentProviderOperation c gi tr isYieldAllowed() thit
lp l true. Khi Provider Contacts gp mt im trung chuyn, n dng thao tc
cc tin trnh khc chy v ng giao dch hin ti li. Khi content provider khi ng
tr li, provider ny s tip tc vi thao tc tip theo trong ArrayList v bt u tin
hnh mt giao dch mi.
im trung chuyn to ra nhiu giao dch trn mi li gi phng thc applyBatch().
Do vy, bn nn thit lp im trung chuyn cho thao tc cui ca tp cc hng lin kt.
V d, bn nn thit lp cho thao tc cui mt im trung chuyn cho tp lnh thm cc
hng d liu lin lc th v nhng hng d liu lin quan ca n, hoc thao tc cui
cho tp cc hng lin h vi mt lin lc n.
im trung chuyn cng l mt n v thao tc n. Tt c cc truy cp gia hai im
trung chuyn s thnh cng hoc tht bi ging nh mt n v n. Nu bn khng thit
lp bt c im trung chuyn no, thao tc n nh nht s l ton b thao tc ca nhm
lnh (batch). Nu s dng im trung chuyn, bn s trnh c cc thao tc lm gim
hiu sut ca h thng, trong khi vn m bo c rng tp con ca cc thao tc l n.

Tham chiu li cho thao tc chnh sa


Khi ang chn mt hng lin lc th mi v nhng hng d liu lin quan di
dng mt tp i tng ContentProviderOperation, bn phi lin kt cc
hng d liu vi hng d liu lin lc th bng cch chn gi tr _ID ca d liu
lin lc th lm gi tr RAW_CONTACT_ID. Tuy nhin, gi tr ny khng sn c khi
bn to i tng ContentProviderOperation cho hng d liu, do bn vn
cha p dng ContentProviderOperation cho hng d liu th. thc hin

242

Lp trnh Android c bn
iu ny, lp ContentProviderOperation.Builder cung cp phng thc
withValueBackReference(). Phng thc ny cho php bn chn hoc chnh
sa mt ct trn kt qu ca thao tc trc .
Phng thc withValueBackReference() c hai i s:

key
Kha ca cp kha-gi tr. Gi tr ca i s ny phi l tn mt ct trong bng bn
ang chnh sa.

previousResult
Ch s bt u t 0 ca mt gi tr trong mng cc i tng
ContentProviderResult tr v t phng thc applyBatch(). Khi cc
thao tc ca nhm c p dng, kt qu ca mi thao tc c lu trong mt
mng kt qu trung gian. Gi tr previousResult l ch s ca mt trong
nhng kt qu ny, c truy xut v lu tr bng gi tr key. iu ny cho php
bn chn mt bn ghi lin lc th mi v ly v gi tr _ID ca bn ghi ny, sau
thc hin mt tham chiu li (back reference) gi tr khi bn thm hng
ContactsContract.Data.
Mng cha ton b kt qu c to ra khi bn gi phng thc applyBatch()
ln u, vi kch thc bng kch thc ArrayList ca cc i tng
ContentProviderOperation m bn cung cp. Tuy nhin, tt c cc phn t ca
mng kt qu c thit lp l null, v nu bn c gng lm mt tham chiu li ti kt qu
ca mt thao tc cha c p dng, phng thc withValueBackReference()
nm ra mt ngoi l Exception.
on m nh sau minh ha cch chn mt d liu lin lc th mi v d liu trong nhm.
on m ny bao gm m thit lp mt im trung chuyn v s dng mt tham chiu
li. on m sau l phin bn m rng ca phng thc createContactEntry(),
l mt phn ca lp ContactAdder trong ng dng mu Contact Manager.
on m u truy xut d liu lin lc t giao din ngi dng. Lc ny, ngi dng
chn mt ti khon thm d liu th mi vo.
// To mt mc lin lc t cc gi tr trn giao din ngi dng
// hin ti, s dng ti khon ang c chn.
protected void createContactEntry() {
/*

* Ly cc gi tr t giao din ngi dng

String name = mContactNameEditText.getText().toString();

String email = mContactEmailEditText.getText().toString();

*/

String phone = mContactPhoneEditText.getText().toString();

int phoneType = mContactPhoneTypes.get(

int emailType = mContactEmailTypes.get(

mContactPhoneTypeSpinner.getSelectedItemPosition());

mContactEmailTypeSpinner.getSelectedItemPosition());

243

Lp trnh Android c bn
on m nh tip theo s to mt thao tc chn hng d liu lin lc th vo bng
ContactsContract.RawContacts:
/*

*
*
*
*
*
*

Chun b nhm lnh (batch) thc hin thao tc chn mt d


liu lin lc th mi v cc d liu ca n. Ngay c khi Provider
Contacts khng c bt c d liu no ca ngi ny, bn cng
khng th thm vo mt Contact, m ch c th thm vo mt d
liu lin lc th. Sau , Provider Contacts s t ng
thm Contact tng ng.

*/

// To mt mng cc i tng ContentProviderOperation mi.


ArrayList<ContentProviderOperation> ops =

new ArrayList<ContentProviderOperation>();

/*
*
*
*
*

To mt d liu lin lc th mi vi loi ti khon (loi server)


ca d liu th v tn ti khon (ti khon ca ngi dng).
Hy nh rng tn hin th khng c lu trong hng ny, m l trong
hng d liu StructuredName. Khng yu cu thm d liu khc.

*/

ContentProviderOperation.Builder op =


ContentProviderOperation.newInsert(ContactsContract.
RawContacts.CONTENT_URI)


.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE,
mSelectedAccount.getType())

.withValue(ContactsContract.RawContacts.ACCOUNT_NAME,
mSelectedAccount.getName());

// Xy dng thao tc v thm thao tc vo mng cc thao tc


ops.add(op.build());

Tip theo, on m to ra cc hng d liu cho tn hin th, s in thoi v a ch e-mail.


Mi i tng trnh xy dng thao tc (operation builder) s dng phng thc
withValueBackReference() ly v RAW_CONTACT_ID. Cc im tham chiu
quay v i tng ContentProviderResult t thao tc u tin, l thao tc thm hng
d liu th v tr v gi tr _ID mi ca hng ny. Kt qu l, mi hng d liu c t ng
lin kt bi gi tr RAW_CONTACT_ID vi hng ContactsContract.RawContacts
mi ca d liu ny.
i tng ContentProviderOperation.Builder thm hng a ch e-mail
c nh du bng c thng qua phng thc withYieldAllowed(), l phng
thc thit lp im trung chuyn:

244

Lp trnh Android c bn


// To tn hin th cho lin lc th mi,


// l mt hng d liu StructuredName.

op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)

/*

* Phng thc withValueBackReference thit lp gi tr ca


* i s u tin l gi tr ca ContentProviderResult c
* nh ch mc bi i s th hai. Trong li gi c th ny,
* ct ID d liu lin lc th ca hng d liu StructuredName
* c thit lp l gi tr tr v ca thao tc u * tin,
cng chnh l thao tc thc s thm hng d liu * th mi.

*/


.withValueBackReference(ContactsContract.Data.RAW_
CONTACT_ID,0)

// Thit lp kiu MIME ca hng d liu l StructuredName


.withValue(ContactsContract.Data.MIMETYPE,

ContactsContract.CommonDataKinds.StructuredName.
CONTENT_ITEM_TYPE)

// Thit lp tn hin th ca hng d liu l tn trong giao


// din ngi dng.


.withValue(ContactsContract.CommonDataKinds.
StructuredName.DISPLAY_NAME, name);

// Xy dng thao tc v thm thao tc vo mng cc thao tc


ops.add(op.build());

// Chn s in thoi c th v loi lm hng d liu Phone


// (in thoi)

op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)

/*

* Thit lp gi tr ca ct id lin lc th l gi tr ID
lin lc th c thao tc u tin ca nhm tr v.

*/


.withValueBackReference(ContactsContract.Data.RAW_
CONTACT_ID,0)

// Thit lp kiu MIME ca hng d liu l Phone


.withValue(ContactsContract.Data.MIMETYPE,

ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)

// Thit lp s in thoi v kiu

.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType);

// Xy dng thao tc v thm thao tc vo mng cc thao tc


ops.add(op.build());

245

Lp trnh Android c bn

// Chn a ch e-mail c th v kiu lm mt hng d liu Email

op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)

/*

* Thit lp gi tr ca ct id d liu th l ID d liu


th mi c tr v t thao tc u tin ca nhm.
*/


.withValueBackReference(ContactsContract.Data.RAW_
CONTACT_ID,0)

// Thit lp kiu MIME cho hng d liu l Email

ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)

.withValue(ContactsContract.Data.MIMETYPE,
// Thit lp a ch e-mail v kiu


.withValue(ContactsContract.CommonDataKinds.Email.
ADDRESS, email)

.withValue(ContactsContract.CommonDataKinds.Email.TYPE,
emailType);
/*

* Minh ha cch s dng im trung chuyn. cui thao tc chn

* ny, lung nhm thao tc s chuyn u tin cho cc lung khc.


* S dng im trung chuyn ny sau mi tp thao tc lin quan n
* mt lin lc n, trnh lm gim hiu sut h thng.

*/

op.withYieldAllowed(true);

// Xy dng thao tc v thm thao tc vo mng cc thao tc

ops.add(op.build());

on m nh cui cng minh ha li gi phng thc applyBatch() chn lin


lc th mi v cc hng d liu.

// Yu cu Provider Contacts to mt lin lc mi

Log.d(TAG,Selected account: + mSelectedAccount.getName()+ (+

mSelectedAccount.getType()+));

Log.d(TAG,Creating contact: + name);

/*

* a mt mng cc i tng ContentProviderOperation vo nhm lnh.


* Kt qu l b b qua.

*/

try {


getContentResolver().applyBatch(ContactsContract.
AUTHORITY, ops);

246

}catch(Exception e){

Lp trnh Android c bn

// Hin th li cnh bo (warning)

CharSequence txt =

int duration =Toast.LENGTH_SHORT;

toast.show();

Context ctx = getApplicationContext();

getString(R.string.contactCreationFailure);

Toast toast =Toast.makeText(ctx, txt, duration);


// Ghi ngoi l

Log.e(TAG,Exception encountered while inserting contact: + e);

Cc nhm thao tc cng cho php bn ci t kim sot truy cp ng thi lc


quan (optimistic concurrency control), mt phng thc p dng cho nhng giao
dch chnh sa m khng phi chn kho lu tr bn di. s dng phng thc
ny, bn p dng giao dch, sau kim tra xem cc chnh sa khc c din ra cng
thi im khng. Nu tm thy c chnh sa khng nht qun, bn roll back giao dch
(hy cc thao tc ca giao dch thc hin) ca mnh li v th li sau.
Kim sot truy cp ng thi lc quan rt hu dng i vi thit b di ng, thng
ch c mt ngi dng ti mt thi im, v him khi xy ra cc truy cp ng thi ti
kho lu tr d liu. Bi vy, vic chn (locking) khng xy ra thng xuyn, do
khng tn thi gian thit lp kha chn v ch cc giao dch khc gii phng kha
ca chng.
s dng Kim sot truy cp ng thi lc quan trong khi ang cp nht mt hng
ContactsContract.RawContracts, bn thc hin theo cc bc sau:
1. Truy xut ct VERSION ca d liu lin lc th cng vi nhng d liu khc m
bn mun truy xut.
2. To mt i tng ContentProviderOperation.Builder ph hp cho vic thc
hin mt rng buc (constraint), bng cch dng phng thc newAssertQuery(Uri).
i vi content URI, s dng RawContacts.CONTENT_URI c gn thm _ID ca
d liu lin lc th.
3. Vi i tng ContentProviderOperation.Builder, gi phng thc
withValue() so snh ct VERSION vi s hiu phin bn bn va truy xut.
4. Trn cng i tng ContentProviderOperation.Builder, gi phng
thc withExpectedCount() m bo ch c duy nht mt hng c xc
nhn (assertion) ny.
5. Gi phng thc build() to i tng ContentProviderOperation,
sau thm i tng ny lm i tng u tin ca ArrayList, l mng s
chuyn n phng thc applyBatch().
6. p dng giao dch hng lot.

247

Lp trnh Android c bn
Nu hng d liu lin lc th c mt thao tc khc cp nht trong thi
gian bn c hng ny v thi im bn th chnh sa hng, vic xc nhn
ContentProviderOperation s b li, ton b nhm thao tc s b li li. Sau ,
bn c th chn th li nhm hoc thc hin mt s thao tc khc.
on m nh di y minh ha cch to xc nhn ContentProviderOperation
sau khi truy vn mt d liu lin lc th n bng cch s dng CursorLoader:
/*

* ng dng dng CursorLoader truy vn bng d liu lin lc th.


* H thng gi phng thc ny khi hon thnh vic np d liu.
*/

public void onLoadFinished(Loader<Cursor> loader,Cursor cursor){



// Ly gi tr VERSION v _ID ca d liu lin lc th

mRawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));


mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.
VERSION));
}

...
// Thit lp Uri cho thao tc xc nhn

Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,


mRawContactID);
// To mt trnh xy dng (builder) cho thao tc xc nhn

ContentProviderOperation.Builder assertOp =ContentProviderOperation.


netAssertQuery(rawContactUri);
// Thm xc nhn cho thao tc xc nhn: Kim tra phin bn v m s
// hng c kim tra

assertOp.withValue(SyncColumns.VERSION, mVersion);
assertOp.withExpectedCount(1);

// To mt i tng ArrayList lu cc i tng


// ContentProviderOperation

ArrayList ops == new ArrayList<ContentProviderOperationg>;


ops.add(assertOp.build());
// Bn s thm cc thao tc cn li ca nhm thao tc vo ops ti y
...
// p dng nhm. Nu vic xc nhn li, h thng s nm ra mt ngoi l
// Exception

248

Lp trnh Android c bn
try

ContentProviderResult[] results =

getContentResolver().applyBatch(AUTHORITY, ops);

}catch(OperationApplicationException e){

// Hoat ng bn mun thc hin trong trng hp xy ra li ti


// ng dng ca ContentProviderOperation v mt s rng buc c th

Truy xut v chnh sa bng intent


Gi mt intent ti ng dng lin lc ca thit b cho php bn gin tip truy cp vo
tProvider Contacts. Intent khi to ti giao din ngi dng ng dng lin lc ca thit
b; ti y, ngi dng c th thc hin cc thao tc lin quan ti d liu lin lc. Vi
kiu truy cp ny, ngi dng c th:

Ly ra mt lin lc t danh sch v tr lin lc ny li ng dng ca bn s dng


cho cc thao tc sau.

Chnh sa d liu lin lc hin c.

Chn mt lin lc th mi cho bt k ti khon no ca ngi dng.

Xa mt lin lc hoc d liu lin lc.

Nu ngi dng ang chn hoc cp nht d liu, bn c th thu thp d liu ny
trc, sau gi chng i nh mt phn ca intent.
Khi s dng intent truy cp Provider Contactsthng qua ng dng lin lc ca thit
b, bn khng phi xy dng giao din ngi dng ca mnh v m truy cp provider
ny. Bn cng khng phi yu cu quyn c v ghi vo provider. ng dng lin lc
ca thit b c th cp quyn c mt lin lc cho bn, v do ang thc hin chnh sa
provider thng qua ng dng khc, nn bn khng cn ti quyn ghi.
Tin trnh chung gi mt intent nhm truy cp provider c m t chi tit trong mc
hng dn C bn v content provider, phn Truy cp d liu thng qua intent. Action,
kiu MIME v gi tr d liu bn s dng cho cc tc v c bn c tng kt trong Bng
4. Ngoi ra, cc gi tr ph tr m bn c th s dng vi phng thc putExtra() c
lit k trong ti liu tham kho ca ContactsContract.Intents.Insert:

249

Lp trnh Android c bn
Bng 4. Cc intent ca Provider Contacts.
Thao
tc

Hnh ng

D liu

Kiu MIME

Ly ra
mt lin
lc t
danh
sch

ACTION_PICK

Mt trong cc d liu sau:

Khng s dng.

Contacts.CONTENT_URI,
hin th danh sch cc lin
lc.
P h o n e . C O N T E N T _ U R I ,
hin th danh sch cc s
in thoi ca mt d liu
lin lc th.
S t r u c t u r e d P o s t a l .
CONTENT_URI, hin th
danh sch cc a ch bu
in ca mt d liu lin lc
th.
E m a i l . C O N T E N T _ U R I ,
hin th danh sch cc a ch
e-mail ca mt d liu lin lc
th.

Chn
mt d
liu lin
lc th
mi

Insert.ACTION

Chnh
sa mt
lin lc

ACTION_EDIT

Hin th
mt View
cho php
ngi
dng
chn
thng tin
(c th
thm
thng
tin vo
View)

A C T I O N _
INSERT_OR_
EDIT

250

Khng c.

RawContacts.
CONTENT_TYPE,
kiu MIME ca
tp d liu lin
lc th.

ca
lin lc ny. Activity chnh sa
s cho php ngi dng sa
bt k d liu no lin kt vi
lin lc ny.

Contacts.
CONTENT_
ITEM_TYPE,

Khng c.

CONTENT_
ITEM_TYPE

CONTENT_LOOKUP_URI

mt lin lc n.

Lp trnh Android c bn
ng dng lin lc ca thit b khng cho php bn xa mt d liu lin lc th hay
bt k d liu no ca lin lc ny bng intent. Thay vo , ng dng cho php bn
xa d liu lin lc th bng cch s dng ContentResolver.delete() hoc
ContentProviderOperation.newDelete().
on m nh di y minh ha cch xy dng v gi mt intent c chc nng chn
d liu lin lc th v d liu mi:
// Ly gi tr t giao din ngi dng

String name = mContactNameEditText.getText().toString();

String phone = mContactPhoneEditText.getText().toString();


String email = mContactEmailEditText.getText().toString();
String company = mCompanyName.getText().toString();
String jobtitle = mJobTitle.getText().toString();

// To mt intent mi gi ti ng dng lin lc ca thit b


Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION);
// Thit lp kiu MIME cho intent bn mun bng activity chn

insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
// Thit lp tn lin lc mi

insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name);
// Thit lp tn cng ty v ngh nghip mi

insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY,
company);

insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE,
jobtitle);
/*

* Minh ha cch thm cc hng d liu di dng mt array list


* lin kt vi kha DATA
*/

// nh ngha mt array list cha cc i tng


// ContentValues cho mi hng

ArrayList<ContentValues> contactData = new ArrayListt<ContentValues>();


/*

* nh ngha hng d liu lin lc th


*/

// Thit lp hng l mt i tng ContentValues

ContentValues rawContactRow = new ContentValues();


// Thm loi ti khon v tn ti khon cho hng

251

Lp trnh Android c bn
rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE,
mSelectedAccount.getType());
rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME,
mSelectedAccount.getName());
// a hng vo mng

contactData.add(rawContactRow);
/*

* Thit lp hng d liu in thoi


*/

// Thit lp hng di dng mt i tng ContentValues


ContentValues phoneRow = new ContentValues();

// Xc nh kiu MIME cho hng d liu ny (tt c cc hng d liu


// phi c nh du bng kiu ca chng)
phoneRow.put(

ContactsContract.Data.MIMETYPE,

);

ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE

// Thm s in thoi v kiu vo hng

phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);
// a hng ny vo mng

contactData.add(phoneRow);
/*

* Thit lp hng d liu e-mail


*/

// Thit lp hng e-mail l mt i tng ContentValues


ContentValues emailRow =newContentValues();

// Xc nh kiu MIME cho hng d liu ny (tt c cc hng d liu


// phi c nh du bng kiu ca chng)
emailRow.put(

ContactsContract.Data.MIMETYPE,

);

ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE

// Thm a ch e-mail v kiu ca a ch vo hng

emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email);
// a hng vo mng

contactData.add(emailRow);

252

Lp trnh Android c bn
/*

* Thm mng vo phn ph tr ca intent. Mng ny phi l i tng c th

* chia nh c (parcelable object) c th di chuyn gia cc tin

* trnh. ng dng lin lc ca thit b mong mun kha ca mng ny phi


* l Intents.Insert.DATA
*/

insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.
Insert.DATA, contactData);
// Gi intent i khi ng ng dng lin lc ca

// thit b trong activity thm lin lc ca ng dng ny.


startActivity(insertIntent);

Tnh ton vn ca d liu


Do kho lu tr d liu lin lc cha cc d liu quan trng v nhy cm m ngi dng
mun phi chnh xc v c cp nht mi nht, nn Provider Contactscha cc quy
tc c nh ngha r rng thc hin ton vn d liu. Nhim v ca bn l tun
theo nhng quy tc ny khi tin hnh chnh sa d liu lin lc. Cc quy tc quan trng
c lit k nh di y:
Lun lun thm mt hng ContactsContract.CommonDataKinds.StructuredName
cho mi hng ContactsContract.RawContacts bn thm vo.
Mt hng ContactsContract.RawContacts khng c hng

ContactsContract.CommonDataKinds.StructuredName trong bng


ContactsContract.Data c th gy ra vn trong qu trnh tng hp.

Lun lun lin kt cc hng ContactsContract.Data mi vi hng cha


ContactsContract.RawContacts .
Mt hng ContactsContract.Data khng c lin kt vi hng
ContactsContract.RawContacts s khng hin th trong ng dng lin lc
ca thit b v c th gy ra vn vi cc adapter c chc nng ng b.
Ch thay i d liu ca nhng d liu lin lc th m bn qun l.
Hy nh rng, Provider Contactsthng qun l d liu ca mt vi service trc
tuyn/loi ti khon khc nhau. Bn cn m bo ng dng ca mnh ch chnh
sa v xa d liu cho cc hng ca mnh, cng nh ch chn d liu cha loi ti
khon v tn m bn qun l.
Lun lun s dng hng c nh ngha trong ContactsContract v lp con ca
n thao tc vi cc ID, content URI, ng dn URI, tn ct, kiu MIME v cc gi
tr TYPE.
S dng nhng hng ny gip bn trnh c li. Bn cng nhn c cc cnh bo
ca trnh bin dch nu cc hng b loi b (khng cn s dng c na).

253

Lp trnh Android c bn

Cc hng d liu ty chnh


Bng cch to v s dng kiu MIME ty chnh t nh ngha, bn c th chn, chnh sa,
xa v truy xut cc hng d liu ca mnh trong bng ContactsContract.Data.
Cc hng ca bn b gii hn ch c php dng ct nh ngha trong
ContactsContract.DataColumns, mc d bn c th nh x cc Tn ct c kiu
xc nh ca mnh vi tn ct mc nh. Trong ng dng lin lc ca thit b, d liu cho
cc hng ca bn c hin th nhng khng th chnh sa hoc xa, v ngi dng
khng th b sung thm d liu. cho php ngi dng chnh sa hng d liu ty
chnh (custom data row) do bn to ra, bn phi cung cp activity chnh sa trong ng
dng do mnh pht trin.
hin th d liu ty chnh ca bn, cung cp file contacts.xml cha mt phn t
<ContactsAccountType> v mt hoc nhiu phn t con <ContactsDataKind>
ca phn t ny. Mc Phn t <ContactsDataKind> m t chi tit hn v iu
ny.
tm hiu thm v kiu MIME ty chnh, c mc hng dn To content provider.

Adapter c chc nng ng b ca Provider Contacts


Provider Contactsc thit k ch yu qun l vic ng b (synchronization)
d liu lin lc gia thit b v service trc tuyn. iu ny cho php ngi dng ti d
liu hin c v mt thit b mi v y (upload) d liu hin c ln mt ti khon mi.
Vic ng b cng m bo ngi dng c c d liu mi nht, m khng phi quan
tm n vic ngun d liu c b sung hay chnh sa. Li ch khc ca vic ng b l
d liu lin lc lun sn sng ngay c khi thit b khng c kt ni mng.
Mc d bn c th ci t vic ng b theo nhiu cch khc nhau, nhng h thng
Android cung cp mt plug-in framework ng b s t ng thc hin cc tc v sau:

Kim tra xem mng c sn sng hay khng.

Ln lch v thc hin ng b, da trn yu cu ca ngi dng.

Khi ng li vic ng b b dng trc .

s dng framework ny, bn cung cp mt plug-in adapter c chc nng ng b.


Mi adapter trn ch dnh cho mt service v mt content provider, nhng adapter ny
c th x l nhiu tn ti khon ca cng mt service. Framework ny cng cho php
nhiu adapter c chc nng ng b thuc cng mt service v provider.

Cc file v lp ca adapter c chc nng ng b


Ci t mt adapter c chc nng ng b di dng mt lp con ca lp
AbstractThreadedSyncAdapter, ng thi ci t adapter lm mt phn ca
nh l mt phn ca ng dng Android. H thng s tm hiu thm v adapter c chc
nng ng b va ci t t cc phn t trong file k khai ca ng dng, v t mt
file XML c bit m file k khai tr ti. File XML nh ngha loi ti khon cho service

254

Lp trnh Android c bn
trc tuyn v chui nh danh cho content provider ny, hai thng tin trn cng xc nh
duy nht mt adapter. Adapter c chc nng ng b ch c kch hot cho n khi
ngi dng thm mt ti khon vo loi ti khon ca adapter ny v cho php ng
b content provider. Ti im ny, h thng khi ng vic qun l adapter, gi phn
ny khi cn thit ng b gia providerv server.
Ghi ch: S dng loi ti khon lm mt phn nhn din adapter c chc nng
ng b cho php h thng pht hin v nhm nhng adapter truy cp cc service
khc nhau t cng mt t chc. V d, cc ti khon ca cc adapterr c chc nng
ng b ca service trc tuyn Google c cng loi ti khon l com.google. Khi
ngi dng thm mt ti khon Google vo thit b ca h, tt c cc adapter c chc
nng ng b ci t ca service Google c lit k cng nhau; trong , mi
adapter c chc nng ng b c lit k cng vi mt content provider trn thit b.
Do hu ht service u yu cu ngui dng phai xc thc nhn dang cua ho truc
khi truy cp d liu, nn h thng Android cung cp framework xc thc tng t nh
vy v cung thung uc s dung kt hp cng framework adapter c chc nang
ng b. Framework xc thc s dung trnh xc thc plug-in, cung l lp con cua
lp AbstractAccountAuthenticator. Trnh xc thc kim tra nhn dang ngui
dng theo cc buc sau:
1. Thu thp tn v mt khu ngi dng hoc thng tin tng t thng tin c nhn
ca ngi dng.
2. Gi thng tin c nhn ti service.
3. Kim tra hi p ca service.
Nu service chp nhn thng tin ny, trnh xc thc c th lu thng tin ny li s
dng v sau. Nh plug-in framework xc thc, AccountManager c th cung cp
truy cp ti bt k m thng bo xc thc (authtoken) no m trnh xc thc h tr v
chn cung cp, chng hn nh m thng bo xc thc OAuth2.
Mc d vic xc thc khng bt buc, nhng hu ht service lin lc u s dng yu
cu ny. Tuy nhin, bn khng bt buc phi s dng framework xc thc ca Android
tin hnh xc thc.

Ci t adapter c chc nng ng b


ci t mt adapter c chc nng ng b cho Provider Contacts, bn bt u bng
vic to mt ng dng Android cha cc thnh phn sau:
Mt thnh phn Service phn hi yu cu ca h thng gn vo adapter c chc
nng ng b.
Khi h thng mun thc hin mt qu trnh ng b, n gi phng thc onBind()
ca service ly mt i tng IBinder cho adapter c chc nng ng b.
iu ny cho php h thng thc hin li gi tin trnh cho (cross-process call)
ti phng thc ca adapter.
Trong ng dng mu Sample Sync Adapter, tn lp cho service ny l

com.example.android.samplesync.syncadapter.SyncService.

255

Lp trnh Android c bn
Adapter c chc nng ng b thc s, c ci t nh mt lp con c th ca lp
AbstractThreadedSyncAdapter.
Lp ny thc hin ti d liu t server, y d liu t thit b ln server v gii
quyt xung t. Cng vic chnh ca adapter c thc hin trong phng thc
onPerformSync(). Lp ny phi c khi to di dng mt Singleton (lp
ch c duy nht mt i tng).
Trong ng dng mu Sample Sync Adapter, adapter c chc nng
ng b c nh ngha ti lp com.example.android.samplesync.
syncadapter.SyncAdapter.
Mt lp con ca lp Application.
Lp ny hot ng ging nhnh my cho ch mt adapter duy nht c chc nng
ng b. S dng phng thc onCreate() khi to adapter, ng thi cung
cp phng thc truy cp get tnh (phng thc c ci t tr v thuc tnh
ca i tng) tr v singleton cho phng thc onBind() ca service adapter c
chc nng ng b.
Ty chn: Thnh phn Service phn hi yu cu t h thng xc thc
ngi dng.

AccountManager khi ng service ny bt u qu trnh xc thc. Phng


thc onCreate() ca service khi to mt i tng trnh xc thc. Khi h

thng mun xc thc mt ti khon ngi dng ca adapter c chc nng ng b


ca ng dng, h thng gi phng thc onBind() ca service ny ly mt
IBinder cho trnh xc thc. iu ny cho php h thng thc hin li gi tin
trnh cho ti cc phng thc ca trnh xc thc.
Trong ng dng mu Sample Sync Adapter, tn lp ca service ny l

com.example.android.samplesync.authenticator.
AuthenticationService.
Ty chn: Mt lp con c th ca lp AbstractAccountAuthenticator
x l yu cu xc thc.
Lp ny cung cp cc phng thc m AccountManager s dng xc thc
thng tin c nhn ca ngi dng vi server. Chi tit v tin trnh x l xc thc
mi ni mt khc, ph thuc vo k thut m server s dng. Bn nn tham kho
ti liu v phn mm server ca mnh tm hiu thm v xc thc.
Trong ng dng mu Sample Sync Adapter, trnh xc thc c nh ngha trong lp

com.example.android.samplesync.authenticator.Authenticator.

File XML nh ngha adapter c chc nng ng b v trnh xc thc ca h thng.


Adapter c chc nng ng b v cc thnh phn service ca trnh xc thc m t
trn c nh ngha trong phn t <service> ca file k khai thuc ng dng. Nhng
phn t ny cha cc phn t con <meta-data> cung cp d liu c th cho h thng:

256

Phn t <meta-data> ca service adapter c chc nng ng b tr ti file XML


res/xml/syncadapter.xml. Ni cch khc, file ny xc nh mt URI cho
Web service s c ng b vi Provider Contacts, ng thi xc nh mt loi
ti khon cho Web service ny.

Lp trnh Android c bn

Ty chn: Phn t <meta-data> ca trnh xc thc tr ti file XML res/xml/


authenticator.xml. Ni cch khc, file XML trn xc nh loi ti khon m
trnh xc thc ny h tr, cng nh ngun ti nguyn giao din ngi dng xut
hin trong sut tin trnh x l xc thc. Loi ti khon c xc nh trong phn t
ny phi ging vi loi ti khon c xc nh cho adapter c chc nng ng b.

D liu thu thp t mng x hi


bng ContactsContract.StreamItems v ContactsContract.
StreamItemPhotos qun l d liu n t cc mng x hi (social network). Bn
Cc

c th vit mt adapter c chc nng ng b th thm D liu thu thp t mng x


hi vo hai bng trn, hoc c th c d liu lung t hai bng ny v hin th d liu
lung trong chnh ng dng ca mnh, hay c hai. Vi nhng tnh nng ny, cc ng
dng v service kt ni mng x hi ca bn c th c tnh hp vo tri nghim
mng x hi ca Android.

D liu vn bn thu thp t mng x hi


Cc hng mc ca lung lun c lin kt vi d liu lin lc th. Ct RAW_CONTACT_ID
lin kt vi gi tr _ID ca d liu th. Loi ti khon v tn ti khon ca d liu th
cng c lu trong hng cc hng mc lung.
Hy lu d liu t lung ca bn vo cc ct sau:

ACCOUNT_TYPE
Bt buc. Loi ti khon ngi dng ca d liu lin lc th lin kt vi hng mc
lung ny. Hy nh thit lp gi tr ny khi bn chn mt hng mc lung.

ACCOUNT_NAME
Bt buc. Tn ti khon ngi dng ca lin lc th lin kt vi hng mc lung
ny. Bn nh thit lp gi tr ny khi chn mt hng mc lung.
Cc ct nh danh
Bt buc. Bn phi chn cc ct nh danh (identifier column) khi chn mt hng
mc lung mi:

CONTACT_ID: Gi tr _ID ca lin lc m hng mc lung ny c lin kt.

CONTACT_LOOKUP_KEY: Gi tr LOOKUP_KEY ca lin lc m hng mc

RAW_CONTACT_ID: Gi tr _ID ca d liu lin lc th m hng mc lung

lung ny c lin kt.


ny c lin kt.

COMMENTS
Ty chn (khng bt buc). Lu thng tin tng kt m bn c th hin th u
mt hng mc lung.

257

Lp trnh Android c bn
TEXT
Vn bn ca hng mc lung, hoc l ni dung c ngun hng mc ng, hoc
m t mt vi hot ng to ra hng mc lung ny. y l ct c th cha bt
c nh dng v cc hnh nh ngun c nhng vo no, sao cho phng thc
fromHtml() c th hin th c. Provider c th ct bt (truncate) hoc ellipsize
(ct bt ni dung v du chm lng) ni dung di, nhng s c gng trnh lm
v cc th (tag).

TIMESTAMP
Chui vn bn cha thi gian m hng mc lung c chn hoc cp nht, thi
gian c biu din di dng mili giy tnh t epoch. ng dng chn hoc cp
nht cc hng mc lung c trch nhim to v cp nht ct ny; y cng l ct
khng c Provider Contactsduy tr t ng.
hin th thng tin nhn dng cho cc hng mc lung ca bn, s dng
RES_ICON, RES_LABEL v RES_PACKAGE lin kt cc ngun d liu
trong ng dng ca bn.
Bng ContactsContract.StreamItems cng cha cc ct t SYNC1 n
SYNC4 dnh ring cho nhng adapter c chc nng ng b.

D liu nh trn lung thu thp t mng x hi


Bng ContactsContract.StreamItemPhotos lu cc nh lin kt vi mt hng
mc lung. Ct STREAM_ITEM_ID ca bng ny lin kt vi cc gi tr trong ct _ID
ca bng ContactsContract.StreamItems. Cc tham chiu nh trong bng ny
nm trn nhng ct sau:
Ct PHOTO (d liu kiu BLOB)
Dng biu din nh phn ca nh, c provider thay i kch thc lu tr
v hin th. Ct ny lun sn sng tng thch ngc tr li vi cc phin bn
trc ca Provider Contactsdng ct ny lu tr nh. Tuy nhin, trong phin
bn hin ti, bn khng nn dng ct ny lu tr nh. Thay vo , hy s
dng ct PHOTO_FILE_ID hoc PHOTO_URI (c hai ct ny s c m t trong
cc mc sau y) lu tr nh di dng file. Hin ti, ct ny lu nh i din
(thumbnail) ca bc nh l d liu c th xem nhanh c.

PHOTO_FILE_ID
L mt con s, nh danh nh ca mt d liu lin lc th. Gn gi tr ny vo
hng DisplayPhoto.CONTENT_URI c content URI tr ti mt file
nh n, sau gi phng thc openAssetFileDescriptor() ly
x l trn file nh.

PHOTO_URI
Mt content URI trc tip tr ti file nh ca nh m hng ny i din. Gi phng
thc openAssetFileDescriptor() vi URI ny ly x l trn file nh.

258

Lp trnh Android c bn

S dng cc bng lung thu thp t mng x hi


Nhng bng ny hot ng ging nh cc bng chnh khc trong Provider Contacts,
ngoi tr:

Cc bng ny yu cu phi c thm quyn truy cp. c, ng dng ca bn


phi c quyn READ_SOCIAL_STREAM. chnh sa, ng dng ca bn phi c
quyn WRITE_SOCIAL_STREAM.

i vi bng ContactsContract.StreamItems, s lng hng c lu


cho mi d liu lin lc th b gii hn. Khi t ti gii hn ny, Provider Contactss
to khng gian cho hng mc lung mi bng cch t ng xa nhng hng c
TIMESTAMP c nht. bit gii hn ny, thc hin mt truy vn ti content
URI CONTENT_LIMIT_URI. Bn c th b qua tt c cc i s khc, ngoi tr
content URI, bng cch thit lp nhng gi tr l null. Truy vn ny tr v mt
Cursor cha mt hng n, c ct n MAX_ITEMS.

Lp ContactsContract.StreamItems.StreamItemPhotos nh ngha mt
bng con ca ContactsContract.StreamItemPhotos cha cc hng nh cho
mt hng mc lung n.

Tng tc vi lung t mng x hi


D liu lung thu thp t mng x hi m Provider Contactsqun l, kt hp vi ng
dng lin lc ca thit b, tr thnh mt cng c hiu qu gip kt ni h thng mng x
hi vi cc lin lc hin c. Di y l nhng tnh nng c cung cp:

Bng cch ng b service mng x hi ca bn vi Provider Contactsnh mt adapter


c chc nng ng b, bn c th truy xut activity gn y cho cc lin lc ca ngi
dng, sau lu chng vo trong cc bng ContactsContract.StreamItems v
ContactsContract.StreamItemPhotos s dng sau.

Bn cnh vic ng b nh k, bn c th t mt trigger (cha tp cc lnh truy


vn kch hot di mt s kin no ) cho adapter c chc nng ng b truy
xut d liu b sung khi ngi dng chn hin th mt lin lc. iu ny cho php
adapter c chc nng ng b ca bn truy xut nh c phn gii cao v cc
hng mc lung mi nht cho lin lc.

Bng cch ng k mt thng bo vi ng dng lin lc ca thit b v Provider


Contacts, bn c th nhn mt intent khi hin th lin lc v ti thi im service
ca bn cp nht trng thi ca lin lc. Cch tip cn ny c th nhanh hn, tn
t bng thng hn so vi s dng ng b ton phn vi adapter c chc nng
ng b.
Ngi dng c th thm mt lin lc vo service mng x hi ca bn trong khi
ang xem lin lc trong ng dng lin lc ca thit b. Bn c th thit lp iu
ny bng tnh nng invite contact (mi lin lc). Tnh nng trn c kch hot
bng mt t hp bao gm mt activity thm mt lin lc hin c vo mng ang
s dng, km theo l mt file XML cung cp ng dng lin lc ca thit b v
Provider Contactsvi nhng thng tin chi tit v ng dng ca bn.

259

Lp trnh Android c bn
Vic ng b nh k cc hng mc lung vi Provider Contactscng ging nh nhng
ng b khc. tm hiu thm v ng b, xem mc Adapter c chc nng ng b
ca Provider Contacts. Cch ng k thng bo v tnh nng invite contact c gii
thiu trong hai mc tip theo.

ng k x l hin th trn mng x hi


ng k adapter c chc nng ng b nhn thng bo mi khi ngi dng hin th
mt lin lc do adapter ny qun l, bn cn:
1. To mt file c tn l contacts.xml trong th mc res/xml/ ca d n. Nu
c file trn, hy b qua bc ny.
2. Trong file ny, thm phn t <ContactsAccountType xmlns:

android=http://schemas.android.com/apk/res/android>.
Nu c phn t trn, hy b qua bc ny.

3. ng k service nhn thng bo khi ngi dng m trang thng tin chi tit
ca lin lc trn ng dng lin lc ca thit b, thm thuc tnh viewContact
NotifyService=serviceclass vo phn t trn, vi serviceclass
l tn lp y ca service nhn intent t ng dng lin lc ca thit b. Vi
service thng bo ny, hy s dng lp m rng IntentService, nhm cho
php service nhn intent. D liu trong intent ti cha content URI ca d liu
lin lc th m ngi dng nhn vo. Nh service thng bo, bn c th lin
kt vi adapter c chc nng ng b, sau gi adapter ny cp nht d
liu cho d liu lin lc th.
ng k activity c gi khi ngi dng nhn vo hng mc lung hay nh, hoc
c hai:
1. To mt file c tn contacts.xml trong th mc res/xml/ ca d n. Nu
c file trn, hy b qua bc ny.
2. Trong file ny, thm vo phn t <ContactsAccountType xmlns:

android=http://schemas.android.com/apk/res/android>.
Nu c phn t trn, hy b qua bc ny.

3. ng k mt trong cc acitvity ca ng dng nhn x l s kin ngi dng


nhn vo hng mc lung trong ng dng lin lc ca thit b, thm thuc tnh
viewStreamItemActivity=activityclass vo phn t trn, trong
activityclass l tn lp y ca activity s nhn intent t ng dng lin
lc ca thit b.
4. ng k mt trong cc activity nhn x l s kin ngi dng nhn vo mt
nh thuc hng mc lung trong ng dng lin lc ca thit b, thm thuc tnh
viewStreamItemPhotoActivity=activityclass vo phn t trn,
trong activityclass l tn lp y ca activity nhn intent t ng
dng lin lc ca thit b.
Mc Phn t <ContactsAccountType> m t chi tit hn v phn t
<ContactsAccountType>.

260

Lp trnh Android c bn
Intent ti cha content URI ca hng mc hoc nh m ngi dng nhn vo.
c cc activity ring bit cho hng mc vn bn v nh, hy s dng cc thuc tnh
trong cng mt file.

Tng tc vi service mng x hi ca bn


Ngi dng khng phi ri ng dng lin lc ca thit b mi mt lin lc vo trang
mng x hi ca bn. Thay vo , bn c th ng dng lin lc ca thit b gi mt
intent mi lin lc ti mt trong cc activity ca mnh. thit lp iu ny, bn cn:
1. To mt file c tn contacts.xml trong th mc res/xml/ ca d n bn pht
trin. Nu c file trn, hy b qua bc ny.
2. Trong file ny, thm phn t <ContactsAccountType

xmlns:android=http://schemas.android.com/apk/res/android>.
Nu c phn t trn, hy b qua bc ny.

3. Thm cc thuc tnh sau:


oo

inviteContactActivity=activityclass

oo

inviteContactActionLabel=@string/invite_action_label

Gi tr activityclass l tn lp y ca activity nhn intent. Gi tr


invite_action_label l chui vn bn c hin th trong menu Add
Connection (thm kt ni) ng dng lin lc ca thit b.
Ghi ch: ContactsSource l tn th c ca ContactsAccountType.

Tham kho hng dn s dng file contacts.xml


File contacts.xml cha cc phn t XML iu khin vic tng tc gia adapter c
chc nng ng b v ng dng vi ng dng lin lc v Provider Contacts. Cc phn
t ca file ny s c gii thiu nhng mc di y.

Phn t <ContactsAccountType>
Phn t <ContactsAccountType> iu khin vic tng tc ca ng dng bn
pht trin vi ng dng lin lc. C php ca phn t ny nh sau:
<ContactsAccountType

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

inviteContactActionLabel=invite_command_text

inviteContactActivity=activity_name

viewContactNotifyService=view_notify_service

viewGroupActivity=group_view_activity

viewStreamItemActivity=viewstream_activity_name

viewGroupActionLabel=group_action_text

viewStreamItemPhotoActivity=viewphotostream_activity_name>

261

Lp trnh Android c bn
c lu trong:

res/xml/contacts.xml
C th bao gm phn t:
<ContactsDataKind>

M t:
Khai bo cc thnh phn ca Android v cc nhn trn giao din ngi dng cho php
ngi dng mi mt trong cc lin lc ca h vo mng x hi, thng bo vi ngi
dng khi mt trong nhng lung mng x hi ca h c cp nht,
Lu , khng cn s dng tin t thuc tnh android: cho thuc tnh
<ContactsAccountType>.
Thuc tnh:

inviteContactActivity
Tn lp y ca activity trong ng dng ca bn, l activity bn mun kch hot
khi ngi dng chn mc Add connection t ng dng lin lc ca thit b.

inviteContactActionLabel
Chui vn bn hin th cho activity, c xc nh trong thuc tnh
inviteContactActivity, trn menu Add connection. V d, bn c th s
dng chui Follow in my network (Theo di trong mng ca ti). Bn c th s
dng mt nh danh ti nguyn dng chui cho nhn ny.

viewContactNotifyService
Tn lp y ca mt service trong ng dng ca bn, l service s nhn thng
bo khi ngi dng hin th lin lc. Thng bo ny c ng dng lin lc ca
thit b gi i; vic ny cho php ng dng ca bn c th hon cc thao tc cn
nhiu d liu cho n khi cn thit. V d, ng dng ca bn c th phn hi thng
bo ny bng vic c cng nh hin th nh c phn gii cao v hng mc
lung mng x hi gn y nht ca lin lc. Mc Tng tc vi lung mng x
hi m t chi tit hn v tnh nng ny. Bn c th xem mt v d v service thng
bo trong file NotifierService.java ca ng dng mu SampleSyncAdapter.

viewGroupActivity

Tn lp y ca activity c th hin th thng tin v nhm trong ng dng ca


bn. Khi ngi dng nhn vo nhn ca nhm trong ng dng lin lc ca thit b,
giao din ngi dng cho activity ny hin th.

viewGroupActionLabel

Nhn m ng dng lin lc hin th cho iu khin giao din ngi dng, l iu
khin cho php ngi dng xem cc nhm trong ng dng ca bn.

V d, nu ci t ng dng Google+ trn thit b v ng b Google+ vi ng


dng lin lc, bn s thy nhng vng kt ni (circle) Google+ c lit k thnh
cc nhm trong tab Groups ca ng dng lin lc. Nu nhn vo nhm Google+,
bn s thy mi ngi trong vng kt ni ny c lit k nh mt nhm. u

262

Lp trnh Android c bn
vng hin th cc lin lc Google+, s xut hin mt biu tng ca Google+; nu
bn nhn vo biu tng ny, iu khin s c chuyn hng sang ng dng
Google+. ng dng lin lc lm c iu ny thng qua viewGroupActivity,
s dng biu tng Google+ lm gi tr cho viewGroupActionLabel.
Thuc tnh ny cng c th s dng mt nh danh ti nguyn dng chui.

viewStreamItemActivity
Tn lp y ca activity trong ng dng ca bn m ng dng lin lc khi ng
khi ngi dng nhn vo mt hng mc lung ca d liu lin lc th.

viewStreamItemPhotoActivity
Tn lp y ca activity trong ng dng m ng dng lin lc khi ng khi
ngi dng nhn vo mt nh trong hng mc lung ca d liu lin lc th.

Phn t <ContactsDataKind>
Phn t <ContactsDataKind> iu khin vic hin th cc hng d liu ty chnh
cho ng dng bn pht trin trong giao din ngi dng ca ng dng lin lc. Phn
t ny c c php nh sau:
<ContactsDataKind
android:mimeType=MIMEtype
android:icon=icon_resources
android:summaryColumn=column_name
android:detailColumn=column_name>

nm trong:

<ContactsAccountType>
M t:
S dng phn t ny ng dng lin lc hin th ni dung ca hng d liu ty
chnh lm mt phn trong cc thng tin chi tit ca d liu lin lc th. Mi phn t
con <ContactsDataKind> ca <ContactsAccountType> i din cho mt kiu
hng d liu ty chnh m adapter c chc nng ng b ca bn thm vo bng
ContactsContract.Data. Thm mt phn t <ContactsDataKind> vo mi
kiu MIME ty chnh bn s dng. Bn khng phi thm phn t ny nu y l hng
d liu ty chnh m bn khng mun hin th d liu.
Thuc tnh:

android:mimeType
Kiu MIME ty chnh m bn nh ngha cho mt trong nhng kiu hng d
liu ty chnh ca mnh ti bng ContactsContract.Data . V d, gi tr
vnd.android.cursor.item/vnd.example.locationstatus c th l
kiu MIME ty chnh cho hng d liu ghi li v tr mi nht ca lin lc.

263

Lp trnh Android c bn
android:icon
Mt ti nguyn drawable (drawable resource) ca Android m ng dng lin lc
hin th bn cnh d liu ca bn. S dng thuc tnh ny ch cho ngi dng
bit rng d liu n t service ca bn.

android:summaryColumn
Tn ct ca gi tr u tin trong hai gi tr c truy xut t hng d liu. Gi tr
ny khi c hin th l dng u tin ca mc cho hng d liu ny. Hng u tin
c mc ch s dng l thng tin tng kt ca d liu, nhng l d liu ty chn (c
th c hoc khng). Xem thm thuc tnh android:detailColumn.

Android:detailColumn
Tn ct ca gi tr th hai trong hai gi tr c truy xut t hng d liu. Gi tr
ny c hin th l dng th hai ca mc cho hng d liu ny. Xem thm thuc
tnh android:summaryColumn.

Cc tnh nng b sung ca Provider Contacts


Bn cnh nhng tnh nng chnh m t trong cc mc trc, Provider Contactsh tr
nhng tnh nng hu dng di y lm vic vi d liu lin lc:

Nhm lin lc.

Cc tnh nng lin quan n nh.

Nhm lin lc
Provider Contactsc th gn nhn ty chn cho tp cc lin lc lin quan thnh d liu
nhm (group). Nu server lin kt vi ti khon ngi dng mun duy tr cc nhm,
adapter c chc nng ng b ca loi ti khon ny phi truyn d liu nhm gia
Provider Contactsv server. Khi ngi dng thm mt lin lc mi vo server, sau
a lin lc ny vo mt nhm mi, adapter c chc nng ng b phi thm nhm
mi vo bng ContactsContract.Groups. Nhm hoc cc nhm cha mt d
liu lin lc th c lu trong bng ContactsContract.Data, s dng kiu MIME
ContactsContract.CommonDataKinds.GroupMembership.
Nu bn ang thit k mt adapter c chc nng ng b thm d liu lin lc
th t server vo Provider Contacts, ng thi ang khng s dng nhm, bn
cn yu cu provider hin th d liu ny. Trong m thc thi khi ngi dng thm
ti khon vo thit b, cp nht hng ContactsContract.Setting m
Provider Contacts thm vo ti khon ny. Trong hng ny, thit lp gi tr ca ct
Settings.UNGROUPED_VISIBLE l 1. Khi thc hin iu ny, Provider Contactslun
hin th d liu lin lc , ngay c khi bn khng s dng nhm.

nh ca lin lc
Bng ContactsContract.Data lu tr nh di dng cc hng c kiu MIME l
Photo.CONTENT_ITEM_TYPE. Ct CONTACT_ID ca hng ny c lin kt vi ct
_ID ca d liu lin lc th cha nh ny. Lp ContactsContract.Contacts.Photo

264

Lp trnh Android c bn
nh ngha mt bng con ca bng ContactsContract.Contacts cha thng tin
nh cho nh chnh ca mt lin lc, y cng l nh chnh cho d liu lin lc th chnh
ca lin lc. Tng t, lp ContactsContract.RawContacts.DisplayPhoto
nh ngha mt bng con ca bng ContactsContract.RawContacts cha thng
tin nh cho nh chnh ca d liu lin lc th.
Ti liu tham kho ca ContactsContract.Contacts.Photo v
ContactsContract.RawContacts.DisplayPhoto cha cc v d minh ha
v truy xut thng tin nh. Khng c lp no tin cho vic truy xut nh i din chnh cho mt
d liu lin lc th, nhng bn c th gi mt truy vn ti bng ContactsContract.Data,
chn _ID ca d liu lin lc th, Photo.CONTENT_ITEM_TYPE v ct IS_PRIMARY
tm hng nh chnh ca d liu lin lc th.
D liu lung t mng x hi ca mt ngi cng c th bao gm nh. Cc nh ny
c lu tr ti bng ContactsContract.StreamItemPhotos, c m t chi
tit hn trong mc D liu nh trn lung t mng x hi.

11. Thit k sao cho ng dng c th phn hi tt


Chng ta c th vit m vt qua mi php kim th v hiu nng trn th gii, song
vn cm thy chm, b treo hoc ng bng (ngng x l) ti mt s thi im, hoc
mt nhiu thi gian cho vic x l u vo. iu ti t nht c th xy ra vi vic phn
hi ca ng dng bn pht trin l xut hin hp thoi Application Not Responding
(ANR) (ng dng khng phn hi).
Trong h iu hnh Android, h thng s theo di trnh xy ra tnh trng cc ng
dng phn hi qu chm trong mt khong thi gian bng cch hin th hp thoi thng
bo rng ng dng ca bn dng phn hi, chng hn nh hp thoi Hnh 1. Ti
thi im ny, ng dng ca bn khng phn hi trong mt khong thi gian ng
k nht nh; do vy, h thng cung cp mt ty chn cho ngi dng thot khi
ng dng. l gii hn thit k phn hi bn trong ng dng ca bn sao cho h
thng khng bao gi phi hin th hp thoi ANR ti ngi dng.
Phn ny m t cch h thng Android xc nh xem mt ng dng c khng phn hi
hay khng v cung cp hng dn m bo ng dng ca bn lun phn hi kp
thi yu cu t ngi dng.

Ch thch
Hello World isnt responding:
ng dng Hello World khng
phn hi
Do you want to close it? :
Bn c mun dng ng dng?
Wait:
Tip tc i phn hi

Hnh 1. Mt hp thoi ANR c hin th cho ngi dng.

265

Lp trnh Android c bn

Trigger ANR l g?
Nhn chung, h thng s hin th mt ANR nu ng dng khng th phn hi u vo
ca ngi dng. V d, nu mt ng dng chn (block) mt s thao tc I/O (Input/Output
- Nhp/Xut) (thng l truy cp mng) trn lung giao din ngi dng (UI thread),
h thng s khng th x l s kin nhp liu ca ngi dng khi n xy ra. Hoc, ng
dng c th mt qu nhiu thi gian xy dng mt cu trc phc tp trong b nh,
hoc tnh ton bc di chuyn tip theo trong mt tr chi trn lung giao din ngi
dng. Bi vy, iu quan trng l cn m bo rng nhng tnh ton ny thc s em
li hiu qu; th nhng, m hiu qu nht vn gy tn thi gian cho vic chy.
Trong mt tnh hung bt k m ti , ng dng ca bn thc hin mt thao tc tn
thi gian ng k, bn khng nn thc hin hot ng ny trn lung giao din
ngi dng. Thay vo , hy to mt lung cng vic (worker thread) v thc hin
hu ht cc vic ti y. iu ny gi cho lung giao din ngi dng - lung iu khin
vng lp s kin giao din ngi dng - chy v trnh cho h thng khi kt lun rng
m ca bn b ng bng (ngng hot ng). Do vic chy lung nh vy thng c
tin hnh ti mc lp, nn bn c th ngh ti vic phn hi nh mt vn v lp. (So
snh vi hiu sut m c bn, vic ny phi x l mc phng thc).
Trong Android, phn hi ca ng dng c cc service ca h thng, bao gm Activity
Manager (trnh qun l activity) v Window Manager (trnh qun l Window) iu khin.
Android lun hin th hp thoi ANR cho mt ng dng c th khi h iu hnh ny pht
hin mt trong nhng trng hp sau:

Khng c phn hi cho mt s kin u vo (chng hn nh s kin nhn phm


hoc s kin chm vo mn hnh) trong vng 5 giy.

i tng BroadcastReceiver khng hon thnh x l trong vng 10 giy.

Cch trnh hp thoi ANR


Thng thng, ng dng Android chy hon ton trn mt lung n mc nh l
lung giao din ngi dng hoc lung chnh. iu ny c ngha l, mi hot ng
ng dng thc hin trong lung giao din ngi dng, nu mt nhiu thi gian hon
thnh, c th lm xut hin hp thoi ANR. l v ng dng ca bn khng c c hi
x l s kin u vo hoc intent broadcast.
Do , bt c phng thc no chy trong lung giao din ngi dng cng nn
thc hin t vic nht c th trong lung ny. C th, cc activity nn thc hin t vic
nht c th trong nhng phng thc lin quan n vng i nh onCreate() v
onResume(). Cc thao tc tn nhiu thi gian, chng hn nh thao tc mng hoc c
s d liu, hay nhng php tnh cn phi tnh ton nhiu nh tnh li kch thc nh
bitmap, nn c thc hin trong lung cng vic (hoc trong trng hp cc thao tc
c s d liu s dng mt yu cu khng ng b).

266

Lp trnh Android c bn
Cch hiu qu nht to lung cng vic cho cc thao tc di l to bng lp
AsyncTask. n gin l m rng (extend) lp AsyncTask v ci t phng thc
doInBackground() thc hin vic ny. chuyn cc thay i ca tin trnh
ti ngi dng, bn c th gi phng thc publishProgress(), l phng thc
gi phng thc callback onProgressUpdate(). Trong bn ci t phng thc
onProgressUpdate() ca mnh (phng thc chy trn lung giao din ngi
dng), bn c th thng bo cho ngi dng thng tin h cn bit. V d:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {

// Thc hin cc thao tc tn nhiu thi gian ti y


protected Long doInBackground(URL... urls){

int count = urls.length;

for(int i =0; i < count; i++){

long totalSize =0;

totalSize +=Downloader.downloadFile(urls[i]);

// Thot ra sm nu phng thc cancel() c gi

publishProgress((int)((i /(float) count)*100));


if (isCancelled())

break;

return totalSize;

// Phng thc sau c gi mi khi bn gi phng thc

protected void onProgressUpdate(Integer... progress){

// publishProgress()

setProgressPercent(progress[0]);

// Phng thc sau c gi khi phng thc doInBackground() hon

protected void onPostExecute(Long result){

// thnh

showNotification(Downloaded + result + bytes);

chy lung cng vic ny, bn ch cn to mt th hin cho lp trn v gi phng


thc execute():
new DownloadFilesTask().execute(url1, url2, url3);

Mc d iu ny phc tp hn vic ci t lp AsyncTask, nhng c th bn vn


mun ci t lp Thread hay mt lp HandlerThread ca chnh mnh. Khi thc
hin, bn nn thit lp mc u tin ca lung l mc u tin background (chy
ngm) bng cch gi phng thc Process.setThreadPriority() v truyn
THREAD_PRIORITY_BACKGROUND. Nu khng thit lp lung do bn xy dng c

267

Lp trnh Android c bn
mc u tin thp theo cch ny, c th lung vn lm chm ng dng ca bn, do mc
nh lung c to ra hot ng mc u tin ging vi lung giao din ngi dng.
Nu ci t lp Thread hoc HandlerThread, cn m bo lung giao din ngi
dng ca bn khng b chn trong khi ch lung cng vic hon thnh - khng gi
phng thc Thread.wait() hay Thread.sleep(). Thay v chn chng trnh
trong khi ch lung cng vic hon thnh, lung chnh ca bn nn cung cp mt i
tng Handler cho cc lung khc gi tr li iu khin sau khi hon thnh. Thit
k ng dng ca bn theo cch ny s cho php lung giao din ngi dng ca ng
dng duy tr vic phn hi cho hot ng u vo, t trnh c hp thoi ANR khi
khng kp phn hi hot ng u vo trong vng 5 giy.
Rng buc c th v thi gian thc thi BroadcastReceiver nhn mnh vo nhng g
broadcast receiver phi lm: Thc hin s lng thao tc nh, ri rc trong lung chy
ngm, chng hn nh lu mt thit lp hoc ng k mt thng bo Notification.
Do , vi cc phng thc khc c gi trong lung giao din ngi dng, ng
dng phi trnh nhng thao tc hoc tnh ton tn nhiu thi gian trong broadcast
receiver. Tuy nhin, thay v thc hin cc tc v chuyn su thng qua lung cng vic,
bn nn pht trin ng dng theo hng khi ng mt IntentService nu cn
thc hin mt action mt nhiu thi gian phn hi mt intent broadcast.
Mch nh: Bn c th s dng StrictMode tm cc thao tc tn nhiu thi
gian, chng hn nh thao tc vi mng hoc trn c s d liu m bn v tnh thc
hin trong lung chnh ca mnh.

Tng cng phn hi


Thng thng, khong thi gian t 100 n 200 mili giy l ngng ti a ngi
dng c th nhn ra rng ng dng ca bn ang b chm. Do , sau y l mt s
mo khc m bn nn thc hin trnh hp thoi ANR, ng thi khin ng dng ca
bn dng nh lun phn hi ngi dng:

Nu ng dng ang thc hin cc thao tc chy ngm phn hi thao tc u


vo ca ngi dng, hy minh ha vic tin trnh ang c x l (chng hn nh
s dng ProgressBar trong giao din ngi dng ca bn).

Ring vi game, hy tnh ton cc bc di chuyn trong tin trnh worker (hay cn
gi l lung cng vic).

Nu ng dng ca bn c pha thit lp khi to tn nhiu thi gian, hy ngh ti


vic hin th mt mn hnh splash (mn hnh xut hin t t) hoc xut ra mn hnh
chnh sao cho nhanh nht c th, cho bit ng dng ang x l vic np v nhp
cc thng tin ng b. Trong c hai trng hp, bn nn ch ra rng v mt vi l
do no cha r m tin trnh ang c x l, ngi dng khng cho rng
ng dng b ng bng (ngng x l).

S dng cc cng c kim tra hiu sut nh Systrace v Traceview xc nh


im tc nghn (bottleneck) ca vic phn hi trong ng dng do bn pht trin.

268

Lp trnh Android c bn

12. Service
Service (dch v) l mt thnh phn ca ng dng, c th thc hin cc thao tc tn
thi gian chy ngm v khng cung cp giao din ngi dng. Cc thnh phn khc
ca ng dng c th khi ng mt service v service s tip tc chy ngm ngay c
khi ngi dng chuyn sang ng dng khc. Ngoi ra, mi thnh phn c th lin kt
vi mt service tng tc vi service , thm ch thc hin cc giao tip lin tin
trnh (interprocess communication - IPC). V d, mt service c th x l cc giao dch
mng, pht nhc, thc hin nhp/xut file hoc tng tc vi mt content provider, tt
c u chy ngm.
V c bn, mt service c th nhn hai dng sau:
Khi ng
Mt service c gi l service khi ng (started) khi mt thnh phn ca ng
dng (chng hn nh mt activity) khi ng service bng cch gi phng
thc startService(). Khi c khi ng, mt service c th chy ngm v
hn nh, thm ch ngay c khi thnh phn khi ng service b hy. Mt service
c khi to thng thc hin mt thao tc n v khng tr li kt qu cho
thnh phn gi. V d, service ny c th ti v hoc y mt file ln trn mng. Khi
thao tc ny hon thnh, service ny nn t dng li.
C lin kt
Mt service c gi l c lin kt (bound) khi mt thnh phn ca ng dng
gn vi service ny bng cch gi phng thc bindService(). Service c lin
kt cung cp giao din client-server cho php cc thnh phn tng tc vi service
ny, gi yu cu, nhn kt qu, thm ch l thc hin cc tin trnh cho (across
process) vi cc giao tip lin tin trnh. Mt service c lin kt ch chy vi lng
thi gian tng t thnh phn ng dng khc c gn vi service ny. Nhiu
thnh phn c th gn cng lc vi mt service kiu ny, nhng khi tt c trong s
chng khng cn lin kt, service b hy.
Nhn chung, ti liu ny s tho lun ring v hai kiu service trn, nhng service ca
bn c th thc hin theo c hai cch - c th c khi ng (chy v hn nh) v
cng cho php vic lin kt. Bn c th d dng thc hin iu ny bng cch ci t
c hai phng thc callback: Phng thc onStartCommand() cho php cc thnh
phn khi ng service v phng thc onBind() to lin kt.
Bt k ng dng ca bn khi ng, c lin kt hay c hai, bt c thnh phn ng
dng no cng c th dng service ny (thm ch t mt ng dng khc), ging nh
cch thnh phn bt k c th s dng mt activity - bng cch khi ng service vi
cng mt Intent. Tuy nhin, bn c th khai bo service ny l private (ring t), trong
file k khai, ng thi kha vic truy cp t cc ng dng khc. Mc Khai bo service
trong file k khai bn di s c tho lun chi tit hn v ni dung ny.
Ch : Service s chy trong lung chnh ca tin trnh cha n - service khng to
lung ring v khng chy trong tin trnh ring (tr phi bn quy nh kiu khc). iu
ny c ngha l, nu service s thc hin cng vic chim nhiu b x l trung tm
(Central Processing Unit - CPU) hoc chn cc thao tc (chng hn nh pht nhc
MP3 hoc kt ni mng), bn nn to mt lung mi bn trong service thc hin

269

Lp trnh Android c bn
cng vic ny. Bng cch s dng mt lung ring, bn s lm gim ri ro xut hin li
ANR (Application Not Responding - ng dng khng phn hi) v lung chnh ca ng
dng c th vn dnh ngi dng tng tc vi activity ca bn.

C bn v service
Bn nn s dng service hay lung?
Service ch n gin l mt thnh phn c th chy ngm ngay c khi ngi dng
khng tng tc vi ng dng. Do vy, bn ch nn to mt service nu l nhng
g bn cn.
Nu cn thc hin cng vic bn ngoi lung chnh (main thread), nhng ch trong khi
ngi dng ang tng tc vi ng dng, bn nn to mt lung mi, khng phi l
service. V d, nu mun pht nhc, nhng ch trong lc activity ca mnh ang chy,
bn c th to mt lung trong phng thc onCreate(), chy lung ny bng
phng thc onStart(), sau dng bng phng thc onStop(). Ngoi ra,
bn nn cn nhc s dng AsyncTask hay HandlerThread, thay v s dng lp
Thread truyn thng. Xem ti liu hng dn Processes and Threads (Tin trnh v
lung) tm hiu thm thng tin v lung.
Cn nh rng, nu bn s dng mt service, th mc nh service s chy trong
lung chnh ca ng dng. Do , bn vn nn to mt lung mi bn trong service nu
service ny thc hin cc thao tc chim nhiu b x l hoc thao tc chn.
to mt service, bn phi to mt lp con ca lp Service (hoc mt trong nhng
lp con c ca lp ny). Trong phn ci t, bn nn ghi (override) mt vi
phng thc callback x l cc cng vic chnh trong vng i ca service, ng
thi cung cp mt c ch cho cc thnh phn lin kt vi service ny, nu thch hp.
Cc phng thc callback quan trng nht cn ghi l:

onStartCommand()
H thng s gi phng thc ny khi mt thnh phn khc, chng hn nh mt activity, yu cu khi ng mt service bng cch gi startService(). Khi phng
thc ny thc thi, service c khi to v c th chy ngm v hn nh. Nu ci t
phng thc ny, nhim v ca bn l dng service khi hon thnh cng vic, bng
cch gi phng thc stopSelf() hoc stopService(). (Nu ch mun cung cp
lin kt, bn khng cn ci t phng thc ny).

onBind()
H thng gi phng thc ny khi thnh phn khc mun lin kt vi service, chng
hn nh thc hin RPC (Remote Procedure Call - Th tc gi hm t xa), bng cch
gi phng thc bindService(). Khi ci t phng thc ny, bn phi cung
cp giao din cho nhng client dng giao tip vi service, bng cch tr v mt
IBinder. Bn lun phi ci t phng thc ny, nhng nu khng mun to lin kt,
bn nn tr v null.

onCreate()
H thng gi phng thc ny khi service c to ln u, nhm thc hin cc th
tc thit lp mt ln (trc khi h thng gi phng thc onStartCommand() hoc

270

Lp trnh Android c bn
onBind()). Nu service chy, phng thc ny khng c gi.
onDestroy()
H thng gi phng thc ny khi service khng cn c s dng v s b hy b.
Service ca bn nn ci t phng thc ny dn sch bt c ti nguyn no ang
s dng, chng hn nh lung, trnh lng nghe ng k (registered listener), trnh
nhn (receiver),... y l li gi cui cng service nhn c.
Nu mt thnh phn khi ng service bng cch gi phng thc startService()
(dn n vic gi phng thc onStartCommand()), service vn chy cho n khi
t dng bng phng thc stopSelf(), hoc khi thnh phn khc dng service ny
bng cch gi phng thc stopService().
Nu mt thnh phn gi phng thc bindService() to mt service (v phng
thc onStartCommand() khng c gi), service ny ch chy vi lng thi gian
tng t thnh phn gn vi n. Khi mt service khng c gn vo bt k client no,
h thng s hy service .
H thng Android ch p mt service dng khi sp ht b nh v h iu hnh phi
khi phc ti nguyn h thng cho activity c ngi dng ang focus. Nu service ny
c gn vi mt activity m ngi dng ang focus th t c kh nng b p dng. Nu
service c khai bo chy trn ch mn hnh chnh (s c tho lun sau),
hu nh service s khng bao gi b p dng. Mt khc, nu service c khi
to v s chy trong thi gian di, h thng s gim v tr ca service ny trong danh
sch cc tc v chy ngm qu hn v service s c kh nng cao b p dng - nu
l service khi ng, bn phi thit k sao cho h thng c th khi ng li service
ny. Khi , nu h thng p service dng, n s khi ng li service ny ngay khi
c ti nguyn (mc d vic ny cn ph thuc vo gi tr bn tr v t phng thc
onStartCommand(), s c bn lun sau). tm hiu thm v thi im h thng
c th hy b mt service, xem mc hng dn v Tin trnh v lung.
Trong cc mc di y, bn s tm hiu cch thc to mi loi service trn v s dng
tng loi service ny t cc thnh phn khc ca ng dng.

Khai bo mt service trong file k khai


Tng t activity (v cc thnh phn khc), bn phi khai bo tt c cc service trong
file k khai ca ng dng.
khai bo mt service, bn thm mt phn t <service> lm phn t con ca phn
t <application>. V d:
<manifest ... >
...

<application ... >

<serviceandroid:name=.ExampleService/>

...

</application>

</manifest>

271

Lp trnh Android c bn
Bn c th thm vo phn t <service> cc thuc tnh khc nh ngha nhng
tnh cht nh cc quyn cn thit khi ng service v tin trnh chy service ny.
Thuc tnh android:name l thuc tnh bt buc duy nht, xc nh tn lp cho service. Khi pht hnh ng dng, bn khng nn thay i tn ny bi nu thay i, bn
c th ph hng mt s chc nng cha cc intent tng minh (explicit intent) c
dng tham chiu n service ca bn (c bi ng trn blog, Things That Cannot
Change - tm dch: Nhng th khng th thay i).
Xem ti liu tham kho v phn t <service> tm hiu thm v cch khai bo
service trong file k khai (manifest file) .
Tng t activity, service c th nh ngha b lc intent cho php nhng thnh
phn khc gi service ny thng qua cc intent ngm nh (implicit intent). Bng cch
khai bo cc b lc intent, nhng thnh phn t mt ng dng bt k c ci t trn
thit b ngi dng c th khi ng service ca bn, nu service miu t mt b lc
intent ph hp vi intent m ng dng truyn vo phng thc startService().
Nu ln k hoch ch s dng service do mnh pht trin mt cch cc b (cc ng
dng khc khng c dng service ny), bn khng cn (v cng khng nn) cung
cp bt c b lc intent no. Khng c b lc intent, bn phi khi ng service bng
cch s dng mt intent xc nh r tn cho lp service. Chi tit v vic khi ng mt
service s c tho lun sau.
Ngoi ra, bn c th m bo service l dnh ring cho ng dng mnh ang pht trin
ch bng cch thm thuc tnh android:exported v thit lp l false. y l
tnh nng hiu qu ngay c khi service c cung cp b lc intent.
tm hiu thm v cch to b lc intent cho service ca bn, xem ti liu hng dn
v Intent v b lc intent.

To service dng khi ng


Service dng khi ng l service m phn t khc khi ng bng cch gi
phng thc startService(), dn n kt qu l mt li gi ti phng thc
onStartCommand() ca service.
Khi c khi ng, vng i ca service s khng ph thuc vo thnh phn khi
ng n v service s chy ngm v hn nh, ngay c khi thnh phn khi ng
service b hy. Do , service phi t dng khi cng vic hon thnh bng cch gi
phng thc stopSelf(), hoc thnh phn khc c th dng service ny bng cch
gi phng thc stopService().
Mt thnh phn ca ng dng, chng hn nh activity, c th khi ng service ny
bng cch gi phng thc startService() v truyn vo mt Intent xc nh
service, sau bao gm d liu bt k service s dng. Service nhn Intent ny
trong phng thc onStartCommand().
Chng hn, gi s mt activity cn lu mt s d liu ln c s d liu trc tuyn.
Activity ny c th khi ng mt service v truyn cho service ny d liu cn lu
bng cch truyn mt intent vo phng thc startService(). Service ny nhn
intent trn trong phng thc onStartCommand(), kt ni vi Internet v thc hin
giao dch c s d liu. Khi giao dch ny hon thnh, service t dng, t h thng
s hy n.

272

Lp trnh Android c bn
Ch : Mt service s chy trong cng tin trnh vi ng dng khai bo n v mc nh
l trong lung chnh ca ng dng. Do vy, nu service ca bn thc hin cc thao
tc s dng nhiu b x l hoc thao tc chn trong khi ngi dng tng tc vi mt
activity cng ng dng, service ny s lm chm hiu sut ca activity. Nhm trnh
lm nh hng n hiu sut ng dng, bn nn khi ng mt lung mi bn trong
service.
V c bn, bn cn m rng hai lp sau to mt service dng khi ng:

Service
y l lp c bn ca mi service. Khi m rng lp ny, quan trng l bn cn to
mt lung mi trong lp thc hin tt c cc cng vic ca service. V mc nh
l service s dng lung chnh ca ng dng, nn c th lm chm hiu sut ca
bt c activity no m ng dng ang chy.

IntentService
y l lp con ca Service s s dng lung cng vic (worker thread) x l
ton b yu cu khi ng, mi yu cu c x l ti mt thi im. y l la
chn tt nht nu bn khng yu cu service ca mnh x l cng lc nhiu yu
cu. Tt c nhng g bn cn lm l ci t onHandleIntent(), l phng
thc s nhn intent cho mi yu cu khi ng bn c th thc hin cng vic
chy ngm.
Cc mc di y s hng dn ci t service ca bn bng cch s dng mt trong
nhng lp trn.

M rng lp IntentService
Do hu ht service dng khi ng khng cn x l cng lc nhiu yu cu (y
thc s l mt kch bn a lung (multi-threading) nguy him), nn vic s dng lp
IntentService ci t service ca bn c th l s la chn tt nht.
Lp IntentService thc hin cc cng vic sau:

To mt lung cng vic mc nh thc thi tt c cc intent truyn ti phng thc


onStartCommand() phn tch vi lung chnh ca ng dng.

To mt hng i (queue) cng vic, truyn tng intent theo tng thi im
ti phn ci t onHandleIntent() , bn khng bao gi phi lo lng v
a lung.

Dng service ny sau khi tt c cc yu cu khi ng c x l, bn


khng bao gi phi gi phng thc stopSelf().

Ci t mc nh cho phng thc onBind() tr v null.

Ci t mc nh cho phng thc onStartCommand() gi intent ti hng i


cng vic, sau ti phn ci t onHandleIntent() ca bn.

Mi iu trnh by trn minh chng cho thc t rng tt c nhng vic bn cn lm


l ci t phng thc onHandleIntent() thc hin cng vic m client yu
cu. (Mc d vy, bn cng cn cung cp mt phng thc khi to n gin cho
service ny).

273

Lp trnh Android c bn
Sau y l mt v d v ci t IntentService:
public class HelloIntentService extends IntentService {
/**

* Cn mt phng thc khi to, v phi gi phng thc khi to *


ca lp cha IntentService(String)vi tn ca lung cng vic.

*/

public HelloIntentService() {

super(HelloIntentService);

/**

* IntentService gi phng thc ny trong lung cng vic mc nh


* Khi phng thc tr v kt qu, IntentService dng
* service khi thch hp.

*/

@Override

protected void

onHandleIntent(Intent intent){

// Thng thng, bn s thc hin mt vi thao tc ti y,


// chng hn nh ti file v.

long endTime = System.currentTimeMillis() + 5*1000;

// Trong v d ny, chng ta ch tm ngh (sleep)


// chng trnh trong vng 5 giy.
while(System.currentTimeMillis()< endTime){

synchronized(this){

try {

} catch(Exception e) {

wait(endTime -System.currentTimeMillis());

}
}
}
}
}

Tt c nhng g bn cn l: Mt phng thc khi to v ci t phng thc


onHandleIntent().
Nu bn cng quyt nh ghi cc phng thc callback khc, chng hn nh
onCreate(), onStartCommand() hoc onDestroy(), hy m bo bn gi
phng thc cha ca chng, IntentService c th x l ng chu k sng ca
lung cng vic.
V d, phng thc onStartCommand() phi tr v cc thao tc c ci t mc
nh (y l cch gi intent n onHandleIntent()):

274

Lp trnh Android c bn
@Override

public int onStartCommand(Intent intent, int flags, int startId) {




}

Toast.makeText(this,service starting,Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);

Bn cnh phng thc onHandleIntent(), ch c mt phng thc m t , bn


khng cn gi lp cha l onBind() (ch cn ci t service ca bn c lin kt
vi thnh phn ng dng khc).
mc tip theo, bn s c hng dn ci t mt loi service tng t bng cch
m rng lp Service c bn. Phng php ny s dng nhiu m hn, nhng s
ph hp nu bn cn x l cng lc nhiu yu cu khi ng.

M rng lp Service
Nh bn thy mc trc, s dng IntentService ci t mt service
dng khi ng l vic rt n gin. Tuy nhin, nu cn service x l a lung (thay v
x l yu cu khi ng thng qua mt hng i cng vic), bn c th m rng lp
Service x l tng intent.
so snh, m v d di y ci t lp Service thc hin cng vic hon ton
ging v d trn (s dng IntentService). C th, vi mi yu cu khi ng,
chng trnh s s dng mt lung cng vic thc hin cng vic v ch x l mt
yu cu vo mt thi im:
public classHelloService extends Service {
private Looper mServiceLooper;

private ServiceHandler mServiceHandler;


// Trnh x l (handler) nhn thng ip t lung

private final class ServiceHandler extends Handler {


public ServiceHandler(Looper looper) {
}

super(looper);

@Override

public void handleMessage(Message msg){

// Thng thng, bn s thc hin mt vi thao tc ti y,


// chng hn nh ti file v. Trong v d ny, chng ta
// ch tm ngh (sleep) chng trnh trong vng 5 giy.

long endTime =System.currentTimeMillis()+5*1000;


while(System.currentTimeMillis()< endTime){
synchronized(this){
try {

275

Lp trnh Android c bn
wait(endTime -System.currentTimeMillis());

} catch(Exception e) {

// Dng service bng cch s dng startId, khng phi dng


// service ny khi ang x l cng vic khc

stopSelf(msg.arg1);

@Override

public void onCreate(){

// Khi ng lung chy service ny. Lu , chng ta to mt lung

// ring, bi v service thng chy trong lung chnh ca tin trnh,

// y l lung m chng ta khng mun chn. Chng ta cng c th


// t cho lung ny mc u tin l chy ngm, cc thao tc

// cn nhiu CPU s khng ngt giao din ngi dng ca chng ta.

HandlerThread thread = new HandlerThread(ServiceStartArguments,


Process.THREAD_PRIORITY_BACKGROUND);

thread.start();

// Ly trnh lp (looper) ca HandlerThread v s dng trnh ny


// cho Handler (trnh x l) ca chng ta
mServiceLooper = thread.getLooper();
}

mServiceHandler == new ServiceHandler(mServiceLooper);

@Override

public int onStartCommand(Intent intent,int flags,int startId){

Toast.makeText(this,service starting,Toast.LENGTH_SHORT).show();
// Vi mi yu cu khi ng, gi thng ip khi ng

// cng vic v gi i start ID chng ta c th nhn bit


// yu cu s dng khi hon thnh vic ny.

Message msg = mServiceHandler.obtainMessage();


msg.arg1 = startId;

mServiceHandler.sendMessage(msg);

// Nu service ny b dng, sau khi tr li kt qu


// t y, khi ng li service
}

276

return START_STICKY;

Lp trnh Android c bn
@Override

public IBinder onBind(Intent intent) {

// Chng ta khng cung cp lin kt, do tr v null

return null;

@Override

public void onDestroy() {

Toast.makeText(this,service done,Toast.LENGTH_SHORT).show();

Nh bn thy, c nhiu vic phi lm hn l s dng IntentService.


Tuy nhin, do bn x l mi li gi ti phng thc onStartCommand() ca mnh,
nn bn c th thc hin cng lc nhiu yu cu. khng phi nhng g v d trn
thc hin nhng nu mun, bn c th to mt lung mi cho tng yu cu v chy
ng cch (thay v ch cho yu cu trc hon thnh).
Lu , phng thc onStartCommand() phi tr v mt s nguyn (integer). S
nguyn ny l mt gi tr m t cch h thng nn thc hin vi service khi h thng p
dng n (nh bn trn, ci t mc nh ca IntentService s x l vic ny,
mc d bn c th t x l n). Gi tr tr v t phng thc onStartCommand()
phi l mt trong nhng hng sau:

START_NOT_STICKY
Nu h thng dng service sau khi phng thc onStartCommand() tr v,
khng to li service, tr phi c intent trng thi ch gi i. y l la chn an
ton nht trnh chy service khi khng cn thit, cng nh khi ng dng ca
bn c th khi ng li bt c cng vic no cha hon thnh.

START_STICKY
Nu h thng dng service sau khi phng thc onStartCommand() tr v,
hy to li service v gi onStartCommand(), nhng khng gi li intent
cui cng. Thay vo , h thng s gi phng thc onStartCommand() vi
mt intent c gi tr null, tr phi c intent trng thi ch khi ng service ny;
trong trng hp , nhng intent ny s c gi i. Cch x l ny ph hp vi
cc trnh pht a phng tin (media player), hoc nhng service tng t, l cc
service khng thc thi lnh, nhng chy v hn nh v ch thc hin cng vic.

START_REDELIVER_INTENT
Nu h thng dng service sau khi phng thc onStartCommand() tr v,
hy to li service v gi phng thc onStartCommand() vi intent cui cng
c gi ti service. Bt c intent trng thi ch no cng s ln lt c gi
i. Cch x l ny ph hp vi cc service ang ch ng thc hin cng vic cn
c khi phc li ngay lp tc, chng hn nh vic ti file v.

277

Lp trnh Android c bn
tm hiu thm v cc hng tr v ny, xem ti liu tham kho tng ng vi
mi hng.

Khi ng service
Bn c th khi ng mt service t activity hoc thnh phn khc cu thnh ng
dng bng vic truyn mt Intent (xc nh service khi ng) vo phng thc
startService(). H thng Android gi phng thc onStartCommand() ca
service ny v truyn Intent trn cho service . (Li khuyn cho bn l ng bao
gi gi trc tip phng thc onStartCommand()).
V d, mt activity c th khi ng service v d trong mc trc (HelloService) bng
cch s dng mt intent tng minh vi phng thc startService():
Intent intent == new Intent(this, HelloService.class);
startService(intent);

Phng thc startService() tr v kt qu ngay lp tc v h thng Android gi


phng thc onStartCommand() ca service ny. Nu service cha chy, h thng
s gi phng thc onCreate() trc, sau gi onStartCommand().
Nu service khng cung cp lin kt, intent s c gi i vi phng thc
startService(), cng l ch duy nht kt ni gia thnh phn ca ng
dng v service. Tuy nhin, nu bn mun service gi kt qu tr li, client khi
ng service c th to mt PendingIntent broadcast (bng phng thc
getBroadcast()) v pht PendingIntent ny ti service trong Intent khi ng
service. Nh , service c th dng broadcast gi kt qu i.
Nu c nhiu yu cu khi ng service th s c nhiu li gi phng thc
onStartCommand() tng ng. Tuy nhin, ch cn c mt yu cu dng
service (bng phng thc stopSelf() hoc stopService() ) l c th
dng service c.

Dng service
Mt service dng khi ng phi qun l vng i ca chnh n. Ngha l, h thng s
khng dng hoc hy service ny, tr phi h thng cn khi phc b nh v service
tip tc chy sau khi phng thc onStartCommand() tr v. Do , service phi
t dng bng cch gi phng thc stopSelf(), hoc gi thnh phn khc c th
dng service ny bng cch gi phng thc stopService().
Khi c yu cu dng vi phng thc stopSelf() hoc stopService(), h
thng s hy service ngay khi c th.
Tuy nhin, nu service ca bn x l nhiu yu cu onStartCommand() cng lc,
bn khng nn dng service khi ang thc hin x k mt yu cu khi ng, bi v
bn c th nhn mt yu cu khi ng mi (vic dng service cui yu cu u
tin c th s kt thc yu cu th hai). trnh vn ny, bn c th s dng
phng thc stopSelf(int) m bo rng yu cu dng service lun da
trn yu cu khi ng mi nht. C th, khi gi phng thc stopSelf(int),
bn truyn vo ID ca yu cu khi ng (cng chnh l startId c gi ti phng

278

Lp trnh Android c bn
thc onStartCommand()) tng ng vi yu cu dng service ca bn. Sau ,
nu service nhn mt yu cu khi ng mi trc khi bn c th gi phng thc
stopSelf(int), ID s khng ph hp v service s khng dng.
Ch : Vic ng dng ca bn dng service ca n khi hon thnh cng vic l rt
quan trng, nhm trnh lng ph ti nguyn h thng v tiu tn in nng. Nu cn, cc
thnh phn khc c th dng service bng cch gi phng thc stopService().
Thm ch, nu c th kch hot lin kt cho service ny, bn phi lun t dng service
nu tng nhn c li gi ti onStartCommand().
tm hiu thm v vng i ca mt service, xem mc Qun l vng i ca service
bn di.

To service c lin kt
Service c lin kt (bound service) l thnh phn cho php cc thnh phn ng dng
khc lin kt vi n bng cch gi phng thc bindService() tng ng to
mt kt ni lu di (v nhn chung l khng cho php cc thnh phn khc khi ng
n bng li gi phng thc startService()).
Bn nn to mt service lin kt khi mun tng tc vi service kiu ny t activity
v cc thnh phn khc trong ng dng, hoc cung cp mt s chc nng ca ng
dng cho nhng ng dng khc, thng qua vic giao tip lin tin trnh (interprocess
communication - IPC).
Mun to mt service lin kt, bn phi ci t phng thc callback onBind() tr
v mt IBinder nh ngha giao din dng cho vic kt ni vi service. Sau , cc
thnh phn ng dng khc c th gi phng thc bindService() truy xut vo
giao din ny v bt u gi cc phng thc trn service. Service ch tn ti phc
v thnh phn ng dng c gn vi n; do , khi khng cn thnh phn gn vi
service na, h thng s hy service (bn khng cn dng service lin kt nh cch phi
thc hin vi service dng khi ng thng qua phng thc onStartCommand()).
to mt service lin kt, vic cn lm trc tin l bn phi nh ngha giao din
xc nh cch mt client giao tip vi service ny. Giao din gia service v client phi
l mt bn ci t ca IBinder v cng l kt qu m service ca bn phi tr v
t phng thc callback onBind(). Khi client nhn IBinder, client c th bt u
tng tc vi service thng qua giao din ny.
Cng lc, nhiu client c th gn vi mt service. Khi ang tng tc vi service, client
gi phng thc unbindService() ngt lin kt. Khi khng cn client lin kt vi
service, h thng s hy service.
C nhiu cch ci t mt service c lin kt v bn ci t service ny phc tp
hn so vi service dng khi ng. Do , phn tho lun v service c lin kt nm
trong mt ti liu ring v Bound Services (Service c lin kt).

Gi thng bo ti ngi dng


Khi ang chy, mt service c th thng bo vi ngi dng v cc s kin bng cch
s dng Thng bo nhanh (Toast Notifications) hoc Thng bo qua thanh trng thi
(Status Bar Notifications).

279

Lp trnh Android c bn
Thng bo nhanh l thng ip xut hin tm thi trn mt ca s hin ti, sau bin
mt. Trong khi , mt thng bo qua thanh trng thi cung cp mt biu tng trn
thanh trng thi cng vi mt thng ip, t ngi dng c th chn thc hin
mt hot ng (chng hn nh khi ng mt activity).
Thng thng, thng bo qua thanh trng thi l k thut tt nht khi hon thnh
mt s cng vic chy ngm (chng hn nh hon thnh ti file v) v gi th ngi
dng c th thao tc trn . Khi ngi dng chn thng bo t view m rng, thng
bo c th khi ng mt activity (chng hn nh hin th file va ti v).
Xem phn hng dn lp trnh v Toast Notifications hoc Status Bar Notifications
tm hiu thm thng tin.

Chy service trong ch mn hnh chnh


Service mn hnh chnh (foreground service) l service c cho l nhng th m ngi
dng c th ch ng thy c v do khng phi l thnh phn m h thng s hy
khi cn t b nh. Mi service mn hnh chnh phi cung cp mt thng bo cho thanh
trng thi, nm di tiu Ongoing (ang tin hnh), iu ny c ngha l thng bo
trn khng th b b i, tr phi service b dng hoc b loi khi mn hnh chnh.
V d, nn thit lp mt trnh chi nhc (music player) pht nhc t mt service chy
trong ch mn hnh chnh, v ngi dng nhn thc r v hot ng ca trnh ny.
Thng bo trong thanh trng thi c th hin th bi ht hin ti, ng thi cho php
ngi dng khi ng mt activity tng tc vi trnh nghe nhc.
yu cu service c chy trong ch mn hnh chnh, gi phng thc
startForeground(). Phng thc ny s dng hai tham s: Mt s nguyn xc
nh thng bo v i tng Notification cho thanh trng thi. V d:
Notification notification = new Notification(R.drawable.icon,
getText(R.string.ticker_text), System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,
notificationIntent,0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

Ch : ID s nguyn bn cung cp cho phng thc startForeground() phi


khc 0.
loi service khi ch mn hnh chnh, gi phng thc stopForeground().
Phng thc ny nhn mt tham s kiu boolean, cho bit liu c nn loi thng bo
trn thanh trng thi hay khng. Phng thc ny khng dng service. Tuy nhin, nu
bn dng service trong khi service ny vn chy mn hnh chnh, thng bo ny cng
s b loi.
tm hiu thm v thng bo, xem phn Creating Status Bar Notifications (To
thng bo qua thanh trng thi).

280

Lp trnh Android c bn

Qun l vng i ca service


Vng i ca service n gin hn rt nhiu so vi vng i ca mt activity. Tuy
nhin, vic ch trng ti cch service c to v b hy thm ch cn quan trng hn,
v mt service c th chy ngm m ngi dng khng bit c.
Vng i ca service - t khi c to ti khi b hy - c th tun theo hai cch khc
nhau sau:
Service dng khi ng
Service c to khi thnh phn khc ca ng dng gi phng thc startService().
Sau , service s chy v hn nh v phi t dng bng cch gi phng thc
stopSelf(). Thnh phn khc cng c th dng service ny bng cch gi phng
thc stopService(). Khi service b dng, h thng s hy service ny.
Service c lin kt
Service c to khi thnh phn khc (mt client) gi phng thc bindService().
Sau , client s kt ni vi service ny thng qua giao din IBinder. Client cng c
th ngt kt ni bng cch gi phng thc unbindService(). Nhiu client c th
cng lin kt vi cng mt service v khi tt c cc client ny ngt lin kt, h thng s
hy service. (Service kiu ny khng cn t dng).
Hai cch ny khng hon ton tch bit. Bi v, bn c th lin kt vi mt service
c khi ng bng phng thc startService(). V d, mt service m nhc
chy ngm c th c khi to thng qua li gi phng thc startService() vi
mt Intent xc nh nhc c pht. Sau , kh nng l khi ngi dng mun thc
hin mt s iu khin trn trnh chi nhc ny hoc ly thng tin v bi ht hin ti,
mt activity c th lin kt vi service ny bng li gi phng thc bindService().
Trong trng hp nh vy, phng thc stopService() hoc stopSelf() khng
thc s dng service cho n khi tt c cc client ngt lin kt.

Ci t cc phng thc callback lin quan n vng i


Tng t activity, mt service c cc phng thc callback lin quan n vng i m
bn c th ci t iu khin nhng thay i bn trong trng thi ca service v thc
hin cc cng vic ti thi im thch hp. Service khung (skeleton service) di y
minh ha tt c cc phng thc v vng i:
public class ExampleService extends Service {
int mStartMode; // cho bit cch x l khi service b dng
IBinder mBinder; // giao din cho client lin kt
boolean mAllowRebind;// cho bit c nn s dng
// phng thc onRebind hay khng

@Override
public void onCreate() {
// Service ang c to
}

281

Lp trnh Android c bn

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Service ang c khi ng, do mt li gi
// ti phng thc startService()
return mStartMode;
}
@Override
public IBinder onBind(Intent intent) {
// Mt client ang lin kt vi service
// qua phng thc bindService()
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// Tt c cc client ngt lin kt bng phng thc unbindService()
return mAllowRebind;
}
@Override
public void onRebind(Intent intent) {
// Mt client s c lin kt vi service
// bng phng thc bindService(),
// sau khi phng thc onUnbind() c gi
}
@Override
public void onDestroy() {
// Service khng cn c s dng v ang b hy
}

Ghi ch: Khng ging nh cc phng thc callback lin quan n vng i ca
activity, bn khng cn gi bn ci t lp cha ca nhng phng thc callback ny.

282

Lp trnh Android c bn

Call to startService()

Gi phng thc startService()

Call to bindService()

Gi phng thc bindService()

Service running

Service ang chy

Clients are bound to service

Cc client c lin kt vi service

Active Lifetime

Vng i sng

The service is stopped by itself or a client Service t dng hoc mt client dng n
All clients unbind by calling unbindService() Tt c client u ngt lin kt bng cch
gi phng thc unbindService()
Service shut down

Service b dng hot ng

Service shut down

Service b dng hot ng

Unbounded service

Service khng c lin kt

Bound service

Service c lin kt

Hnh 2. Vng i ca service. Biu bn tri minh ha vng i khi service c


to bng phng thc startService(). Biu bn phi minh ha vng i khi
service c to bng phng thc bindService().

283

Lp trnh Android c bn
Bng cch ci t nhng phng thc ny, bn c th iu khin hai vng lp lng
nhau ca vng i service:

Ton b vng i (entire lifetime) ca mt service l khong thi gian gia thi
im gi phng thc onCreate() v thi im phng thc onDestroy()
tr v kt qu. Tng t activity, mt service thc hin cc thit lp ban u ca
n trong phng thc onCreate() v gii phng tt c ti nguyn ang gi trong
phng thc onDestroy(). V d, mt service nghe nhc c th to lung pht
nhc trong phng thc onCreate(), sau dng lung ny trong phng thc
onDestroy().
Tt c cc service u gi hai phng thc onCreate() v onDestroy(), bt
k chng c to bng phng thc startService() hay bindService().

Vng i sng (active lifetime) ca service bt u bng li gi phng thc


onStartCommand() hoc onBind(). Mi phng thc s x l Intent c
chuyn n t phng thc startService()hay bindService().

Nu service c khi ng, vng i sng s kt thc cng thi im vi thi


im kt thc ton b vng i (service vn hot ng ngay c sau khi phng
thc onStartCommand() tr v). Nu service c lin kt, vng i sng s kt
thc khi phng thc onUnbind() tr v.

Ghi ch: Mc d mt service dng khi ng b dng bi li gi phng thc


stopSelf() hoc stopService(), song khng c phng thc callback no
tng ng cho service (khng c phng thc callback onStop()). Do vy, tr
phi service c lin kt vi mt client, h thng mi hy service ny khi n b
dng - onDestroy() ch l phng thc callback c nhn.

Hnh 2 minh ha cc phng thc callback in hnh ca mt service. Mc d hnh


ny tch bit nhng service do phng thc startService() to ra v cc
service to thnh t phng thc bindService(), nhng hy nh rng bt c
service no, khng quan trng l c khi ng theo cch no, cng c kh nng
cho php client lin kt vi service . Do vy, mt service c khi ng u tin
bng phng thc onStartCommand() (khi mt client gi startService())
vn c th nhn mt li gi ti onBind() (khi client gi bindService()).

tm hiu thm v cch to service cung cp lin kt, xem ti liu Bound
Services (Service c lin kt). Chi tit v phng thc callback onRebind()
c trnh by trong mc Managing the Lifecycle of a Bound Service (Qun l
vng i ca service c lin kt) ca ti liu trn.

13. Lp BroadcastReceiver
Tng quan v lp BroadcastReceiver
BroadcastReceiver l lp c s cha m dng nhn intent do phng thc
sendBroadcast() gi ti.

284

Lp trnh Android c bn
Nu bn khng cn gi broadcast trn nhiu ng dng, hy cn nhc dng lp ny vi
lp LocalBroadcastManager thay v thm nhiu chc nng chung s c m t
sau y. Vic ny s gip bn ci t hiu qu hn nhiu (khng cn cc giao tip tin
trnh cho), ng thi cho php bn trnh phi bn tm n nhng vn bo mt
lin quan ti vic cc ng dng khc c th nhn hoc gi tn hiu broadcast ca bn.
Bn c th ng k ng mt th hin ca lp ny bng phng thc
Context.registerReceiver() , hoc pht hnh tnh mt bn ci t
thng qua th <receiver> trong file AndroidManifest.xml .
Ghi ch: Nu ng k mt trnh nhn trong bn ci t phng thc
Activity.onResume() , bn nn hy ng k phng thc Activity.
onPause(). (Bn s khng nhn intent khi dng trnh nhn, v iu ny
s lm gim nhng ph ti (overhead) khng cn thit). ng hy ng
k trong Activity.onSaveInstanceState() , v phng thc ny s
khng c gi nu ngi dng quay li ngn xp history (lch s).
C hai lp broadcast chnh c th c nhn:
Broadcast thng (normal broadcast) (c gi i bng cch dng phng thc
Context.sendBroadcast) l kiu broadcast khng ng b hon ton. Tt c
cc trnh nhn broadcast chy u theo th t khng xc nh, thng l cng lc.
Cch truyn ny hiu qu hn, nhng cng c ngha l trnh nhn khng th s dng
kt qu hoc ngng API (Application Programming Interface - Giao din lp trnh ng
dng) ti y.
Broadcast theo th t (ordered broadcast) (c gi i bng cch dng phng
thc Context.sendOrderedBroadcast) c gi ti mt trnh nhn ti mt thi
im. Khi mi trnh nhn thc thi theo th t, trnh ny c th nhn bn kt qu cho
trnh nhn tip theo, hoc c th ngng hon ton broadcast khng chuyn broadcast ny ti trnh nhn khc. Th t chy ca cc trnh nhn c th c qun l bng
thuc tnh android:priority ca b lc intent ph hp; nhng trnh nhn c cng
mc u tin s chy theo th t bt k.
Thm ch, trong trng hp broadcast thng, h thng c th ri vo mt s tnh th
c th khi phc vic broadcast ti mt trnh nhn ring. C th, cc trnh nhn c th
yu cu to mt tin trnh, ch mt trnh nhn chy ring nhm trnh cc tin trnh
mi lm qu ti h thng. Tuy nhin, trong tnh hung ny, vic x l v ngha vn l
khng theo th t: Cc trnh nhn ny vn khng th tr v kt qu hoc ngng vic
broadcast ca chng.
Lu , mc d lp Intent c dng gi v nhn cc tn hiu broadcast, nhng
c ch Intent broadcast y hon ton khc so vi nhng Intent c s dng
khi ng cc Activity thng qua phng thc Context.startActivity().
Khng c c ch i tng BroadcastReceiver thy hoc bt Intent c
dng vi phng thc startActivity(); tng t, khi broadcast mt Intent, bn
s khng bao gi tm thy hoc khi ng mt Activity. V mt ng ngha, y l hai
thao tc rt khc nhau: Vic khi ng mt Activity bng Intent l mt thao tc chy
trn mn hnh chnh (foreground), lm thay i nhng g ngi dng hin ang tng
tc; vic broadcast mt Intent l mt hot ng chy ngm m ngi dng thng
khng nhn thy.

285

Lp trnh Android c bn
Lp BroadcastReceiver (khi khi ng ging nh mt thnh phn thng qua th
<receiver> trong file k khai) l mt thnh phn quan trng trong ton b vng i
ca ng dng. Xem thm v ton b vng i ca ng dng ti mc Kin thc c bn
v ng dng.
Ch ny s tho lun v cc ni dung:
1. Bo mt.
2. Vng i ca trnh nhn.
3. Vng i ca tin trnh.

Hng dn pht trin chng trnh


tm hiu thm thng tin v cch s dng lp ny nhn v x l intent, mi bn
c phn hng dn dnh cho nh pht trin Intents and Intent Filters (Intent v b
lc Intent).

Bo mt
Cc trnh nhn c s dng vi cc API (giao din lp trnh ng dng) Context
bng tnh nng a ng dng (cross-application) t nhin ca chng, nn bn phi tnh
n kh nng nhng ng dng khc c th lm dng vic s dng ca bn trn cc
trnh nhn ny. Mt s vn cn cn nhc sau:

Namespace ca Intent phi l ton cc (global). Hy m bo tn action ca Intent


v cc chui khc phi c vit trong namespace ca chnh bn; nu khng, bn
c th v tnh gy xung t vi cc ng dng khc.

Khi bn s dng phng thc registerReceiver(BroadcastReceiver,


IntentFilter), mt ng dng bt k c th gi broadcast ti trnh nhn
c ng k ny. Bn c th iu khin i tng c broadcast ti trnh nhn
thng qua cc quyn c m t bn di.

Khi bn pht hnh trnh nhn trong file k khai ca ng dng v xc nh b lc


intent cho file ny, cc ng dng khc c th gi broadcast ti trnh nhn trn m
khng cn quan tm ti b lc m bn xc nh. trnh khng cho nhng ng
dng khc gi broadcast ti, hy cung cp thuc tnh trnh nhn ny khng b
cc tc nhn bn ngoi truy cp l android:exported=false.

Khi bn s dng sendBroadcast(Intent) hoc cc phng thc lin quan,


thng th bt c ng dng no khc cng c th nhn cc broadcast ny. Bn c
th iu khin i tng c th nhn nhng broadcast ny bng cc quyn c
m t bn di. Mt cch khc l khi ng vi hng ICE_CREAM_SANDWICH,
bn cng c th gii hn vic broadcast mt cch an ton cho mt ng dng bng

Intent.setPackage.

Cc vn trn s khng tn ti nu bn s dng LocalBroadcastManager, do


cc intent tin hnh broadcast i tng ny khng bao gi ra khi tin trnh hin ti.
Cc quyn truy cp c th cho php xc nh hoc trnh gi (sender) v trnh nhn
broadcast.

286

Lp trnh Android c bn
p buc mt quyn khi gi, bn cung cp mt i s permission khc null cho phng thc
sendBroadcast(Intent, String) hoc sendOrderedBroadcast(Intent,

String, BroadcastReceiver, android.os.Handler, int, String,


Bundle). Ch nhng trnh nhn c quyn ny (bng cch yu cu quyn thng qua th
<uses-permission> trong file AndroidManifest.xml) mi c th nhn broadcast.

p buc mt quyn khi nhn, bn cung cp i s permission khc null khi ng


k trnh nhn ca bn - khi gi phng thc registerReceiver(BroadcastRe
ceiver, IntentFilter, String, android.os.Handler), hoc trong th
tnh <receiver> ca file AndroidManifest.xml do bn pht trin. Ch cc i
tng broadcast (broadcaster) c quyn trn (bng cch yu cu quyn trn vi th
<uses-permission> trong file AndroidManifest.xml ca i tng ny) mi
c th gi mt Intent ti trnh nhn.
Xem ti liu hng dn Security and Permissions (Quyn v bo mt) tm hiu
thm thng tin v quyn v bo mt.

Vng i ca trnh nhn


i tng BroadcastReceiver ch tn ti trong thi hn ca li gi ti phng
thc onReceive(Context, Intent). Khi m ca bn tr kt qu v t hm ny,
h thng s cho rng i tng BroadcastReceiver hon thnh v khng cn hot
ng na.
Vic ny c tc ng quan trng n nhng g bn ci t trong phng thc
onReceiver(Context, Intent): Bt c th g yu cu thao tc khng ng b
u khng c x l ti y, v bn s phi tr kt qu v t hm ny x l thao tc
khng ng b. Tuy nhin, ti im , i tng BroadcastReceiver khng cn
hot ng, nn h thng s t kt thc tin trnh ca i tng ny trc khi thao tc
khng ng b hon thnh.
C th, bn s khng hin th hp thoi hoc lin kt vi mt service t bn trong
i tng BroadcastReceiver. i vi hp thoi, bn c th s dng API ca
NotificationManager. i vi service, bn c th dng Context.startService()
gi lnh ti service ny.

Vng i ca tin trnh


Mt tin trnh ang thc thi i tng BroadcastReceiver (ngha l, ang chy m
trong phng thc onReceive(Context, Intent)) c xem l tin trnh chy trn
mn hnh chnh (foreground) v s c h thng duy tr, tr phi b nh cc k qu ti.
Khi bn tr kt qu v t phng thc onReceive(), i tng BroadcastReceiver
khng cn hot ng na, tin trnh cha i tng ny s ch quan trng i vi
nhng thnh phn ca ng dng khc chy trong . iu ny cc k quan trng, v
nu tin trnh ch host i tng BroadcastReceiver (trng hp thng gp i
vi cc ng dng m ngi dng khng bao gi hoc hin ang khng tng tc),
sau khi tr kt qu v t phng thc onReceive(), h thng s coi tin trnh ny
l rng, ng thi nhanh chng ngt n dnh ti nguyn cho nhng tin trnh khc
quan trng hn.

287

Lp trnh Android c bn
iu ny c ngha l, i vi nhng thao tc tn thi gian, bn thng s dng
Service kt hp vi BroadcastReceiver gi tin trnh cha tn ti trong sut
thi gian din ra thao tc ca bn.

Tng kt
Lp lng nhau (nested class)
Lp

BroadcastReceiver.PendingResult

Trng thi ca kt qu
c gi li cho broadcast
receiver.

Phng thc khi to public


BroadcastReceiver()
Phng thc public
final void

final void

abortBroadcast()
Thit lp c (flag) cho bit trnh nhn ny nn hy broadcast
hin ti; phng thc ny ch lm vic vi nhng tn hiu
broadcast c gi thng qua phng thc
Context.sendOrderedBroadcast.

clearAbortBroadcast()

Xa c cho bit trnh nhn ny hy broadcast hin ti.


final boolean

getAbortBroadcast()
Tr v c cho bit liu trnh nhn ny c nn hy broadcast
hin ti hay khng.

final boolean

final int

getDebugUnregister()
Tr v gi tr cui cng nhn c t phng thc
setDebugUnregister(boolean).
getResultCode()

Truy xut m kt qu hin ti, do trnh nhn trc thit lp.


final String

getResultData()
Truy xut d liu kt qu hin ti, do trnh nhn trc thit lp.

final Bundle

getResultExtras (boolean makeMap)


Truy xut d liu kt qu ph tr (result extra data) hin ti, do
trnh nhn trc thit lp.

final

goAsync()

BroadcastReceiver.
Phng thc ny c th c ng dng gi trong phng
PendingResult
thc onReceive(Context, Intent) cho php gi tn
hiu broadcast hot ng sau khi c tr v t phng thc
onReceive(Context, Intent).

288

Lp trnh Android c bn
final boolean

isInitialStickyBroadcast()
Tr v true nu trnh nhn ang x l gi tr khi to ca tn
hiu broadcast kiu sticky (dnh) - gi tr ny c broadcast
sau cng v hin ang c lu gi trong cache sticky; bi
vy; ti thi im , gi tr ny khng phi l kt qu trc tip
ca mt broadcast.

final boolean

isOrderedBroadcast()
Tr v gi tr true nu trnh nhn ang x l mt broadcast c
th t.

abstract void

onReceive(Context context, Intent intent)


Phng thc ny c gi khi i tng BroadcastReceiver
ang nhn mt Intent broadcast.

IBinder

peekService(Context myContext, Intent service)


Cung cp i tng lin kt ti service ang chy.

final void

final void

setDebugUnregister(boolean debug)
Cung cp tp cc iu khin tr gip g li cho nhng li gi khng
ph hp vi phng thc Context.registerReceiver().
setOrderedHint(boolean isOrdered)

Phng thc ny c s dng bn trong, thit lp gi xem


i tng BroadcastReceiver ny c ang chy trong ch
c th t hay khng.
final void

final void

final void

final void

[M rng]

setResult(int code, String data, Bundle extras)


Thay i tt c cc d liu kt qu tr v t vic pht broadcast
ny; ch lm vic vi nhng tn hiu broadcast c gi ti
thng qua Context.sendOrderedBroadcast.
setResultCode(int code)

Thay i m kt qu hin ti ca tn hiu broadcast ny; phng


thc ny ch lm vic vi nhng tn hiu broadcast c gi
ti thng qua Context.sendOrderedBroadcast.
setResultData(String data)

Thay i d liu kt qu hin ti ca vic broadcast ny; phng


thc ny ch lm vic vi nhng tn hiu broadcast c gi
ti thng qua Context.sendOrderedBroadcast.
setResultExtras(Bundle extras)

Thay i gi tr ph tr ca kt qu hin ti i vi vic


broadcast ny; ch lm vic vi nhng tn hiu broadcast c
gi ti thng qua Context.sendOrderedBroadcast.

Cc phng thc tha k (inherited method)


Thuc lp java.lang.Object

289

Lp trnh Android c bn

Cc phng thc khi to public


public BroadcastReceiver()
c a vo API cp 1 (API level 1)

Cc phng thc public


public final void abortBroadcast()
c a vo API cp 1 (API level 1)
Thit lp c cho bit trnh nhn ny nn hy vic broadcast hin ti; ch lm vic vi nhng
tn hiu broadcast c gi ti thng qua Context.sendOrderedBroadcast.
Phng thc ny ngn khng cho cc broadcast receiver khc khng nhn c tn
hiu broadcast. Phng thc public final void abortBroadcast() vn gi phng
thc onReceive(Context, Intent) ca i tng BroadcastReceiver do
li gi phng thc Context.sendOrderedBroadcast truyn n.
Phng thc public final void abortBroadcast() khng lm vic vi
cc tn hiu broadcast khng theo th t, chng hn nh nhng tn hiu
broadcast c gi ti t phng thc Context.sendBroadcast.
public final boolean clearAbortBroadcast()
c a vo API cp 1 (API level 1)
Xa c cho bit trnh nhn ny nn hy vic broadcast hin ti.
public final boolean getAbortBroadcast()
c a vo API cp 1 (API level 1)
Tr v c cho bit liu trnh nhn ny c nn hy vic broadcast hin ti hay khng.
Kt qu tr v

Tr v true, nu hy vic broadcast ny.

public final boolean getDebugUnregister()


c a vo API cp 1 (API level 1)
Tr v gi tr cui cng nhn c t phng thc
setDebugUnregister(boolean).
public final int getResultCode()
Truy xut m kt qu hin ti, do trnh nhn trc thit lp.
Kt qu tr v

M kt qu hin ti kiu int.

public final String getResultData()


c a vo API cp 1 (API level 1)

290

Lp trnh Android c bn
Truy xut d liu kt qu hin ti, do trnh nhn trc thit lp. Thng l null.
Kt qu tr v

D liu kt qu hin ti kiu String; c th l null.

public final Bundle getResultExtras (boolean makeMap)


c a vo API cp 1 (API level 1)
Truy xut d liu kt kt qu ph tr (d liu extra) hin ti, do trnh nhn trc
thit lp. Bt c thay i no bn thc hin trn Map (i tng bn nh x) tr
v s c nhn bn cho trnh nhn tip theo.
Tham s

makeMap
Nu true th s thit lp cho bn mt Map rng mi khi Map hin ti l null; Nu
false, bn c chun b nhn mt Map null.
Kt qu tr v
Bn nh x ph tr hin ti kiu Map.
public final BroadcastReceiver.PendingResultgoAsync()
c a vo API cp 11 (API level 11)
Phng thc ny c th c mt ng dng gi trong phng thc
onReceive(Context, Intent) cho php ng dng gi vic broadcast
ny vn hot ng sau khi phng thc onReceive(Context, Intent) tr
v kt qu. Khng thay i thi gian ch phn hi tn hiu broadcast mong mun
(hon thnh trong vng 10 giy), nhng cho php ci t chuyn nhng cng
vic lin quan sang lung khc, nhm trnh nh hng ti lung giao din ngi
dng chnh do IO (u vo/u ra) ca a.
Kt qu tr v
Tr v BroadcastReceiver.PendingResult i din cho kt qu ca
tn hiu broadcast ang hot ng. Bn thn i tng BroadcastRecord
khng cn hot ng na; tt c cc d liu v tng tc khc phi i
qua API ca BroadcastReceiver.PendingResult. Phng thc
PendingResult.finish() phi c gi khi tin trnh x l broadcast
hon thnh.
public final boolean isInitialStrickyBroadcast()
c a vo API cp 5 (API level 5)
Tr v true, nu trnh nhn ang x l gi tr khi to ca tn hiu broadcast kiu
sticky - gi tr ny c broadcast sau cng v hin ang c lu gi trong cache
sticky; do vy, ti thi im , gi tr ny khng phi l kt qu trc tip ca mt
broadcast.
public final boolean isOrderedBroadcast()
c a vo API cp 5 (API level 5)
Tr v true, nu trnh nhn ang x l mt broadcast c th t.

291

Lp trnh Android c bn
public abstract void onReceive (Context context, Intent intent)
c a vo API cp 1 (API level 1)
Phng thc ny c gi khi i tng BroadcastReceiver ang nhn mt
Intent broadcast. Sut thi gian ny, bn c th s dng cc phng thc khc
trong BroadcastReceiver hin th/chnh sa gi tr kt qu hin ti. y l
phng thc lun c gi trong lung chnh ca tin trnh x l phng thc,
tr phi bn yu cu c th phng thc ny c a vo lung khc bng
cch s dng phng thc registerReceiver(BroadcastReceiver,
IntentFilter, String, android.os.Handler). Khi phng thc ny
chy trn lung chnh, li khuyn cho bn l ng bao gi thc hin cc thao tc
tn thi gian trong phng thc (thi gian ch (timeout) l 10 giy; qu thi gian
ny, h thng s cho rng trnh nhn b chn v mt ng c vin b hy). Bn
khng nn ci t bt hp thoi popup trong phng thc onReceive().
Nu i tng BroadcastReceiver c pht i thng qua th <receiver>,
i tng ny s khng hot ng sau khi c tr v t hm ny. iu
ny c ngha rng, bn khng nn thc hin bt k thao tc no tr v kt qu
mt cch khng ng b - c th, tng tc vi service, bn nn s dng
phng thc startService(Intent) thay v bindService(Intent,
ServiceConnection, int). Nu mun tng tc vi mt service ang chy,
bn c th s dng phng thc peekService(Context, Intent).
B lc Intent c dng trong phng thc registerReceiver(Broadcast
Receiver, IntentFilter) v trong file k khai, ng dng khng m bo
vic broadcast c s dng ring. B lc intent l gi h iu hnh bit cch
tm trnh nhn ph hp. Chng ta c th thit k trnh gi c kh nng chn
broadcast ti cc trnh nhn c th, b qua vic dng b lc. Do vy, bn nn ci
t sao cho phng thc onReceive() ch phn hi nhng hot ng bit,
b qua nhng Intent khng mun nhn v.
Tham s
context

Context m trnh nhn ang chy.


intent

Intent ang c nhn.


public IBinder peekService (Context myContext, Intent service)
c a vo API cp 3 (API level 3)
Cung cp mt i tng lin kt (binder) ti mt service ang chy. y l
phng thc ng b v s khng khi ng service ch nu service ny cha
hot ng. Do , phng thc ny hot ng tt khi c gi t phng thc
onReceive(Context, Intent).
Tham s
myContext

292

Lp trnh Android c bn
Context truyn vo phng thc onReceive(Context, Intent).
service
L Intent ch ra service bn mun s dng. Xem thm phng thc
startService(Intent) tm hiu k hn.
public final void setDebugUnregister (boolean debug)
c a vo API cp 1 (API level 1)
Cung cp tp cc iu khin tr gip g li cho nhng li gi khng ph hp
vi phng thc Context.registerReceiver(). Nu phng thc
ny c gi vi gi tr true, trc khi nhn kt qu tr v t phng thc
registerReceiver(), callstack (ngn xp li gi) cho phng thc Context.
unregisterReceiver() sau s tip tc c s dng, c in ra nu sau
c mt li gi cha ng k khng hp l c thc hin. Lu , phng thc
ny cn duy tr thng tin v BroadcastReceiver trong sut thi gian chy ng
dng, tr v vt li (leak) - ch dng g li.
public final void setOrderedHint(boolean isOrdered)
c a vo API cp 1 (API level 1)
Phng thc ny c s dng bn trong, thit lp gi v vic i tng
BroadcastReceiver ny c ang chy trong ch c th t hay khng.
public final void setResult (int code, String data, Bundle extras)
c a vo API cp 1 (API level 1)
Thay i tt c cc d liu kt qu tr v t vic broadcast ny; ch lm vic vi tn
hiu broadcast c gi thng qua Context.sendOrderedBroadcast. Ton
b d liu kt qu hin ti c thay th bng gi tr nhn v t phng thc ny.
Phng thc ny khng lm vic vi cc tn hiu broadcast khng theo th t,
chng hn nh nhng tn hiu c gi ti t Context.sendBroadcast.
Tham s
code
M kt qu mi. Thng s dng cc hng Activity RESULT_CANCELED v
RESULT_OK, mc d ngha thc s ca gi tr ny lin quan ti i tng
broadcast.
data
D liu kt qu mi. y l mt chui bt k gii thch cho i tng broadcast; c th l null.
extras
Bn nh x d liu ph tr mi. y l i tng Bundle lu d liu bt k,
lin quan n i tng broadcast. C th c thit lp l null. D liu ny
gp phn thay th hon ton bn nh x hin ti (nu c).

293

Lp trnh Android c bn
public final void setResultCode (int code)
c a vo API cp 1 (API level 1)
Thay i m kt qu hin ti ca tn hiu broadcast ny; phng thc
setResultCode() ch lm vic vi cc tn hiu broadcast c gi ti thng
qua Context.sendOrderedBroadcast. Phng thc ny thng s dng
cc hng Activity RESULT_CANCELED v RESULT_OK, mc d ngha thc s
ca gi tr ny lin quan n i tng broadcast.
Phng thc setResultCode() khng lm vic vi cc tn hiu broadcast khng
theo th t, chng hn nh nhng tn hiu c gi ti t Context.

sendBroadcast.
Tham s
code

M kt qu mi.

Tham kho thm


setResult(int, String, Bundle)

public final void setResultData (String data)


c a vo API cp 1 (API level 1)
Thay i d liu kt qu hin ti ca vic broadcast ny; phng thc
setResultData() ch lm vic vi tn hiu broadcast c gi thng qua
Context.sendOrderedBroadcast. Chui bt k gii thch cho i tng
broadcast.
Phng thc ny khng lm vic vi cc tn hiu broadcast khng theo th t,
chng hn nh nhng tn hiu c gi ti t Context.sendBroadcast.
Tham s
Data

D liu kt qu mi; c th l null.

Tham kho thm


setResult(int, String, Bundle)

public final void setResultExtras (Bundle extras)


Thay i gi tr ph tr (gi tr extra)cho kt qu hin ti ca vic broadcast ny; ch lm
vic vi cc tn hiu c gi ti thng qua Context.sendOrderedBroadcast.
y l i tng Bundle lu d liu bt k, gii thch cho i tng broadcast. C
th c thit lp l null. Gi phng thc ny hon thnh vic thay th bn
nh x hin ti (nu c).
Phng thc setResultExtras khng lm vic vi cc tn hiu
broadcast khng theo th t, chng hn nh nhng tn hiu c gi ti
t Context.sendBroadcast.

294

Lp trnh Android c bn
Tham s
Extras

Bn nh x d liu ph tr (extra) mi, c th l null

Tham kho thm


setResult(int, String, Bundle)

14. Mo bo mt
Android c nhng tnh nng bo mt c xy dng bn trong h iu hnh ny, gip
gim thiu ng k tn sut v nh hng ca cc vn bo mt (security) ng dng.
H thng ny c thit k bn c th xy dng ng dng ca mnh mt cch c
th vi h iu hnh mc nh v cc quyn trn file, gip trnh c nhng quyt nh
kh khn v bo mt.
Mt s tnh nng bo mt ct li gip bn xy dng ng dng an ton, bao gm:

Cng ngh Sandbox (mi trng o chy ng dng) dnh cho ng dng Android,
gip cch ly d liu ng dng ca bn vi vic thc thi m t cc ng dng khc.

Mt framework pht trin ng dng c ci sn cc chc nng bo mt chung mnh


m, chng hn nh k thut m ha (cryptography), quyn v IPC (Inter-process
communication - Giao tip lin tin trnh) an ton.

Cc cng ngh nh ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD


calloc v Linux mmap_min_addr gp phn gim thiu ri ro lin quan n li qun
l b nh thng thng.

H thng file c m ha (encrypted file system) cho php bo v d liu khi b


mt hoc trnh b thit b n cp.

Quyn cp cho ngi dng gii hn truy cp ti cc tnh nng ca h thng v


d liu ngi dng.

Quyn do ng dng nh ngha qun l d liu ng dng trn nn tng ca tng


ng dng.

Tuy nhin, quan trng l bn phi lm quen vi cc k thut tt nht v bo mt trn


h thng Android c hng dn trong ti liu ny. Cc phng php ny s rn cho
bn nhng thi quen vit m chung gip gim thiu kh nng v tnh l nhng vn
lin quan n bo mt gy bt li cho ngi dng ng dng.

Lu tr d liu
Mi lo ngi ln nht v bo mt i vi mt ng dng Android l xem xt liu d liu
bn lu trn thit b c th c cc ng dng khc truy cp hay khng. C ba cch c
bn lu d liu trn thit b:

S dng b nh trong
Mc nh, cc file bn to ra trn b nh trong ch c ng dng ca bn truy cp.
Tnh nng bo v ny c Android thit lp v c p dng cho hu ht ng dng.

295

Lp trnh Android c bn
Thng th bn nn trnh s dng ch MODE_WORLD_WRITEABLE hoc
MODE_WORLD_READABLE cho cc file IPC, bi nhng quyn ny khng cung cp
kh nng gii hn truy cp ln cc ng dng c th, cng nh khng cung cp
bt c iu khin no nh dng d liu. Nu mun chia s d liu ca bn vi
cc tin trnh x l ng dng khc, bn c th ngh n vic dng mt content
provider. Provider ny s cung cp quyn c v ghi cho cc ng dng khc v
c th s dng quyn ng (dynamic permission) trong tng trng hp c th.
cung cp thm tnh nng bo v cho d liu nhy cm, bn c th chn m ha
cc file cc b (local file) bng cch dng mt kha (key) ng dng khng trc tip
truy cp c. V d, kha c th c t trong mt KeyStore v c bo v bng
password (mt khu) ca ngi dng, password ny khng c lu tr trn thit b.
iu ny khng th bo v d liu khi quyn qun tr (root) c th theo di ngi dng
nhp password, nhng cng gip bo v trong trng hp mt thit b v cha m ha
file h thng.

S dng b nh ngoi
Cc file c to trn b nh ngoi, chng hn nh th SD, c th c c v ghi
tng th. B nh ngoi c th c ngi dng di chuyn v cng c th c mt
ng dng bt k chnh sa; do , bn khng nn lu nhng thng tin nhy cm vo
b nh ny.
Cng nh d liu t cc ngun khng ng tin khc, bn nn thc hin kim tra tnh
hp l ca d liu u vo khi x l d liu lu trong b nh ngoi. Chng ti nhn
mnh rng, bn khng nn lu tr cc file c th thc thi hoc file lp vo b nh ngoi
trc khi tin hnh np ng (dynamic loading). Nu ng dng ca bn thc hin truy
xut file c th thc thi t b nh ngoi, cc file ny nn c nh du v kim nh
m ha trc khi np ng.

S dng content provider


Content provider cung cp c ch lu tr c cu trc c th ch c gii hn trong
ng dng ca bn, hoc c xut ra nhng ng dng khc truy cp. Nu bn
khng nh cho php ng dng khc truy cp vo content provider ca mnh, hy nh
du provider ny bng thuc tnh android:exported=false trong file k khai ca
ng dng. Ngc li, bn cn thit lp thuc tnh android:exported l true
cho php ng dng khc truy cp vo d liu c lu tr.
Khi to mt content provider c xut ra cho nhng ng dng khc dng, bn c th
xc nh mt quyn kt hp cho php c v ghi, hoc cc quyn phn bit c
v ghi bn trong file k khai. Chng ti khuyn ngh rng, bn nn hn ch s quyn
c yu cu va cho nhng quyn trn hon thnh tc v trc mt. Nh rng,
thng th vic thm quyn sau khi gii thiu chc nng mi s d hn so vi vic b
bt quyn i v ph v nhng ngi dng c.
Nu bn ang dng mt content provider chia s d liu ch trong cc ng dng do
bn pht trin, la chn ph hp l s dng thuc tnh android:protectionLevel
v thit lp bo v l signature. Quyn signature khng yu cu xc nhn ca
ngi dng, nn cc quyn ny cung cp tri nghim ngi dng tt hn v truy cp

296

Lp trnh Android c bn
c kim sot hn cho d liu content provider khi vic truy cp d liu ca cc ng
dng c k vi cng mt kha.
Content provider cng c th cung cp thm truy cp chi tit (granular access) bng
cch khai bo thuc tnh android:grantUriPermissions v s dng cc c
FLAG_GRANT_READ_URI_PERMISSION cng nh FLAG_GRANT_WRITE_URI_
PERMISSION trong i tng Intent kch hot thnh phn. Phm vi ca nhng quyn
ny c th c gii hn c th hn bi phn t <grant-uri-permission>.
Khi truy cp mt content provider, bn cn s dng cc phng thc truy vn tham
s ha (parameterized query method) nh query(), update() v delete()
trnh s can thip ca cc l hng SQL injection (l l hng an ninh nh hng trc
tip n c s d liu v ti nguyn ca mt h thng Website) tim tng t nhng
ngun khng ng tin. Lu , vic s dng cc phng thc truy vn tham s ha l
cha nu i s selection c xy dng da trn s ghp ni vi d liu ngi
dng trc khi gi ti phng thc ny.
ng nh gi sai vic bo mt i vi quyn ghi. Lu , quyn ghi cng vi cu lnh
SQL cho php xc nhn mt s d liu bng cch s dng sng to mnh WHERE
v phn tch kt qu tr v. V d, k tn cng (attacker) c th s d c mt s in
thoi c th c mt trong bn nht k ghi li cc cuc gi bng cch chnh sa mt
hng ch khi s in thoi ny thc s tn ti. Nu d liu content provider c cu trc
d pht hin, quyn ghi c th tng ng vi vic cung cp c quyn c v ghi.

S dng quyn
Do h thng sandbox Android bo v ng dng khi cc ng dng khc, nn cc ng
dng phi chia s ti nguyn v d liu mt cch tng minh. ng dng thc hin vic
ny bng cch khai bo quyn chng cn dng cho nhng tnh nng b sung khng
c sandbox c bn cung cp, bao gm quyn truy cp ti cc tnh nng ca thit b
nh camera.

Yu cu quyn
Chng ti khuyn ngh nn ti thiu ha s quyn m ng dng ca bn yu cu. Vic
khng truy cp vo quyn nhy cm gip gim thiu ri ro c th v tnh lm dng
nhng quyn ny, tng kh nng ngi dng chp nhn ng dng v cng khin ng
dng t b tn cng hn. Thng thng, nu khng cn quyn thc hin chc nng
no trong chng trnh ca mnh, bn ng yu cu quyn .
Nu c th thit k ng dng ca bn theo cch khng cn yu cu quyn th tt hn.
V d, thay v yu cu truy cp ti thng tin thit b to mt nh danh duy nht, hy
to mt GUID (Globally unique identifier - nh danh duy nht ton cu) cho ng dng
ca bn (xem mc X l d liu ngi dng bn di). Hoc, thay v s dng b nh
ngoi (phi yu cu quyn), hy lu tr d liu b nh trong.
Ngoi vic yu cu quyn, ng dng ca bn c th s dng <permissions> bo
v IPC rt cn bo mt cc d liu nhy cm v s c xut ra cho nhng ng dng
khc, chng hn nh mt ContentProvider. Nhn chung, chng ti khuyn bn nn

297

Lp trnh Android c bn
s dng cc iu khin truy cp (access control) thay v quyn cn xc nhn ca ngi
dng (user confirmed permission) nhng v tr kh thi, v cc quyn ny c th khin
ngi dng bi ri. V d, hy xt ti vic s dng mc bo v xc nhn bng ch k
(signature protection level) cho nhng quyn ca giao tip IPC gia cc ng dng ca
cng mt nh pht trin chng trnh.
Trnh r r d liu c quyn bo v. iu ny c th xy ra khi ng dng ca bn
xut d liu thng qua IPC duy nht c sn v IPC ny c mt quyn xc nh, nhng
khng yu cu quyn cho client no trong giao din IPC ny.

To quyn
Thng thng, bn nn c gng nh ngha t quyn nht c th trong khi vn p ng
c yu cu v bo mt. Vic to quyn mi thng khng ph bin i vi a s
ng dng, do cc quyn c h thng nh ngha thng bao ph rt nhiu tnh
hung. Ti v tr thch hp, hy thc hin kim tra truy cp bng cch s dng nhng
quyn c.
Nu phi to mt quyn mi, hy cn nhc xem liu bn c th hon thnh tc v ny
vi mc bo v signature hay khng. Ngi dng s khng nhn thy s c mt ca
quyn xc nhn bng ch k v khi ng dng thc hin kim tra quyn, ch cho php
cc ng dng c xc nhn ch k l ca cng mt nh pht trin chng trnh th
mi c th truy cp c.
Nu mun to mt quyn vi mc bo v dangerous (nguy him), bn phi tnh n
mt s vn phc tp sau:

Quyn phi l mt chui din t ngn gn cho ngi dng bit v quyt nh bo
mt m h c yu cu thc hin.

Chui quyn phi c bn a ha cho nhiu ngn ng khc nhau.

Ngi dng c th chn khng ci t ng dng nu c quyn no lm h bi ri


hoc c cho l ri ro.

Cc ng dng c th yu cu quyn khi trnh to quyn khng c ci t.

Mi vn nu trn u l mt thch thc phi k thut in hnh vi bn trong t cch


mt nh pht trin chng trnh, ngoi ra cn khin ngi dng bi ri. l l do ti
sao chng ti khng khuyn khch bn dng mc quyn dangerous.

S dng kt ni mng
Cc giao dch mng vn tim n nhiu ri ro v bo mt, v chng bao gm vic truyn
d liu thng l thng tin ring t ca ngi dng. Mi ngi ngy cng cnh gic vi
cc mi lo ngi v bo mt trn thit b di ng, c bit l khi thit b thc hin giao dch
mng. Do , y l yu t quan trng khi ng dng ca bn thc hin cc bin php
ci t tt nht, hng ti bo v d liu ngi dng trong mi hon cnh.

298

Lp trnh Android c bn

S dng kt ni mng IP
Kt ni mng trn h iu hnh Android khng khc nhiu so vi cc mi trng Linux
khc. Mi bn tm chnh l m bo s dng giao thc (protocol) ph hp vi d liu
nhy cm, chng hn nh HttpsURLConnection i vi cc lu lng truy cp
Web an ton (secure web traffic). Chng ti khuyn bn nn s dng giao thc HTTPS
thay v HTTP mi ni m HTTPS c server h tr, bi v thit b di ng thng
kt ni ti mt mng khng an ton, chng hn nh im truy cp Wi-Fi cng cng.
C th d dng ci t giao tip mc cng m ha, c xc thc bng cch s
dng lp SSLSocket. Cc thit b Android thng xuyn kt ni vi nhng mng
khng dy thiu an ton thng qua Wi-Fi, nn vic s dng kt ni mng an ton cho
tt c cc ng dng kt ni qua mng rt c khuyn khch.
Chng ti cng nhn thy rng mt s ng dng dng cng mng (network port)
localhost x l cc IPC nhy cm. Chng ti phn i cch tip cn nh vy, v
cc ng dng khc trn thit b c th truy cp giao din ny. Thay vo , bn nn
s dng mt c ch IPC ca Android; nh c ch ny, vic xc thc c th thc hin
c, chng hn nh khi dng mt Service. (Thm ch iu ny cn khng tt bng
s dng vng lp ngc (loopback) lin kt vi INADDR_ANY, bi v sau ng
dng ca bn c th nhn yu cu t mi ni).
Mt vn chung nhm bo v vic lp l m bo rng bn khng tin vo nhng
d liu c ti v t HTTP hoc cc giao thc khng an ton khc. iu ny bao
gm vic kim tra u vo trn WebView v bt c phn hi intent no c pht
ra t HTTP.

S dng kt ni mng in thoi


Ban u, giao thc SMS c thit k cho giao tip t ngi dng-ti-ngi dng v
khng ph hp vi ng dng truyn d liu. Do hn ch ny ca SMS, nn chng ti
rt khuyn khch vic s dng Google Cloud Messaging (Gi tin nhn qua m my
Google - GCM) v mng IP gi tin nhn d liu t mt Web server ti ng dng ca
bn trn thit b ngi dng.
Hy cnh gic vi vic SMS khng c m ha hoc c xc thc cn thn trn
mng cng nh thit b. C th, bt c i tng nhn SMS no cng nn phng
vic ngi dng c gi tin nhn SMS ti ng dng ca bn - Khng phn hi nhng
d liu SMS cha c xc thc c th thc hin cc lnh nhy cm. Bn cng nn
nhn thc c rng SMS c th l i tng gi mo v/hoc b chn trn mng. Trn
chnh nhng thit b chy trn nn Android, tin nhn SMS c th c truyn di dng
cc broadcast intent; do , nhng tin nhn ny c th b cc ng dng khc c hoc
ly cp nu c quyn READ_SMS.

Thc hin kim tra tnh hp l ca d liu u vo


Vic kim tra tnh hp l ca d liu u vo khng y l mt trong nhng vn
bo mt ph bin nht nh hng ti ng dng, bt k cc d liu ny ang chy trn
loi nn tng (platform) no. Android c nhng bin php x l mc nn tng lm gim
tc ng xu ca vn lin quan n vic kim tra tnh hp l ca d liu u vo ln

299

Lp trnh Android c bn
ng dng v bn nn s dng cc tnh nng ny bt c ni no c th. Cng cn lu
rng, vic chn cc ngn ng an ton c th lm gim thiu kh nng xy ra nhng
vn v kim tra u vo.
Nu bn ang s dng m my (native code), bt c d liu no c c t file, c
nhn thng qua mng hoc t IPC u c th tim n nguy c gy ra cc vn v
bo mt. Vn ph bin nht l trn b m (buffer overflow), s dng sau khi gii
phng (use after free) v li lgc off-by-one error (li b st iu kin bin). Android
cung cp mt s k thut nh ASLR v DEP, gip gim thiu kh nng xy ra cc li
ny, nhng khng gii quyt c tn gc vn . Bn c th trnh nhng sai st ny
bng cch x l con tr v qun l b m mt cch cn thn.
Cc ngn ng ng da trn chui, chng hn nh JavaScript v SQL, cng l i
tng cn kim tra u vo do thot ra k t v cho php chn script (script injection).
Nu bn ang s dng d liu bn trong truy vn s c gi ti c s d liu SQL
hoc content provider, SQL Injection l mt vn . Cch bo v tt nht l s dng
truy vn tham s ha, nh tho lun mc trc v content provider. Gii hn cc
quyn l ch c (only-read) hoc ch ghi (only-write) cng lm gim kh nng gy hi
lin quan n SQL Injection.
Nu khng th s dng nhng tnh nng bo mt trn, chng ti rt khuyn khch bn
dng cc nh dng cu trc d liu tt v kim tra xem d liu c ph hp vi nh
dng mong mun hay khng. Vic lp danh sch en cc k t hoc k t thay th
khng c s dng c th l mt chin lc hiu qu, song bn nn trnh nhng k
thut ny v chng d pht sinh li trong thc t.

X l d liu ngi dng


Nhn chung, cch tip cn tt nht bo mt d liu ngi dng l hn ch ti a vic
s dng API truy cp d liu nhy cm hoc c nhn ca ngi dng. Nu c truy
cp ti d liu ca ngi dng, bn c th trnh lu tr hoc truyn thng tin, khng
lu tr hay truyn d liu. Cui cng, hy cn nhc xem liu c cch no ci t
bng bm (hash) hoc dng d liu khng o chiu (non-reversible) cho ng dng
ca bn. V d, ng dng ca bn c th dng bng bm vi mt a ch e-mail lm
kha chnh, nhm trnh truyn hoc lu tr a ch e-mail. Vic ny lm gim kh nng
c th v tnh l d liu, ng thi lm gim c hi cc i tng tn cng c gng
li dng ng dng ca bn.
Nu ng dng ca bn truy cp thng tin c nhn, chng hn nh password (mt khu)
hoc username (tn ngi dng), cn nh rng mt s quyn ti phn (jurisdiction) c
th yu cu bn cung cp chnh sch ring gii thch vic s dng v lu tr d liu
. Do vy, tun theo nhng k thut bo mt tt nht theo cch hn ch ti a vic
truy cp vo d liu ngi dng cng c th gip n gin ha yu cu ngi dng.
Bn cng nn cn nhc xem liu ng dng ca bn c v tnh l thng tin c nhn
cho bn khc khng, chng hn nh cc thnh phn thuc bn th ba dnh qung
co hoc nhng service bn th ba c ng dng ca bn dng. Nu khng chc
chn l do ti sao mt thnh phn hoc service cn thng tin c nhn, ng cung cp
nhng thng tin ny. Ni chung, gim vic ng dng ca bn truy cp vo thng tin c
nhn s gip gim thiu kh nng xy ra vn trong lnh vc ny.

300

Lp trnh Android c bn
Nu buc phi truy cp d liu nhy cm, hy c tnh xem liu cc thng tin ny
c cn truyn ti server khng, hoc liu thao tc c th thc hin trn client hay
khng. Bn cng cn cn nhc v vic chy bt c m no s dng d liu nhy cm
trn client trnh truyn i d liu ngi dng.
Ngoi ra, cng cn m bo rng bn khng v tnh l d liu ngi dng cho ng
dng khc trn thit b khi qu d di vi IPC, cc file c th ghi c (world writable
file) hoc cng mng. y l mt trng hp c bit lm r r d liu c bo v
bi quyn, nh tho lun mc Yu cu quyn.
Nu bn cn mt GUID, hy to mt s ln, duy nht v lu tr n. Khng s dng
nh danh in thoi, chng hn nh s in thoi hoc IMEI (International Mobile
Equipment Identity - S nhn dng thit b di ng trn ton th gii) c th lin h vi
thng tin c nhn. Ch ny s c tho lun chi tit ti Android Developer Blog
(Blog dnh cho nh pht trin Android).
Hy cn thn khi ghi nht k (log) trn thit b. Trong Android, nht k l ti nguyn
c chia s, c th c mt ng dng c quyn READ_LOGS d dng truy cp. Mc
d d liu nht k in thoi l tm thi v c th xa c ghi li, nhng nht k
khng thch hp cha thng tin ngi dng c th v tnh lm r r d liu ngi dng
cho cc ng dng khc.

S dng WebView
Do WebView s dng ni dung Web c th bao gm HTML v JavaScript, nn nu s
dng khng ng c th gp phi nhng vn bo mt thng thng, chng hn nh
cross-site-scripting (cn gi l XSS hoc CSS, thng c cho l mt trong nhng
lp ng dng ph bin nht cc k thut hacking. Ni chung, cross-site scripting cho
thy rng k thut hacking thc y nhng l hng trong m ca mt ng dng Web
cho php mt k tn cng gi ni dung c hi t mt ngi dng cui v thu thp
mt s loi d liu t cc nn nhn). Android cha mt s c ch gip gim thiu phm
vi nh hng ca nhng vn ny bng cch gii hn kh nng ca WebView cho
mt s chc nng nh ca ng dng.
Nu ng dng ca bn khng trc tip s dng JavaScript bn trong WebView, ng
gi phng thc setJavaScriptEnable(). Mt s m mu s dng phng thc
ny, v c th bn s dng li vi cng mc ch trong ng dng sn phm. Do , hy
loi b li gi phng thc ny nu khng cn thit. Mc nh, WebView khng thc
hin JavaScript, nn khng th xy ra cross-site-scripting.
S dng phng thc addJavaScriptInterface() trong cc x l c th, v
phng thc ny cho php m JavaScript thc hin thao tc thng ch dnh cho ng
dng Android. Nu s dng phng thc ny, ch cho php tc ng trn nhng trang
Web m tt c d liu u vo u ng tin. Nu cho php u vo khng ng tin, m
JavaScript c c th x l cc phng thc Android trong ng dng ca bn. Ni chung,
chng ti khuyn khch ch s dng phng thc addJavaScriptInterface()
cho m JavaScript bn trong APK ng dng ca bn.
Nu ng dng truy cp d liu nhy cm bng mt WebView, c th bn mun dng
phng thc clearCache() xa nhng file c lu tr cc b. Phn header

301

Lp trnh Android c bn
pha server kiu nh no-cache (khng lu cache) c th c dng quy nh rng
mt ng dng khng nn lu cache ni dung c th.

X l chng thc
Nhn chung, chng ti khuyn ngh bn nn hn ch ti a vic yu cu chng thc
ngi dng (user credential) - d nhn ra cc v tn cng gi mo (phising attack),
v nhng v ny cng t c kh nng thnh cng. Thay vo , hy s dng token xc
thc (authorization token) v lm mi token ny.
Nu c th, bn khng nn lu tr username (tn ngi dng) v password (mt
khu) trn thit b. Thay vo , hy thc hin xc thc khi to bng cch s dng
username v password c ngi dng cung cp, sau s dng token xc thc i
vi service c th trong thi gian ngn.
Cc service m nhiu ng dng nn c truy cp s dng AccountManager. Nu
c th, hy dng lp AccountManager x l nhng service da trn m my
v khng lu tr password trn thit b.
Sau khi dng AccountManager truy xut mt Account, CREATOR trc khi
truyn i trong chng thc bt k, bn s khng b ri vo tnh trng v tnh truyn sai
chng thc ti ng dng.
Nu chng thc ch c dng trong nhng ng dng do bn pht trin, bn c th
kim tra ng dng truy cp vo AccountManager bng cch s dng phng thc
checkSignature(). Mt khc, nu ch c mt ng dng dng chng thc ny, bn
c th s dng mt KeyStore (i tng lu kha) lu tr.

S dng k thut m ha
Ngoi vic cung cp c ch cch ly d liu, h tr m ha ton b file h thng v cung
cp knh giao tip an ton, Android cn cung cp rt nhiu thut ton bo v d liu
nh s dng k thut m ha (cryptography).
Nhn chung, hy c gng s dng mc thc thi cao nht ca framework c t trc
h tr trng hp s dng ca bn. Nu cn truy xut an ton mt file t ni bit,
mt URI HTTPS n gin c th ph hp v khng cn n k thut m ha. Nu cn
mt ng bo mt (secure tunnel), hy xem xt s dng HttpsURLConnection hoc
SSLSocket thay v vit giao thc ca chnh bn.
Nu bn ang cn ci t giao thc ring, chng ti rt khuyn ngh rng bn khng
nn ci t thut ton m ha ca ring mnh. Hy s dng cc thut ton m ha
(cryptographic algorithm) c nh thut ton m ha AES hoc RSA c cung cp
trong lp Cipher.
S dng c ch sinh ngu nhin s bo mt (secure random number generator),
SecureRandom, khi to kha m ha bt k, KeyGenerator. S dng mt
kha khng c to t c ch sinh ngu nhin s bo mt thng lm gim ng
k kh nng bo mt ca thut ton, to iu kin cho tn cng offline (ngoi tuyn).
Nu bn cn lu tr mt kha ti s dng, hy dng c ch ging nh KeyStore
cung cp mt c ch lu tr lu di v truy xut kha m ha (cryptographic key).

302

Lp trnh Android c bn

S dng giao tip lin tin trnh


Mt s ng dng c gng ci t IPC bng cch s dng cc k thut Linux truyn
thng nh cng mng v file chia s. Thay vo , chng ti rt khuyn khch bn s
dng tnh nng ca h thng Android nh Intent, Binder hoc Messenger vi mt
Service v BroadcastReceiver. C ch giao tip lin tin trnh ca Android cho
php bn xc nhn danh tnh ca vic kt ni ng dng ti IPC ca bn v thit lp
chnh sch bo mt cho tng c ch IPC.
Rt nhiu phn t bo mt c chia s thng qua c ch IPC. Nu c ch IPC ca bn
khng xc nh ng dng khc dng, hy thit lp thuc tnh android:exported
l false trong phn t tng ng ca file k khai, chng hn nh phn t <service>.
Vic ny rt hu dng i vi nhng ng dng bao gm nhiu tin trnh trong cng UID
(Unique identification - nh danh duy nht), hoc trong trng hp bn ra quyt nh
mun khi pht trin ng dng l thc s khng mun xut ra bn ngoi chc nng nh
IPC nhng li khng mun vit li m.
Nu IPC c xc nh l cho php ng dng khc truy cp, bn c th p dng
mt chnh sch bo mt bng cch s dng phn t <permission>. Nu IPC
thc hin vic giao tip gia tng ng dng khc nhau ca bn c k vi cng
ch k, tt hn ht bn nn s dng quyn mc signature trong thnh phn

android:protectionLevel.

S dng intent
Intent l c ch c a dng cho IPC khng ng b trong Android. Ty
thuc vo yu cu ca ng dng, bn c th s dng sendBroadcast(),
sendOrderedBroadcast(), hoc mt intent tng minh cho mt thnh phn ng
dng xc nh.
Lu , vic broadcast theo th t c th b mt i tng nhn tiu th, nn c th
chng khng c gi ti tt c ng dng. Nu ang gi mt intent cn chuyn ti
mt trnh nhn xc nh, bn phi s dng mt intent tng minh khai bo trnh nhn
bng intent tn.
Trnh gi intent c th kim nh trnh nhn c mt quyn xc nh quyn khc null gi
cng li gi phng thc. Ch nhng ng dng c quyn ny mi c nhn intent.
Nu d liu bn trong intent broadcast c tnh cht nhy cm, bn nn cn nhc p
dng quyn m bo rng nhng ng dng xu khng th ng k nhn cc thng
ip ny nu thiu quyn thch hp. Trong nhng hon cnh ny, bn cng c th cn
nhc ti vic trc tip ch ra trnh nhn thay v gi broadcast.
Ghi ch: Khng nn cn nhc b lc intent cho tnh nng bo mt - cc thnh phn
c th c dn ra bng nhng intent tng minh v c th khng cha d liu
ph hp vi b lc intent. Bn nn thc hin xc thc u vo bn trong trnh nhn
intent chc chn d liu ny c nh dng ph hp vi trnh nhn, service hoc
activity c dn ra.

303

Lp trnh Android c bn

S dng service
Service thng c dng cung cp tnh nng s dng cho ng dng khc. Mi
lp service phi c khai bo tng ng trong file k khai ca lp ny.

Mc nh, service khng c xut ra v cc ng dng khc cng khng th gi n.


Tuy nhin, nu bn thm b lc intent bt k khai bo service, th mc nh service
ny c xut ra. Tt nht, bn nn khai bo r thuc tnh android:exported
m bo service s hot ng nh cch bn mun. Chng ta cng c th bo v cc
service bng cch s dng thuc tnh android:permission. Khi lm vy, cc ng
dng khc s phi khai bo phn t <uses-permission> tng ng trong file k
khai ca chnh nhng ng dng c th khi ng, dng hoc lin kt vi service.
Mt service c th bo v cc li gi IPC c nhn trong service bng quyn, nh gi
phng thc checkCallingPermission() trc khi thc thi ci t li gi IPC
ny. Thng thng, chng ti khuyn ngh bn nn s dng cc quyn khai bo trong
file k khai, nh vy nhng quyn ny s t b xm phm hn.

S dng i tng Binder v Message


S dng Binder v Messenger l c ch c a dng cho IPC kiu RPC (Remote
procedure call - Th tc gi hm t xa). Hai i tng ny cung cp mt giao din c
nh ngha tt, cho php xc thc qua li gia cc im endpoint (im giao tip cui),
nu cn.
Chng ti rt khuyn khch vic thit k giao din theo cch khng yu cu kim tra
quyn c th ca giao din. Cc i tng Binder v Messenger khng c khai
bo bn trong file k khai ca ng dng; do , bn khng th p dng quyn khai bo
trc tip ln nhng i tng ny. Thng thng, hai i tng ny tha k cc quyn
c khai bo trong file k khai ca ng dng cho Service v Activity cha
chng. Nu bn ang to giao din yu cu xc thc v/hoc iu khin truy cp, cc
iu khin ny phi c thm vo mt cch r rng di dng m trong giao din
Binder hoc Messenger.
Nu cung cp mt giao din yu cu iu khin truy cp, bn c th s dng phng
thc checkCallingPermission() kim tra xem liu li gi c km theo quyn
hay khng. Vic ny c bit quan trng trc khi truy cp mt service i din cho li
gi ny, nu nh danh ca ng dng do bn pht trin c chuyn ti cc giao din
khc. Nu gi ra mt giao din do Service cung cp, vic dn bindService() ra
c th gp li nu bn khng c quyn truy cp ti service xc nh . Nu gi mt
giao din c chnh ng dng ca bn cung cp cc b, th vic s dng phng
thc clearCallingIdentify() s c ch khi cn vt qua qu trnh kim tra bo
mt bn trong.
tm hiu thm v vic thc hin IPC vi service, xem mc Bound Services (Service
c lin kt).

304

Lp trnh Android c bn

S dng broadcast receiver


Mi i tng BroadcastReceiver x l cc yu cu khng ng b do mt
Intent khi to.
Mc nh, trnh nhn c xut ra bn ngoi v bt c ng dng no khc u c
th gi trnh ny. Nu i tng BroadcastReceiver ca bn c thit k
cc ng dng khc s dng, c th bn mun p dng quyn bo mt cho trnh
nhn bng cch dng phn t <receiver> trong file k khai ca ng dng. Vic
ny s ngn nhng ng dng cha c quyn thch hp khng gi c intent ti
BroadcastReceiver ny.

Np m ng
Chng ti khuyn co bn khng c np m t bn ngoi APK ng dng. Vic lm
ny s gia tng ng k kh nng ng dng tha hip vi vic chn m (code injection)
hoc can thip m (code tampering). Lm nh vy cng khin vic qun l phin bn
v kim th ng dng tr nn phc tp hn. Cui cng, vic np m t bn ngoi APK
ng dng khin chng ta khng th kim tra hnh vi ca ng dng; do , hot ng
ny c th b cm trong mt s mi trng.
Nu ng dng ca bn np m ng, iu quan trng nht nn nh l m c np
ng chy cng quyn bo mt vi APK ca ng dng. Ngi dng quyt nh ci t
ng dng da trn danh tnh ca bn, v h mong mun c cung cp bt c m no
chy bn trong ng dng, bao gm c m np ng.
Ri ro bo mt ch yu lin quan ti m np ng l m ny cn c ly t mt ngun
c th xc minh c. Nu cc m un ny c thm trc tip vo APK ca bn, th
ng dng khc khng th chnh sa c. iu ny lun ng, bt k m ca ca bn
l th vin m my (native library) hay mt lp c np bng DexClassLoader.
Chng ta tng thy rt nhiu ng dng c gng np m t nhng a im khng an
ton, nh ti v t mng thng qua giao thc khng m ha, hoc t a im c th
ghi c nh b nh ngoi. Nhng ni a im c th cho php i tng tn cng
trn mng chnh sa ni dung trong khi truyn, hoc cho php ng dng khc trong
thit b ngi dng chnh sa ni dung.

Bo mt trn my o
Dalvik l my o (VM - Virtual Machine) chy trn h thng Android. Dalvik c xy
dng dnh ring cho Android, nhng nhiu mi quan ngi lin quan n m bo mt
trong cc my o khc cng tn ti Android. Ni chung, bn khng cn bn tm
n vn bo mt lin quan n my o. ng dng ca bn chy trong mi trng
sandbox an ton, nn cc tin trnh khc trong h thng khng th truy cp vo m
hoc d liu ring ca bn.
Nu bn quan tm ti ch bo mt trn my o, chng ti khuyn ngh bn nn lm
quen dn vi cc ti liu hin c v ch ny. Hai ngun ti liu ph bin hn l:

305

Lp trnh Android c bn

http://www.securingjava.com/toc.html.

https://www.owasp.org/index.php/Java_Security_Resources.

Ti liu ny ch tp trung vo cc kha cnh lin quan n Android hoc nhng im


khc mi trng my o khc. i vi cc nh pht trin chng trnh c kinh
nghim lp trnh my o trong mi trng khc, hai vn ln di y c th khc
vi khi vit ng dng cho Android:

Mt s my o, chng hn nh JVM hoc .net runtime, hot ng ging nh mt


bin bo mt (security boundary), cch ly m khi cc tnh nng ca h iu hnh
bn di. Trong Android, my o Dalvik khng phi l mt bin bo mt - sandbox
ca ng dng c ci ti mc h iu hnh, nn Dalvik c th hot ng tng
thch vi m my trong cng ng dng m khng c bt c rng buc no v bo
mt.

Nhn mt khng gian lu tr gii hn trn thit b di ng, vic ny vn quen thuc
vi nhng nh pht trin mun xy dng ng dng kiu m un v s dng vic
np lp ng. Khi lm vy, hy xt ti c ngun bn truy xut lgc ng dng v
v tr lu tr ng dng cc b. Khng nn np lp ng t ngun cha c kim
nh, chng hn nh nhng ngun mng khng c bo mt hoc b nh ngoi,
v m c th b chnh sa cha cc hnh vi c hi.

Bo mt trong m my
Nhn chung, chng ti khuyn khch cc lp trnh vin dng Android SDK (Software
development kit - B pht trin phn mm) pht trin ng dng thay v dng m my
i km Android NDK (Native Development Kit - B pht trin m my). Cc ng dng
c xy dng vi m my phc tp hn, t linh ng hn v thng bao gm nhiu
li b nh hn, chng hn nh trn b m.
Android c xy dng da trn nhn (kernel) Linux; bi vy, nm r vic pht trin
bo mt trn Linux s c bit c ch trong trng hp bn mun s dng m my.
Hng dn v bo mt trn Linux l ni dung nm ngoi phm vi ca ti liu ny,
nhng c bn lun trong mt ti liu vo loi ph bin nht l Programming for
Linux and Unix HOWTO, ti a ch http://www.dwheeler.com/secure-programs.
Mt khc bit quan trng gia Android v mi trng Linux l Sandbox ca ng dng.
Trn Android, tt c cc ng dng u chy trong Sandbox ca ng dng, bao gm c
cc ng dng c vit bng m my. mc c bn nht, mt cch hay m cc lp
trnh vin quen vi Linux ngh v Sandbox ca Andorid l mi ng dng u nhn
mt UID duy nht vi cc quyn c gii hn. iu ny c tho lun chi tit hn
trong mc Android Security Overview (Tng quan v bo mt trong Android). Ngoi
ra, bn nn lm quen vi quyn ca ng dng ngay c khi ang s dng m my.

306

Lp trnh Android c bn

15. WebView
15.1 Tng quan v lp WebView
WebView l mt View dng hin th trang Web. y l lp c bn m bn c th
da vo cun trnh duyt Web, hoc ch n gin l hin th mt s ni dung trc
tuyn bn trong Activity ca bn. Lp ny s dng WebKit rendering engine hin
th trang Web v bao gm cc phng thc iu hng tin v li thng qua mt
history (lch s), phng to v thu nh, thc hin tm kim vn bn,
Lu , Activity ca bn truy cp Internet v np trang Web trong mt WebView, bn
phi thm quyn Internet vo file k khai ca Android:
<uses-permission android:name="android.permission.INTERNET" />

Khai bo quyn trn phi l con ca phn t INTERNET.


tm hiu thm thng tin, mi bn tham kho mc Xy dng ng dng Web thng
qua WebView bn di.

Cc trng hp s dng c bn
Mc nh, mt WebView khng cung cp widget ging nh trnh duyt, khng cho php
m JavaScript v b qua li Web. Nu mc ch ch l hin th mt s HTML l mt
phn trong giao din ngi dng ca bn th s dng WebView c v n; ngi dng
khng cn tng tc vi trang Web, ngoi tr vic c n v trang Web cng khng
cn tng tc vi ngi dng. Nu thc s mun mt trnh duyt Web ang pht trin
mnh, c th bn s mun gi ti ng dng Browser vi mt intent URL hn l hin th
trang Web bng WebView. V d:
Uri uri = Uri.parse("http://www.example.com");

Intent intent = new Intent(Intent.ACTION_VIEW, uri);


startActivity(intent);

Xem ch v Intent tm hiu thm thng tin.


cung cp mt WebView trong Activity ca bn, hy bao gm mt Activity trong layout
Web ca bn, hoc thit lp ton b ca s Activity lm mt WebView trong phng
thc onCreate().
WebView webview = new WebView(this);
setContentView(webview);

Sau np trang Web mong mun:

307

Lp trnh Android c bn
// Cch s dng n gin nht: Lu , nu c li khi np trang ny
// th s KHNG c ngoi l no c nm ra (xem bn di).
webview.loadUrl(http://slashdot.org/);

// HOC, bn cng c th np t mt chui HTML:

String summary = <html><body>You scored <b>192</b>points.</body></html>;


webview.loadData(summary, text/html, null);

// ... mc d lu rng tn ti mt s hn ch v nhng g HTML


// ny c th thc hin.

// Xem JavaDocs v loadData() v loadDataWithBaseURL() tm hiu thm.

Mt WebView c vi im ty chnh v ti y, bn c th thm hnh vi ca ng dng.


l:

To v thit lp mt lp con WebChromeClient. Lp ny c gi khi xy ra


mt s s kin c th gy nh hng n giao din ngi dng trnh duyt, v d
nh cp nht tin trnh v cnh bo JavaScript c gi ti WebView. Xem mc
Debugging Tasks (G li tc v) bit thm thng tin.

To v thit lp mt lp con WebViewClient. Lp con ny c th c gi khi


xy ra mt s s kin nh hng ti vic hin th ni dung, v d nh cc li hoc
tin trnh gi form. Bn cng c th chn vic np URL y (thng qua phng
thc shouldOverrideUrlLoading()).

Chnh sa WebSettings, chng hn nh cho php chy m JavaScript bng


phng thc setJavaScriptEnabled().

Chn i tng Java vo WebView bng cch s dng


addJavascriptInterface(Object, String). Phng thc ny cho
php bn chn i tng Java vo ng cnh JavaScript ca trang; do , cc i
tng ny c th c m JavaScript trn trang truy cp.

Sau y l mt v d phc tp hn, minh ha qu trnh x l li, ci t v thng bo


v tin trnh:
// Cho php hin th tin trnh trong thanh tiu ca activity,
// ging nh cch ng dng trnh duyt lm.

getWindow().requestFeature(Window.FEATURE_PROGRESS);
webview.getSettings().setJavaScriptEnabled(true);
final Activity activity = this;

webview.setWebChromeClient(new WebChromeClient() {

public void onProgressChanged(WebView view, int progress) {

// Cc activity v WebView c lng tin trnh bng nhng tiu

// chun khc nhau. Thc o tin trnh (progress meter) s t


// ng bin mt khi chng ta t ti 100%
activity.setProgress(progress * 1000);

308

Lp trnh Android c bn
}

});

webview.setWebViewClient(new WebViewClient() {

public void onReceivedError(WebView view, int errorCode, String


description, String failingUrl) {
Toast.makeText(activity, Oh no! + description,

Toast.LENGTH_SHORT).show();

});
webview.loadUrl(http://developer.android.com/);

Thu phng WebView


cho php chc nng thu phng (phng to, thu nh) c sn, hy thit lp
WebSettings.setBuiltInZoomControls(boolean) (c gii thiu trong
API cp CUPCAKE).
Ghi ch: S dng chc nng thu phng khi chiu cao hoc rng c thit lp l
WRAP_CONTENT c th dn n hnh vi khng xc nh v nn trnh.

Qun l cookie v ca s
V l do bo mt c gii thch r phn trc, nn ng dng ca bn c cache
ring, lu tr cookie,... - cache ny khng chia s vi d liu ng dng trnh duyt.
Mc nh, yu cu m ca s mi ca HTML b b qua. iu ny ng trong c trng
hp ca s c m bng m JavaScript ln bng thuc tnh ch trn lin kt (link).
Bn c th ty chnh phng thc WebChromeClient cung cp hnh vi ca chnh
mnh nhm m nhiu ca s, ng thi hin th chng theo cch bn mun.
Hnh vi chun ca Activity b hy v c to li khi hng ca thit b thay i, hoc
khi c bt c cu hnh no khc thay i. iu ny cng lm cho WebView np li trang
hin ti. Nu khng thch cch x l trn, bn c th thit lp Activity ca mnh x
l thay i trong orientation v keyboardHidden, sau ch li mt mnh
WebView. Khi , WebView s t ng nh hng li cho ph hp. c mc Handling
Runtime Changes (X l cc thay i trong thi gian chy) tm hiu thm v cch
x l vic thay i cu hnh trong thi gian chy.

Xy dng trang Web h tr cc mt mn hnh khc nhau


Mt mn hnh (screen density) ca mt thit b da trn phn gii mn hnh
(screen resolution). Mt mn hnh vi mt thp s c s pixel trn mi inch (1 inch =
2,54 cm) thp hn; trong khi , mt mn hnh c mt ln hn i khi c s lng
pixel trn mi inch nhiu hn ng k. Mt ca mn hnh l mt thng s quan trng
bi v, nu cc thng s khc u nh nhau, mt thnh phn giao din ngi dng
(chng hn nh mt button) c chiu cao v rng c nh ngha theo s pixel mn
hnh s xut hin ln hn trn mn hnh mt thp, ng thi nh hn trn mn hnh

309

Lp trnh Android c bn
mt cao hn. n gin, Android chia tt c cc mt mn hnh thc thnh ba
mt chung: Cao, trung bnh v thp.
Mc nh, WebView s cn t l mt trang Web trang ny c v kch thc
ph hp vi vic hin th mc nh trn mn hnh mt trung bnh. Do , Android p
dng t l 1,5x trn mn hnh mt cao (do s pixel ca mn hnh ny nh hn) v t
l 0,75 trn mn hnh mt thp (do s pixel ln hn). Bt u vi API cp ECLAIR,
WebView h tr DOM, CSS v cc tnh nng ca th meta gip bn (trong vai tr
mt nh lp trnh Web) x l mn hnh vi nhng mt khc nhau.
Sau y l phn tng kt nhng tnh nng bn c th dng x l cc mt mn
hnh khc nhau:
Thuc tnh DOM window.devicePixelRatio. Gi tr ca thuc tnh
ny xc nh yu t t l mc nh dng cho thit b hin ti. V d, nu gi tr
window.devicePixelRatio l 1,0, thit b c xem l c mt trung bnh
(medium density - mdpi) v vic iu chnh kch thc mc nh s khng c
p dng cho trang Web ny; nu gi tr ny l 1,5, thit b ny c xem l thit
b mt cao (high density device - hdpi) v ni dung trang Web s c ko vi
t l 1,5x; nu gi tr ny l 0,75, thit b c xem l thit b c mt thp (low
density device - ldpi) v ni dung c ko vi t l 0,75x.

Truy vn media CSS -webkit-device-pixel-ratio. S dng thuc tnh ny


xc nh mt mn hnh m stylesheet ny thng dng. Gi tr tng ng c
th l 0,75, 1 hoc 1,5, cho bit kiu ny dng cho thit b c mn hnh mt
thp, trung bnh hoc cao tng ng. V d:

<link rel=stylesheet media=screen and


(-webkit-device-pixel-ratio:1.5) href=hdpi.css />

Stylesheet hdpi.css ch c s dng cho thit b c t l pixel mn hnh mt


cao l 1,5.

H tr video trong HTML5


h tr video HTML5 ni tuyn trong ng dng, bn cn bt ch tng tc phn
cng (hardware acceleration), ng thi ci t mt WebChromeClient. h tr
ton mn hnh, bn cn ci t onShowCustomView(View, WebChromeClient.
CustomViewCallback) v onHideCustomView(), cn phng thc
getVideoLoadingProgressView() th khng bt buc.

15.2 Xy dng ng dng Web trong WebView


Nu mun cung cp mt ng dng Web (hoc ch mt trang Web) l mt phn ca ng
dng client, bn c th dng WebView. Lp WebView l lp m rng t lp View cho
php hin th trang Web thnh mt phn ca layout activity. WebView khng bao gm
bt k tnh nng no ca mt trnh duyt Web y , chng hn nh iu khin iu
hng hoc thanh a ch (address bar). Mc nh, tt c nhng g WebView thc hin,
u l hin th trang Web.

310

Lp trnh Android c bn
Mt kch bn ph bin cho thy vic s dng WebView rt c ch l khi bn mun cung
cp thng tin trong ng dng c th cn cp nht, chng hn nh mt tha thun vi
ngi dng cui hoc hng dn ngi dng. Bn trong ng dng Android, bn c
th to mt Activity cha WebView, sau dng Activity ny hin th vn bn
c host trc tuyn.
Kch bn khc m trong , WebView c th h tr l khi ng dng ca bn cung cp
d liu cho ngi dng, nhng ngi lun mun yu cu kt ni Internet truy xut
d liu, chng hn nh e-mail. Trong trng hp ny, bn c th thy tht d dng
xy dng mt WebView trong ng dng Android ca mnh nhm hin th trang Web vi
ton b d liu ngi dng thay v thc hin mt yu cu mng, sau phn tch v
hin th d liu trn mn hnh Android. Thay v th, bn c th thit k mt trang Web
ph hp vi thit b Android, sau ci t WebView trong ng dng Android np
trang Web.
Ti liu ny s hng dn bn cch khi ng vi WebView cng nh cch b sung
thm mt s tnh nng, chng hn nh x l iu hng trang v lin kt JavaScript t
trang Web ti m pha client (client-side code) trong ng dng Android.

Thm WebView vo ng dng ca bn


thm WebView vo ng dng ca mnh, bn ch cn thm phn t <WebView>
vo layout cho activity. V d, sau y l mt file layout, trong WebView s hin th
ton mn hnh:
<?xml version=1.0 encoding=utf-8?>
<WebView xmlns:android=http://schemas.android.com/apk/res/android
android:id=@+id/webview
android:layout_width=fill_parent
android:layout_height=fill_parent
/>

np trang Web trong WebView, s dng phng thc loadUrl(). V d:


WebView myWebView =(WebView) findViewById(R.id.webview);
myWebView.loadUrl(http://www.example.com);

Tuy nhin, trc khi thc hin m trn, ng dng ca bn phi c truy cp vo Internet.
ly truy cp vo Internet, hy yu cu quyn INTERNET trong file k khai. V d:
<manifest ... >
<uses-permissionandroid:name=android.permission.INTERNET/>
...
</manifest>

Tt c nhng g bn cn l mt WebView c bn hin th trang Web.

311

Lp trnh Android c bn

S dng m JavaScript trong WebView


Nu mt trang Web d nh s np trong WebView s dng m JavaScript, bn phi
cho php chy m JavaScript trong WebView ca mnh. Khi cho php JavaScript, bn
cng c th to giao din gia m ng dng v m JavaScript.

Cho php chy m JavaScript


Mc nh, JavaScript b chn trong WebView. Bn c th cho php chy m ny
thng qua i tng WebSettings c gn vo WebView. Bn c th truy xut
WebSettings bng phng thc getSettings(), sau cho php chy m
JavaScript bng phng thc setJavaScriptEnabled().
V d:
WebView myWebView =(WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

WebSettings cung cp truy cp vo rt nhiu thit lp m bn c th thy hu dng.


V d, nu ang pht trin mt ng dng Web c thit k dnh ring cho WebView

trong ng dng Android, bn c th nh ngha mt chui agent ty chn ngi dng


(custom user agent string) bng phng thc setUserAgentString(), sau
thc hin truy vn agent ty chn ngi dng trong trang Web ca mnh xc nh
client vn tin trang Web ca bn thc s l ng dng Android ca bn hay khng.

Lin kt m JavaScript vi m Android


Khi pht trin mt ng dng Web c thit k ring cho WebView trong ng dng
Android, bn c th to giao din gia m JavaScript v m Android pha client. V d,
m JavaScript c th gi mt phng thc trong m Android hin th mt i tng
Dialog (hp thoi), thay v s dng hm alert() ca JavaScript.
lin kt mt giao din mi gia m JavaScript vi m Android, bn gi phng thc
addJavascriptInterface(), truyn cho phng thc ny mt th hin ca lp
lin kt JavaScript vi tn mt giao din m m JavaScript c th gi truy cp
lp ny.
V d, bn c th a lp sau vo ng dng Android ca mnh:
public class WebAppInterface {
Context mContext;

312

/** To giao din v thit lp ng cnh */


WebAppInterface(Context c){
mContext = c;
}

Lp trnh Android c bn

/** Hin th mt thng ip nhanh t trang Web */


@JavascriptInterface
public void showToast(String toast){
Toast.makeText(mContext, toast,Toast.LENGTH_SHORT).show();
}

Ch Nu thit lp targetSdkVersion l 17 hoc cao hn, bn phi thm ch


thch @JavascriptInterface vo bt k phng thc no bn mun dng cho
JavaScript (phng thc ny cng phi l public). Nu bn khng cung cp ch
thch ny, trang Web ca bn s khng truy cp c phng thc khi chy trn
Android 4.2 hoc phin bn cao hn.
Trong v d di y, lp WebAppInterface cho php trang Web to mt thng ip
nhanh (Toast), s dng phng thc showToast().
Bn c th lin kt lp ny vi JavaScript chy trong WebView ca mnh bng phng
thc addJavascriptInterface() v t tn cho giao din Android. V d:
WebView webView =(WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), Android);

M trn s to ra mt giao din c gi l Android, cho php JavaScript chy trong


WebView. Khi , ng dng Web ca bn c th truy cp vo lp WebAppInterface.
V d, di y l mt s m HTML v JavaScript dng to thng ip nhanh s s
dng giao din mi khi ngi dng nhn vo button:
<input type=button value=Say hello onClick=showAndroidToast
(Hello Android!) />
<script type=text/javascript>
function showAndroidToast(toast){
Android.showToast(toast);
}
</script>

Khng cn khi to giao din Android t m JavaScript. WebView s t ng khin


giao din ny c th s dng c cho trang Web ca bn. Do , khi nhn vo
button ny, phng thc showAndroidToast() s dng giao din Android gi
phng thc WebAppInterface.showToast().
Ghi ch: i tng ny c lin kt vi m JavaScript chy trong lung khc v
khng nm trong lung xy dng i tng ny.

313

Lp trnh Android c bn
Ch S dng phng thc addJavascriptInterface() cho php JavaScript
iu khin ng dng Android ca bn. y c th l mt tnh nng hu dng, hoc
l mt vn bo mt nguy him. Khi HTML trong WebView c ngun gc khng
ng tin (v d, mt phn hoc tt c HTML c mt ngi hoc tin trnh khng
xc nh cung cp), i tng tn cng c th a vo m HTML thc thi m pha
client ca bn v a vo bt c m no m i tng tn cng mun. Nh vy, bn
khng nn s dng phng thc addJavascriptInterface(), tr phi mun
ghi c m HTML ln JavaScript vo WebView ca bn. Bn cng khng nn cho
php ngi dng iu hng sang trang Web khc khng phi ca mnh, bn trong
i tng WebView (thay vo , hy cho php ng dng trnh duyt mc nh m
lin kt ngoi (foreign link) - mc nh, trnh duyt Web ca ngi dng m tt c lin
kt URL, nn bn cn cn thn khi x l iu hng trang nh miu t mc sau).

X l iu hng trang
Khi ngi dng nhn vo lin kt t trang Web trong WebView ca bn, hnh vi mc
nh ca Android l khi chy mt ng dng x l URL. Thng th trnh duyt Web
mc nh m v np URL ch (destination URL). Tuy nhin, bn c th ghi hnh vi
ny cho WebView ca mnh; do , lin kt m bn trong WebView ca bn. Sau ,
bn c th cho php ngi dng iu hng li hoc tin thng qua history trang Web
ca h c lu trong WebView do bn pht trin.
m lin kt c ngi dng nhn vo, bn ch cn cung cp WebViewClient
cho WebView ca bn, bng cch s dng phng thc setWebViewClient().
V d:
WebView myWebView =(WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());

Nh vy l n y, tt c lin kt ngi dng nhn vo u c np bn trong


WebView ca bn.
Nu bn mun thm iu khin nhng ni lin kt c nhn np, hy to
WebViewClient ca chnh bn, trong WebViewClient ny ghi phng thc
shouldOverrideUrlLoading(). V d:
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(Uri.parse(url).getHost().equals(www.example.com)){
// y l trang Web ca ti, do khng ghi ; hy

// WebView ca ti np trang
return false;
}
// Ngc li, lin kt ny khng phi l mt trang trn min

314

Lp trnh Android c bn

// ca ti, nn hy khi ng Activity khc x l cc URL


Intent intent ==new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}

Sau , bn to mt th hin cho WebViewClient mi ny ca WebView:


WebView myWebView =(WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new MyWebViewClient());

Lc ny, khi ngi dng nhn vo mt lin kt, h thng s gi


shouldOverrideUrlLoading(), l phng thc s kim tra xem liu host ca
URL c ph hp vi mt min c th (c nh ngha nh bn trn) khng. Nu ph hp,
phng thc ny tr v false khng ghi vic np URL (iu ny cho php WebView
np URL nh thng l). Nu host ca URL khng ph hp, mt Intent s c to
khi ng Activity mc nh x l URL (x l trnh duyt mc nh ca ngi dng).

iu hng lch s trang Web


Khi WebView ca bn ghi vic np URL, WebView s t ng lu li mt history ca
cc trang Web c gh thm. Bn c th iu hng tin v li thng qua history
ny bng phng thc goBack() v goForward().
V d, sau y l cch thc Activity c th s dng button Back ca thit b iu
hng li:
@Override
public boolean onKeyDown(int keyCode, KeyEventevent) {
// Kim tra xem s kin phm c phi l ca button Back khng

// v xem c history trang Web no khng.


if((keyCode ==KeyEvent.KEYCODE_BACK)&& myWebView.canGoBack()){
myWebView.goBack();
return true;
}
// Nu khng phi phm Back hoc khng c history trang
// Web, hnh vi x l mc nh ca h thng (c th l

// thot khi activity) s c s dng


return super.onKeyDown(keyCode, event);
}

Phng thc canGoBack() tr v true nu y thc s l history trang Web


ngi dng gh thm. Tng t, bn c th s dng phng thc canGoForward()
kim tra xem liu y c phi l history tin hay khng. Nu bn khng thc hin
vic kim tra ny, th khi ngi dng tin ti cui history, cc phng thc goBack()
hay goForward() u khng c tc dng.

315

You might also like