Operacijski sustav Android i načini povezivanja s poslužiteljem
Android je programsko okruženje za pokretne uređaje bazirano na otvorenom
kodu (eng. Open Source) koje se sastoji od kompleta programske
opreme: operacijskog sustava, programske međuopreme (eng. middleware)
i ključnih aplikacija za pokretne uređaje. Također, sadrži mnoštvo sučelja
za izradu aplikacija (API, eng. application programming interface) koja
razvojnim inženjerima omogućuju samostalan razvoj i rad na aplikacijama.
Predstavljanje Androida i njegove razvojne okoline za pisanje aplikacija (SDK, eng. software development kit) započelo je u studenom 2007. godine od strane Googlea i grupacije Open Handset Alliance (OHA). Open Handset Alliance je konzorcij s ciljem razvoja otvorenih standarda za pokretne uređaje, promocija inovacija i prilagodba uređaja korisniku s poboljšanom izvedbom i pristupačnom cijenom. Broji nekoliko desetaka članica među kojima se nalazi i Google.
Shodno svojoj politici OHA ističe slijedeće karakteristike Android programskog
okruženja:
- otvorenost - programeru omogućava potpunu slobodu u razvoju novih i već postojećih aplikacija, a proizvođaču uređaja slobodno korištenje i prilagodbu platforme bez plaćanja autorskih prava;
- sve aplikacije su ravnopravne - što znači da ne postoji razlika između osnovnih jezgrenih aplikacija uređaja i dodatnih aplikacija. Svim aplikacijama omogućen je ravnopravni pristup resursima pokretnog uređaja što daje mogućnost potpune prilagodbe uređaja specifičnim potrebama individualnog korisnika;
- automatsko upravljanje ž ivotnim ciklusom aplikacije - omogućava nadzor pokretanja i izvršavanja aplikacija na sistemskoj razini optimiziranim korištenjem memorije i snage uređaja. Krajnji korisnik više ne brine o gašenju određenih aplikacija prije pokretanja drugih;
- rušenje granica "klasičnih" aplikacija - mogućnost razvoja novih i inovativnih aplikacija temeljenih na međusobnoj kolaboraciji tehnologija;
- brz i jednostavan razvoj aplikacija - omogućen je bogatom bazom korisnih programskih biblioteka (eng. libraries) i alata za izradu aplikacija;
- visokokvalitetni grafički prikaz i zvuk - podržana 2D vektorska i 3D OpenGL (eng. Open Graphics Library) grafika, te ugrađeni kodeci svih često korištenih audio i video formata;
- kompatibilnost s većinom sadašnjeg i budućeg hardvera - uključuje prenosivost Androidovih aplikacija na ARM, x86 i ostale arhitekture, te prilagodljivost sustava ulaznim i izlaznim komponentama.
2. Arhitektura sustava Android
Arhitektura sustava Android [3] bazira se na Linux 2,6 jezgri
(eng. kernel) koja se koristi kao sloj apstrakcije hardvera (HAL, eng.
Hardware Abstraction Layer). Razlog za korištenje jezgre operacijskog
sustava Linux je dokazana pogonska podrška (eng. driver model), mogućnost
upravljanja memorijom i procesima, sigurnosni model, mrežni sustav, te
dokazana robusnost, konstantni razvoj i unapređivanje sustava. Slika 2.1
prikazuje arhitekturu sustava Android.
Slika 2.1: Arhitektura sustava Android
Najvažniji elementi jezgre su:
• pogonski program za međuprocesnu komunikaciju između aplikacija i usluga (eng. service) (eng. Binder (IPC) Driver) - omogućava međuprocesnu komunikaciju između aplikacija i usluga, te
• upravljanje napajanjem (eng. Power Management) - komponenta Androida temeljena na standardnom Linuxovom sustavu upravljanja napajanjem.
Izvorne programske biblioteke (eng. native libraries) pisane su u programskim jezicima C i C++ i čine idući sloj u arhitekturi sustava. Neke od značajnijih su:
- program za upravljanje grafičkim sučeljem (eng. Surface Manager) -biblioteka odgovorna za pravilno iscrtavanje različitih aplikacijskih komponenti u vremenu i prostoru;
- OpenGL ES (eng. OpenGL for Embedded Systems) - biblioteke koje se koriste za hardversku 3D akceleraciju (ukoliko je podržana) ili za 3D rasterizaciju;
- SGL (eng. Scalable Graphics Library) - predstavlja 2D biblioteke na kojima je temeljena većina aplikacija. Spomenimo još da se 2D i 3D elementi mogu kombinirano prikazivati u jednom korisničkom sučelju;
- Media Framework - skupina kodeka za snimanje i reprodukciju audio formata, video formata i nepomičnih slika. Omogućena je od strane PacketVidea;
- FreeType - biblioteka koja služi za vektorsku rasterizaciju oblika pisma (eng.
font);
- SSL (eng. Secure Socket Layer) - omogućuje sigurnosnu komunikaciju preko Interneta;
- SQLite - programska biblioteka koja implementira bazu podataka (eng.
database engine);
- WebKit - jezgra preglednika koji podržava JavaScript i ostale standarde na malom uređaju;
- System C library - implementacija standardne C-ove sistemske biblioteke (libc) izvedene iz operacijskog sustava BSD.
Idući sloj u arhitekturi Androida je radno okruženje (eng. Android runtime) kojeg čine virtualni stroj Dalvik (DVM, eng. Dalvik Virtual Machine) i jezgrene biblioteke (eng. core library).
DVM je registarski baziran virtualni stroj, dok je klasični Javin virtualni stroj (JVM, eng. Java Virtual Machine) baziran na stogu. Više o Dalvik virtualnom stroju u poglavlju 2.1. Jezgrene biblioteke pisane su u programskom jeziku Java i predstavljaju sve esencijalne klase kao što su klase za manipulaciju kolekcijama, klase za komunikaciju s okolinom i slično. Bitna novost je i to što se Androidove jezgrene biblioteke razlikuju od biblioteka u Java Standard Edition (J2SE) i Java 2 Micro Edition (J2ME).
Sloj aplikacijskih okvira (eng. Application Framework) napisan je u programskom jeziku Java i sadrži proširiv skup programskih komponenti kojeg koriste sve aplikacije uređaja. Neki od važnijih elemenata su:
- upravljanje aktivnostima (eng. Activity Manager) - upravljanje životnim ciklusom aplikacije,
- upravljanje programskim paketima (eng. Package Manager) - sadrži informaciju o aplikacijama instaliranim na sustavu,
- upravljanje prozorima (eng. Window Manager) - upravljanje aplikacijskim prozorima,
- upravljanje pozivima (eng. Telephony Manager) - sadrži API-je koji se koriste pri izradi aplikacija za upravljanje pozivima,
- pružatelji sadržaja (eng. Content Providers) - omogućuju zajedničko korištenje podataka od strane više aplikacija,
- upravljanje resursima (eng. Resource Manager) - služi za pohranu dijelova aplikacije koji nisu kod (npr. slike),
- sustav grafičkog prikaza (eng. View System) - sadrži bazu gotovih grafičkih prikaza i alata (eng. widget),
- upravljanje lokacijski temeljenim uslugama (eng. Location Manager) i
- upravljanje obavijestima (eng. Notification Manager) - upravljanje obavijestima i događajima (npr. dospijeće poruke, nadolazeći sastanak).
Aplikacijski sloj je zadnji sloj u arhitekturi sustava Android i č ine
ga korisničke aplikacije uređaja. Predstavlja sloj vidljiv krajnjem korisniku.
Uključuje neke od standardnih sistemskih aplikacija kao što su Web preglednik,
lista kontakata, telefon, itd.
2.1 Dalvik virtualni stroj
Umjesto upotrebe standardnog Java 2 Micro Edition (J2ME) kao mehanizma
za pokretanje Javinih aplikacija na pokretnim uređajima, Google je razvio
vlastiti virtualni stroj za Android. DVM je najvjerojatnije razvijen kako
bi se zaobišla problematika s dozvolama korištenjem Sunovog J2ME. Svaki
pokretni uređaj koji u sebi sadrži J2ME mora kod Suna licencirati bilo
kakvu promjenu izvornog koda J2ME-a. Virtualni stroj Dalvik dobio je ime
po istoimenom Islandskom gradu u kojem su živjeli preci glavnog razvijatelja
DVM-a Dan Bornsteina.
Osnovna razlika između Sun Java virtualnih strojeva, te DVM-a je u tome
što su prvo spomenuti stožno bazirani virtualni strojevi, dok je DVM registarski
baziran virtualni stroj. Međukod (eng. bytecode) Dalvik virtualnog stroja
transformira se pomoću alata dx (koji je sastavni dio Android SDK-a) iz
Javinih klasnih datoteka (eng. Java class file) prevedenih Javinim prevoditeljem
u novu klasu *.dex (eng. Dalvik Executable) formata. Međukod kojeg izvršava
DVM nije Javin međukod, nego upravo spomenuti .dex oblik. Transformacija
formata omogućava bolju prilagodbu za rad na manjim procesorima boljim
iskorištavanjem raspoložive memorije i procesorske snage. Rezultat svega
je mogućnost višestrukog instanciranja samog virtualnog stroja š to znači
da se svaka Androidova aplikacija pokreće kao zasebni proces, s vlastitom
instancom virtualnog stroja Dalvik.
Struktura datoteke .dex prikazana je slikom 2.2 [5]. Datoteka se sastoji
od jednostavnog zaglavlja, identifikatora nizova, tipova, prototipova,
polja i metoda, definicija klasa i podataka. Ovime se osigurava da se
konstante koje se ponavljaju u klasnim datotekama pojavljuju samo jednom
u datoteci .dex kako bi se sačuvala memorija.
3. Android SDK
Paket softverskih razvojnih alata Android SDK [6] pruža podršku za razvoj, testiranje, pronalaženje i uklanjanje pogrešaka (eng. debugging) aplikacija. Uključuje sljedeće komponente:
- android API-je;
- razvojne alate - alati za prevođenje i debagiranje. Najznačajniji
je programski dodatak (eng. plugin) za Eclipse IDE naziva ADT (eng.
Android Development Tools Plugin) koji omogućuje jednostavni pristup
LogCatu, uređivaču datoteke AndroidManifest.xml, kontrolu dolaznih poziva,
SMS simulaciju i slično;
- emulator - služi za izvršavanje progama na računalu;
- DDMS (eng. Dalvik Debug Monitoring Service) - služi za kontrolu i
nadzor pronalaženja i uklanjanja pogrešaka u aplikacijama;
- AAPT (eng. Android Asset Packaging Tool) - koristi se za stvaranje
i distribuciju Androidovog programskog paketa u .apk formatu;
- ADB (eng. Android Debug Bridge) - klijentsko-poslužiteljska aplikacija
za instaliranje i pokretanje datoteka .apk na emulatoru ili uređaju,
te pristup komandnom retku uređaja. Koristi se i za povezivanje standardnog
programa za pronalaženje i uklanjanje pogrešaka (eng. debugger) s kodom
na emulatoru ili uređaju;
- detaljnu dokumentaciju;
- primjerke koda - jednostavni primjerci koda za demonstraciju korištenja
određenih API-ja, te mogućnosti koje pruža Android.
3.1 Android emulator
U Android SDK uključen je emulator pokretnog uređaja koji omogućava razvoj
i testiranje aplikacija. Jedino ograničenje emulatora je nemogućnost uspostave
dolaznih i odlaznih poziva. Korištenjem ADT-a kao programskog dodatka
za Eclipse emulator se automatski poziva prilikom izvođenja i procesa
pronalaženja i uklanjanja programskih pogrešaka. Izgled grafičkog sučelja
jednog od emulatora prikazan je na slici 3.1.
Android emulator je aplikacija temeljena na QEMU (eng. Open source processor
emulator) s virtualnim pokretnim uređajem temeljenom na procesoru ARM
(eng. Advanced RISC Machine). QEMU je strojni emulator temeljen na otvorenom
kodu. Uključuje cjeloviti Android sistemski stog (eng. system stack) sve
do razine jezgre sustava, skup unaprijed instaliranih aplikacija (npr.
birač brojeva) kojima se može pristupati korištenjem vlastitih aplikacija,
korisničko grafičko sučelje, prilagodljivo dodjeljivanje vrijednosti tipkama,
te mnoštvo naredbi i mogućnosti za kontrolu ponašanja emuliranog okruženja.
3.2 Dalvik Debug Monitoring Service (DDMS)
DDMS je alat koji omogućava upravljanje procesima na emulatoru ili pokretnom
uređaju, te pomaže prilikom pronalaženja i uklanjanja pogrešaka u programskom
kodu. Pruža mogućnost preusmjeravanja vrata (eng. port redirection), informacije
o stanju dretvi i gomila na uređaju, upotrebu LogCata (naredba koja komprimirane
datoteke evidencije događaja ispisuje u oovjeku čitljivom obliku), praćenje
informacija o procesima, snimanje aktivnog zaslona uređaja, kontrolu lažiranih
(eng. spoofing) poziva, SMS poruka i podataka o lokaciji, te mnoge druge
usluge.
Cijeli se alat ponaša kao poveznica između IDE-a i aplikacija koje se
izvršavaju na uređaju. Kao što je već spomenuto, na sustavu Android svaka
aplikacija pokreće se kao zasebni proces koji se izvodi kao zasebna instanca
virtualnog stroja Dalvik. Svaki od tih procesa povezan je s programom
za pronalaženje i uklanjanje programskih pogrešaka preko jedinstvenih
vrata počevši uzlazno od vrata 8600. DDMS se također spaja i na pretpostavljena
lokalna vrata 8700.
Prilikom pokretanja DDMS se spaja na ADB koji mu prosljeđuje informaciju
o tome da li je uređaj spojen ili odspojen. Kada je uređaj spojen kreira
se VM (eng. Virtual Machine) nadzorna usluga između ADB-a i DDMS-a čija
je uloga obavještavanje DDMS-a da li je virtualni stroj na uređaju pokrenut
ili ugašen. Prilikom pokretanja virtualnog stroja DDMS posredstvom ADB-a
dobavlja njegov jedinstveni ID i otvara vezu prema programu za pronalaženje
i uklanjanje pogrešaka preko ADBD-a (eng. ADB Deamon) na uređaju. Na taj
način ostvarena je veza između DDMS-a i virtualnog stroja korištenjem
uobičajenog wire protokola.
3.3 Android Debug Bridge (ADB)
ADB je klijentsko-poslužiteljski alat koji služi za povezivanje s Androidovim emulatorom ili uređajem. Uključuje tri komponente:
- klijent - aplikacije (npr. DDMS) koje komuniciraju s pozadinskim procesom preko poslužitelja,
- poslužitelj - pozadinski proces koji se pokreće na računalu na kojem razvijamo aplikaciju i upravlja komunikacijom između klijenta i pozadinskog procesa ADB-a koji se izvršava na emulatoru, te
- pozadinski proces ADB-a na emulatoru.
Prilikom pokretanja ADB-ovog klijenta prvo se provjerava postoji li već
aktivni ADB-ov poslužitelj. Ukoliko ne postoji, pokreće se i spaja na
lokalna TCP vrata 5037 na kojima osluškuje naredbe poslane od strane ADB
klijenta. Svi ADB klijenti koriste vrata 5073 za komunikaciju s ADB poslužiteljem.
Nakon toga se uspostavlja komunikacija poslužitelja i svih instanci emulatora
ili uređaja. To se ostvaruje na način da poslužitelj pregledava sva neparna
vrata u rasponu od 5555 do 5585. Ukoliko ADB poslužitelj prilikom pretraživanja
na određenim neparnim vratima naiđe na pozadinski proces ADB-a uspostavlja
se veza na tim vratima. Pretraživanje samo neparnih vrata vrši se iz razloga
š to je za uspostavu veze potreban jedan par vrata i to jedna vrata za
vezu s konzolom i jedna vrata za vezu emulatora ili uređaja s ADB-om.
Tako se, na primjer, konzoli emulatora povezanog s ADB poslužiteljem na
vratima 5555 pristupa preko vrata 5554.
Nakon uspostave veze moguće je kontrolirati emulator različitim ADB naredbama.
4. Koncept aplikacije
Sve Androidove aplikacije pisane su u programskom jeziku Java. Aplikacijom se smatra kompletni kod paketa upakiran pomoću AAPT alata koji kao rezultat stvara datoteku sufiksa .apk. Upravo se u ovom formatu aplikacije distribuiraju na pokretni uređaj.
Većina stvorenih aplikacija pripada u jednu od slijedećih kategorija [4]:
- aktivnost koja se izvršava u prvom planu (eng. foreground activity) - aplikacije bez korisne pozadinske aktivnosti (npr. igre ili kartografija). Kada su izvan fokusa aplikacije ove vrste se uglavnom privremeno zaustavljaju;
- pozadinska usluga (eng. background service) - aplikacije ograničene interakcije s korisnikom koje se uglavnom izvršavaju u pozadini (npr. aplikacija za upravljanje dolaznim pozivima);
- aktivnost s prekidima - aplikacije koje podrazumijevaju određeni stupanj interakcije s korisnikom, ali se uglavnom odvijaju u pozadini (npr. mp3 svirač (eng. mp3 player)).
Za razliku od većine aplikacija na drugim sustavima, Androidove aplikacije
nemaju samo jednu pokretnu točku (ovo konkretno znači da ne postoji samo
jedna main() funkcija). Razlog tome je karakteristika sustava koja zastupa
ideju međusobne interakcije dvije ili više različitih aplikacija, a da
bi to bilo ostvarivo sustav mora biti u mogućnosti pokrenuti proces pojedine
aplikacije i kada se zatraži rad samo nekog njenog određenog dijela, te
instancirati Javin objekt za dotični dio.
4.1 Osnovna struktura
Postoje četiri osnovne komponente koje čine aplikaciju [2]:
- aktivnost (eng. Activity) - predstavlja komponentu aplikacije koja se uglavnom može poistovjetiti s jednim konkretnim prozorom aplikacije u kojem je korisnik u mogućnosti izvršiti određenu radnju. Aplikacija može sadržavati jednu ili više definiranih aktivnosti, pri č emu je jedna od aktivnosti uvijek definirana kao primarna aktivnost. Prijelaz između aktivnosti odvija se tako što aktualna aktivnost invocira novu. Iako više aktivnosti tvori jedno kompaktno korisničko sučelje treba imati na umu da su one međusobno nezavisne. Svaka aktivnost implementira se kao zasebna klasa koja nasljeđuje klasu Activity, te je sama odgovorna za čuvanje svog stanja u životnom ciklusu aplikacije;
- namjera (eng. Intent) - omogućava prijelaz između zaslona aplikacija. Ustvari predstavlja namjeru za obavljanjem određene radnje. Ovdje ćemo još spomenuti Broadcast Reciever koji predstavlja dio koda koji se pokreće isključivo ukoliko je aktiviran nekim vanjskim faktorom i Intent Filter koji opisuje koje namjere je aplikacija u stanju izvršiti;
- usluga (eng. Service) - predstavlja proces bez vidljive korisničke interakcije. Uglavnom se izvršava u pozadini nedefinirani period vremena. Služi za obnavljanje podatkovnih resursa, vidljivih aktivnosti i signalizacijskih obavijesti. Svaka usluga nasljeđuje klasu Service;
- pružatelj sadržaja (eng. Content Provider) - omogućava uzajamno korištenje podataka između različitih aplikacija i njihovih procesa. Pružatelj sadržaja nasljeđuje klasu ContentProvider.
Aplikacija ne mora sadržavati sve spomenute komponente, a isto tako može
sadržavati i neke druge.
4.2 Životni ciklus aplikacije
Kod klasične radne površine operacijskog sustava Windows ili Linux postoji
jedan aktivni prozor i ravnopravni niz ostalih aplikacija, a kontrolu
ž ivotnog ciklusa vrši korisnik. Android sam brine o ž ivotnom ciklusu
aplikacija, prikaz se vrši na principu LIFO (eg. Last In First Out) stoga
na koji se spremaju aktivnosti pokrenutih aplikacija kao što je prikazano
na slici 4.1 [4].
Svaki zaslon korisničkog sučelja prikazan je pomoću klase Activity. Aplikaciju
čine jedna ili više aktivnosti. Vrlo je važno napomenuti da aplikacija
nije isto što i proces što bitno utječe na ponašanje i životni ciklus
aplikacije.
Kako bi se očuvala efikasnost cijelog sustava, procesi i njihove aplikacije
će, ukoliko je potrebno, biti ugašeni bez upozorenja s ciljem oslobađanja
memorijskih resursa za aplikacije višeg prioriteta (uglavnom one koje
korisnik koristi u tom trenu). Slika 4.2 prikazuje stablo prioriteta procesa
[4].
Slika 4.2: Stablo prioriteta
Definiramo slijedeće vrste prioriteta:
aktivni procesi - ovakvih procesa je uglavnom malo i imaju vrlo visoki prioritet iz razloga š to podržavaju aplikacije s kojima korisnik ostvaruje aktivnu interakciju. Neki od ovih procesa uključuju vidljive aktivnosti,
Broadcast Recievere koji izvršavaju onReceive() metodu, te usluge koje izvršavaju onStart(), onCreate() ili onDestroy() metodu; vidljivi procesi - predstavljaju vidljive, ali neaktivne procese. Uglavnom ih je vrlo malo, te se gase u krajnjoj nuždi;
pokrenuti uslužni procesi - procesi pokrenutih usluga s kojima korisnik nema aktivnu interakciju, te iz tog razloga imaju nešto niži prioritet. I dalje ih se smatra aktivnim procesima, te će biti ugašeni samo u nuždi;
- pozadinski procesi - predstavljaju procese nevidljivih aktivnosti bez pokrenutih usluga. U pravilu ih je veliki broj, te se gase po principu "zadnji viđen prvi ubijen" (LSFK, eng. Last Seen First Killed);
- prazni procesi - predstavljaju zapis pokrenutih procesa u privremenoj memoriji s ciljem smanjenja vremena ponovnog pokretanja.
Na životni ciklus aplikacije utječe isključivo sustav, a ne sama aplikacija. Stanje u kojem se nalazi aplikacija određuje njezinu prioritetnu razinu. Aktivnost aplikacije može se nalaziti u nekom od sljedećih stanja prikazanih slikom 4.3 [1]:
- aktivno - vidljiva aktivnost u fokusu;
- privremeno zaustavljeno - vidljiva aktivnost izvan fokusa;
- zaustavljeno - nevidljiva aktivnost izvan aktivne upotrebe. U memoriji se čuva njezino stanje i ostale informacije;
- neaktivno - stanje aktivnosti nakon gašenja, a prije pokretanja.
Slika 4.3: Stanja aktivnosti
Prijelazi između pojedinih stanja nevidljivi su krajnjem korisniku, ali kontrolirani na razini sustava upotrebom odgovarajućih nadjačavajućih (eng. override) metoda:
onCreate(Bundle) - poziva se prilikom pokretanja aplikacije, onStart() - naznačuje početak prikaza aplikacije korisniku, onResume() - poziva se prilikom početka ili nastavka interakcije s korisnikom, onPause() - poziva se prilikom prebacivanja u pozadinski način rada, onStop() - poziva se u slučaju dužeg perioda nekorištenja aplikacije, onRestart() - naznačuje ponovo pozivanje aplikacije iz zaustavljenog stanja, onDestroy() - poziva se trenutak prije gašenja aplikacije,
onSaveInstanceState(Bundle) - opcionalna metoda koja se poziva u slučaju čuvanja stanja instance i
onRestoreInstanceState(Bundle) - poziva se prilikom reinicijalizacije aktivnosti iz stanja prethodno pohranjenog onSaveInstanceState() metodom.
4.3 Korisničko sučelje
Postoje dva načina dizajniranja korisničkog sučelja: proceduralno i deklarativno. Proceduralni dizajn odnosi se na pisanje Java koda, a deklarativni na pisanje XML (eng. EXtensible Markup Language) koda. U praksi se za kreiranje grafičkog korisničkog sučelja uglavnom koristi XML.
Kreiranjem sučelja aktivnosti dobivaju svoju funkcionalnost, tj. vidljivost na zaslonu uređaja i na taj se način omogućava interakcija s korisnikom. Osnovne jedinice korisničkog sučelja su objekti pogled (eng. View) i grupe pogleda (eng. ViewGroup) [2]:
pogled - objekt čija podatkovna struktura u sebi nosi zapis izgleda i sadržaja određenog pravokutnog područja na zaslonu, te upravlja iscrtavanjem elemenata, pomicanjem sadržaja na zaslonu (eng. scrolling) i ostalim faktorima koji utječu na izgled definiranog dijela zaslona. U hijerarhijskom stablu objekti pogled su listovi stabla. Android raspolaže s već gotovim skupovima objekata ove vrste kao što su gumbi, kvadratići za odabir (eng. checkbox) i slično. Ovi objekti nasljeđuju klasu View;
- grupe pogleda - posebna vrsta objekta pogled koja sadrži i upravlja skupinom zavisnih objekata pogleda i grupe pogleda čime je omogućena kompleksnost prikaza korisničkog sučelja. Objekti ove vrste su inastance klase ViewGroup.
Hijerarhijska ovisnost objekata pogleda i grupe pogleda prikazana je
slikom 4.4. Iscrtavanje elemenata stabla započinje od korijena stabla
tako š to aktivnost prvo poziva svoju setContentView() metodu i Android
sustavu predaje referencu na korijenski objekt. Svaki podčvor iscrtava
se sam pozivanjem draw() metode i to pod uvjetom da čvor sam postavlja
zahtjev za lokacijom i veličinom, ali roditeljski č vor (grupa pogleda)
donosi konačnu odluku o veličini prostora za iscrtavanje podčvora i njegovoj
lokaciji na zaslonu. Svaka grupa pogleda je odgovorna za renderiranje
prikaza svojih podčvorova.
4.3.1 Izbornik
Za pristup izborniku aplikacije najčešće se koristi tipka MENU koja se
nalazi na samom uređaju (ukoliko je hardverski podržano) ili se izbornik
može prikazati ukoliko se odabere neka od komponenti aplikacije. Strukturu
izbornika, koja je hijerarhijska, nije potrebno ručno konfigurirati nego
se isto postiže definiranjem povratnih (eng. callback) metoda onCreateOptionsMenu()
ili onCreateContextMenu() s popisom stavki izbornika za određenu aktivnost.
Upravljanje događajima također se odvija automatski pozivanjem metoda
onOptionsItemSelected() ili onContextItemSelected() od strane sustava.
4.3.2 Događaji unutar korisničkog sučelja
Kako bi se znalo da je korisnik uopće odabrao neku od aktivnosti ili stavku u izborniku sučelja potrebno je definirati način na koji korisnik vrši interakciju s određenim komponentama sučelja. Postoje dva načina:
- definiranje slušača događaja (eng. Event listener) - najčešći način
osluškivanja događaja. View klasa sadrži kolekciju ugniježđenih sučelja
On<event>Listener od kojih svako sadrži povratnu metodu On<event>()
pri čemu događaj može biti ili odabir određenog elementa ili dodir ekrana
ili nešto treće;
- nadjačavanje (eng. override) postojeće povratne metode za View klasu
- koristi se u slučaju implementiranja vlastite View klase i osluškivanja
posebnih događaja koji se u njoj pojavljuju.
4.3.3 Dodatne mogućnosti
Osim osnovnih komponenti aplikacija može sadržavati mnoštvo dodatnih
elemenata i njihovih varijacija. Spomenut ćemo adaptere, te stilove i
teme.
Adapteri su vrsta podklase ViewGroup koja se koristi za prikaz gotovih
pohranjenih podataka (za razliku od iscrtavajućih grupa i nizova).
Kao dio aplikacijskog sustava postoje već gotovi stilovi i teme, no također
je moguće stvoriti i vlastite. Stil je skup jednog ili više atributa za
oblikovanje zasebnih elemenata u prikazu (npr. definiranje određene veličine
prikaza i boje slova). Tema je skup jednog ili više atributa za oblikovanje
koji se primjenjuju na jednu ili sve aktivnosti u aplikaciji (npr. definiranje
određenih pozadinskih boja, izgleda teksta za određenu aktivnost).
4.4 Datoteka AndroidManifest.xml
Svaka aplikacija obavezno mora sadržavati datoteku AndroidManifest.xml koja ju opisuje. Ova datoteka nalazi se u korijenskom direktoriju paketa, te sadrži slijedeće informacije o aplikaciji:
naziv paketa -služi kao jedinstveni identifikator aplikacije,
opis komponenti - aktivnosti, usluge, pružatelji sadržaja, filtere namjera
(eng.
Intent Filters), Broadcast Recievers itd.,
odredbe o tome koji će procesi sadržavati programske komponente, deklaracija
dozvola za pristup aplikacijskim komponentama od strane drugih aplikacija,
minimalna razina Android API-ja koju zahtjeva aplikacija,
popis biblioteka s kojima aplikacija treba biti povezana i
popis instrumentacijskih klasa koje osiguravaju oblikovanje i ostale informacije
dok je aplikacija aktivna - ove deklaracije su prisutne u AndroidManifest.xml
datoteci prilikom razvoja i testiranja, te se izbacuju prije njenog objavljivanja.
<?xml version="1.0" encoding=Mutf-8M?> <manifest>
<uses-permission /> <permission /> <permission-tree /> <permission-group /> <instrumentation /> <uses-sdk /> <application> <activity> <intent-filter> <action /> <category /> <data /> </intent-filter> <meta-data /> </activity> <activity-alias>
<intent-filter> . . . </intent-filter> <meta-data /> </activity-alias>
<service>____________________________
<intent-filter> . . . </intent-filter>
<meta-data/> </service> <receiver>
<intent-filter> . . . </intent-filter>
<meta-data /> </receiver> <provider>
<grant-uri-permission />
<meta-data /> </provider> <uses-library /> </application>
</manifest>____________________________________________
Tablica 4.1: Struktura AndroidManifest.xml datoteke
U tablici 4.1 [7] prikazani su osnovni elementi datoteke AndroidManifest.xml čije značenje sljedeće:
- <action> - opisuje akciju dodijeljenu <intent-filter> elementu. Obavezan dio <intent-filter> polja. Ukoliko se ne definira Intent objekti ne prolaze kroz filter;
- <activity> - obavezni deklarirajući element za svaku aktivnost aplikacije. Podržava podelement <intent-filter> kojim se specificiraju pojedine namjere aktivnosti. Pokretanje aktivnosti koja nije definirana u AndroidManifest.xml datoteci rezultira dojavom greške pri izvođenju (eng. runtime error);
- <activity-alias> - zamjenska aktivnost. Ciljanu aktivnost predstavlja kao nezavisni entitet s vlastitim skupom filtera namjera koji umjesto definiranja namjera za izravno pokretanje ciljane aktivnosti određuju namjere koji ju pokreću preko zamjenske aktivnosti;
- <application> - korijenski element s opisom dubine stabla kojeg čine komponente paketa. Također može sadržavati globalne i/ili unaprijed zadane aplikacijske atribute kao što su tema, ikona, dozvole itd. Manifest datoteka može sadržavati samo jedan element ove vrste;
- <category> - vrsta kategorije Intent filtera. Sadržan u bloku <intent-filter>;
- <data> - određuje vrstu podatka Intent filtera. To mogu biti opcionalni, ali međusobno zavisni atributi MIME ili URI. Sadržan u bloku <intent-filter>;
- <grant-uri-permission> - određuje garantirane dozvole podatkovnih podskupova pružatelja sadržaja. Sadržan u bloku <provider>;
- <instrumentation> - deklarira koje su instrumentacijske komponente raspoložive za testiranje funkcionalnosti paketa. Sadržan u bloku <manifest>;
- <intent-filter> - određuje vrstu namjere na koju reagiraju aktivnost, usluga ili Broadcast Receiver. Sadržan u blokovima <activity>, <activity-alias>, <service> i <receiver>;
- <manifest> - definira komponente, sigurnosne postavke i testne klase koje čine aplikaciju. Ovo je korijenski element AndroidManifest.xml datoteke;
- <meta-data> - par ime-vrijednost dodatnih metapodataka koji mogu biti isporučeni roditeljskoj komponenti. Sadržan u blokovima <activity>, <activity-alias>,<service> i <receiver>;
- <permission> - deklarira sigurnosne dozvole nad komponentama kojima pristupaju druge aplikacije;
- <permission-group> - određuje grupaciju povezanih dozvola;
- <permission-tree> - određuje stablo dozvola;
- <provider> - definira pružatelja sadržaja. Sadržan u <application>;
- <receiver> - definira Broadcast Reciever koji omogućuje prihvat namjera i u slučaju kada aplikacija i njene komponente nisu pokrenute;
- <service> - definira usluge. Sadržan u <application> bloku, a može sadržavati <intent-filter> i <meta-data>;
- <uses-library> - specificira biblioteku s kojom aplikacija mora biti povezana. Sadržan u <application> bloku;
- <uses-permission> - dio sigurnosnog modela koji sadrži sigurnosne dozvole dodijeljene od strane korisnika, a odnose se na funkcije aplikacije. Dozvole se definiraju prilikom instaliranja aplikacije;
- <uses-sdk> - definira razine Android API-ja na kojima se može izvoditi aplikacija.
Dozvole se definiraju zbog hardverski ograničenog pristupa memoriji jednog procesa od strane drugog, te zato što je svakoj aplikaciji dodijeljen specifični korisnički ID. Neke od najčešće korištenih dozvola su:
- INTERNET - pristup Internetu,
- READCONTACTS - dozvola za čitanje podataka kontakata,
- WRITECONTACTS - dozvola za pisanje podataka kontakata,
- RECEIVESMS - nadzor pristigle SMS poruke,
- ACCESS_COARSE_LOCATOR - grubo bežično lociranje ili lociranje preko bazne stanice i
- ACCESS_FINE_LOCATION - finije lociranje korištenjem npr. GPS-a.
Uređivanje AndroidManifest.xml može biti ručno pisanjem XML koda ili
korištenjem uređivača koji dolazi kao dio ADT-a.
4.5 Podatkovni resursi
Pod pojmom podatkovnih resursa podrazumijevaju se vanjski podaci (slike, video, teme, XML kod i slično) koji se koriste u aplikaciji, a nisu dio programskog koda. Podatkovni resursi u aplikacijskom paketu smješteni su u vlastitom direktoriju pod nazivom res/. Ovo odjeljivanje se prvenstveno radi zbog lakšeg upravljanja, ažuriranja i manipulacije podacima. Podatkovni resursi prevode se pomoću alata AAPT ovisno o tipu i poddirektoriju u kojem se nalaze. Ovisnost tipa podatkovnog resursa i lokacije u paketu prikazana je u tablici 4.2.
Važno je napomenuti da se XML datoteke pretvaraju u binarni zapis kako bi se zbog veće efikasnosti mogle brže učitati.
LOKACIJA |
PODATKOVNI RESURS |
/res/layout/ |
Datoteke prikaza |
/res/drawable/ |
Slike |
/res/anim/ |
Animacije |
/res/values/ |
Jednostavne vrijednosti (stilovi, konstantni nizovi, boje...) |
/res/raw/ |
Sirovi (eng. raw) podaci (mp3 ili video) |
Tablica 4.2: Tipovi podatkovnih resursa i njihova lokacija u paketu
Dozvoljeni znakovi u zapisu podatkovnih resursa su mala slova, brojevi,
točka i podvlaka. Prilikom prevođenja stvara se posebna klasa naziva R
koja sadrži identifikatore podatkovnih resursa za razliku od standardnih
Java podatkovnih resursa koji su referencirani po ključevima tipa String.
Ova klasa sastoji se od niza podklasa, svaka za različitu vrstu podataka.
4.5.1 Upotreba resursa u kodu
Podaci se u kodu pozivaju preko identifikatora sintaksama R.resource_type.resource_name
ili android.R.resource_type.resource_name pri eemu nije potrebno navoditi
ime paketa. Resource_type je podklasa koja sadrži određenu vrstu podatkovnog
resursa, a resource_name je ime resursovog atributa definiranog u XML
datoteci ili ime datoteke, bez sufiksa, za podatkovne resurse definirane
od strane nekog drugog podatkovnog tipa. Razlika između ove dvije spomenute
sintakse je u tome što se sintaksa android.R.resource_type.resource_name
koristi za već postojeće podatkovne resurse u sustavu.
4.5.2 Upotreba resursa u drugim podatkovnim resursima
Podaci se mogu referencirati i iz drugih resursa (npr. XML datoteke).
Ovo se ponajviše
koristi prilikom izrade stilova i datoteka prikaza. Za referenciranje
jednog resursa iz
drugog koristi se notacija @ u sintaksi
attribute="@[packagename:]resourcetype/resourceidentifier ".
4.5.3 Upotreba sistemskih resursa
Odnosi se na upotrebu resursa koje već koriste neke izvorne aplikacije.
Korištenje ovih podatkovnih resursa sli no je korištenju vlastitih resursa
s razlikom da im se pristupa u klasi android.R.
5. Povezivanje s poslužiteljem
Komunikacija pokretnog uređaja i udaljenog poslužitelja odvija se na
razini arhitekture klijent - poslužitelj (eng. Client - Server).
Postoje razli iti na ini kojima se može ostvariti komunikacija između
klijenta i poslužitelja. Izbor određene kombinacije protokola i na ina
povezivanja ovisi o vrsti usluge.
Razmatranje na ina povezivanja zapo et ć emo na transportnom sloju usporedbom
protokola UDP (eng. User Datagram Protocol) i TCP (eng. Transmission
Control Protocol). Transportni sloj rješava nedostatke IP (eng. Internet
Protocol) sloja. Sadrži rješenja za kontrolu pogrešaka i kontrolu toka.
Izbor protokola transportnog sloja određuje se ovisno o korisnikovim
zahtjevima. Transportni sloj omogućava više transportnih veza preko
jedne mrežne veze tzv. multipleksiranje. Takvu konekciju definiraju
dvije priključnice (eng. socket) koje se sastoje od tri parametara:
vrste protokola (UDP ili TCP), IP adrese i broja vrata (eng. port).
Nakon transportnog sloja promatrat ć emo povezivanje korištenjem protokola
aplikacijskog sloja, konkretno HTTP (eng. Hyper Transfer Protocol) konekciju
u sklopu čega ćemo obradit parsiranje jednostavnog XML dokumenta koji
se nalazi na udaljenom poslužitelju.
5.1 Protokol UDP
UDP je standardni Internetski protokol opisan u specifikaciji RFC 768.
To je jednostavni protokol koji osigurava beskonekcijski orijentiranu
uslugu s nepouzdanim prijenosom podataka, bez kontrole toka i kontrole
zagušenja. Paketi nisu numerirani, a zaštitna suma u zaglavlju nije
obavezna tako da se ne vrši provjera pogreške prilikom prijenosa. O
pouzdanosti prijenosa, ako je potrebno, brine sama aplikacija. Ukoliko
iz nekog razloga dođe do odbacivanja paketa, ne vrši se dojava o grešci.
UDP protokol zapravo služi kao omotač (eng. wrapper) između aplikacije
i IP protokola.
5.1.1 Aplikacija koja koristi UDP komunikaciju
U nastavku je prikazan primjer jednostavne UDP komunikacije Android
klijenta s udaljenim poslužiteljem. Aplikaciju čine dvije klase: klasa
aktivnosti UDPConnection i klasa koja predstavlja klijent. Klijent je
u mogućnosti poslati i primiti jedan UDP paket. Za potrebe testiranja
aplikacije UDP poslužitelj ostvaren je pomoću programa netcat na udaljenom
poslužitelju sintaksom nc -u -l -p 6666.
Kod 5.1: Klasa UDPExample (Main Activity)
package hr.fer.tel.android;
import android.app.Activity; import android.os.Bundle;
public class UDPExample extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.maiw);
// Start the Client Client c = new Client(); new Thread(c).start();
Klasa UDPExample obavlja inicijalizaciju UDP klijenta. Metoda onCreate()
u klasi UDPExample nadjačava metodu istog naziva iz klase Activity.
Ako se aktivnost ponovo inicijalizira u varijabli icicle nalazit ć e
se podaci prethodno spremljeni metodom onSavelnstanceState(Bundle).
Pozivom metode setContentView(R.layout.main) definira se prikaz na zaslonu.
Zatim se klijent inicijalizira i pokreće u novoj dretvi.
Kod 5.2: Klasa Client
package hr.fer.tel.android;
import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
import android.util.Log;
public class Client implements Runnable {
public static final String SERVERIP = "161.53.71.194"; // Remote host IP
public static final int SERVERPORT = 6666;
@Override
public void run() { try {
// Retrieve the ServerName InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.d("UDP", "C: Connecting...");
/* Create new UDP Socket */
DatagramSocket socket = new DatagramSocket(); // Sending packet
byte[] bufS = ("Hello from Client!\n").getBytes();
/* Create UDP packet */
DatagramPacket packets = new DatagramPacket(bufS,
bufS.length,
serverAddr, SERVERPORT); Log.d("UDP", "C: Sending: '" + new String(bufS) +
);
/* Sending out the packet */
socket.send(packetS);
Log.d("UDP", "C: Sent.");
// Receiving packet
byte[] bufR = new byte[10];
DatagramPacket packetR = new DatagramPacket(bufR,
bufR.length);
/* Receiving the packet */ socket.receive(packetR); Log.d("UDP", "C: Received: '" + new String(packetR.getData())
+ );
} catch (Exception e) {
Log.e("UDP", "C: Error", e);
}
}
J_______________________________________________________________________
Klasa Client implemetira sučelje Runnable što je nužno kako bi se mogla
odvijati u posebnoj dretvi. Komunikacija s UDP serverom obavlja se korištenjem
klasa DatagramSocket i DatagramPacket. Klasa InetAddress koristi
se za pohranu IP adrese servera. U ovom jednostavnom primjeru klijent
šalje znakovni niz "Hellofrom Client!\n", te prima 10 okteta
podataka i sprema ih u polje.
5.2 Protokol TCP
TCP je standardni konekcijski orijentirani Internetski protokol opisan
u osnovnoj specifikaciji RFC 793. Osigurava uspostavu konekcije i dvosmjerni
prijenos kontinuiranog niza podataka pakiranjem okteta podataka u segmente
koje prenosi protokol mrežnog sloja. Svakom oktetu dodjeljuje se slijedni
broj (eng. sequence number) č ime se osigurava retransmisija podataka
u slučaju gubitka ili pogrešnog prijenosa na principu potvrde prijama
ispravnog okteta na prijamnoj strani. Također, omogućava simultano korištenje
od strane više procesa definiranjem dodatne adresne informacije tzv.
broja vrata (eng. port number) koji jednoznačno određuje IP korisnika.
5.2.1 Aplikacija koja koristi TCP komunikaciju
U nastavku je prikazan kod jednostavne TCP komunikacije Android klijenta
s udaljenim poslužiteljem. Klijent šalje i prima po jedan paket podataka.
Za potrebe testiranja aplikacije TCP poslužitelj ostvaren je pomoću
programa netcat na udaljenom poslužitelju sintaksom nc -l -p 6666.
Kod 5.3: Klasa TCPConnection (Main Activity)
package hr.fer.tel.android;
import android.app.Activity; import android.os.Bundle;
public class TCPConnection extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.maiw);
Thread cThread = new Thread( new Client());
cThread.start();
}
Klasa TCPConnection ponaša se isto kao i klasa UDPExample.
Kod 5.4: Klasa Client
package hr.fer.tel.android;
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket;
import android.util.Log;
public class Client implements Runnable {
public static final String SERVERIP = "161.53.71.194"; public static final int SERVERPORT = 6666;
public static String STR;
public void run() {
try {
InetAddress serverAddr =
InetAddress.getByName(SERVERIP);
Log.d("TCP", "C: Connecting...");
Socket socket = new Socket(serverAddr, SERVERPORT); // Sending message
String message = "Hello from Client!";
Log.d("TCP", "C: Sending: '" + message + "'"); PrintWriter out = new PrintWriter( new BufferedWriter( new
OutputStreamWriter(socket.getOutputStream())), true);
out.println(message); Log.d("TCP", "C: Sent."); Log.d("TCP", "C: Done.");
// Getting message
Log.d("TCP", "C: Getting message.."); BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
String STR = in.readLine();
System.out.println("C: Received: '" + STR + "'");
} catch (Exception e) {
Log. e("TCP", "C: Error", e);
J_
Kod TCP komunikacije situacija je slična kao i kod UDP komunikacije
uz manje izmjene. Za komunikaciju se koristi klasa Socket, a podaci
se ne enkapsuliraju u datagrame nego se prenose kao struja podataka.
Metode za rad sa strujom podataka su PrintWriter(), BufferedWriter()
i OutputStreamWriter() koje služe za slanje, te BufferedReader() i InputStreamWriter()
za primanje znakovnog niza.
5.3 Korištenje protokola HTTP
WWW (eng. World Wide
Web) usluga u mreži je izvedena na modelu klijent-poslužitelj protokolom
HTTP. HTTP je standardni Internetski protokol aplikacijskog sloja koji
definira format i način razmjene poruka između klijenta i poslužitelja.
Poruke koje se prenose formirane su u obliku zahtjeva i odgovora. HTTP
asocijacija ostvaruje se preko TCP veze. Poslužitelj konstantno osluškuje
TCP zahtjeve na dobro poznatim vratima 80 (ukoliko nije drugačije definirano),
dok klijent pokreće TCP vezu sa slobodno odabranih vrata na lokalnom
računalu na IP adresu poslužitelja i TCP vrata 80. Nakon uspostave TCP
veze, dolazi do izmjene zahtjeva i odgovora.
5.3.1 Aplikacija koja koristi protokol HTTP
U narednim primjerima bit ć e prikazana izvedba uspostave HTTP veze
i načini obrade jednostavne XML datoteke s udaljenog poslužitelja.
5.3.1.1 HTTP konekcija
Kod 5.5: Metoda za ostvarenje HTTP veze
private InputStream openHttpConnection(String urlString)
throws IOException
{
InputStream in = null; int response = -1;
URL url = new URL(urlString); URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection))
throw new IOException("Not an HTTP connection");
try{
HttpURLConnection httpConn = (HttpURLConnection) conn; httpConn.setAllowUserInteraction( false); httpConn.setInstanceFollowRedirects( true); httpConn.setRequestMethod("GET"); httpConn.connect();
response = httpConn.getResponseCode(); if (response == HttpURLConnection.HTTP_OK) { in = httpConn.getInputStream();
}
}
catch (Exception ex) {
throw new IOException("Error connecting");
}
return in;
}____________________________________________________________________________
Metoda openHttpConnection(String urlString) otvara HTTP vezu prema
poslužitelju, te vraća sadržaj na adresi urlString kao struju podataka.
Klase URL i URLConnection obavljaju spajanje na zadani urlString. Korištenjem
instanceof operatora provjerava se da li je otvorena konekcija uistinu
HTTP. Spajanje na URL obavlja se korištenjem HTTP metode GET. Uspješnost
zahtjeva provjerava se pomoću koda odgovora (eng. response code). U
slučaju uspješnog zahtjeva kod odgovora mora imati vrijednost HttpURLConnection.HTTPOK,
tj.brojčanu vrijednost 200.
5.3.1.2 XML parser
XML je jezik č ija je glavna namjena olakšavanje pohrane i razmjene podataka. SAX (eng. Simple API for XML) i DOM (eng. Document Object Model) su u Javi dva najvažnija API-a za pristup XML dokumentima, također podržanih u Android SDK. SAX API temelji se na serijskom č itanju XML dokumenta. Upotrebom DOM API-a dokument se č ita odjednom i pohranjuje u memoriju u obliku stabla, gdje su čvorovi stabla komponente dokumenta.
DOM se najčešće upotrebljava kod aplikacija gdje se određenom dokumentu pristupa uzastopno i nesekvencijalno, dok se SAX koristi za sekvencijalno i jednoprolazno čitanje dokumenta.
U nastavku ćemo obraditi sljedeći primjer XML dokumenta:
Kod 5.6: XML primjer
<?xml version="1.0" encoding="UTF-8"?>
<popis> <tramvaj id="1"> <broj>14</broj>
<smjer>+</smjer> <n>454600</n> <e>155100</e>
</tramvaj>
</popis>_________________________________________________________________
DOM API
Parsiranje XML dokumenta DOM metodom ostvaruje se pomoću ugrađenih
klasa DocumentBuilder koja izvornu XML datoteku pretvara u objekt Document,
te DocumentBuilderFactory stvara instance klase DocumentBuilder. Nakon
učitavanja dokumenta u Document objekt moguće je izdvojiti i obraditi
željene elemente. Prilikom DOM parsiranja najprije se uspostavlja HTTP
veza i preuzima XML datoteka. U nastavku su prikazani važniji elementi
koda za parsiranje dokumenta.
Kod 5.7: Dio koda za parsiranje XML-a DOM metodom
(... )
doc.getDocumentElement().normalize(); // Retrieve all the <item>
nodes
NodeList itemNodes = doc.getElementsByTagName("tramvaj");
for (int i = 0; i < itemNodes.getLength(); {
Node itemNode = itemNodes.item(i);
if (itemNode.getNodeType() == Node.ELEMENT_NODE){ // Convert the Node
into an Element Element itemElement = (Element) itemNode;
String strNumber = getInnerText(itemElement,
"broj");
String strDirection = getInnerText(itemElement,
"smjer");
String strN = getInnerText(itemElement, "n"); String strE
= getInnerText(itemElement, "e");
Kod 5.8: Dio koda za parsiranje XML-a DOM metodom
private String getInnerText(Element itemElement, String tagName){
String result = "";
// Get all the <tagName> element under the <itemElement> NodeList numberNodes = itemElement.getElementsByTagName(tagName);
// Convert a Node into an Element
Element numberElement = (Element) numberNodes.item(0);
// Get all the child nodes under the <broj> element NodeList textNodes = ((Node) numberElement).getChildNodes();
// Retrieve the text of the <tagName> element result = ((Node) textNodes.item(0)).getNodeValue();
return result;
}____________________________________________________________________________
Kod parsiranja DOM metodom, osnovne klase koje koristimo su Node i
Element i predstavljaju reprezentacije čvorova u XML dokumentu. Osnovne
metode koje koristimo su getElementsByTagName() koja dohvaća listu čvorova
određene oznake (eng. tag), getNodeType() kojom provjeravamo tip čvora,
te item(index) kojom dohvaćamo podčvor s indeksom index.
Metoda getInnerText() je pomoćna metoda napisana za potrebe ovog specifičnog
primjera. Ta metoda za neki objekt tipa Element i oznaku tagName dohvaća
sadržaj prvog podčvora koji je oznake tagName.
SAX API
Parsiranje XML dokumenta SAX metodom ostvaruje se pomoću ugrađenih klasa SAXParser koja stvara omotač oko objekta SAX XMLReader, te klase SAXParserFactory stvara instance klase SAXParser.
Aplikacija je izvedena pomoću tri klase iz kojih će biti prikazani najvažniji dijelovi.
Kod 5.9: Dio koda za SAX parsiranje iz klase XMLParser
// Create a URL we want to load the tram info from URL
url = new URL("http://.../zeljeni.xml");
// Get a SAXParser from the SAXPArserFactory SAXParserFactory parserFactory
= SAXParserFactory.newI^stance();
SAXParser parser = parserFactory.newSAXParser();
// Get the XMLReader of the SAXParser we created XMLReader reader =
parser.getXMLReader();
// Create a new ContentHandler and apply it to the XML-
Reader
TramXmlParser tramParser = new TramXmlParser(); reader.setContentHandler(tramParser);
// Parse the xml-data from our URL reader.parse( new InputSource(url.openStream()));
// Get the parsed data from the Tram XML Parser TramDataSet tramDataSet
= tramParser.getParsedData();
Kod 5.10: Kod za SAX parsiranje iz klase TramXmlParser
public class TramXmlParser extends DefaultHandler {
/** the fields representing the XML tags for each tram, used in parsing */
private boolean number = false;
private boolean direction = false;
private boolean n = false;
private boolean e = false;
/** the object in which the data from the XML will be stored */ private TramDataSet tramDataSet = new TramDataSet();
public TramDataSet getParsedData() { return this.tramDataSet;
}
@Override
public void startDocument() throws SAXException { this.tramDataSet = new TramDataSet();
}
@Override
public void endDocument() throws SAXException {
}
/** Gets called on opening tags like:
- <tag>
- Can provide attribute(s), when xml has attributes, like:
* <tag attribute="attributeValue">*/ @Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { if (localName.equals("tramvaj")) {
// Extract an Attribute
String attrValue = atts.getValue("id"); tramDataSet.setId(Integer. parseInt(attrValue)); } else if (localName.equals("smjer")) {
this.direction = true; } else if (localName.equals("broj")) {
this.number = true; } else if (localName.equals("n")) {
this.n = true; } else if (localName.equals("e")) { this.e = true;
}
/** Gets called on closing tags like:
* </tag> */
@Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException { if (localName.equals("smjer")) {
this.direction = false; } else if (localName.equals("broj")) { this.number = false;
} else if (localName.equals("n")) {
this.n = false;
} else if (localName.equals("e")) {
this.e = false;
}
}
/** Gets called on the following structure:
* <tag>characters</tag> */
@Override
public void characters( char ch[], int start, int length) { if ( this .number) {
tramDataSet.setNumber(Integer. parseInt( new String(ch,
length)); length)); length));
} |
start, length)) );
}
if ( this.direction) {
}
if ( this.n) {
tramDataSet.setLatitude( new String(ch, start,
}
if ( this.e) {
tramDataSet.setLongitude( new String(ch, start,
} |
tramDataSet.setDirection( new String(ch, start,
Kod 5.11: Kod za SAX parsiranje iz klase TramDataSet
public
class TramDataSet { /** the number of the tram */ private int number;
/** the direction of the tram, can be '+' or '-' */ private String direction = null;
/** geographic latitude (N), parallels */ private String latitude = null;
/** geographic longitude (E), meridians */ private String longitude = null;
/** the ID of the specific tram since there can be multiple trams with the same tram number */ private int id = 0;
public int getNumber() { return number;
}
public void setNumber(int number) { this.number = number;
}
(... )
Number of get/set methods.
public String toString() {
return "Tramvaj broj = " + this.number + "\nSmjer = "
+ this.direction + "\nN: " + this.latitude +
"\nE: " + this.longitude
+ "\nID = " + this.id;
}
}________________________________________
Kod SAX parsiranja osnovne 2 klase su TramXmlParser koja obavlja parsiranje
XML dokumenta te TramDataSet u koju se spremaju parsirani podaci. TramXmlParser
sadrži metode koje predstavljaju radnje koje parser mora obaviti kada
naiđe na ključne dijelove XML dokumenta kao recimo otvaranje oznake
i zatvaranje oznake.
5.3.1.3 Ostali formati zapisa strukturiranih podataka
Od ostalih formata zapisa strukturiranih podataka spomenut ćemo još
JSON (eng. JavaScript Object Notation) i CSV (eng. Comma separated values).
JSON je vrlo jednostavan jezik za razmjenu podataka ekstenzije .json.
Koristi se prilikom programiranja Ajax (eng. Asynchronous JavaScript +
XML) web-aplikacija kao alternativa XML-u.
CSV je zapis koji se najčešće koristi kod tabličnih struktura zapisa.
Podaci su međusobno odvojeni zarezom. Svaka linija CVS zapisa odgovara
jednom retku tablice.
5.4 Protokol HTTPS
Protokol HTTPS (eng. Hyper Text Transfer Protocol Secure) kombinacija
je protokola HTTP i kriptografskih protokola SSL (eng. Secure Socket Layer)
ili TLS (eng. Transport Layer Security). Sintaksa protokola HTTPS identična
je protokolu HTTP s time da je inicijalna postavka dobro znanih vrata
443 (umjesto 80). Koristi se kao sigurna verzija
protokola HTTP.
Kod komunikacije s poslužiteljem protokolom HTTPs neće biti detaljno prikazan
zbog velike sličnosti s protokolom HTTP.
5.5 Ostali načini komunikacije s poslužiteljem
Osim spomenutih protokola UDP, TCP, HTTP i HTTPS, klijent i poslužitelj
mogu komunicirati preko FTP (eng. File Transfer Protocol), protokola Telnet,
protokola SSH (eng. Secure Shell) i drugih protokola za koje postoji već
ostvarena aplikacijska programska podrška za Android, te ih nećemo detaljnije
obrađivati.
Zaključak
U sklopu seminarskog rada napravljen je pregled cjelokupne arhitekture sustava Android, osvrt na paket softverskih razvojnih alata (Android SDK), objašnjen je koncept aplikacije, te realizirana praktična izvedba različitih načina povezivanja s poslužiteljem. Govoreći o arhitekturi sustava posebna pažnja posvećena je slojevima sustava i njihovim elementima, te virtualnom stroju Dalvik koji je istaknut kao novitet u arhitekturi sustava za male uređaje. U sklopu poglavlja o paketu softverskih razvojnih alata dan je detaljan opis najvažnijih komponenti i njihovih funkcija. Obrađeni su emulator pokretnog uređaja, DDMS i ADB. Na razini aplikacije opisani su njezina osnovna struktura, životni ciklus, način razvoja i princip prikaza elemenata korisničkog sučelja, datoteka AndroidManifest.xml, te podatkovni resursi i njihova upotreba. Na kraju su realizirani praktični primjeri povezivanja Android klijenta s udaljenim poslužiteljem upotrebom
protokola UDP, TCP i HTTP. Korištenjem protokola HTTP obrađeno je DOM i SAX
parsiranje jednostavnog XML dokumenta. Za realizaciju praktičnog dijela zadatka korišteni su Eclipse IDE, Android SDK, Android ADT i udaljeni Linux poslužitelj. Aplikacije su testirane na emulatoru.
S obzirom na činjenicu da je Android tek kratko vrijeme zastupljen u svijetu pokretnih uređaja iza sebe ima izrazito bogatu bazu stručne literature i podrške na Internetu. Zahvaljujući otvorenosti programskog koda razvojnim programerima omogućen je uvid u već postojeće aplikacije i primjerke koda. Na Internetu je moguće pronaći primjerke različitih vrsta aplikacija ili dijelova koda. Razvojnim programerima u korist ide i bogata baza biblioteka i alata za izradu aplikacija.
Također, Android SDK vrlo dobro funkcionira s Eclipse IDE. Zamjerke su siromašan skup grafičkih sučelja za emulator, te nepravilno funkcioniranje emulatora ukoliko se pokreće automatski pozivom iz Eclipsea. To znači da je za ispravan rad emulator u pravilu trebalo pokrenuti prije pokretanja Eclipsea, jer u suprotnom dolazi do neispravnog rada aplikacije na emulatoru.
U sklopu diplomskog zadatka bit ć e potrebno realizirati uslugu praćenja
tramvajskog prometa korisniku u pokretu na operacijskom sustavu Android.
Za ostvarenje istog koristit ć e se postojeći simulator tramvajskog prometa.
Ovisno o implementaciji simulatora trebat će razmotriti najbolji način
spajanja na poslužitelj i dohvat podataka s njega. Vrlo vjerojatno će
se raditi o kombinaciji protokola HTTP i dohvata podataka u nekom od spomenutih
zapisa.
Osnovna vizija klijentske aplikacije za pokretni uređaj je izvedba korisničkog
sučelja s vizualnim prikazom položaja svih ili ž eljenih tramvaja na karti
na temelju podataka dobivenih od udaljenog poslužitelja.
Literatura
[1] E. Burnette, Hello, Android, 2008. [2] N. Gramlich, andbook!
http://andbook.anddev.org/
[3] Mike, Androidology Part 1 of 3 - ArchitectureOverview
http://www.youtube.com/watch?v=Mm6Ju0xhUW8, 2007.
[4] R. Meier, Professional Android Application Development, 2009.
[5] D. Bornstein, Dalvik Virtual Machine Internals.
http://www.youtube.com/watch?v=ptjedOZEXPM, 2008.
[6] Android deveopers, Tools Overview.
http://developer.android.com/guide/developing/tools/index.html, 2009.
[7] Android developers, The AndroidManifest.xml File.
http://developer.android.com/guide/topics/manifest/manifest-intro.html,
2009.
Besplatni
Seminarski Radovi
|