Professional Documents
Culture Documents
http://commonsware.com/AdvAndroid
; vance
"ervice Patterns
0n The Busy Coder's Guide to Android Deve opment , Ae 'o!ere" hoA to 'reate an" 'onsume ser!i'es an" 'o!ere" some basi' ser!i'e patterns. +oAe!er, ser!i'es 'an 'ertainly "o more than Ahat is 'o!ere" in those intro"u'tory patterns. 0n this 'hapter, Ae Aill e>amine some more poAer&ul options &or ser!i'es, in'lu"ing remote ser!i'es an" using ser!i'es in the role o& G'ron NobsG or Gs'he"ule" tasksG.
Cemote "ervices
1y "e&ault, ser!i'es are use" Aithin the appli'ation that publishes them. +oAe!er, it is possible to e>pose ser!i'es &or other appli'ations to take a"!antage o&. 8hese are basi'ally inter-pro'ess e"itions o& the bin"ing pattern an" 'omman" patterns outline" in The Busy Coder's Guide to Android Deve opment. We start Aith an e>planation o& the inter-pro'ess 'ommuni'ation (0#C) me'hanism o&&ere" in An"roi" &or alloAing ser!i'es to Aork Aith 'lients in other appli'ations. 8hen, Ae mo!e onto the steps to alloA a 'lient to 'onne't to a remote ser!i'e, be&ore "es'ribing hoA to turn an or"inary ser!i'e into a remote one. We then look at hoA one 'an implement a 'allba'k system to alloA ser!i'es, through 0#C, to pass in&ormation ba'k to 'lients. A&ter noting the possibility o& bin"er errors, Ae Arap by e>amining other Aays to get results &rom remote ser!i'es, ba'k to 'lients, Aithout going through bin"ing.
'30
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
As Aith a -a!a inter&a'e, you "e'lare a pa'kage at the top. As Aith a -a!a inter&a'e, the metho"s are Arappe" in an inter&a'e "e'laration ( interface IScript ; ... A). An", as Aith a -a!a inter&a'e, you list the metho"s you are making a!ailable. 8he "i&&eren'es, though, are 'riti'al. *irst, not e!ery -a!a type 'an be use" as a parameter. Bour 'hoi'es are,
'3&
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
(&rom java.util)
Any other A0DL-"e&ine" inter&a'es Any -a!a 'lasses that implement the <arcelable inter&a'e, Ahi'h is An"roi":s &la!or o& serialiCation
0n the 'ase o& the latter tAo 'ategories, you nee" to in'lu"e import statements re&eren'ing the names o& the 'lasses or inter&a'es that you are using (e.g., import com.commonsware.android.ISomet0ing). 8his is true e!en i& these 'lasses are in your oAn pa'kage O you ha!e to import them anyAay. 2e>t, parameters 'an be 'lassi&ie" as in, out, or inout. .alues that are out or 'an be 'hange" by the ser!i'e an" those 'hanges Aill be propagate" ba'k to the 'lient. #rimiti!es (e.g., int) 'an only be inP Ae in'lu"e" in &or the A0DL &or enable ! Nust &or illustration purposes.
inout
Also, you 'annot throA any e>'eptions. Bou Aill nee" to 'at'h all e>'eptions in your 'o"e, "eal Aith them, an" return &ailure in"i'ations some other Aay (e.g., error 'o"e return !alues). 2ame your A0DL &iles Aith the .aidl e>tension an" pla'e them in the proper "ire'tory base" on the pa'kage name. When you buil" your proNe't, either !ia an 0D@ or !ia Ant, the aidl utility &rom the An"roi" %DK Aill translate your A0DL into a ser!er stub an" a 'lient pro>y.
'31
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
0mplement metho"s mat'hing up Aith ea'h o& the metho"s you pla'e" in the A0DL eturn this pri!ate instan'e &rom your on7ind ! metho" in the Service sub'lass
2ote that A0DL 0#C 'alls are syn'hronous, an" so the 'aller is blo'ke" until the 0#C metho" returns. +en'e, your ser!i'es nee" to be ?ui'k about their Aork. We Aill see e>amples o& ser!i'e stubs later in this 'hapter.
A Consumer Economy
F& 'ourse, Ae nee" to ha!e a 'lient &or A0DL-"e&ine" ser!i'es, lest these ser!i'es &eel lonely.
the ser!i'e 2. onService>isconnected !, Ahi'h is 'alle" i& your 'onne'tion en"s normally, su'h as you unbin"ing your a'ti!ity &rom the ser!i'e
'33
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
@a'h o& those metho"s re'ei!es a Component9ame, Ahi'h simply i"enti&ies the ser!i'e you 'onne'te" to. More importantly, onServiceConnected ! re'ei!es an I7inder instan'e, Ahi'h is your gateAay to the 0#C inter&a'e. Bou Aill Aant to 'on!ert the I7inder into an instan'e o& your A0DL inter&a'e 'lass, so you 'an use 0#C as i& you Aere 'alling regular metho"s on a regular -a!a 'lass (IScript.Stub.asInterface binder!). 8o a'tually hook your a'ti!ity to the ser!i'e, 'all bindService ! on the a'ti!ity,
bindService new Intent )com.commonsware.android.advservice.IScript)!@ svcConn@ Conte%t.7I9>16E?41C=:6?:!5
8he bindService ! metho" takes three parameters, 1. An Intent representing the ser!i'e you Aish to in!oke
2. Bour ServiceConnection instan'e /. A set o& &lags O most times, you Aill Aant to pass in 7I9>16E?41C=:6?:, Ahi'h Aill start up the ser!i'e i& it is not alrea"y running A&ter your bindService ! 'all, your onServiceConnected ! 'allba'k in the ServiceConnection Aill e!entually be in!oke", at Ahi'h time your 'onne'tion is rea"y &or use.
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
'ross-pro'ess 'ommuni'ations problem. Again, you shoul" probably 'ease your use o& the ser!i'e.
#etting Unbound
When you are "one Aith the 0#C inter&a'e, 'all unbindService !, passing in the ServiceConnection. @!entually, your 'onne'tion:s onService>isconnected ! 'allba'k Aill be in!oke", at Ahi'h point you shoul" null out your inter&a'e obNe't, "isable rele!ant Ai"gets, or otherAise &lag yoursel& as no longer being able to use the ser!i'e. Bou 'an alAays re'onne't to the ser!i'e, !ia bindService !, i& you nee" to use it again.
'36
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
ser!i'e is kept tightly 'ontrolle", it minimiCes the mis'hie& a rogue s'ript 'oul" possibly "o.
Service 1a es
8o bin" to a ser!i'e:s A0DL-"e&ine" A#0, you nee" to 'ra&t an 0ntent that 'an i"enti&y the ser!i'e in ?uestion. 0n the 'ase o& a lo'al ser!i'e, that 0ntent 'an use the lo'al approa'h o& "ire'tly re&eren'ing the ser!i'e 'lass. Fb!iously, that is not possible in a remote ser!i'e 'ase, Ahere the ser!i'e 'lass is not in the same pro'ess, an" may not e!en be knoAn by name to the 'lient. When you "e&ine a ser!i'e to be use" by remote, you nee" to a"" an intent&ilter element to your ser!i'e "e'laration in the mani&est, in"i'ating hoA you Aant that ser!i'e to be re&erre" to by 'lients. 8he mani&est &or =emoteService is shoAn beloA,
&'%ml version()$.*) encoding()utf-+)', &manifest android/versionCode()$) android/version9ame()$.*) package()com.commonsware.android.advservice) %mlns/android()0ttp/""sc0emas.android.com"apk"res"android), &uses-sdk android/minSdkVersion()O) android/targetSdkVersion()N) ", &supports-screens android/largeScreens()false) android/normalScreens()true) android/smallScreens()false) ", &application android/icon()2drawable"cw) android/label()2string"app1name), &service android/name().7s0Service), &intent-filter, &action android/name()com.commonsware.android.advservice.IScript) ", &"intent-filter, &"service, &"application, &"manifest,
+ere, Ae say that the ser!i'e 'an be i"enti&ie" by the name com.commonsware.android.advservice.IScript. %o long as the 'lient uses this name to i"enti&y the ser!i'e, it 'an bin" to that ser!i'e:s A#0.
'37
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
0n this 'ase, the name is not an implementation, but the A0DL A#0, as you Aill see beloA. 0n e&&e't, this means that so long as some ser!i'e e>ists on the "e!i'e that implements this A#0, the 'lient Aill be able to bin" to something.
The Service
1eyon" the mani&est, the ser!i'e implementation is not too unusual. 8here is the A0DL inter&a'e, IScript,
package com.commonsware.android.advservice5 "" >eclare t0e interface. interface IScript ; void e(ecuteScript String script!5 A
public class 7s0Service e%tends Service ; private final IScript.Stub binder(new IScript.Stub ! ; public void e(ecuteScript String script! ; e(ecuteScriptImpl script!5 A A5 private Interpreter i(new Interpreter !5 24verride public void onCreate ! ; super.onCreate !5 tr. ; i.set )conte%t)@ t0is!5 A catc0 bs0.:val:rror e! ; -og.e )7s0Service)@ ):rror e%ecuting script)@ e!5 A
'58
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
24verride public I7inder onBind Intent intent! ; return binder!5 A 24verride public void on"estroy ! ; super.on"estroy !5 A private void e(ecuteScriptImpl String script! ; tr. ; i.eval script!5 A catc0 bs0.:val:rror e! ; -og.e )7s0Service)@ ):rror e%ecuting script)@ e!5 A A
0& you ha!e seen the ser!i'e an" 1eanshell samples in The Busy Coder's Guide to Android Deve opment then this implementation Aill seem &amiliar. 8he biggest thing to note is that the ser!i'e returns no result an" han"les any errors lo'ally. +en'e, the 'lient Aill not get any response ba'k &rom the s'ript O the s'ript Aill Nust run. 0n a real implementation, this Aoul" be silly, an" Ae Aill Aork to re'ti&y this later in this 'hapter. Also note that, in this implementation, the s'ript is e>e'ute" "ire'tly by the ser!i'e on the 'alling threa". Fne might think this is not a problem, sin'e the ser!i'e is in its oAn pro'ess an", there&ore, 'annot possibly be using the 'lient:s $0 threa". +oAe!er, A0DL 0#C 'alls are syn'hronous, so the 'lient Aill still blo'k Aaiting &or the s'ript to be e>e'ute". 8his too Aill be 'orre'te" later in this 'hapter.
The Client
8he 'lient O 7s0Service>emo out o& 6dvServices"=emoteClient O is a &airly straight-&orAar" mashup o& the ser!i'e an" 1eanshell 'lients, Aith tAo tAists,
package com.commonsware.android.advservice.client5 import android.app.6ctivit.5
'5/
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
import import import import import import import import import import import
android.app.6lert>ialog5 android.content.Component9ame5 android.content.Conte%t5 android.content.Intent5 android.content.ServiceConnection5 android.os.7undle5 android.os.I7inder5 android.view.View5 android.widget.7utton5 android.widget.:dit?e%t5 com.commonsware.android.advservice.IScript5
public class 7s0Service>emo e%tends 6ctivit. ; private IScript service(null5 private ServiceConnection svcConn(new ServiceConnection ! ; public void onServiceConnected Component9ame class9ame@ I7inder binder! ; service(IScript.Stub.asInterface binder!5 A public void onService"isconnected Component9ame class9ame! ; service(null5 A A5 24verride public void onCreate 7undle icicle! ; super.onCreate icicle!5 setContentView =.la.out.main!5 7utton btn( 7utton!findViewById =.id.eval!5 final :dit?e%t script( :dit?e%t!findViewById =.id.script!5 btn.set$nClic)Listener new View.$nClic)Listener ! ; public void onClic) View view! ; String src(script.get+e(t !.toString !5 tr. ; service.e(ecuteScript src!5 A catc0 android.os.=emote:%ception e! ; 6lert>ialog.7uilder builder( new 6lert>ialog.Builder 7s0Service>emo.t0is!5 builder .set+itle ):%ceptionM)! .set'essage e.toString !! .set ositiveButton )4U)@ null! .s!ow !5 A A!5 A
'5'
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
Fne tAist is that the 'lient nee"s its oAn 'opy o& IScript.aidl. A&ter all, it is a totally separate appli'ation, an" there&ore "oes not share sour'e 'o"e Aith the ser!i'e. 0n a pro"u'tion en!ironment, Ae might 'ra&t an" "istribute a -A &ile that 'ontains the IScript 'lasses, so both 'lient an" ser!i'e 'an Aork o&& the same "e&inition (see the up'oming 'hapter on reusable 'omponents). *or noA, Ae Aill Nust ha!e a 'opy o& the A0DL. 8hen, the bindService ! 'all uses a slightly "i&&erent Intent, one that re&eren'es the name the ser!i'e is registere" un"er, an" that is the glue that alloAs the 'lient to &in" the mat'hing ser!i'e. 0& you 'ompile both appli'ations an" uploa" them to the "e!i'e, then start up the 'lient, you 'an enter in 1eanshell 'o"e an" ha!e it be e>e'ute" by the ser!i'e. 2ote, though, that you 'annot per&orm $0 operations (e.g., raise a ?oast) &rom the ser!i'e. 0& you 'hoose some s'ript that is long-running, you Aill see that the ;o= button is blo'ke" until the s'ript is 'omplete,
'50
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
2. 8he 'lient blo'ke" Aaiting &or the s'ript to 'omplete 0& Ae Aere not Aorrie" about the blo'king-'all issue, Ae 'oul" simply ha!e the e%ecuteScript ! e>porte" A#0 return some sort o& result (e.g., toString ! on the result o& the 1eanshell eval ! 'all). +oAe!er, that Aoul" not sol!e the &a't that 'alls to ser!i'e A#0s are syn'hronous e!en &or remote ser!i'es. Another approa'h Aoul" be to pass some sort o& 'allba'k obNe't Aith e%ecuteScript !, su'h that the ser!er 'oul" run the s'ript asyn'hronously an" in!oke the 'allba'k on su''ess or &ailure. 8his, though, implies that there is some Aay to ha!e the a'ti!ity e>port an A#0 to the ser!i'e.
'5&
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
*ortunately, this is eminently "oable, as you Aill see in this se'tion, an" the a''ompanying samples (6dvServices"=emoteService:% an" 6dvServices"=emoteClient:%).
2oti'e that Ae nee" to spe'i&i'ally import IScript=esult, Nust like Ae might import some GregularG -a!a inter&a'e. An", as be&ore, Ae nee" to make sure the 'lient an" the ser!er are Aorking o&& o& the same A0DL "e&initions, so these tAo A0DL &iles nee" to be repli'ate" a'ross ea'h proNe't.
'51
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
1ut other than that one little tAist, this is all that is re?uire", at the A0DL le!el, to ha!e the 'lient pass a 'allba'k obNe't to the ser!i'e, "e&ine the A0DL &or the 'allba'k an" a"" it as a parameter to some ser!i'e A#0 'all. F& 'ourse, there is a little more Aork to "o on the 'lient an" ser!er si"e to make use o& this 'allba'k obNe't.
'53
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
6lert>ialog.7uilder builder( new 6lert>ialog.Builder 7s0Service>emo.t0is!5 builder .set+itle ):%ceptionM)! .set'essage error! .set ositiveButton )4U)@ null! .s!ow !5
An", o& 'ourse, Ae nee" to up"ate our 'all to e%ecuteScript ! to pass the 'allba'k obNe't to the remote ser!i'e,
24verride public void onCreate 7undle icicle! ; super.onCreate icicle!5 setContentView =.la.out.main!5 7utton btn( 7utton!findViewById =.id.eval!5 final :dit?e%t script( :dit?e%t!findViewById =.id.script!5 btn.set$nClic)Listener new View.$nClic)Listener ! ; public void onClic) View view! ; String src(script.get+e(t !.toString !5 tr. ; service.e(ecuteScript src@ callback!5 A catc0 android.os.=emote:%ception e! ; failureImpl e.toString !!5 A A A!5 bindService new Intent )com.commonsware.android.advservice.IScript)!@ svcConn@ Conte%t.7I9>16E?41C=:6?:!5
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
'allba'k to supply the results o& the eval ! (on su''ess) or the message o& the :%ception (on &ailure),
package com.commonsware.android.advservice5 import import import import import import android.app.Service5 android.content.Intent5 android.os.I7inder5 android.util.-og5 java.util.concurrent.-inked7locking[ueue5 bs0.Interpreter5
public class 7s0Service e%tends Service ; private final IScript.Stub binder(new IScript.Stub ! ; public void e(ecuteScript String script@ IScript=esult cb! ; e(ecuteScriptImpl script@ cb!5 A A5 private Interpreter i(new Interpreter !5 private -inked7locking[ueue&Job, B(new -inked7locking[ueue&Job, !5 24verride public void onCreate ! ; super.onCreate !5 new +!read B<rocessor!.start !5 tr. ; i.set )conte%t)@ t0is!5 A catc0 bs0.:val:rror e! ; -og.e )7s0Service)@ ):rror e%ecuting script)@ e!5 A A 24verride public I7inder onBind Intent intent! ; return binder!5 A 24verride public void on"estroy ! ; super.on"estroy !5 B.add new #illJob !!5 A private void e(ecuteScriptImpl String script@ IScript=esult cb! ; B.add new E(ecuteScriptJob script@ cb!!5 A =unnable B<rocessor(new Runnable ! ;
'56
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
public void run ! ; w0ile true! ; tr. ; Job j(B.ta)e !5 if j.stop+!read !! ; break5
A else ; j.process !5 A A catc0 Interrupted:%ception e! ; break5 A A A5 class Job ; boolean stop+!read ! ; return false!5 A void process ! ; "" no-op A A class UillJob e%tends Job ; 24verride boolean stop+!read ! ; return true!5 A A class :%ecuteScriptJob e%tends Job ; IScript=esult cb5 String script5 E(ecuteScriptJob String script@ IScript=esult cb! ; t0is.script(script5 t0is.cb(cb5 A void process ! ; tr. ; cb.success i.eval script!.toString !!5 A catc0 ?0rowable e! ; -og.e )7s0Service)@ ):rror e%ecuting script)@ e!5 tr. ; cb.failure e.get'essage !!5 A
'57
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
A A A A
2oti'e that the ser!i'e:s oAn A#0 Nust nee"s the IScript=esult parameter, Ahi'h 'an be passe" aroun" an" use" like any other -a!a obNe't. 8he &a't that it happens to 'ause 'alls to be ma"e syn'hronously ba'k to the remote 'lient is in!isible to the ser!i'e. 8he net result is that the 'lient 'an 'all the ser!i'e an" get its results Aithout tying up the 'lient:s $0 threa". Bou may be Aon"ering Ahy Ae "o not simply use an 6s.nc?ask. 8he reason is that remote ser!i'e metho"s e>pose" by A0DL are not in!oke" on the main appli'ation threa" O one o& the &eA pla'es in An"roi" Ahere An"roi" 'alls your 'o"e &rom a ba'kgroun" threa". An 6s.nc?ask e>pe'ts to be 'reate" on the main appli'ation threa".
'68
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
2. Bou 'an use introspe'tion to see i& the ser!i'e is in"ee" installe" be&ore you e!en try 'alling bindService ! We Aill look at introspe'tion te'hni?ues later in this book.
2. 0t ?ueues up Intents, so i& another one arri!es Ahile you are Aorking on a pre!ious one, there is no problem /. 0t automati'ally shuts "oAn the ser!i'e Ahen there is no more Aork to be "one 8he biggest issue is getting results ba'k to the 'lient. 8here is no possibility o& a 'allba'k i& there is no bin"ing. *ortunately, An"roi" o&&ers some alternati!es that Aork ni'ely Aith this approa'h.
Private )roadcasts
8he 'on'ept o& a Gpri!ate broa"'astG may seem like an o>ymoron, but it is something a!ailable to you in An"roi".
'6/
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
%en"ing a broa"'ast Intent is &airly easy O 'reate the Intent an" 'all send7roadcast !. +oAe!er, by "e&ault, any appli'ation 'oul" &iel" a 7roadcast=eceiver to Aat'h &or your broa"'ast. 8his may or may not 'on'ern you. 0& you &eel that GspiesG 'oul" be troublesome, you 'an 'all set<ackage ! on your Intent, to limit the "istribution o& the broa"'ast. With set<ackage !, only 'omponents in the name" appli'ation Aill be able to re'ei!e the broa"'ast. Bou 'an e!en arrange to sen" the name o& the pa'kage !ia an e>tra to the remote ser!i'e, so the ser!i'e "oes not nee" to knoA the name o& the pa'kage in a"!an'e.
Pending Results
Another Aay &or a remote ser!i'e to sen" "ata ba'k to your a'ti!ity is !ia create<ending=esult !. 8his is a metho" on 6ctivit. that gi!es you a <endingIntent set up to trigger on6ctivit.=esult ! in your a'ti!ity. 0n essen'e, this is the un"erpinnings behin" start6ctivit.Jor=esult ! an" set=esult !. Bou 'reate the <endingIntent Aith create<ending=esult ! an" pass it in an Intent e>tra to the remote ser!i'e. 8he remote ser!i'e 'an 'all send ! on the <endingIntent, supplying an Intent Aith return "ata, Nust like set=esult ! Aoul" "o in an a'ti!ity starte" !ia start6ctivit.Jor=esult !. 0n your a'ti!ity:s on6ctivit.=esult !, you Aoul" get an" inspe't the returne" Intent. 8his Aorks ni'ely &or a'ti!ities, but this me'hanism "oes not Aork &or other 'omponents. +en'e, you 'annot use this te'hni?ue &or one ser!i'e 'alling another remote ser!i'e, &or e>ample.
)shService2 Revisited
Let us take a 'loser look at those tAo te'hni?ues, as implemente" in 6dvServices"=emoteClientEnbound an" 6dvServices"=emoteServiceEnbound. 8hese !ersions o& the 1eanshell sample are "esigne" to "emonstrate both pri!ate broa"'asts an" pen"ing results.
'6'
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
;it+ub proNe't, in a""ition to the implementation o& WakefulIntentService itsel&, spe'i&i'ally looking at these &rom the stan"point o& using 6larm8anager &or s'he"ule" tasks. 2ote that to use WakefulIntentService you Aill nee" the W6U:1-4CU permission in your appli'ation, an" i& you are using the 6larm-istener approa'h "es'ribe" in this 'hapter, you Aill also nee" the =:C:IV:1744?1C48<-:?:> permission.
/istener
8he WakefulIntentService o&&ers an 6larm-istener inter&a'e. 0& you 'reate one an" register it properly, the WakefulIntentService Aill han"le mu'h o& the "etails o& arranging to s'he"ule your alarms Ahene!er they nee" to be s'he"ule", plus "o the a'tual perio"i' Aork that you nee" the alarms &or. An 6larm-istener nee"s to implement three metho"s,
sc0edule6larms !,
Ahi'h is Ahere you Aill tea'h An"roi" Ahen an alarm is suppose" to go o&&
sendWakefulWork !, get8a%6ge !,
Ahi'h is Ahere you tell WakefulIntentService Ahat shoul" o''ur Ahen an alarm goes o&& Ahere you in"i'ate hoA long o& a time betAeen alarms shoul" elapse be&ore WakefulIntentService assumes that the alarms Aere lost an" nee" to be re-s'he"ule"
*or e>ample, &rom the WakefulIntentService "emo proNe't, here is an 6larm-istener implementation name" 6pp-istener,
package com.commonsware.cwac.wakeful.demo5 import import import import import android.app.6larm8anager5 android.app.<endingIntent5 android.content.Conte%t5 android.os.S.stemClock5 com.commonsware.cwac.wakeful.WakefulIntentService5
public class 6pp-istener implements WakefulIntentService.6larm-istener ; public void sc!edule*larms 6larm8anager mgr@ <endingIntent pi@
'6&
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
public void send.a)eful.or) Conte%t ct%t! ; WakefulIntentService.send.a)eful.or) ct%t@ 6ppService.class!5 A public long get'a(*ge ! ; return 6larm8anager.I9?:=V6-1JIJ?::918I9E?:S*F!5 A A
Bour sc0edule6larms ! metho" Aill be passe" e!erything you shoul" nee" to "e&ine Ahen you Aant to get 'ontrol again in the &uture. Mostly, this is in the &orm o& an 6larm8anager, to sa!e you &rom ha!ing to 'all getS.stemService ! on a Conte%t to get an 6larm8anager instan'e. 6larm8anager has three metho"s &or "e&ining Ahen your s'he"ule" tasks shoul" run,
set=epeating !,
Ahere you stipulate Ahen the &irst time is you Aant your task to run, an" hoA &re?uently therea&ter
setIne%act=epeating !, Ahi'h "oes set !,
the same thing but gi!es An"roi" the &le>ibility to slightly tAeak your s'he"ule &or more e&&i'ien'y Ahi'h is &or Gone-shotG alarms, Ahere you Aant a task to run on'e at a "esignate" time
8he 6larm-istener pattern is &or use Aith the &irst tAo approa'hes, not &or one-shot alarms !ia set !. @a'h o& these metho"s takes a GtypeG o& alarm. 8here are &our types, base" upon tAo orthogonal a>es o& "e'ision,
Do you Aant the "e!i'e to Aake up out o& sleep mo"e to per&orm the taskJ Do you Aant to spe'i&y the time &or the &irst task in terms o& a'tual real Aorl" time, or simply an amount o& time &rom noAJ
'61
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
8here are &our !alues, there&ore, you 'an 'hoose &rom &or the &irst parameter,
:-6<S:>1=:6-?I8: in"i'ates you Aant to spe'i&y a time relati!e to S.stemClock.elapsed=ealtime ! (a goo" 'hoi'e &or spe'i&ying a time
relati!e to noA), an" you "o not Aant to Aake up the "e!i'e &or the alarms
is the same as the abo!e one, e>'ept that you "o Aant the "e!i'e to Aake up out o& sleep mo"e
:-6<S:>1=:6-?I8:1W6U:E< =?C in"i'ates that you Aant to S.stem.current?ime8illis ! (a goo"
spe'i&y a time relati!e to 'hoi'e &or spe'i&ying a realAorl" time, as you 'an get a suitable !alue &or this out o& a Calendar obNe't), an" you "o not Aant to Aake up the "e!i'e &or the alarms is the same as the abo!e one, e>'ept that you "o Aant the "e!i'e to Aake up out o& sleep mo"e
=?C1W6U:E<
%o, in the abo!e sample, Ae are using setIne%act=epeating !, in"i'ating that Ae Aant the &irst e!ent to o''ur one minute (50,000 millise'on"s) &rom noA, then re'ur e!ery 16 minutes or so. 8he metho" is Ahere you in"i'ate to is to be "one Ahen ea'h alarm goes o&&. Most times, you Aill simply turn aroun" an" 'all sendWakefulWork ! on WakefulIntentService itsel&, i"enti&ying your 'ustom sub'lass o& WakefulIntentService, Ahere your business logi' Aill resi"e. 0n the abo!e sample, our business logi' is in 6ppService, Ahi'h Ae Aill e>amine shortly.
sendWakefulWork ! WakefulIntentService Ahat
8he get8a%6ge ! metho"... takes a bit o& e>plaining, Ahi'h Ae Aill "o later in this 'hapter. *or the moment, take it on &aith that a !alue o& tAi'e your perio" is a reasonable approa'h.
'63
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
'ontrol Ahen the "e!i'e Aakes up. *or e>ample, here is the mani&est &rom the "emo proNe't,
&'%ml version()$.*) encoding()utf-+)', &manifest %mlns/android()0ttp/""sc0emas.android.com"apk"res"android) package()com.commonsware.cwac.wakeful.demo) android/versionCode()G) android/version9ame()$.*) android/install-ocation()auto), &uses-sdk android/minSdkVersion()O) android/targetSdkVersion()N)", &supports-screens android/largeScreens()false) android/normalScreens()true) android/smallScreens()false)", &uses-permission android/name()android.permission.=:C:IV:1744?1C48<-:?:>)", &uses-permission android/name()android.permission.W6U:1-4CU)", &application android/label()2string"app1name), &receiver android/name()com.commonsware.cwac.wakeful.6larm=eceiver), &intent-filter, &action android/name()android.intent.action.744?1C48<-:?:>)", &"intent-filter, &meta-data android/name()com.commonsware.cwac.wakeful) android/resource()2%ml"wakeful)", &"receiver, &service android/name().6ppService), &"service, &activit. android/label()2string"app1name) android/name().>emo6ctivit.) android/t0eme()2android/st.le"?0eme.9o>ispla.), &intent-filter, &action android/name()android.intent.action.86I9)", &categor. android/name()android.intent.categor..-6E9CC:=)", &"intent-filter, &"activit., &"application, &"manifest,
Fur &receiver, points to the com.commonsware.cwac.wakeful.6larm=eceiver 'lass an" ties it to a 744?1C48<-:?:> a'tion. 8his re?uires a &uses-permission,
'65
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
element to re?uest the =:C:IV:1744?1C48<-:?:> permission, so users Aill knoA at install time that Ae nee" to get 'ontrol Ahen the "e!i'e turns on. Fur &receiver, element also has a &meta-data, element. 8hese elements are use" to supply more in&ormation about a 'omponent than the mani&est IML 'alls &or. 0n our 'ase, Ae are in"i'ating that there is a""itional "ata, knoAn as com.commonsware.cwac.wakeful, a!ailable !ia a wakeful IML resour'e ("res"%ml"wakeful.%ml). 8hat resour'e 'ontains a single WakefulIntentService element,
&WakefulIntentService listener()com.commonsware.cwac.wakeful.demo.6pp-istener) ",
8he one attribute in that element, listener, points to our 6larm-istener implementation &rom the pre!ious step.
'66
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
.awn!)!5
An" that:s it. 8hose tAo steps O plus WakefulIntentService O is all you nee" to get 'ontrol on a perio"i' basis to "o Aork, Aaking up the phone as nee"e". F& 'ourse, Ae ha!e not yet s'he"ule" any alarms. 8o un"erstan" hoA to "o that, Ae nee" to &irst un"erstan" when to "o that.
public class >emo6ctivit. e%tends 6ctivit. ; 24verride public void onCreate 7undle savedInstanceState! ; super.onCreate savedInstanceState!5 Strict8ode.set+!read olicy new Strict8ode.?0read<olic..Builder ! .detect*ll ! .penaltyLog ! .build !!5 WakefulIntentService.sc!edule*larms new *ppListener !@ t0is@ false!5 ?oast.ma)e+e(t t0is@ )6larms activeM)@ ?oast.-:9#?C1-49#!.s!ow !5 finis! !5
'67
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
A A
8he sc0edule6larms ! metho" on WakefulIntentService takes an implementation o& your 6larm-istener, a Conte%t, an" an optional boolean &lag in"i'ating Ahether or not the alarms shoul" be &or'e" to be s'he"ule", e!en i& they probably are alrea"y a'ti!e. 1y "e&ault, this is set to true, though our >emo6ctivit. has it as false. %o, the &irst time your a'ti!ity is e>e'ute", the alarms Aill be s'he"ule", &olloAing the rules set "oAn in your 6larm-istener. 0n an i"eal Aorl", this is all you Aoul" nee". 0& this Aere an i"eal Aorl", though, this part o& the book Aoul" not nee" to be Aritten. %in'e you are rea"ing it, you 'an tell that this is not an i"eal Aorl". %o, Ahen else "o Ae nee" to s'he"ule alarmsJ
+n a Reboot
A $ni>-style 'ron "aemon Aill pi'k up Nobs Ahere it le&t o&& a&ter a reboot. %imilarly, Win"oAs G%'he"ule" 8asksG Aill resume a&ter a reboot. Fn the other han", 6larm8anager in An"roi" is Aipe" 'lean, starting Aith Cero s'he"ule" alarms. 8he argument that Ae ha!e been gi!en is that the 'ore An"roi" team "oes not Aant apps to s'he"ule alarms an" G&orgetG about them, 'ausing them to pile up an" sloA "oAn the "e!i'e. While this is a noble obNe'ti!e, it "oes 'ause some annoyan'e, as Ae nee" to get 'ontrol at boot time an" arrange to res'he"ule the alarms.
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
&or'e-stops your app Aill 'ause you to not re'ei!e any s'he"ule" alarms e!er again, as the e>isting alarms are remo!e" an" you Aill not be able to get 'ontrol again at boot time. 8his is Ahy Ae are looking at s'he"uling the alarms e!ery time the >emo6ctivit. runs. 2ot only might it be the !ery &irst time the user has laun'he" our a'ti!ity, but it might be the !ery &irst time the user has laun'he" our a'ti!ity a&ter being &or'e-stoppe". *ortunately, WakefulIntentService han"les these s'enarios &or you, so long as you 'all sc0edule6larms ! Ahene!er your app is laun'he". 8his is Ahere get8a%6ge ! 'omes into play O i& WakefulIntentService "ete'ts that an alarm has not gone o&& in the number o& millise'on"s you return &rom get8a%6ge !, it assumes that the user &or'e-stoppe" your appli'ation an" it s'he"ules the alarms again.
Concept of Wa*e/oc*s
Most o& the time in An"roi", you are "e!eloping 'o"e that Aill run Ahile the user is a'tually using the "e!i'e. A'ti!ities, &or e>ample, only really make sense Ahen the "e!i'e is &ully aAake an" the user is tapping on the s'reen or keyboar". #arti'ularly Aith s'he"ule" ba'kgroun" tasks, though, you nee" to bear in min" that the "e!i'e Aill e!entually Ggo to sleepG. 0n &ull sleep mo"e, the "isplay, main C#$, an" keyboar" are all poAere" o&&, to ma>imiCe battery li&e. Fnly on a loA-le!el system e!ent, like an in'oming phone 'all, Aill anything Aake up.
'7/
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
Another thing that Aill partially Aake up the phone is an Intent raise" by the 6larm8anager. %o long as broa"'ast re'ei!ers are pro'essing that Intent, the 6larm8anager ensures the C#$ Aill be running (though the s'reen an" keyboar" are still o&&). Fn'e the broa"'ast re'ei!ers are "one, the 6larm8anager lets the "e!i'e go ba'k to sleep. Bou 'an a'hie!e the same e&&e't in your 'o"e !ia a Wake-ock, obtaine" !ia the <ower8anager system ser!i'e. When you a'?uire a Gpartial Wake-ockG (<6=?I6-1W6U:1-4CU), you pre!ent the C#$ &rom going ba'k to sleep until you release sai" Wake-ock. 1y proper use o& a partial Wake-ock, you 'an ensure the C#$ Aill not get shut o&& Ahile you are trying to "o ba'kgroun" Aork, Ahile still alloAing the "e!i'e to sleep most o& the time, in betAeen alarm e!ents. +oAe!er, using a Wake-ock is a bit tri'ky, parti'ularly Ahen respon"ing to an alarm Intent, as Ae Aill see in the ne>t &eA se'tions.
'7'
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
8he problem is that there is a gap in Wake-ock 'o!erage, as "epi'te" in the &olloAing "iagram,
8he 7roadcast=eceiver Aill 'all startService ! to sen" Aork to the IntentService, but that ser!i'e Aill not start up until a&ter on=eceive ! en"s. As a result, there is a Ain"oA o& time betAeen the en" o& on=eceive ! an" Ahen your IntentService 'an a'?uire its oAn Wake-ock. During that Ain"oA, the "e!i'e might &all ba'k asleep. %ometimes it Aill, sometimes it Aill not. What you nee" to "o, instea", is arrange &or o!erlapping Wake-ock instan'es. Bou nee" to a'?uire a Wake-ock in your 7roadcast=eceiver, "uring the on=eceive ! e>e'ution, an" hol" onto that Wake-ock until the Aork is 'omplete" by the IntentService,
'70
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
8hen you are assure" that the "e!i'e Aill stay aAake as long as the Aork remains to be "one.
$nside 'a?e*ul$ntent"ervice
With all that behin" us, noA Ae 'an take a look at some pie'es o& hoA WakefulIntentService per&orms its magi'.
'7&
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
scheduleAlar s-.
Fur >emo6ctivit. 'alle" sc0edule6larms !. 8he Nob o& sc0edule6larms ! is to get your 6larm-istener to s'he"ule the alarms, i& it appears that this is ne'essary,
public static void sc!edule*larms 6larm-istener listener@ Conte%t ct%t! ; sc!edule*larms listener@ ct%t@ true!5 A public static void sc!edule*larms 6larm-istener listener@ Conte%t ct%t@ boolean force! ; S0ared<references prefs(ct%t.getS!ared references 968:@ *!5 long last6larm(prefs.getLong -6S?16-6=8@ *!5 if last6larm((* LL force LL S.stem.current+ime'illis !,last6larm ZZ S.stem.current+ime'illis !-last6larm,listener.get'a(*ge !!! ; 6larm8anager mgr( 6larm8anager!ct%t.getSystemService Conte%t.6-6=81S:=VIC:!5 Intent i(new Intent ct%t@ 6larm=eceiver.class!5 <endingIntent pi(<endingIntent.getBroadcast ct%t@ *@ i@ *!5
8he sc0edule6larms ! metho" Aill think that s'he"uling alarms is ne'essary i&,
Bou &or'e" it !ia passing true to the force parameter, or 0& it 'annot &in" the last time the alarm Aent o&&, !ia a !alue store" in a ser!i'e-spe'i&i' S0ared<references obNe't, or 0& the last time the alarm Aent o&& is longer than your "esire" ma>imum age, suggesting that perhaps the user &or'e-stoppe" your app
0n prin'iple, Ae 'oul" Nust alAays s'he"ule the alarms. 0& you 'all set=epeating ! (or kin) on 6larm8anager &or a <endingIntent, any e>isting alarm &or an e?ui!alent <endingIntent is repla'e". +ere, Ge?ui!alentG means that the un"erlying 0ntent has the same a'tion, 'omponent, 'ategories, an" M0M@ type.
'71
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
8he "oAnsi"e o& alAays s'he"uling the alarms is that i& you use set=epeating !, the alarm Aill ne>t go o&& at your "esignate" time, Ahi'h may be &ar sooner than the e>isting alarm Aoul" 'all &or. *or e>ample, suppose that you Aant to get 'ontrol on'e per "ay. 0& you 'all set=epeating ! or setIne%act=epeating ! e!ery time the user laun'hes your main a'ti!ity, you Aill trigger the alarm to go o&& ea'h o& those times, in a""ition to the on'e per "ay. $sing set=epeating ! Aith a spe'i&i' time o& the "ay (e.g., /am) Aill not ha!e that e&&e't, but set=epeating ! Aith G"o the &irst one a minute &rom noAG Aoul".
Alar Receiver
8he WakefulIntentService-supplie" 6larm=eceiver Aill get 'ontrol Ahen the "e!i'e poAers on (!ia our mani&est entry) an" Ahen the alarm goes o&&. At those times, on=eceive ! Aill be 'alle",
24verride public void onReceive Conte%t ct%t@ Intent intent! ; 6larm-istener listener(getListener ct%t!5 listenerM(null! ; intent.get*ction !((null! ; S0ared<references prefs(ct%t.getS!ared references WakefulIntentService.968:@ *!5 if prefs .edit ! .putLong WakefulIntentService.-6S?16-6=8@ S.stem.current+ime'illis !! .commit !5 listener.send.a)eful.or) ct%t!5 A else ; WakefulIntentService.sc!edule*larms listener@ ct%t@ true!5 A if
A A
0& the Intent that Aas broa"'ast "oes not ha!e an a'tion, Ae assume this is the broa"'ast &rom 6larm8anager, an" so Ae 'all sendWakefulWork ! on your 6larm-istener a&ter up"ating our pri!ate S0ared<references to note that the alarm Aent o&& (&or use by sc0edule6larms !). 0&, hoAe!er, the a'tion is not-
'73
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
null, that means Ae are being starte" &rom the 744?1C48<-:?:> broa"'ast, in Ahi'h 'ase Ae 'all sc0edule6larms ! on your 6larm-istener. Where "oes the 6larm-istener obNe't 'ome &romJ A pri!ate get-istener ! metho" that takes a"!antage o& the &meta-data, &rom the mani&est,
2Suppress.arnings )unc0ecked)! private WakefulIntentService.6larm-istener getListener Conte%t ct%t! ; <ackage8anager pm(ct%t.get ac)age'anager !5 Component9ame cn(new Component%ame ct%t@ getClass !!5 tr. ; 6ctivit.Info ai(pm.getReceiverInfo cn@ <ackage8anager.#:?18:?61>6?6!5 Vml=esource<arser %pp(ai.load3ml'eta"ata pm@ W6U:JE-18:?61>6?6!5 w0ile %pp.getEvent+ype !M(Vml<ull<arser.:9>1>4CE8:9?! ; if %pp.getEvent+ype !((Vml<ull<arser.S?6=?1?6#! ; if %pp.get%ame !.equals )WakefulIntentService)!! ; String cls9ame(%pp.get*ttributeValue null@ )listener)!5 Class&6larm-istener, cls( Class&6larm-istener,!Class.for%ame cls9ame!5 return cls.newInstance !!5 A A A
%pp.ne(t !5 A catc0 9ame9otJound:%ception e! ; -og.e getClass !.get%ame !@ )Cannot find own info''')@ e!5 A catc0 Vml<ull<arser:%ception e! ; -og.e getClass !.get%ame !@ )8alformed metadata resource V8-)@ e!5 A catc0 I4:%ception e! ; -og.e getClass !.get%ame !@ )Could not read resource V8-)@ e!5 A catc0 Class9otJound:%ception e! ; -og.e getClass !.get%ame !@ )-istener class not found)@ e!5 A catc0 Illegal6ccess:%ception e! ; -og.e getClass !.get%ame !@ )-istener is not public or lacks public constructor)@ e!5 A catc0 Instantiation:%ception e! ; -og.e getClass !.get%ame !@ )Could not create instance of listener)@ e!5 A
'75
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
return null!5 A
8o rea" "ata &rom a &meta-data, element, you use <ackage8anager to get in&ormation about your 7roadcast=eceiver !ia get=eceiverInfo ! an" the 6ctivit.Info obNe't it returns. Bou 'an ask the 6ctivit.Info obNe't to get you the meta"ata &or a gi!en name !ia the loadVml8eta>ata ! metho", Ahi'h returns an Vml=esource<arser. 8his is an implementation o& the Vml<ull<arser inter&a'e, so you 'an start iterating o!er the parse e!ents until you en'ounter your "esire" element. 0n this 'ase, Ae s'an &or the start-tag e!ent &or the WakefulIntentService element, then rea" out the listener attribute, use Class.for9ame ! to &in" the 'lass, an" 'all newInstance ! on the Class obNe't to 'reate an instan'e o& your 6larm-istener. An alternati!e approa'h Aoul" be to ha!e you sub'lass 6larm=eceiver an" o!erri"e get-istener !, an" you are 'ertainly Ael'ome to "o that i& the &meta-data, approa'h 'auses you "i&&i'ulty. %o, the net o& 6larm=eceiver is that Ae alloA you to s'he"ule your alarms (i& the "e!i'e is &reshly boote") or Ae alloA you to "o your Aake&ul Aork (i& the alarm is &rom 6larm8anager).
Co
and Processing
Ahen triggere" by 6larm8anager, "ete'ts that there is no supplie" a'tion an", in that 'ase, passes 'ontrol to WakefulIntentService !ia sendWakefulWork !. Bou 'an 'all this metho" yoursel& &rom other, non-alarm s'enarios Ahere you Aant Aork to be "one that 'an be 'omplete" Aithout the "e!i'e &alling asleep. 8here are tAo &la!ors o& sendWakefulWork !. 1oth take a Conte%t O the "i&&eren'e is in the se'on" parameter. Fne takes a Class obNe't, i"enti&ying the WakefulIntentService sub'lass that shoul" be in!oke" to "o the Aake&ul Aork. 8his is a 'on!enien'e metho", Arapping aroun" the other &la!or o& sendWakefulWork ! that takes an Intent.
6larm=eceiver,
'76
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
public static void send.a)eful.or) Conte%t ct%t@ Intent i! ; getLoc) ct%t.get*pplicationConte(t !!.acquire !5 ct%t.startService i!5 A
8he get-ock ! implementation laCy-'reates our Wake-ock by getting the <ower8anager, 'reating a neA partial Wake-ock, an" setting it to be re&eren'e 'ounte" (meaning i& it is a'?uire" se!eral times, it takes a 'orrespon"ing number o& release ! 'alls to truly release the lo'k). 0& Ae ha!e alrea"y retrie!e" the Wake-ock in a pre!ious in!o'ation, Ae reuse the same lo'k. 1a'k in 6larm=eceiver, up until this point, the C#$ Aas running be'ause 6larm8anager hel" a partial Wake-ock. 2oA, the C#$ is running be'ause both 6larm8anager and WakefulIntentService hol" a partial Wake-ock. 8hen, sendWakefulWork ! starts up our ser!i'e an" e>its. %in'e this is the only thing on=eceive ! Aas "oing in 6larm=eceiver, on=eceive ! e>its. 2otably, 6larm=eceiver "oes not release the Wake-ock it a'?uire" !ia sendWakefulWork !. 8his is important, as Ae nee" to ensure that the ser!i'e 'an get its Aork "one Ahile the C#$ is running. +a" Ae release" the Wake-ock be&ore returning, it is possible that the "e!i'e Aoul" &all ba'k asleep be&ore our ser!i'e ha" a 'han'e to a'?uire a &resh Wake-ock. 8his is one o& the keys o& using Wake-ock su''ess&ully O as nee"e", use o!erlapping
'77
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
2oA, our ser!i'e Aill start up an" be able to "o something, Ahile the C#$ is running "ue to our a'?uire" Wake-ock. %o, WakefulIntentService Aill noA get 'ontrol, un"er an a'ti!e Wake-ock. %in'e it is an IntentService sub'lass, onCandleIntent ! is 'alle". +ere, Ae Nust route 'ontrol to the sub'lass: implementation o& an abstra't doWakefulWork ! metho", ensuring that Ae release the Wake-ock Ahen the Aork is "one, e!en i& a =untime:%ception is raise",
24verride final protected void on,andleIntent Intent intent! ; tr. ; do.a)eful.or) intent!5 A finall. ; getLoc) t0is.get*pplicationConte(t !!.release !5 A A
As a result, ea'h pie'e o& Aork that gets sent to the WakefulIntentService Aill a'?uire a Wake-ock !ia sendWakefulWork ! an" Aill release that Wake-ock Ahen doWakefulWork ! en"s. Fn'e that Wake-ock is &ully release", the "e!i'e 'an &all ba'k asleep.
&in"
out
088
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
7roadcast=eceiver to Aat'h &or the 6C?I49176CU#=4E9>1>6?61S:??I9#1CC69#:> broa"'ast, also "e&ine" on Connectivit.8anager. *or e>ample, you 'oul" ele't to 'ompletely 'an'el your alarm i& the ba'kgroun" "ata setting is &lippe" to false.
Bou
'an
also
register
8he ser!i'e takes up memory all o& the time. 8his is ba" in its oAn right i& the ser!i'e is not 'ontinuously "eli!ering su&&i'ient !alue to be Aorth the memory. $sers, &earing ser!i'es that sap their "e!i'e:s C#$ or AM, may atta'k the ser!i'e Aith so-'alle" Gtask killerG appli'ations or may terminate the ser!i'e !ia the %ettings app, thereby "e&eating your original goal. An"roi" itsel&, "ue to user &rustration Aith sloppy "e!elopers, Aill terminate ser!i'es it "eems ill-use", parti'ularly ones that ha!e run &or ?uite some time.
F''asionally, an e!erlasting ser!i'e is the right solution. 8ake a .F0# 'lient, &or e>ample. A .F0# 'lient usually nee"s to hol" an open so'ket Aith the .F0# ser!er to knoA about in'oming 'alls. 8he only Aay to 'ontinuously Aat'h &or in'oming 'alls is to 'ontinuously hol" open the so'ket. 8he only 'omponent 'apable o& "oing that Aoul" be a ser!i'e, so the ser!i'e Aoul" ha!e to 'ontinuously run. +oAe!er, in the 'ase o& a .F0# 'lient, or a musi' player, the user is the one spe'i&i'ally re?uesting the ser!i'e to run &ore!er. 1y using startJoreground !, a ser!i'e 'an ensure it Aill not be stoppe" "ue to ol" age &or 'ases like this.
08/
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved
; vance
"ervice Patterns
http://commonsware.com/AdvAndroid
As a 'ounter-e>ample, imagine an email 'lient. 8he 'lient Aishes to 'he'k &or neA email messages perio"i'ally. 8he right solution &or this is the 6larm8anager pattern "es'ribe" earlier in this 'hapter. 8he anti-pattern Aoul" ha!e a ser!i'e running 'onstantly, spen"ing most o& its time Aaiting &or the polling perio" to elapse (e.g., !ia ?0read.sleep !). 8here is no !alue to the user in taking up AM to Aat'h the 'lo'k ti'k. %u'h ser!i'es shoul" be reAritten to use 6larm8anager. Most o& the time, though, it appears that ser!i'es are simply leake". 8hat is one a"!antage o& using 6larm8anager an" an IntentService O it is "i&&i'ult to leak the ser!i'e, 'ausing it to run in"e&initely. 0n &a't, IntentService in general is a great implementation to use Ahene!er you use the 'omman" pattern, as it ensures that the ser!i'e Aill shut "oAn e!entually. 0& you use a regular ser!i'e, be sure to shut it "oAn Ahen it is no longer a'ti!ely "eli!ering !alue to the user.
08'
Free excerpt from _The Busy Coder's Guide to Advanced Android Development_. Copyright (c) 2011 CommonsWare, LLC. All Rights Reserved