+ All Categories
Home > Documents > Android Bonus

Android Bonus

Date post: 05-Apr-2018
Category:
Upload: zu1232
View: 214 times
Download: 0 times
Share this document with a friend

of 15

Transcript
  • 8/2/2019 Android Bonus

    1/15

    www.android360.de

    MIT CD! Vol. 1iOS unter Druck Android auf dem Vormarsch

    Fakten fr Android-Entwickler

    S O N D E R H E F T

    O N L I N E B O N U S

    Android RemotingClientseitige Implementierung derServerkommunikation

    Caching fr ProsCaching mit den Content-Providern

  • 8/2/2019 Android Bonus

    2/15

    EDITORIAL

    www.android360.de ANDROID 3602 www.android360.de2

    Liebe Le s e rinnen und Le s e r,

    wie ic h berei ts in der Prin t-Ausga be ange kn

    -

    dig t ha be, ha t Android se hr vie l me hr zu bie te

    n,

    a ls wir in ein einziges Hef t pac ken knn ten. Da

    -

    bei ha ben wir I hnen darin sc hon so vie l Wisse

    n

    ge bo ten: Sie ha ben die Neuerungen in Andr

    o-

    id 2.2 kennenge lern t, Sie ha ben erfa hren, w

    ie

    sic h Goog les Open-Source-OS nic h t t nur in der

    We l t der Smar tp hones einen fes ten P la tz sic her t

    und wie das Sic her hei ts konzep t von Andro

    id

    fun k tionier t. Dar ber hinaus ha ben Sie eine

    n

    ers ten Ein b lic k in die App li ka tionsen t wic k lun

    g

    auf Basis der F las h- Tec hno logie A I R er ha l te

    n

    und einen B lic k durc h die Augmen ted- Rea li t y

    -

    Bri l le auf die We l t ge worfen. Vie l Wissen a be

    r

    nic h t genug aus unserer Sic h t. Des wegen er ha

    l-

    ten Sie mi t dieser On lineausga be z wei wei ter

    e

    spannende Ar ti ke l.

    Sie se hen a lso: Das ers te t hemen bezogene Son

    -

    der hef t unseres vier te l

    j hr lic h ersc heinenden

    Hef ts Mo bi le Tec hno log y, das sic h ber An-

    droid hinaus mi t der vo l len Band brei te wic

    h-

    tiger mo bi ler Tec hno logien und S tra tegie

    n

    besc hf tig t, is t noc h nic h t am Ende ange kom

    -

    men

    In die s em S inne vie l S pa m i t dem

    Online bonu s von Android 3 6 0

    Thom a s Wie ecke l

    R e d a k te u r

    F O L G END E SPANN END E

    AR TIK EL WAR T EN A U F SI E:

    Android Rem o t ing

    von Gregor Ro t h

    Die zune hmend bes-

    sere Versorgung mi t

    mo bi len, brei t bandigen

    Da tendiens ten so wie die immer leis tungsf

    -

    higeren Endger te sc haf-

    fen immer bessere Vor-

    ausse tzungen fr die En t wic k lung hoc h wer tige

    r,

    mo bi ler Apps auf Basis ver tei l ter An wendung

    s-

    arc hi te k turen. T ypisc her weise kommuniziere

    n

    so lc he Apps ber den R ES Tfu l- H T T P-Ansa

    tz

    mi t ser versei tigen Diens ten, um bes timme Us

    e

    Cases umzuse tzen. Dieser Ar ti ke l be leuc h t

    e t

    un tersc hied lic he Ans tze fr die c lien tsei tig

    e

    Imp lemen tierung der Ser ver kommuni ka tion.

    Ca ching -Con t en t -Pro vide r

    von Ronan Sch wa rz

    Jeder, der mo bi le An-

    wendungen en t wic ke l t,

    wird sic h fr her oder

    sp ter mi t Cac hing be-

    sc hf tigen mssen. Eine

    App li ka tion, die Da ten

    von einem Ser ver be-

    zie h t, sei es vom In terne t oder einem V P N, pro

    -

    tier t in na hezu a l len F l len von einem Cac he.

    Das Android- Frame wor k bie te t mi t Con ten t-

    Pro vidern eine einfac he und leis tungsf hig

    e

    Mg lic h kei t, das Pro b lem zu lsen.

    DI E M O BIL E R E V O L U TI O N I S T DA,

    DARAN B E S T EH T K EIN ZW EI F EL

  • 8/2/2019 Android Bonus

    3/15

    REST 3 2 1

    ANDROID 360www.android360.de 3

    von Gregor Roth

    Typischerweise ver gten die meisten Android-Applika-tionen ber ein User Inter ace. Ein User Inter ace wirdbei Android mithil e von Activity-Komponenten imple-mentiert, wobei eine Activity in der Regel eine einzelneBildschirmseite reprsentiert. Die Ober che einer Bild-schirmseite setzt sich aus den sichtbaren Ober chenele-menten, den Views zusammen. Beispielsweise wird einText eld mithil e einer TextView abgebildet. Typischer-weise werden die Ober chen in einer XML-Datei de-fniert. Um innerhalb des Java-Programmcodes mittelsder fndViewById() -Methode au eine View zugrei enzu knnen, ist bei der Deklaration der View-Komponen-te eine andorid:id anzugeben. Wie in der UserIn oActi-vity-Klasse zu sehen ist, wird typischerweise innerhalb

    der Activity-Initialisierung bzw. der Li ecycle-MethodeonCreate() zunchst der Bildschirm ber die MethodesetContentView(..) gesetzt. Hierbei wird der Name der

    entsprechenden XML-Layoutdatei bergeben. Danachwerden die dynamischen Ober chenelemente mithil eder Methode fndViewById() ermittelt und mit denentsprechenden Werten gesetzt. Bei verteilten Anwen-dungen sind die relevanten Daten hufg au einem Ser-ver gespeichert und werden dort verwaltet. Das heit,um die bentigten Daten r die Darstellung zu erhalten,muss zunchst eine Remote-Ab rage beim Server er ol-gen (Listing 1).

    RESTful HTTPBei Android-Applikationen stellt in der Regel der REST-

    ul-HTTP-Ansatz die pr erierte Architektur r dieServerkommunikation dar. Die REST ul-HTTP-Archi-tektur besagt im Wesentlichen, dass die Methoden desHTTP-Protokolls wie GET , POST , DELETE oder PUT

    protokollkon orm angewendet werden, um mit demServer In ormationen auszutauschen. GET dient dazu,Daten von der Serverseite abzuholen, POST bzw. PUT

    Implementierungsanstze fr eine REST-basierte Serverkommunikation

    Android Remoting Die zunehmend bessere Versorgung mit mobilen, breitbandigen Datendiensten sowie die immer

    leistungsfhigeren Endgerte schaffen immer bessere Voraussetzungen fr die Entwicklung hoch-wertiger, mobiler Apps auf Basis verteilter Anwendungsarchitekturen. Typischerweise kommuni-zieren solche Apps ber den RESTful-HTTP-Ansatz mit serverseitigen Diensten, um bestimme UseCases umzusetzen. Dieser Artikel beleuchtet unterschiedliche Anstze fr die clientseitige Imple-mentierung der Serverkommunikation.

  • 8/2/2019 Android Bonus

    4/15

    REST 2 3

    www.android360.deANDROID 3604

    dazu, u Dat n an di S rv rs it zu b rtrag n bzw. zuaktualisi r n. Ein d tailli rt r B trachtung v n RESTbzw. REST ull HTTP ist unt r [1] zu fnd n.

    I G g nsatz zu SOAP-Pr t k ll wird REST durchAndr id dir kt unt rsttzt. Di Andr id-Platt r b -inhalt t all Bibli th k n, di typisch rw is r inREST-basi rt K unikati n b ntigt w rd n. Ssind b ispi lsw is d r Apach C nsHTTPClient und in JSON-Pars r au Basis d sorg.json -APIs T il d rAndr id-Distributi n. Art akt r das h r schw rg -wichtig r SOAP-Pr t k ll sind in d r aktu ll n I pl -

    nti rung v n Andr id nicht zu fnd n. In di s Fall

    uss dann au Bibli th k n wikSOAP2 zurckg gri -n w rd n. Da di Andr id-Platt r j d ch nicht das

    k pl tt Java-5.0-API b r itst llt, sind inig Java-Bibli th k n nicht hn W it r s ins tzbar. U au di B s nd rh it n d r Andr id-Platt r inzug h n,sind v n anch n Bibli th k n sp zi ll V rsi n n rAndr id ntstand n. Di s tri t auch r kSOAP2 zu.Au grund d r Inaktivitt d s kSOAP2-Pr j kts sind diPatch s j d ch au rhalb d s Pr j kts ntstand n.

    I G g nsatz zu stati nr n PCs, di hufg it in rh h n Bandbr it an das Int rn t ang schl ss n sind,spi l n b i bil n Endg rt n di N tzabd ckung, div r gbar Bandbr it und di li iti rt n Hardwar -r ss urc n in wichtig R ll . O t v r g n di -bil n Endg rt nur b r in g ring Bandbr it , waszu lang n Lad z it n hr n kann. D s W it r n kann

    in rhht r Bandbr it nb dar , j nach V rtragstyp d sNutz rs, schn ll zu h h n K st n hr n. Ein R du-

    zi rung d s b ntigt n Dat nstr s spart au grund d rv rkrzt n K unikati nsz it wichtig Batt ri lau -z it. Dah r ist b i d r R t -K unikati n darau zu acht n, dass glichst nur di wirklich b ntigt nDat n b rtrag n w rd n s wi dass di Hufgk it d rR t -Au ru glichst ni drig g halt n wird. B id r Wahl d r Enc di rung d r zu b rtrag nd n Dat nist in k pakt s F r at zu whl n.

    Fl xibl REST-S rvic s rlaub n s d Cli nt, d ng wnscht n MIME-Typ d r Antw rtstruktur i R -qu st itzut il n. HTTP d fni rt hi r r d nHeaderAccept , d r d n g wnscht n MIME-Typ d klari rt.

    Hufg unt rsttz n REST-S rvic s di MIME-Typ napplication/json bzw. application/xml . Manch REST-S rvic s bi t n d s W it r n binr MIME-Typ n an.Aus d G sichtspunkt d r Bandbr it nb trachtunggilt lg nd T nd nz: Binrdat n v r JSON v r XML.

    J d ch hrt di Nutzung binr r F r at hufg zurhht n Au w ndung n und K pl xitt b i d r I -

    pl nti rung d s (D -)Marshallings. I G g nsatz zuXML d r JSON kann b i U gang it d n binr nTyp n in d r R g l nicht au hh rw rtig Bibli th k nin d r Andr id-Platt r zurckg gri n w rd n. Zu-d xisti r n nur w nig , nicht pr pri tr binr Da-t n r at it in r n nn nsw rt n V rbr itung. Dah rwird t au JSON zurckg gri n. U tr tzd ingut s Bandbr it nv rhltnis zu rr ich n, s llt n di zub rtrag nd n Dat n k pri i rt w rd n. In d r R g lknn n b iapplication/json und application/xml s hrgut K pr ssi nsrat n rzi lt w rd n. Ein V rgl ichd r b ntigt n Bandbr it und d r P r r anc r un-t rschi dlich MIME-Typ n ist unt r [2] zu fnd n.

    I C d b ispi l wird d r R qu st it d H ad rAccept-Encoding: GZIP ang r ich rt, u d S rv r

    itzut il n, dass di s r glichst di Antw rtdat nk pri i r n s ll. Fr d n Au ru d s S rv rs wirdi B ispi l d rAndroidHttpClient v rw nd t, d r

    s it d R l as 2.2 v n Andr id zu V r gung st ht.D r AndroidHttpClient basi rt au d Apach C -ns HTTPClient und s tzt b i di s typisch K n-

    Listing 1: Activity-Klasse

    public class UserIn oActivity extends Activity {

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

    UserIn o userIn o = TextView nameView = (TextView) ndViewById(R.id.name);nameView.setText(userIn o.getName());//

    }}

    Listing 2: REST-Aufruf

    public class UserRESTClient {

    private nal AndroidHttpClient httpClient =AndroidHttpClient.newInstance("MyUserAgent");

    public UserIn o getUserIn o(String userURI) {HttpUriRequest request = new HttpGet(userURI);request.setHeader("Accept", "application/json");request.setHeader("Accept-Encoding", "GZIP");

    HttpResponse response = httpClient.execute(request);int status = response.getStatusLine().getStatusCode();i (status == HttpStatus.SC_OK) {InputStream instream =

    AndroidHttpClient.getUngzippedContent(response.getEntity());String charset = EntityUtils.getContentCharSet(response.getEntity());String jsonString = IOUtils.toString(instream, charset);

    JSONObject jsonObject = new JSONObject(userIn oString);UserIn o userIn o = new UserIn o();userIn o.setUri(jsonObject.getString("uri"));//

    return userIn o;}

    //

    }}

  • 8/2/2019 Android Bonus

    5/15

    REST 3 2 1

    ANDROID 360www.android360.de 5

    fgurati nsw rt , pass nd r di Andr id-U g bung.B ispi lsw is wird durch d nAndroidHttpClient d rconnectionTimeout und d r soTimeout d s zugrundli g nd nHttpClient au 20 S kund n g s tzt.

    Di S curityarchit ktur v n Andr id r rd rt r d nZugri au b sti t Syst r ss urc n sp zi ll Privi-l gi n. U di b ntigt n B r chtigung n r d n Zugri au das Int rn t zu rhalt n, ist in d rAndroidMani est.xml di P r issi nandroid.permission.INTERNET zus tz n. Di d r Applikati n zug rdn t n P r issi nsaus AndroidMani est.xml w rd n d Anw nd r b id r Installati n d r Applikati n ang z igt. D r B nutz rhat dann di Mglichk it, di Installati n abzubr ch n,

    alls ih di P r issi ns zu w itr ich nd sind.

    Prozessierung langlaufender OperationenD r nah li g nd Ansatz, di getUserIn o() -M th dd s RESTServiceClient dir kt inn rhalb d r Activi-

    ty au zuru n, rw ist sich als in Fall . P t nzi lllanglau nd Aktivitt n, z. B. S rv rau ru , dr nni inn rhalb in r Activity dir kt ausg hrt w rd n.Aktivitt n lau n i K nt xt d s Main Thr ads. Dash it, di Li cycl -M th d n d r Activity, b ispi lsw i-s di onCreate() -M th d , w rd n durch d n MainThr ad b hand lt. Das Gl ich gilt auch r di B hand-lung v n Ob r ch n r igniss n wi intouch event .Ist b ispi lsw is inOnClickListener b i in Aktu-alisi rungsbutt n r gistri rt, s wird di ntspr ch ndList n r-M th d inn rhalb d s Main Thr ads au g -ru n. Find t nun in d ronCreate()- M th d d r in

    d r List n r-I pl nti rung in S rv rau ru statt, sb st ht di G ahr, dass d r Main Thr ad zu lang bl -cki rt. In d r R g l s llt d r Main Thr ad nicht lng rals 100 bis 200 s durch in inz ln Akti n bl cki rtw rd n, u au w it r ing h nd Er igniss z itnahr agi r n zu knn n. Da di Ob r ch n l nt v nAndr id nicht thr ad-sa sind, ss n auch all Ob r-

    ch naktualisi rung n inn rhalb d s Main Thr adsdurchg hrt w rd n.

    B i Start n in r Applikati n wird standard igin Linux-Pr z ss it in r d dizi rt n Dalvik-VM-In-

    stanz g start t, inn rhalb d r r di Applikati n ausg -hrt wird. P r D ault wird b i d r Initialisi rung ininzig r Applikati ns-Thr ad, d r Main Thr ad g star-

    t t. D Main Thr ad ist wi d ru inMessageQueue zug rdn t. Di sMessageQueue li st d r Main Thr adnach d Start n in in r Endl sschl i aus und ru t

    r j d M ssag d n ntspr ch nd n Handl r zur B -handlung au . Tr t n b ispi lsw is an d r Ob r chUs r v nts au , s w rd n di s v n d Andr id UIT lkit in di MessageQueue ing st llt, u dann ind r Endl sschl i durch d n Main Thr ad b hand lt zuw rd n. Mithil di s s Ansatz s w rd n di Ev nts d rApplikati n s rialisi rt und durch d n Main Thr ad syn-chr nisi rt b hand lt. Bl cki rt in Handl r, b ispi ls-

    w is d r b n rwhntOnClickListener d n MainThr ad r in lng r Z it, s ist di g sa t Applika-ti n ing r r n. U di s zu v rhind rn, b rwacht

    das Andr id-Lau z itsyst das Antw rtv rhalt nv n Applikati n n. Er lgt b ispi lsw is inn rhalb

    in r g wiss n Z it k in R akti n au d n Us r v ntd r Ob r ch , wird inApplication Not Responding (ANR) ausg lst. D r ANR n t in n Dial g, d r d nB nutz r au in nicht hr r agi r nd Applikati nhinw ist und ih di Mglichk it gibt, di Applikati nzu schli n, d. h. das T r ini r n d s zugrund li g n-d n Pr z ss s zu rzwing n.

    P t nzi ll langlau nd Aktivitt n wi S rv rau rus llt n dah r i r inn rhalb d dizi rt r Java Thr adsausg hrt w rd n. Typisch rw is wird d r S rv rau -ru als in ig nstndig r Akti nsc d i pl nti rt.Fr di Pr z ssi rung d s S rv rau ru s inn rhalb in sW rk r Thr ads bi t t sich das Ex cut r-Fra w rkaus d java.util.concurrent Packag an. Das Ex cut r-Fra w rk st llt v rschi d n Thr ad-P ls zur V r-waltung und Aus hrung v n Thr ads b r it.

    Au Basis d r Erg bnisdat n d s S rv rau ru s ist hu-fg di B nutz r b r ch zu aktualisi r n. Di s Aktu-alisi rung dar j d ch nur i Rah n d s Main Thr ads

    r lg n. Anal g zu S rv rau ru wird di Akti n zurOb r ch naktualisi rung typisch rw is als in ig n-stndig s C d rag nt i pl nti rt. Da di Ob r -ch naktualisi rung durch d n Main Thr ad stattfnd n

    uss, ist d r Ob r ch naktualisi rungsc d in diMessageQueue d s Main Thr ads inzust ll n. Hi rzukann au di Handl r-Klass d s Andr id-APIs zurck-g gri n w rd n. Di Handl r-Klass st llt unt r and -r di post() -M th d zu V r gung. B i Au ru

    di s r M th d wird inRunnable Obj ct b rg b n,das in in M ssag v rpackt und anschli nd in diQu u ing st llt wird. Inn rhalb d r Endl sschl i d s

    Listing 3: Threaded Serveraufruf innerhalb der Activity

    public void onCreate(Bundle savedInstanceState) {//

    nal Handler handler = new Handler();

    Runnable serverCallAction = new Runnable() {public void run() {

    nal UserIn o userIn o =restClient.getUserIn o("http://myserrver/srv/UserIn o/34");

    Runnable uiUpdateAction = new Runnable() {public void run() {TextView nameView = (TextView) ndViewById(R.id.name);nameView.setText(userIn o.getName());//

    }};handler.post(uiUpdateAction);

    }};executor.execute(serverCallAction);

    }}

  • 8/2/2019 Android Bonus

    6/15

    REST 2 3

    www.android360.deANDROID 3606

    Main Thr ads wird dann di M ssag bzw. dasRunn-able -Obj kt aus d rMessageQueue g l s n und b rd n Au ru d r nrun() -M th d inn rhalb d s MainThr ads pr z ssi rt. I Rah n d r Ob r ch nak-tualisi rungsakti n kann s auch passi r n, dass diActivity zwisch nz itlich z rstrt wurd . B ispi lsw islst in Dr h n d s Endg rts in z rstr n d r Activityaus.

    Di V rbindung zwisch n d Handl r-Obj kt undd rMessageQueue d s Main Thr ads r lgt i K nst-rukt r d r Handl r-Klass . Inn rhalb d s K nstrukt rsgr i t das Handl r-Obj kt au inThreadlocal -Varia-bl d s aktu ll n Main Thr ads zu und sp ich rt d ss nMessageQueue als member -Variabl . Di Message-Queue wird i Rah n d r Initialisi rung d s MainThr ads alsThreadlocal -Variabl an d n Main Thr adg bund n. Aus di s Grund ist d r Handl r i rinn rhalb d s Main Thr ads zu instanzii r n. Au grund

    d s Andr id-Pr z ss-/Thr ad-M d lls b st ht in typi-sch r S rv rau ru aus zw i Akti n n. D ig ntlich nS rv rau ru , d r in in d dizi rt n W rk r Thr adstattfnd n s llt , s wi aus in r Aktualisi rungsakti-

    n, di wi d ru i K nt xt d s Main Thr ads ausg -hrt w rd n uss. Alt rnativ zu big n C d b ispi l

    kann statt d r Handl r-Klass auch di C nv ni nc -M th d runOnUiThread() d r Activity v rw nd tw rd n. Di s M th d nutzt int rn anal g dC d b ispi l, in n Handl r, d r dasActivity-Obj kti plizit b i d r n Initialisi rung rst llt. B i d r Nut-zung d r C nv ni nc -M th d uss i Applikati ns-

    c d k in Handl r-Obj kt hr r di Synchr nisati nrz ugt w rd n. Mit d r V rsi n 1.5 wurd Andr idzud u di Klass AsyncTask rw it rt. Di s Klassist au das Sz nari Hint rgrundakti n it anschli - nd r M difkati n d r Ob r ch zug schnitt n.Zur V rw ndung di s r Klass ist v n ihr abzul it n

    und di ntspr ch nd n Callback-M th d n sind zui pl nti r n.

    Lebenszyklus von KomponentenDi Andr id-Lau z itu g bung kann j d rz it d n d rApplikati n zugrund li g nd n Pr z ss b nd n. Indi s Fall w rd n i plizit all inn rhalb d s Pr z ss sg start t n Thr ads b nd t und di inn rhalb d r Ap-plikati n lau nd n K p n nt n, b ispi lsw is inActivity d r in S rvic , z rstrt. In d r R g l v rsuchtAndr id s lang wi glich, Pr z ss nicht ig nstn-dig zu b nd n. St ht j d ch nur n ch w nig Sp ich rzur V r gung, d r v n k nkurri r nd n Applikati n nb ntigt wird, g ht Andr id dazu b r, w nig r wich-tig Pr z ss zu b nd n. Di Pri ritt in s Pr z ss shngt dav n ab, w lch K p n nt ntyp n inn rhalbd s Pr z ss s ausg hrt w rd n und in w lch Statussich di K p n nt n b fnd n. Di hchst Pri ritt

    hab n Pr z ss , di b ispi lsw is in au d r Ob r -ch d s Endg rts sichtbar Activity darst ll n. R lativh h Pri ritt hab n auch Pr z ss , di in n S rvicpr z ssi r n. Pr z ss , di nur Activity-K p n nt naus hr n, di au d r Ob r ch nicht hr sichtbarsind bzw. b i d n n di Li cycl -M th donStop() au -g ru n wurd , hab n nur n ch in r lativ ni drig Pri-

    ritt. B ispi lsw is tr t n s lch Pr z ss au , w nnd r Nutz r di Home-Tast drckt, u in in and rApplikati n zu spring n. In d r R g l xisti r n r chtvi l s lch r Pr z ss .

    Ist di Activity d s big n B ispi ls nicht hr sicht-

    bar, s ist di Wahrsch inlichk it h ch, dass d r n Pr -z ss i Fall v n Sp ich r ang l b nd t wird. B i d rZ rstrung d s Pr z ss s w rd n auch all v ntu ll -

    n n S rv rau ru t r ini rt. Di s s V rhalt n kannstr nd wirk n, w nn zu B ispi l i Hint rgrundThr ads r di V rwaltung in s R sp ns Cach sausg hrt w rd n d r w nn langlau nd HTTP-V rbindung n g halt n w rd n s ll n. B ispi lsw isnutz n Chatapplikati n n t in n S rv r-Push-An-satz [3], d r au langlau nd n HTTP-V rbindung nbasi rt. U zu v rhind rn, dass R t -Au ru bzw.

    n HTTP-V rbindung n au grund d r ni drig nPr z sspri ritt z rstrt w rd n, knn n di S rv r-au ru in in n S rvic ausg lag rt w rd n. N b n d rActivity sind d rService, d r ContentProvider und d rBroadcastReceiver di vi r K p n nt ntyp n d r An-dr id-Platt r . Ein S rvic di nt dazu, langlau ndOp rati n n i Hint rgrund auszu hr n. Wi di an-d r n K p n nt ntyp n auch, uss in S rvic in d rAndroidMani est.xml -Dat i d klari rt w rd n. D r S r-vic wird i Main Thr ad d r Applikati n pr z ssi rt.All in in r Applikati n v rhand n n K p n nt nwi di Activity-K p n nt n d r in S rvic k -p n nt w rd n i gl ich n Main Thr ad ausg hrt.Ein S rvic ist w d r in ig n r Thr ad n ch in ig -

    n r Pr z ss. Er b fnd t sich i gl ich n Pr z ssrauwi in Activity-K p n nt . Au grund d r Pri ri-ttsr g l hat d r Pr z ss auch dann n ch in r lativ

    Listing 4: Local-Service-Implementierung

    public class MyService extends Service { public int onStartCommand(Intent intent, int fags, int startId) {

    // }

    public IBinder onBind(Intent intent) {return binder;

    }

    private nal MyLocalServiceBinder binder = new MyLocalServiceBinder();public class MyLocalServiceBinder extends Binder implements IMyService {public UserIn o getUserIn o(String userURI) throws IOException {return restClient.getUserIn o(userURI);

    }}

    }

  • 8/2/2019 Android Bonus

    7/15

    REST 3 2 1

    ANDROID 360www.android360.de 7

    h h Pri ritt, w nn di Activity nicht hr sichtbarist, d r nthalt n S rvic ab r n ch lu t. U di Fair-n ss zwisch n d n Applikati n n au r chtzu rhalt n,s llt n S rvic s nur dann g start t w rd n, w nn di sauch wirklich b ntigt w rd n. Eb ns s llt n S rvi-c s glichst z itnah wi d r b nd t w rd n, w nn sinicht hr b ntigt w rd n.

    Android Local ServicesAndr id unt rsch id t zwisch nlocal- und remote- S r-vic s. I G g nsatz zu in remote -S rvic kann inlocal -S rvic nur v n K p n nt n d r gl ich n Appli-kati n au g ru n w rd n. D r Au ru r, b ispi lsw is

    in Activity, lu t i gl ich n Pr z ss wi d r au g -ru n S rvic . Ein S rvic kann au zw i Art n g star-t t w rd n. D r Au ru d rstartService() -M th da C nt xt-Obj kt start t d n S rvic und gibt d nComponentName zurck. S llt d r S rvic b r its lau-

    n, wird r nicht in zw it s Mal g start t. Inn rhalbd r startService()- M th d ist in Int nt-Obj kt zub rg b n, das d n Zi ls rvic adr ssi rt. Typisch r-w is wird hi rb i in Int nt-Obj kt rz ugt, d iK nstrukt r di Klass d s b tr n n S rvic b rg -b n wird. Au d r S it d s S rvic w rd n inn rhalbd r Startpr z dur di Li cycl -M th d nonCreate() und onStartCommand() au g ru n. D r Au ru d rLi cycl -M th d n fnd t durch d n Main Thr ad d rApplikati n statt.

    Di onBind() -M th d d s S rvic wird b i Star-t n d s S rvic durchstartService() nicht au g ru n.

    Di s M th d k t rst dann ins Spi l, w nn au d r Cli nts it in K unikati nsv rbindung itd S rvic b r di M th dbindService() h rg -st llt wird. b r di s K unikati nsv rbindungknn n di Cli nts d n S rvic au Basis in s RPC-Patt rns au ru n. Anhand in sfag -Para t rs wirdzud b i Au ru d rbind -M th d g st u rt, b d rS rvic g start t w rd n s ll, alls r n ch nicht lu t.Di s rspart in n v rh rig nstartService() -Au ru .Di onBind() -M th d d s S rvic gibt in applika-ti nssp zifsch s Bind r-Obj kt zurck, das di Cli ntsv rw nd n, u d n S rvic au zuru n. Hi rb i ist zub acht n, dass di Au ru d s S rvic s, anal g n r a-l r M th d nau ru , synchr n r lg n. D r Au ru wart t bzw. bl cki rt s lang , bis di Antw rt vS rvic zurckg g b n wird. U langz itig bl cki -r nd M th d nau ru inn rhalb d s Main Thr adszu v r id n, kann v n d rAsyncTask -Klass abg -l it t w rd n. Di cli nts itig I pl nti rung d sS rv rau ru s fnd t dann in d r M th ddoInBack-

    ground() statt, di Aktualisi rung d r Ob r chin d r onPostExecute() -Callback-M th d . L id runt rsttzt di AsyncTask -Klass k in un itt lbarB handlung v n Exc pti ns.

    Alt rnativ knnt hi r auch in Callback Patt rn [4]

    v rw nd t w rd n. In di s Fall wird statt d r Busin ss-th d UserIn o getUserIn o(String userURI) throwsIOException in M th d wivoid getUserIn o(String

    userURI, IResultCallback callback) v r-w nd t. D r Main Thr ad bl cki rt nur r in s hrkurz Z it, da d r S rvic d n R qu st l diglich zurPr z ssi rung anni t, u ihn dann asynchr n b r

    in n d dizi rt n Thr ad zu v rarb it n. Di V rw n-dung in sAsyncTask au d r Cli nts it wird b r-

    ssig. L diglich di Aktualisi rung d r Ob r chau Basis d s Erg bniss s uss wi d r i Rah n d sMain Thr ads stattfnd n. Zur b r ittlung d s Er-g bniss s ru t d r S rvic di ntspr ch nd Callback-M th d d s IResultCallback -Obj ktsau , b ispi lsw isonResult(UserIn o userIn o) d ronError(IOException ioe) . Ein Callback Patt rn wird

    b n alls b i Au ru d rbindService() -M th d and r Context -Klass v rw nd t. Fr d n Au bau in rK unikati nsv rbindung zu S rvic b rgibt d rCli nt n b n d Intent und d start Flag auch inapplikati nssp zifsch s ServiceConnection -Obj kt.

    Di ServiceConnection -Klass d fni rt Callback-M -th d n, u Statusnd rung n d r K unikati ns-v rbindung zu rk nn n. DibindService(...) -M th dgibt als w d r inBinder - n ch inServiceConnection -Obj kt dir kt zurck. Das n tw ndig Binder -Obj ktzur K unikati n it d S rvic wird rst in innach lg nd n L pzyklus d s Main Thr ads durchd n Au ru d r Callback-M th donServiceConnect-ed() d sServiceConnection -Obj kts b rg b n.

    Listing 5: Serviceaufruf innerhalb der Activity

    public class UserIn oActivity extends Activity {private IMyService myService;

    public void onCreate(Bundle savedInstanceState) {// Intent intent = new Intent(this, MyService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE);

    }

    private ServiceConnection connection = new ServiceConnection() {public void onServiceConnected(ComponentName className, IBinder service) {myService = (IMyService) service;

    new AsyncTask() {protected UserIn o doInBackground(String... params) {return myService.getUserIn o(params[0]);

    }protected void onPostExecute(UserIn o userIn o) {TextView nameView = (TextView) ndViewById(R.id.name);nameView.setText(userIn o.getName());//

    }}.execute("http://myserrver/srv/UserIn o/34");

    }//

    };}

  • 8/2/2019 Android Bonus

    8/15

    REST 2 3

    www.android360.deANDROID 3608

    Android Remote ServicesDie Implementierungen von local -Services und re-mote -Services sind sich sehr hnlich. Der wesentlicheUnterschied ist die Binder-Implementierung, die vomService in der onBind() -Methode bereitgestellt wird.Im Gegensatz zum Binder des local -Service unter-sttzt der Binder des remote -Service eine Inter ProcessCommunication (IPC). Der Begri Binder steht beiAndroid nicht nur r einen Inter ace- bzw. Klassena-men, sondern de niert auch eine Architektur r InterProcess Communication. Die Binder-Architektur vonAndroid hat ihren Ursprung in Open Binder [5] und

    ndet hu ge Anwendung innerhalb des Lau zeitsys-tems von Android. Im Beispiel des local -Service gibt dieonBind(...) -Methode ein MyLocalServiceBinder -Objektan die Android-Lau zeitumgebung zurck. Genau dieseObjektinstanz wird dann dem Client mittels der Call-

    back-Methode onServiceConnected() bereitgestellt.Im Fall des remote -Service gibt die onBind() -Methodestattdessen den MyRemoteServiceBinder zurck. DieseKlasse implementiert sowohl das achliche Inter ace alsauch die schnittstellenspezi sche Logik zur Unterstt-zung des Remote-Au ru s. Leider untersttzt die IPC-Architektur keine anwendungsspezi schen Exceptions.Fr die Exception-Behandlung knnte beispielsweisedie Antwort in ein Result-Objekt eingebettet werden,das ein zustzliches Feld r die Fehlermeldung bein-haltet. Alternativ kann auch ein Callback Pattern im-plementiert werden:

    private fnal MyRemoteServiceBinder binder = new MyRemoteServiceBinder();public class MyRemoteServiceBinder extends IMyService.Stub {public UserIn o getUserIn o(String userURI) throws RemoteException {return restClient.getUserIn o(userURI);

    }

    }

    Der IPC-relevante Code wird im Beispiel von der ge-nerierten Klasse IMyService.Stub geerbt.Typischer-weise wird der IPC-relevante Code nicht per Handimplementiert, sondern es wird au die Generierung derentsprechenden Klassen zurckgegri en. Die Android-Platt orm stellt hier r eine eigene Schnittstellenbe-schreibungssprache aidl zur Ver gung. Mithil e deraidl kann die Remote-Schnittstelle de niert werden.Die Syntax ist stark an Java angelehnt, jedoch existiereneinige Einschrnkungen. Werden applikationsspezi -

    sche Datenstrukturen bertragen, so sind diese eben-alls in einer aidl -Datei zu deklarieren. Des Weiterenmuss die Implementierung der Datenstruktur wie dieUserInfo- Bean-Hil skonstrukte r die Serialisierungund Deserialisierung bereitstellen. Die IPC von Androidverwendet aus E zienzgrnden nicht den Java-Serializ-able-Ansatz, sondern de niert mit dem Parcelable eineneigenen Serialisierungsmechanismus. Das ADT-Eclipse-Plug-in generiert automatisch die entsprechenden Java-Klassen und -Inter aces im /gen/ -Verzeichnis.

    Im Fall des Remote-Service kann in der onService-Con nected()-Methode das bergebene Binder-Objektnicht mehr unmittelbar verwendet werden. Im Gegen-satz zum local -Service ist immer die statische MethodeasInterface() der generierten Binder-Klasse zu ver-wenden, um das Proxy-Objekt r den Serviceau ru zu erhalten. Diese Methode erkennt, ob der Remote-Service im gleichen Prozess wie auch der Au ru er lu t.Falls dies nicht zutri t, wird ein Remote-Proxy-Objektzurckgegeben, das die Serialisierung der Au ru datenvornimmt, den remote -Service au ru t und die Deseria-lisierung der Antwort durch hrt. Ansonsten wird, wieauch beim local -Service, das konkrete Binder-Objektzurckgegeben.

    Android Content Provider Neben dem serviceorientierten Ansatz knnen Remote-Ab ragen des Servers auch mithil e eines ContentProvi-

    Listing 6: ContentProvider-Aufruf innerhalb der Activity

    public class UserIn oActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {// AsyncQueryHandler handler = new AsyncQueryHandler(getContentResolver()) {protected void onQueryComplete(int token, Object cookie, Cursor cursor) {i (cursor.moveToFirst()) {TextView nameView = (TextView) fndViewById(R.id.name);nameView.setText(cursor.getString(cursor.getColumnIndex("name")));//

    }}

    };handler.startQuery(1, null, Uri.parse("content://org.example.myprovider/UserIn o/

    http%3A%2F%2Fmyserrver%2Fsrv%2FUserIn o%2F34"), null, null, null, null);}

    }

    Listing 7: Content-Provider-Implementierung

    public class MyContentProvider extends ContentProvider {// public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,

    String sortOrder) {switch (uriMatcher.match(uri)) {case USER_INFO:String userURI = uri.getLastPathSegment();UserIn o userIn o = restClient.getUserIn o(userURI);MatrixCursor cursor = new MatrixCursor(new String[] { "uri", "name", "city", "zip" });cursor.addRow(new Object[] { userIn o.getUri(), userIn o.getName(),

    userIn o.getCity(), userIn o.getZip() } );

    return cursor;//

    }

    // }

  • 8/2/2019 Android Bonus

    9/15

    REST 3 2 1

    ANDROID 360www.android360.de 9

    der implementiert werden. Ein Content-Provider wirdtypischerweise verwendet, um au Daten der lokalenDatenbank zuzugrei en. Die Android-Umgebung bein-haltet beispielweise eine SQLite-Datenbank. Obwohl dieSchnittstelle des Content-Providers datenbankorientiertist, werden Content-Provider nicht nur r Datenbank-zugri e verwendet. Ein Content-Provider kann auchgenutzt werden, um Remote-Au ru e zu einem nach-gelagerten Server zu kapseln. Wie auch die REST-Ar-chitektur ist der Content-Provider ressourcenorientiert.Die Entitten werden wie beim REST ul-HTTP-Ansatzber URIs re erenziert. Eine solche Content-URI be-steht aus drei Teilen: dem Standardpre x content:// ,der Authority wie org.example.mycontentprovider, die den Content-Provider identi ziert, sowie dem ver-bleibenden Teil, der die Entitt identi ziert. Analogzur AsncTask -Klasse stellt Android eine Convenience-Klasse AsyncQueryHandler bereit, die das Threading

    bzw. die Thread-Synchronisierung bernimmt. In derstartQuery() -Methode des AsyncQueryHandler kn-nen dann neben dem Content-URI auch die Parameter

    projection , selection und orderBy bergeben werden.Das Ergebnis der Ab rage wird mithil e eines Cursorsbereitgestellt.

    Die applikationsspezi sche Implementierung einesContent-Providers muss von der Klasse ContentProvi-der ableiten. Im Wesentlichen sind hierbei die Metho-den query() , insert() , delete(), update() und

    get Type() zu implementieren. Zur Aufsung desbergebenen URIs au die betro ene Entitt wird in

    der Regel au die UriMatcher -Klasse zurckgegri en.Das Ergebnis der Remote-Ab rage des nachgelagertenServers muss ber einen Cursor bereitgestellt werden.Im Codebeispiel wird hier r die Android-Klasse Ma-trixCursor verwendet. Gibt der Server komplexe, ver-schachtelte Datenstrukturen zurck, so sind diese inder Regel nur schwer in einer e zienten Art und Weiseau den Cursor-Ansatz abbildbar. Hu g sind weitereSubab ragen am Content-Provider notwendig, um daskomplette Ergebnis des Serverau ru s zu erhalten.

    FazitDie hier vorgestellen Anstze zur Implementierung vonRemote-Ab ragen nachgelagerter Server stellen nur einenAusschnitt der mglichen Lsungen dar. Des Weiterenwurde in diesem Artikel das Caching von Applikations-daten nicht betrachtet. Insbesondere bei hochverteiltenSystemarchitekturen entwickelt sich das Caching au der Applikationsebene schnell zu einem wichtigen The-ma. Eine gute Betrachtung der Implementierungsanstzeau Basis von Android Services und Content-Proivder istauch im Video Podcast [6] zu nden.

    Fr ein ache, vereinzelte Serverau ru e ist es o tausreichend, au ein richtiges Threading bzw. au dieThread-Synchronisierung zu achten und sich der Pro-

    zesspriorisierung und deren Folge bewusst zu sein. Wer-den jedoch um angreichere HTTP-Schnittstellen wie einHTTP-basierter Mail-Service oder ein Contact-Service

    eingebunden, geht die Tendenz dazu, die Au ru e bereinen Android-Service oder einen Content-Provider zukapseln. Dies gilt insbesondere, wenn ein applikations-spezi sches Caching der Serverau ru e implementiertwerden soll oder Server-Push-Architekturen umgesetztwerden mssen. Obwohl der Content-Provider ressour-cenorientiert ist, dar er nicht mit der REST ul-HTTP-Architektur gleichgesetzt werden. Bei der Abbildungeiner REST ul-HTTP-Schnittstelle au die Content-Provider-Schnittstelle knnen insbesondere komple-xe Datenstrukturen Probleme bereiten. Des Weiterenist die Abbildung eines HTTP-Service-URIs au einenContent-Provider-URI nicht trivial. Beim REST ul-HT-TP-Ansatz ist es ein schlechter Stil, au der ClientseiteHTTP-URI-Strukturen zu interpretieren. Der zunchstnaheliegende Ansatz, die Struktur eines URIs des HT-TP-Service wie http://myserrver/srv/UserInfo/455 au eine Content URI wie content://org.example.myprovi-

    der/UserInfo/4554 abzubilden, verstt gegen das Hy-permedia-Prinzip von REST [7], da Teilstrukturen desHTTP URIs clientseitig interpretiert werden. Die Kap-selung von HTTP-Services ber einen Android-Servicelsst gegenber dem Content-Provider mehr Spielraum,stellt da r aber keine (teil-)standardisierte Schnittstellebereit. Wird ein Service nur innerhalb einer Applikationverwendet, so ist es in der Regel ein acher, einen local -Service zu nutzen bzw. zu implementieren.

    Links & Literatur

    [1] RESTful HTTP in Practice: http://www.infoq.com/articles/designing-restful-http-apps-roth

    [2] Using Internet Data in Android Applications: http://www.ibm.com/developerworks/xml/library/x-dataAndroid/

    [3] HTML5 Server-Push Technologies: http://today.java.net/article/2010/04/26/html5-server-push-technologies-part-2

    [4] SOA Patterns Service Callback: http://www.soapatterns.org/service_callback.php

    [5] Open Binder: http://en.wikipedia.org/wiki/OpenBinder

    [6] Developing Android REST Client Applications: http://code.google.com/intl/de-DE/events/io/2010/sessions/developing-RESTful-android-apps.

    html[7] REST APIs must be Hypertext-driven: http://roy.gbiv.com/

    untangled/2008/rest-apis-must-be-hypertext-driven

    Gregor Roth arbeitet als Softwarearchitekt bei der 1&1 Internet AG. Er verfgt ber langjhrige Erfahrungen im Bau verteilt er, hoch-skalierbarer Anwendungssysteme und betreut architektonisch dieEntwicklung der webbasierten Applikationen der Marken WEB.DE,GMX und 1&1. Zuvor war er knapp zehn Jahre als Softwarearchi-

    tekt im Finanzdienstleistungsbereich ttig.

  • 8/2/2019 Android Bonus

    10/15

    CaChing2 3

    www.android360.de10 ANDROID 360

    vo Ro Sc w rz

    Fr Caching gibt es bei Android drei Hauptkategorienoder Vorgehensweisen: Dateien, Datenbanken oderContent-Provider. Allen ist gemeinsam, das die physi-kalische Speicherung entweder au dem Gert oder demexternen Speichermedium (SD-Card oder Festplatte beieinigen MIDs) geschehen kann. Das mag verbl en, dadies im Zusammenhang mit Content-Providern seltengeschieht und nicht dokumentiert ist trotzdem ist es

    ohne Weiteres mglich, wie wir noch sehen werden.Eine IO-Operation au eine Datei hat von allen Metho-den sicherlich den geringsten Programmierau wand,

    die Sicherstellung einer sinnvollen Struktur und derentsprechenden Datenintegritt kann sich jedoch alskompliziert erweisen. Datenbanken haben den Vorteilder klaren Struktur und sind lange erprobte Tools, mitdenen sich wohl jeder Programmierer auskennt. Aller-dings muss die Frontseite entweder einiges an Wissenber die Struktur und den Zugri au die Daten mit-bringen (und man hat SQL-Statements im GUI-Code),oder man muss zustzlich das Datenmodell in Klas-sen abbilden (was r eine mobile Platt orm ein nicht

    unbedingt wnschenswerter Overhead ist). Content-Provider bieten ein klares, URL-basiertes Inter ace,die Struktur und Mchtigkeit einer Datenbank und

    Automatische Aktualisierung der GUI mit einem Content-Providerals Cache

    Caching-Content-Provider

    Jeder, der mobile Anwendungen entwickelt, wird sich rher oder spter mit Caching be-sch tigen mssen. Eine Applikation, die Daten von einem Server bezieht, sei es vom In-ternet oder einem VPN, pro tiert in nahezu allen Fllen von einem Cache. Denn anders alsbei einer Desktopanwendung sind im Mobile-Bereich Verbindungsabbrche oder gar derTotalaus all des Netzwerks an der Tagesordnung. Das betreten einer U-Bahn-Station maggengen. Die Daten r einen gewissen Zeitraum, selbst wenn dieser nur wenige Minutenum asst, au dem Gert lokal zu speichern, wird den Workfow r den Anwender deutlicherleichtern. Das Android-Framework bietet mit Content-Providern eine ein ache und leis-tungs hige Mglichkeit, das Problem zu lsen.

  • 8/2/2019 Android Bonus

    11/15

    CaChing3 2 1

    www.android360.de 11 ANDROID 360

    schirmen das GUI von der physikalischen Speicherungab. Content-Provider bieten von vornherein auch dieMglichkeit, Daten mit anderen Applikationen zu tei-len. Mchte man das nicht oder nur in Teilen, so kannman im Mani est File die entsprechenden Permissionssetzen. Einen berblick ber Content-Provider andererApps, die zur Ver gung stehen, bietet die OpenIntentsRegistry [1].

    Caching-Content-Provider Das sich ein Content Provider als Cache verwendenlsst, liegt au der Hand. Der groe Vorteil von Con-tent-Providern ist jedochnicht so o ensichtlich:die Content Observer.Ein Content Observerist eine Android-spezi-fsche Implementierung

    des Observer-Patternsr Datenbanken. Wannauch immer sich ein bestimmtes Datum in der Daten-bank ndert, werden alle vorher registrierten Obser-ver darber in ormiert. Dies gilt gleichermaen rContent-Provider. Mit dieser im Grunde sehr ein achenIdee lassen sich GUI, Content-Provider und Backend soverbinden, dass sich die angezeigten Daten automatischaktualisieren.

    Als GUI-Komponente bietet sich eineListActivity an.Eine ListActivity kann bereits mit wenigen Zeilen Codedie in einem Cursor enthaltenen Daten anzeigen. Sie

    bietet zudem eine ein ache Mglichkeit, einen ContentObserver zu implementieren (zu lassen). Der sorgt dannda r, dass die in der Liste angezeigten Eintrge jeder-

    zeit synchron zu den Daten des Content-Providers sind.Die Klasse CursorAdapter und ihre abgeleiteten Klas-sen stellen diese Funktionalitt bereits zur Ver gung.Es reicht also aus, in der ListActivity einen passendenAdapter zu bergeben.

    Nun muss noch der Cache mit den Daten aus demBackend be llt werden. Da r benutzen wir einen Ser-vice. Ein Service in Android ist ein Hintergrundprozess,hnlich einem Daemon in Unix. Der entscheidendeUnterschied ist, dass ein Service nicht konstant lu t,sondern hchstens in Intervallen vom System gestartetwerden kann. Wie alle Prozesse kann auch ein Service

    vom Garbage Collectorgestoppt werden, allsdas System mehr Leis-tung r den momenta-nen Vordergrundprozessbraucht. Das ermglicht

    es Daten, im Hinter-grund zu synchronisierenund schont gleichzeitig die Batterie. Fr mehr In ormati-onen zu Android-Prozessen und dem Garbage Collectorempfehlt sich das exzellente Posting Multitasking theAndroid Way von Diane Hackborn im Android-Devel-oper-Blog [2].

    Implementierung Fr einen Caching-Content-Provider werden also dreiKomponenten bentigt: eine ListActivity zur Anzeige,ein Service, um die Daten vom Web zu lesen, und ein

    Content-Provider r die Speicherung. Diese werdennun anhand eines Beispielprojekts exemplarisch imple-mentiert und besprochen. Wir versuchen, eine Reihe

    Listing 1: Die Klasse CCPListActivity

    public class CCPListActivity extends ListActivity {Cursor mCursor;

    @Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mCursor = this.getContentResolver().query(Customers.CONTENT_URI, null, null,

    null, null);startManagingCursor(mCursor);ListAdapter adapter = new SimpleCursorAdapter(this, // Context.R.layout.three_row_layout,mCursor,new String[] {Customers.NAME,Customers.EMAIL,Customers._ID},new int[] {R.id.text1, R.id.text2,R.id.text3});

    setListAdapter(adapter);}

    }

    Listing 2: Die Klasse Customers

    public class Customers implements BaseColumns {// This class cannot be instantiatedprivate Customers() {}

    public static nal Uri CONTENT_URI = Uri.parse("content://org.openintents.ccp/ customers");

    public static nal String CONTENT_TYPE = "vnd.android.cursor.dir/ vnd.openintents.examples.ccp.customers";

    public static nal String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/ vnd.openintents.examples.ccp.customer";

    public static nal String NAME = "name";public static nal String EMAIL = "note";public static nal String[] DEFAULT_PROJECTION_MAP={_ID,NAME,EMAILpublic static nal String DEFAULT_SORT_ORDER=_ID+" asc";

    }

    Fr e e C c -Co te t-Prov der werde dre

    Kompo e te be t t.

  • 8/2/2019 Android Bonus

    12/15

    CaChing2 3

    www.android360.de12 ANDROID 360

    von Kunden mit Name und E-Mail aus dem Backend zuladen und anzuzeigen. Da es in Wirklichkeit keinen Ser-ver gibt, von dem die Daten kommen knnten (und dieAnbindung an einen realen den Um ang dieses Artikelssprengen wrde), wird der Service dies simulieren. Aberder Reihe nach.

    Das Frontend: ListActivity Die ListActivity kommt hier tatschlich mit einer ein-zigen Methode aus, nmlich onCreate(..) . Das XML-Layout ist ein ListActivity -Standard und enthlt eineListView mit der ID android:list und eine TextView mitder ID android:empty . Sind in der Liste keine Daten ent-

    halten, zeigt die ListActivity die TextView an; sobaldsich die Liste llt, verschwindet diese wieder. All daswird bereits r uns erledigt und bedar keines weiterenCodes.

    Wir erzeugen einen Cursor mittels eines Querysau den De ault-URL des Content-Providers, der alleCusto mer -Eintrge lie ert. Die Funktionstart Mana-

    ging Cur sor(mCur sor) sorgt da r, dass automatischein Requery ausge hrt wird, wenn sich am Zustanddes Cursors etwas ndert z. B. auch dann, wenn dieActivity in den Hintergrund geht. Der SimpleCursor-Adapter verwendet das angegebene Layout r die An-zeige und ordnet den Spalten die jeweiligenTextViews

    Listing 3: Die Klasse CCProvider

    public class CCProvider extends ContentProvider {

    @Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[]selectionArgs, String sortOrder) {

    //we start the service that retrieves data rom the backendIntent intent=new Intent();intent.setClass(getContext(), DataService.class);getContext().startService(intent);SQLiteQueryBuilder qb = new SQLiteQueryBuilder();switch (sUriMatcher.match(uri)) {case CUSTOMERS:qb.setTables(CUSTOMERS_TABLE_NAME);qb.setProjectionMap(sCustomersProjectionMap);break;

    case CUSTOMER_ID:qb.setTables(CUSTOMERS_TABLE_NAME);qb.setProjectionMap(sCustomersProjectionMap);qb.appendWhere(Customers._ID + "=" +

    uri.getPathSegments().get(1));break;

    de ault:throw new IllegalArgumentException("Unknown URI " + uri);

    }

    // I no sort order is speci ed use the de aultString orderBy;

    i (TextUtils.isEmpty(sortOrder)) {orderBy = Customers.DEFAULT_SORT_ORDER;

    } else {orderBy = sortOrder;

    }SQLiteDatabase db = mOpenHelper.getReadableDatabase();Cursor c = qb.query(db, projection, selection, selectionArgs, null, null,

    orderBy);

    c.setNoti cationUri(getContext().getContentResolver(), uri);return c;

    }

    @Overridepublic Uri insert(Uri uri, ContentValues initialValues) {i (sUriMatcher.match(uri) != CUSTOMERS) {throw new IllegalArgumentException("Unknown URI " + uri);

    }

    ContentValues values;i (initialValues != null) {values = new ContentValues(initialValues);

    } else {values = new ContentValues();

    }

    // Make sure that the elds are all seti (values.containsKey(Customers.NAME) == alse) {

    Resources r = Resources.getSystem();values.put(Customers.NAME, r.getString(android.R.string.untitled));

    }i (values.containsKey(Customers.EMAIL) == alse) {values.put(Customers.EMAIL, "");

    }

    SQLiteDatabase db = mOpenHelper.getWritableDatabase();//the name eld will be assigned a null value i the row is empty.long rowId = db.insert(CUSTOMERS_TABLE_NAME, Customers.NAME

    values);i (rowId > 0) {Uri rowUri = ContentUris.withAppendedId(Customers.CONTENT_URI,

    rowId);getContext().getContentResolver().noti yChange(rowUri, null);//return the uri o the newly created datasetreturn rowUri;

    }throw new SQLException("Failed to insert row into " + uri);

    }}

  • 8/2/2019 Android Bonus

    13/15

    CaChing3 2 1

    www.android360.de 13 ANDROID 360

    zu. Fr komplexere Layouts, z. B. mit Bildern, sollteeine eigene Adapterklasse implementiert werden. Wirweisen der ListActivity den Adapter zu und erzeugensomit die Liste und ihre enthaltenen Elemente.

    Die Datenstruktur anlegen mit BaseColumnsDie Datenstruktur des Content-Providers wird mitKlassen defniert, die das Inter aceBaseColumns im-plementieren. Wir halten es simpel und defniereneine Klasse Customers (Listing 2), die auer den inBaseColumns gegebenenFeldern nur noch Nameund E-Mail enthlt. Con-tent-Provider verwendenURLs, um die gewnsch-ten Daten zu adressieren.Diese Content Uris ol-gen dem simplen Sche-

    ma content:com.mypackage/dataType/ r alle Dateneines Typs bzw. content:com.mypackage/dataType/ID r ein spezielles Datum. Wir setzen die passendeCon-

    tentUrl als statisches Feld in die KlasseCustomer . Einweiteres statisches Feld ist dieDe ault Projection Map ,um die Daten im Cursor zu selektieren. Wenn wir mehrbentigen, lsst sich das jederzeit nachholen. Hier ist esso ein acher, da es nur drei Felder von Interesse gibt.

    Der Content-Provider Der Content-Provider enthlt eine Menge an zustz-lichem Code, der sich mit Au bau und Versionierungder darunter liegenden SQLite-Datenbank sowie demberpr en der au geru enen URLs besch tigt. Diesesind immer hnlich, weshalb wir uns au die wichtigenTeile konzentrieren. Es sei allerdings noch darau hin-gewiesen, dass sich die Datenbank keineswegs au deminternen Speicher befnden muss; der P ad kann durch-aus auch au der SD-Karte liegen. Man kann auch ganz

    au eine Datenbankverzichten solangeein valider Cursor zu-rckgegeben wird, sindder Phantasie ast keineGrenzen gesetzt.Die entscheidendenMethoden des Con-

    tent-Providers sindquery() , insert() und update() .In query starten wir den Service, nachdem wir einenCursor zurckgeben, der entweder leer ist oder veralteteDaten enthlt. Mit c.setNotifcationUri(get Context().

    get ContentResolver(), uri); sorgen wir da r, dass derCursor aktualisiert wird, wenn sich die Daten im Con-tent-Provider ndern. Das erreichen wir, wenn wir in in-sert und update die Content Observer benachrichtigen.

    Listing 4: Proof-of-Concept-Code

    public class DataService extends Service{

    @Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);Log.d(TAG,"started");

    //normally all o this should be loaded o to another thread//a ~30% chance o deleteing all data in the cursori ((int)Math.foor((Math.random() *100))>66) {getContentResolver().delete(Customers.CONTENT_URI, null,null);

    }//write some random data

    or (int i=0;i

  • 8/2/2019 Android Bonus

    14/15

    CaChing2 3

    www.android360.de14 ANDROID 360

    Ob man das auch in delete() macht, hngt davon ab,ob dieser Event wirklich bentigt wird. In unserem Fall

    olgt au jedesdelete ein insert , um neue Daten einzu -gen; die Aktualisierung des GUI mit einem leeren Cursorzwischen beiden Operationen wird eher verwirren, alsntzen.

    Damit der Service auch wei, welche Daten ge ragtsind, bergibt man einen passenden Parameter als Extrain den Intent. Der URL bietet sich hier besonders an.Der Content-Provider verwendete bereits eine Hil sklas-se vom Typ UriMatcher , um einem URL eine eindeutigeID zuzuordnen, au die man entsprechend reagiert. DerCode kann ein ach in den Service kopiert werden. Wennman obendrein noch eine REST-Schnittstelle anspricht,kann man eigentlich auch die REST-URLs alsContent-Urls verwenden und somit direkt an den Service weiter-geben.

    Die entscheidende Zeile, die unsere Cursor von den n-

    derungen in Kenntnis setzt, ist getContext().get Con tent-Resolver().noti yChange(uri, null); . Die null -Variableist der Content Observer, der die nderungen ausgelsthat. In diesem Fall nicht existent und damit null . uri istdie ContentUrl des Datensatzes, der sich gendert hat.Bei eineminsert muss dieser URL erzeugt werden. Dieinsert -Funktion der Datenbank lie ert uns die ID der ge-nderten Zeile, sie wird ein ach mitContent Uris.with-AppendedId(Customers.CONTENT_URI, rowId); andie passende ContentUri angehngt. In query oder up-date nehmen wir dieselbe URI, die als Parameter beimAu ru bergeben wurde.

    Daten erzeugen mit einem ServiceDie letzte Komponente ist der Backgroundservice. DerProo -o -Concept-Code llt recht simpel aus (Lis-ting 4).

    Wir bentigen r unser Beispiel kein echtes Backend,deshalb implementiert der Service eine Funktion getIm-

    portantDataFromTheInternet() , die ein mit zu lligenWerten ge lltesContentValues -Objekt zurckgibt. Obman in einer echten Anwendung den Zwischenschrittdes Parsings in POJOs1 geht, ist Geschmacksache dasich ContenValues direkt in den Content-Provider sch-reiben lassen, kann man darau eigentlich auch verzich-ten.

    Der Service startet alle 90 Sekunden, um neue Datenzu erzeugen. Fr den echten Anwendungs all sollte manbesser ein Intervall grer als 10 Minuten whlen, umdie Batterie nicht unntig zu belasten. Da der Service injedem Query au den Content-Provider gestartet wird,ist die Aktualitt der Daten immer noch garantiert.Mchte man nicht alle Daten neu Laden, kann manz. B. im Content-Provider eine zustzliche Tabelle mitTimestamps anlegen und nur die Ressourcen aktualisie-ren, deren Mindesthaltbarkeitsdatum berschritten ist.

    Die Funktion scheduleNextRun() verwendet den

    AlarmManager , um den nchsten Start vorzuberei-ten. Der AlarmManager ist die sicherste Methode, inIntervallen einen Service aus hren zu lassen. Threads

    knnten vom Garbage Collector beendet werden, wenndas System mehr Ressourcen braucht. Dessen Instanzholen wir uns vom Context (also der Serviceklasse) mit

    getSystemService(ALARM_SERVICE) , eine direkte In-stanzierung ist nicht mglich. Wir erzeugen einenIntent und wandeln diesen in einen PendingIntent . Pending-In tent.get Service(..) sorgt da r, dass der Service vomSystem gestartet wird. Wir setzen den nchsten Startmit AlarmManager.set(..) und benutzen RTC_WAKE-UP , um sicherzustellen, dass der Intent ausgelst wird auch wenn das Device im Sleep Mode ist (z. B. beiausgeschaltetem Bildschirm). Die FunktionSet setzt nureinen einzigen Alarm, stattdessen knnte man auchset-Repeating(..) verwenden, um eine Serie zu setzten.

    Fr dieses Beispiel gengt es, den gesamten Code inonStart auszu hren. In der Realitt ist das keine sogute Idee, es empfehlt sich stattdessen, z. B. WorkerThreads zu verwenden.

    FazitDamit sind nun alle Komponenten zusammen. Wir ha-ben eine e fziente und ein ache Struktur, um Cachingin unsere Anwendung zu integrieren, das eine saubereTrennung von Backend, Speicher und Darstellung ge-whrleistet. Die Anzeige aktualisiert sich von alleine,wenn neue Daten bereit stehen. Der Cache kann im Hin-tergrund mit neuen Daten ge llt werden, wann immerdie Mglichkeit und/oder Notwendigkeit besteht. DasBeispielprojekt setzt au Android 1.6 au , sollte aberproblemlos au ltere Versionen angepasst werden kn-

    nen. Die vorgestellte Methodik ist au nahezu alle Pro-jekte anwendbar. Der gesamte Beispielcode steht unterder Apache License 2 und kann mit olgendem Be ehlheruntergeladen werden:

    svn checkout http://openintents.googlecode.com/svn/trunk/samples/ CachingContentProvider openintents-read-only

    Links & Literatur

    [1] Ope i te ts: ttp://www.ope te ts.or

    [2] Mult t sk t e a dro d W y: ttp://b t.ly/a360_CC_2

    [3] C c Co te t Prov der (Be sp el): ttp://b t.ly/a360_CC_3

    Ronan Schwarz wuc s m t der D t l s eru u . heute st er e Te l d vo u d rbe tet ls mob le-So tw ree tw ckler be TiC-mo-b le. Ro st e Experte r a dro d u d e er der erste E t-w ckler r d s eue S msu -OS B d .

  • 8/2/2019 Android Bonus

    15/15

    Das neue Magazin frMobile Development, Marketing, Business

    N E U

    iPhone, iPad

    Android

    Mobile Web

    Windows Phone 7

    Tools & Best Practices

    App Stores

    Mobile Commerce &Marketing

    Business & Strategien

    go: mobiletechnolog mag de

    J e t z t a bo n n ie re n u nd So nde rp re i s s ic he r n!

    ( Limi tier tes A ngebo t )


Recommended