Upload
others
View
4
Download
1
Embed Size (px)
Citation preview
SVEUČILIŠTE U ZAGREBU
FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA
DIPLOMSKI RAD br. 3239
Prisutnost korisnika na operacijskom
sustavu Android
Marta Tinodi
Zagreb, travanj 2010.
Sadržaj:
UVOD __________________________________________________________________________________ 1
1 PROTOKOL SIP ______________________________________________________________________ 2
1.1 MREŽNI ENTITETI SIP-A ________________________________________________________________ 2
1.1.1 Korisnički agenti______________________________________________________________ 3
1.1.2 Posrednički poslužitelji ________________________________________________________ 3
1.1.3 Poslužitelj za preusmjeravanje __________________________________________________ 3
1.1.4 Registrar ____________________________________________________________________ 4
1.1.5 SIP poruke __________________________________________________________________ 4
1.2 PRISUTNOST KORISNIKA ________________________________________________________________ 6
1.2.1 Korisnički agent prisutnosti _____________________________________________________ 8
1.2.2 Agent prisutnosti _____________________________________________________________ 8
1.2.3 Poslužitelj prisutnosti __________________________________________________________ 8
1.2.4 Opis komunikacije ____________________________________________________________ 9
1.2.5 Model za prisutnost i trenutno poručivanje _______________________________________ 11
1.2.6 PIDF - Format za slanje informacija o prisutnosti ___________________________________ 14
2 OPERACIJSKI SUSTAV ANDROID _______________________________________________________ 16
2.1 OSNOVNE ZNAČAJKE _________________________________________________________________ 16
2.2 STRUKTURA APLIKACIJE U ANDROIDU ______________________________________________________ 17
2.2.1 Activity ____________________________________________________________________ 18
2.2.2 Service ____________________________________________________________________ 21
2.2.3 Broadcast receiver ___________________________________________________________ 24
2.2.4 Content provider ____________________________________________________________ 25
2.2.5 Datoteka manifest ___________________________________________________________ 25
2.2.6 Aktivacijska komponenta – Intent ______________________________________________ 25
3 IDEJNO RJEŠENJE DIPLOMSKOG RADA _________________________________________________ 27
4 IMPLEMENTACIJA POSLUŽITELJSKE STRANE – PROJEKT PRESENCESERVER ____________________ 28
4.1 OPIS OSNOVNIH METODA _____________________________________________________________ 28
4.2 OPIS KOMUNIKACIJE _________________________________________________________________ 31
5 IMPLEMENTACIJA KORISNIČKE STRANE – PROJEKT ANDROIDSIPCHAT _______________________ 36
5.1 KNJIŽNICA MJSIP ___________________________________________________________________ 36
5.1.1 Agent za registraciju _________________________________________________________ 38
5.1.2 Agent za slanje i primanje poruka_______________________________________________ 39
5.1.3 Agent prisutnosti ____________________________________________________________ 40
5.2 ŽIVOTNI CIKLUS APLIKACIJE _____________________________________________________________ 42
5.2.1 Početni ekran i Glavni izbornik _________________________________________________ 43
5.2.2 Registracija korisnika_________________________________________________________ 45
5.2.3 Popis kontakta i prisutnost ____________________________________________________ 49
5.2.4 Chat prozor ________________________________________________________________ 51
6 INSTALACIJA I POKRETANJE APLIKACIJE ________________________________________________ 56
ZAKLJUČAK _____________________________________________________________________________ 63
LITERATURA ____________________________________________________________________________ 64
POPIS SKRAĆENICA ______________________________________________________________________ 65
1
Uvod
Razvojem mobilnih komunikacija, tj. mobilnih ureĎaja i mobilnog pristupa
Internetu, dolazi do povećanog razvoja aplikacija i usluga za mobilne ureĎaje koje
su do sada bile namijenjene računalima. MeĎu te usluge spada i trenutno
poručivanje (eng. instant messaging - IM) kao jedan od popularnijih načina
komunikacije putem Interneta.
Trenutno poručivanje je oblik komunikacije izmeĎu dva ili više korisnika putem
Interneta, razmjenom kratkih tekstualnih poruka u realnom vremenu (eng. real-
time). Postoje dvije vrste trenutnog poručivanja: sobe za razgovor na web-
stranicama ili programi za trenutno poručivanje koje je potrebno instalirati na
računalo (npr. Skype, ICQ, G Talk, ICQ, MSN, itd). (Chat, 2010)
Ti programi osim što omogućavaju komunikaciju razmjenom poruka pruţaju i neke
druge mogućnosti kao što su: pohranjena lista kontakata s kojima je moguće
komunicirati, prikaz prisutnosti pojedinog kontakta, promjena vlastite prisutnosti,
glasovni i video pozivi, višemedijska konferencije, razmjena datoteka, i slično.
Zadatak ovog diplomskog rada je proučiti način kako se kreiraju i distribuiraju
informacije o prisutnosti korisnika te ispitati mogućnosti korištenja prisutnosti na
operacijskom sustavu Andorid, uz pomoć protokola SIP.
U radu je tako dan opis protokola SIP kao osnovnog protokola za uspostavu veze
izmeĎu klijenata te je napravljen pregled osnovnih značajki operacijskog sustava
Android. Sam prikaz razvoja korisničke aplikacije koja koristi prisutnost se nalazi u
sklopu prikaza razvoja aplikacije za trenutno poručivanje. Uz korisničku aplikaciju
potrebno je bilo izraditi i posluţiteljsku stranu komunikacije što je takoĎer opisano
u ovom diplomskom radu.
2
1 Protokol SIP
SIP je kratica za Session Initiation Protocol. To je kontrolni (signalni) protokol
aplikacijskog sloja koji se bavi uspostavom i prekidom veze (sjednice) izmeĎu
klijenata. Razvijen je unutar IETF-a, a specifikacija je dana u nekoliko RFC-ova,
zadnja je RFC 3261. (Rosenberg, 2002)
Zahvaljući SIP-u moguće je uspostaviti i upravljati različitim višemedijskim
komunikacijskim sjednicama izmeĎu dva ili više korisnika i to u obliku: trenutnog
poručivanja (eng. instant messaging), glasovnih ili video poziva preko protokola IP
(eng. voice over IP, video over IP), višemedijske konferencije, razmjene podataka
(eng. streaming mulitimedia distribution), informacije o prisutnosti korisnika (eng.
presence information) i igrice putem Interneta.
SIP sam po sebi nije zamišljen da bude sveobuhvatan stoga su za komunikaciju
meĎu ureĎajima potrebni i drugi protokoli. Njegova je namjena da omogući
komunikaciju koja se nakon toga odvija na različite načine i pomoću nekog drugog
protokola. Uz SIP se najčešće koriste protokoli RTP (Real-time Transport Protocol
- protokol za prijenos višemedijskih podataka u realnom vremenu) i SDP (Session
Description Protocol - protokol koji pregovara o krarakteristikama sjednice i kodira
ih, na primjer: pregovaranje o kodecima, tako da svi sudionici mogu dekodirati
sadrţaj paketa).
Sam SIP je baziran na internetskom protokolu HTTP (HyperText Transfer
Protocol), a HTTP se takoĎer moţe klasificirati kao signalni protokol jer ga klijenti
koriste da bi posluţitelju rekli koji ih dokumenti zanimaju. SIP se tako koristi za
prenošenje opisa parametara sjednice, opis se kodira u dokument pomoću SDP
protokola. [Stipica, 2006]
1.1 Mreţni entiteti SIP-a
Mreţni entiteti SIP-a identificiraju se pomoću SIP URI-a (SIP Uniform Resource
Identifier). SIP URI je oblika: sip:username@domain (na primjer: sip:[email protected])
i sastoji se od dva dijela: korisničkog imena i imena domene koji su odvojeni
znakom @.
3
1.1.1 Korisnički agenti
Korisnički agenti (eng. User Agents - UA) su krajnje točke koje koriste SIP za
meĎusobno lociranje i pregovaranje o karakteristikama sjednice. Obično se nalaze
na korisničkom računalu u obliku aplikacije, no korisnički agenti mogu biti i mobilni
telefoni, PSTN mreţni prilazi (eng. gateway), PDA ureĎaji itd.
Korisničke agente često nazivamo: posluţitelj korisničkog agenta (eng. User Agent
Server - UAS) i klijent korisničkog agenta (eng. User Agent Client - UAC).
UAS i UAC su samo logičke jedinice, svaki korisnički agent, ovisno o situaciji, ima
ulogu UAC-a ili UAS-a. UAC je tako dio korisničkog agenta koji ima zadatak slanja
zahtjeva (eng. request) i primanja odgovora (eng. response) dok UAS ima zadatak
primanja zahtjeva (eng. request) i slanja odgovora (eng. response).
1.1.2 Posrednički posluţitelji
SIP takoĎer omogućava izgradnju infrastrukture s mreţnim računalima koji se
zovu posrednički posluţitelji (eng proxy server) kojima korisnički agenti (UA) mogu
slati poruke (eng. messages).
Najvaţniji zadatak posredničkog posluţitelja je usmjeravanje poruka za uspostavu
sjednice. Zahtjev za uspostavom sjednice obično prelazi nekoliko posredničkih
posluţitelja dok ne pronaĎe onoga koji zna stvarnu lokaciju pozivanog. Taj će
posrednički posluţitelj izravno proslijediti zahtjev za sjednicom prema pozivanom
koji će prihvatiti ili odbiti zahtjev.
Postoje dvije osnovne vrste SIP-ovih posredničkih posluţitelja - bez stanja
transakcije (eng. stateless) i sa stanjem transakcije (eng. stateful). [Stipica, 2006]
1.1.3 Posluţitelj za preusmjeravanje
Posluţitelj za preusmjeravanje zaprima zahtjev, te pretraţuje lokacijsku bazu
podataka koju kreira registrar, kako bi pronašao primatelja kojem je zahtjev
namijenjen. Zatim kreira popis trenutnih lokacija korisnika i šalje ih pošiljatelju
zahtjeva kao odgovor unutar 3xx grupe. Pošiljatelj zahtjeva zatim povlači popis
odredišta i direktno njima šalje novi zahtjev.
4
1.1.4 Registrar
Registrar je poseban SIP-ov entitet koji zaprima registracije od korisnika, dobavlja
informacije o njihovoj trenutnoj lokaciji (IP adresa, vrata i korisničko ime) te
sprema informacije u lokacijsku bazu podataka.
Zadatak lokacijske baze podataka je preslikati URI sip:[email protected] u nešto
poput sip:[email protected]:5060. Tako da kada posrednički posluţitelj
zaprimi poziv za sip:[email protected] pretraţuje lokacijsku bazu podataka i
pronalazi sip:[email protected]:5060 te poziv za uspostavu sjednice šalje
tamo.
Svaka registracija ima ograničeno vremensko trajanje, a to je odreĎeno poljem
Expires u zaglavlju ili parametarom prestanka valjanosti polja Contact u
zaglavlju. Korisnik mora obnoviti registraciju unutar odreĎenog roka ili će ona
isteći, a korisnik će postat nedostupan.
Registracija se vrši porukom REGISTER koja sadrţi AoR (Address of Record)
sip:[email protected] i kontakt adresu sip:[email protected]:5060, gdje je
192.168.1.2 IP adresa telefona. Te se informacije šalju registraru, a on ih šalje u
lokacijsku bazu podataka. (Stipica, 2006)
1.1.5 SIP poruke
Komunikacija pomoću protokla SIP ili signalizacija se sastoji od niza poruka (eng.
messages). Uobičajeno je da se svaka poruka prenosi u posebnom UDP (User
Datagram Protocol) datagramu.
Svaka se poruka sastoji od početnog retka (eng. line), zaglavlja poruke i tijela
poruke. Početni redak označava vrstu poruke, postoje dvije vrste poruka: zahtjev
(eng. request) i odgovor (eng. response). Zahtjevi se obično koriste za iniciranje
neke akcije ili za obavještavanje primatelja zahtjeva o nečemu. Odgovori se
koriste za potvrdu da je zahtjev primljen i obraĎen te sadrţe rezlutat obrade.
Primjer SIP poruke:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:6060
From: <sip:[email protected]> ;tag=z9hG4bK13730296
To: sip:[email protected]
5
Call-Id: [email protected]
CSeq: 1 INVITE
Subject: Neki naslov
Content-Type: application/sdp Content-Length:...
U prvom retku se pojavljuje zahtjev INVITE koji predstavlja poziv za uspostavom
veze. U polju From se nalazi SIP URI korisnika koji je pokrenuo zahtjev za
komunikacijom, a polje To sadrţi SIP URI korisnika s kojim se ţeli komunicirati.
Polje Call-Id identificira poruke koje pripadaju istoj komunikaciji, polje CSeq
osigurava pravilan redoslijed izvršavanja zahtjeva. Polje Subject sadrţi naslov ili
temu komunikacije, a Content-Type opisuje njenu vrstu.
SIP zahtjevi mogu biti (SIP requests, 2008):
o INVITE - uspostavljanje sjednice izmeĎu korisničkih agenata,
o ACK - potvrĎuje primitak završnog odgovora na INVITE poruku,
o BYE - prekid sjednice izmeĎu dva korisnika,
o CANCEL - otkazivanje sjednice koja još nije u potpunosti ustanovljena,
o REGISTER - omogućuje registraru da bude upoznat s trenutnom lokacijom
korisnika (prenosi trenutnu IP adresu i vrata na koji se korisnik moţe dobiti).
o SUBSCRIBE - pretplata na neki dogaĎaj ili obavijest.
o NOTIFY - slanje obavijesti on nekom dogaĎaju onome tko se na njega
pretplatio.
o PUBLISH - objava dogaĎaja na posluţitelja.
o MESSAGE - prijenos kratke tekstualne poruke.
Kad korisnički agent ili posrednički posluţitelj zaprimi zahtjev na njega moraju i
odgovoriti. Izuzetak su zahtjevi ACK na koje ne treba odgovarati. Kôd odgovora je
cijeli broj od 100 do 699 i ukazuje na vrstu odgovora.
6
SIP odgovori su grupirani u sljedećih 6 grupa:
o 1xx – zahtjev je zaprimljen i obraĎuje se (npr. 100 Trying),
o 2xx – uspješno primljen i obraţen zahtjev (npr. 200 OK ),
o 3xx – zatjev je potrebno preusmjeriti kao bi se izvršio do kraja,
o 4xx – Client Error - zahtjev se ne moţe obraditi jer sadrţi krivu sintaksu ili se
ne moţe izvršiti na tom posluţitelju,
o 5xx – Server Error - zahtjev je naizgled valjan, ali ga posluţitelj nije uspio
izvršiti i
o 6xx – globalna greška - zahtjev se ne moţe izvršiti ni na jednom posluţitelju.
(Rosenberg, 2002)
1.2 Prisutnost korisnika
Prisutnost (eng. Presence, Presence Information) je informacija koja je indikator
sposobnosti i ţelje korisnika za komunikacijom s drugim korisnicima. Podrţana je
protokolom SIP, a njen je opis dan unutar RFC-a 3856 (Rosenberg J., 2008).
Usluga prisutnosti korisniku pruţa informacije o dohvatljivosti i dostupnosti drugog
korisnika te njegovoj sposobnosti i volji za komunikacijom. Ona prenosi informacije
o tome da li je korisnik priključen ili ne, te ako je priključen da li je moţda zauzet ili
odsutan ili nešto treće. Uz to moguće je prenositi i dodatne informacije koje
detaljnije opisuju s kakvim komunikacijskim sredstvima i kapacitetima korisnik
raspolaţe, na primjer: da li je moguće ostvariti tekstualnu komunikaciju ili glasovni
i/ili video poziv i sl. (Camarillo, 2004)
Prisutnost je jedna od osnovih usluga koju na protokol SIP pruţa i za očekivat je
da će s vremenom koristiti unutar raznih usluga a danas ju najčešće susrećemo
kao sastavni dio komunikacijskih usluga s trenutnim poručivanjem. Primjer
informacija o prisutnosti su različite promjene statusa kod IM programa kao što su
Skype ili MSN pomoću kojih vidimo da li je korisnik priključen ili ne (eng.
online/offline) te dodatne statuse kao što su: “zaposlen”, “nedostupan”, “odsutan”,
itd.
7
Ti IM programi su zapravo korisnički agenti koji informaciju o prisutnosti šalju
posluţitelju koji ju potom dostavlja drugim korisnicima koji su zainteresirani za tu
informaciju, tj. koji su se na nju pretplatili.
U RFC 2778 (Day, 2000), koji definira model i terminologiju za opis prisutnosti,
opisan je i sustav koji pruţa informacije o prisutnosti. U tom modelu usluga
prisutnosti (eng. Presence Service) predstavlja taj sustav koji prima, pohranjuje i
distribuira informacije zainteresiranim stranama, tj. klijentima koji se nazivaju
promatrači (eng. watchers). U stvarnom ţivotu, to su korisnici koji u svom IM
programu imaju listu korisnika čiji se statusi mijenjaju ovisno o njihovoj aktivnosti.
Protokol prisutnosti (eng. Presence Protocol) omogućava uslugu prisutnosti preko
Interneta ili bilo koje IP mreţe.
Na slici (Slika 1.2.1) je prikazan tipičan scenarij slanja informacija o prisutnosti
izmeĎu tri korisnika od kojih jedan posjeduje više komunikacijskih ureĎaja.
1.2.1Arhitektura SIP prisutnosti (Camillo, 2004)
Osoba koja šalje informacije o vlastitoj prisutnosti naziva se presence entity,
skraćeno presentity a u ovom slučaju je to Alice. Ona ima mogućnost birati koje
informacije ţeli slati i to je predstavljeno setom atributa koji detaljno opisuju njenu
prisutnost (status, kapacitete, kontakt adresu, i sl.). Te informacije je moguće
postaviti za jedan ili više komunikacijskih ureĎaja. U ovom slučaju Alice raspolaţe
s tri ureĎaja: telefon, laptop i stolno računalo. Unutar sustava koji pruţa inforamcije
o prisutnosti ti se ureĎaji nazivaju korisnički agenti prisutnosti (eng. PUA -
Presence User Agent).
8
Svi PUA ureĎaji prosljeĎuju svoje informacije o prisutnosti prvom agentu
prisutnosti (eng. PA – Presence Agent) koji prima i pohranjuje pojedine informacije
i tako stvara cijelovitu informaciju o prisutnosti pojedinog korisnika, u ovom slučaj
Alice.
Na slici su prikazana i dva promatrača: Bob i Chris. Oni šalju zahtjeve kojima traţe
informacije o prisutnosti ţeljenog presentity-a i informacije o promatračima koji njih
promatraju te šalju .
1.2.1 Korisnički agent prisutnosti
Korisnički agent prisutnosti (eng. PUA - Presence User Agent) upravlja
informacijama o prisutnosti za odgovarajuću promjenu statusa. To se moţe
aktivirati kao poslijedica neke druge aktivnosti (npr. nakon zahtjeva REGISTER
prilikom dodavanja novog kontakta) ili moţe biti izravno aktivirano. Izravnim
aktiviranjem je omogućeno postavljanje višestrukih PUA i različitih statusa. To
znači da korisnik moţe imati više ureĎaja (npr. telefon, laptop i računalo – kao što
je i prikazano na slici (Slika 1.2.1)) i svaki od njih moţe neovisno generirati
informacije o prisutnosti. PUA postavljaju podatke na sustav prisutnosti dok su oni
sami izvan tog sustava, što znači da oni ne obraĎuju poruke SUBSCRIBE i
NOTIFY. To je zadatak agenta prisutnosti. (Rosenberg, 2008)
1.2.2 Agent prisutnosti
Agent prisutnosti (eng. PA – Presence Agent) je SIP-ov korisnički agent koji ima
mogućnost primanja zahtjeva za pretplatu (eng. SUBSCRIBE), odgovaranja na
njih te generiranja obavijesti u slučaju promjene statusa. On stoga mora
raspolagati informacijama o prisutnosti za svaku promjenu statusa. (Rosenberg,
2008)
1.2.3 Posluţitelj prisutnosti
Posluţitelj pristutnosti (eng. Presence Server- PS) je mreţni entitet koji se moţe
ponašati kao PA i tada sam raspolagati informacijama o prisutnosti za pojedine
promjene statusa ili se moţe ponašati kao posrednički prosluţitelj za zahtjeve
SUBSCRIBE. U tom se slučaju je njegova zadaća prosljediti te poruke sljedećem
entitetu koji se ponaša kao PA. (Rosenberg, 2008)
9
1.2.4 Opis komunikacije
Kada neki korisnik (eng. subscriber) ţeli doznati informacije o prisutnosti nekog
drugog korisnika on kreira zahtjev SUBSCRIBE i na taj način inicira pretplatu na
tog korisnika. Unutar dijela Request-URI dijela se daje identificikacija ţeljenog
presentitya i takav se zahtjev proslijeĎuje preko posredničkih posluţitelja dok ne
doĎe do entiteta koji raspolaţe s traţenim inforamcijama, dakle do PA. PA
primljeni zahtjev za pretplatom provjeri i ako je on ispravan odobri ga, tj pošalje
odgovor 200 OK ili pošalje odgovor 202 što znači da se ona još obraĎuje. U oba
slučaja PA odmah šalje poruku NOTIFY koja sadrţi informacije o stanju statusa te
pretplate. Moguće je da informacija o statusu bude i kriva, tj da pokazuje da je
korisnik nedostupan, i to je zato što se štiti privatnost korisnika koji moţda ne ţeli
da davati svoje informacije o prisutnosti. Čim se promjeni informacija o status
korisnika PA generira novu poruku NOTIFY koja sadrţi infromaciju čiji se status
promjenio i šalje ju svim korsnicima kojima je odobrena pretplata na tu nju.
Na slici (Slika 1.2.2) je prikazano kako Presence Server sudjeluje u razmjeni
inforamacija o prisutnosti. On od PUA prima informacije o promjenama statusa i
kreira odgovarajuće poruke NOTIFY.
Slika 1.2.2 Tijek obrade poruka (Rosenberg, 2008)
Opis i sadrţaj pojedinih poruka:
F1 SUBSCRIBE watcher->example.com server
SUBSCRIBE sip:[email protected] SIP/2.0
Via: SIP/2.0/TCP watcherhost.example.com;branch=z9hG4bKnashds7
To: <sip:[email protected]>
From: <sip:[email protected]>;tag=xfg9
Call-ID: [email protected]
10
CSeq: 17766 SUBSCRIBE
Max-Forwards: 70
Event: presence
Accept: application/pidf+xml
Contact: <sip:[email protected]>
Expires: 600
Content-Length: 0
F2 200 OK example.com server->watcher
SIP/2.0 200 OK
Via: SIP/2.0/TCP watcherhost.example.com;branch=z9hG4bKnashds7
;received=192.0.2.1
To: <sip:[email protected]>;tag=ffd2
From: <sip:[email protected]>;tag=xfg9
Call-ID: [email protected]
CSeq: 17766 SUBSCRIBE
Expires: 600
Contact: sip:server.example.com
Content-Length: 0
F3 NOTIFY example.com server-> watcher
NOTIFY sip:[email protected] SIP/2.0
Via: SIP/2.0/TCP server.example.com;branch=z9hG4bKna998sk
From: <sip:[email protected]>;tag=ffd2
To: <sip:[email protected]>;tag=xfg9
Call-ID: [email protected]
Event: presence
Subscription-State: active;expires=599
Max-Forwards: 70
CSeq: 8775 NOTIFY
Contact: sip:server.example.com
Content-Type: application/pidf+xml
Content-Length: ...
[PIDF Document]
F4 200 OK watcher-> example.com server
SIP/2.0 200 OK
Via: SIP/2.0/TCP server.example.com;branch=z9hG4bKna998sk
;received=192.0.2.2
From: <sip:[email protected]>;tag=ffd2
To: <sip:[email protected]>;tag=xfg9
Call-ID: [email protected]
CSeq: 8775 NOTIFY
Content-Length: 0
F5 NOTIFY example.com server -> watcher
NOTIFY sip:[email protected] SIP/2.0
Via: SIP/2.0/TCP server.example.com;branch=z9hG4bKna998sl
From: <sip:[email protected]>;tag=ffd2
To: <sip:[email protected]>;tag=xfg9
Call-ID: [email protected]
CSeq: 8776 NOTIFY
Event: presence
Subscription-State: active;expires=543
11
Max-Forwards: 70
Contact: sip:server.example.com
Content-Type: application/pidf+xml
Content-Length: ...
[New PIDF Document]
F6 200 OK
SIP/2.0 200 OK
Via: SIP/2.0/TCP server.example.com;branch=z9hG4bKna998sl
;received=192.0.2.2
From: <sip:[email protected]>;tag=ffd2
To: <sip:[email protected]>;tag=xfg9
Call-ID: [email protected]
CSeq: 8776 NOTIFY
Content-Length: 0
1.2.5 Model za prisutnost i trenutno poručivanje
Usluga prisutnosti korisnika najviše se primjenjuje u sklopu programa za trenutno
poručivanje. To omogućuje korisnicima da se pretplate da druge korisnike s kojima
ţele komunicirati razmjenom kratkih poruka.
Takav način komunikacije opisan je u RFC 2778 (Day, 2000). U ovom modelu su
povezane dvije usluge: usluga prisutnosti (eng. presence service) i usluga
trenutnog poručivanja (eng. message service). Usluga prisutnosti obuhvaća
primanje, spremanje i distribuiranje informacija o prisutnosti, dok usluga
poručivanja obuhvaća primanje i dostavljanje trenutnih poruka (eng. instant
messages) u poštanske pretince (eng. instant inboxes).
Usluga prisutnosti
Usluga prisutnosti (eng. Presence Service) upravlja dvjema vrstama klijenata:
Presentities i Watchers. (Slika 1.2.3) Presentities su oni klijenti koji šalju
informacije o prisutnosti i te informacije posluţitelj mora primiti i pohraniti. Druga
vrsta klijent su Watchers i oni su ti koji traţe infromaciju o prisutnosti.
12
Slika 1.2.3 Prikaz Presence Servera (Day, 2000)
TakoĎer, postoje i dvije vrste klijenata Watcher. Fetcher je onaj koji traţi trenutno
stanje prisutnosti i odgovarajuće informacije, dok Subscriber očekuje obavijesti
(eng. notifications) o novim promjenama informacija o prisutnosti. (Slika 1.2.4)
Slika 1.2.4 Slanja obavijesti Watcher klijetima (Day, 2000)
Usluga trenutnog poručivanja
Usluga trenutnog poručivanja (eng. Instant Message Service) takoĎer ima dvije
vrste klijenata: Senders i Instant Inboxes. Sender je onaj koji daje poruke Message
Serviceu kako bi ih potom on predao odgovarajućem Instant Inboxu. (Slika 1.2.5)
13
Slika 1.2.5 Prikaz Mesage Servica (Day, 2000)
Principals
Principals su stvarni korisnici, tj. ljudi, grupe ili aplikacije u “stvarnom svijetu” koji
se nalaze izvan spomenutih sustava ali koriste njihove usluge, a sa sustavom
komuniciraju prekon nekog od korisničikih agenata (Inbox User Agent, Sender
User Agent, Presence User Agent, Watcher User Agent).
Na slikama (Slika 1.2.6) i (Slika 1.2.7) je prikazan taj način komunikacije.
1.2.6 Kominikacija Principal – Presence Service (Day, 2000)
1.2.7 Kominikacija Principal – Message Service (Day, 2000)
14
1.2.6 PIDF - Format za slanje informacija o prisutnosti
Format predviĎen za slanje informacije o prisutnosti je PIDF format (eng.
Presence Information Data Format), a njegova specifikacija je dana unutar RFC
3863 (Sugano, 2004).
Za opis PIDF objekta odabran je jezik XML (Extensible Mark-up Language) jer je
njime najlakše opisati hijerarhijsku strukturu koju informacije o prisutnosti zahtjeva
i moguće ga je transportirati poput bilo kojeg drugog MIME dokumenta
(Multipurpose Internet Mail Extension). PIDF dokument tako definira novi MIME
media type: application/pidf+xml koji predstavlja tip aplikacije i kodiranje.
U trenu kad se korisnikovo stanje promjeni tada klijent zaduţen za kreiranje i
slanje informacija o prisutnosti kreira PIDF objekt koje se dalje proslijeĎuje do
klijenta Watcher koji će znati taj objekt pročitati.
Informacija koja se prenosi PIDF dokumentom se sastoji od skupa elemenata koji
se nazivaju tuple. Svaki tuple sadrţi korisnikov status (open ili closed, ovisno da li
je on online ili offline) i neke dodatne neobvezne elemente kao što su:contact
element s korisnikovim URI, note element, timestamp, itd. (Camarillo, 2004)
Osnovni PIDF elementi:
o element <presence/> – korijenski element unutar kojeg se nalaze
elementi <tuple/> i <note/> a mora sadrţavati xmlns deklaraciju i
entitiy atribut. Vrijednost entity atributa je pres URL onoga tko
objavljuje tu promjenu statusa;
o element <tuple/> – sluţi za lakše segmentiranje informacije o prisutnosti.
Mora sadrţavati “id” atribut kako bi se se ovaj tuple moglao razlikovati od
ostalih tupleova istog presence-a, tj istih promjena statusa;
o element <status/> – sadrţi jedan ili više <basic/> elementa unutar
kojih će se opisuje korisnikov status;
o element <basic/> – On sadrţi indikaciju sposobnosti primanja poruke i
moţe vrijednost open ili closed. Open znači da je Instant Inbox spreman
za primanje poruka, dok closed znači da Instant Inbox nije u mogućnosti
primati poruke;
15
o element <contact/> – sadrţi URL kontakta;
o element <note/> – sadrţi string s “čovjeku razumljivim” sadrţajem (eng.
human readable);
o element <timestamp/> – string koji sadrţi datum i vrijeme promjene
statusa. (Sugano, 2004)
Primjer jednostavog PIDF objekta za presentitiya identificiranog kao
pres:[email protected] :
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns: "urn:ietf:params:xml:ns:pidf"
entity="pres:[email protected]">
<tuple id="sg89ae">
<status>
< basic>open</impp:basic>
</status>
<contact priority="0.8">tel:+09012345678</contact>
</tuple>
</presence>
U gornjem primjeru vidimo da PIDF zampravo daje minimalistički opis prisutnosti i
tako da je status kao open ili close. Za dodatne, detaljnije opise prisutnosti korisiti
se prošireni PIDF format RPID (eng. Rich Presence Information Data Format)
16
2 Operacijski sustav Android
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 (eng. application programming interface, skraćeno API) koja razvojnim
inţenjerima omogućuju samostalan razvoj i rad na aplikacijama. (Čarapina, 2009)
Predstavljanje Androida i njegove razvojne okoline za pisanje aplikacija (eng.
software development kit, skraćeno SDK) započelo je u studenom 2007. godine
od strane tvrtke Google i grupacije Open Handset Alliance (skraćeno OHA).
2.1 Osnovne značajke
Arhitektura sustava Android bazira se na Linuxovoj jezgri (eng. kernel) koja se
koristi kao sloj apstrakcije hardvera (eng. Hardware Abstraction Layer, skraćeno
HAL). 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.
Paket softverskih razvojnih alata Android SDK pruţa podršku za razvoj, testiranje,
pronalaţenje i uklanjanje pogrešaka (eng. debugging) aplikacija. Uključuje
sljedeće komponente: Androidove API-je, razvojne alate za prevoĎenje i
debagiranje (npr. programski dodatak (eng. plugin) za Eclipse IDE je ADT),
emulator koji sluţi za izvršavanje programa na računalu, DDMS (eng. Dalvik
Debug Monitoring Service) koji sluţi za kontrolu i nadzor pronalaţenja i uklanjanja
pogrešaka u aplikacijama, AAPT (eng. Android Asset Packaging Tool) alat za
stvaranje i distribuciju Androidovog programskog paketa u .apk formatu, ADB
(eng. Android Debug Bridge) koji predstavlja klijentsko-posluţiteljsku aplikaciju za
instaliranje i pokretanje datoteka .apk na emulatoru ili ureĎaju.
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
17
Eclipse, emulator se automatski poziva prilikom izvoĎenja i procesa pronalaţenja i
uklanjanja programskih pogrešaka.
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 i takve se distribuiraju na pokretni ureĎaj.
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, opis komponenti, 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, popis instrumentacijskih klasa koje
osiguravaju oblikovanje i ostale informacije dok je aplikacija aktivna. (Čarapina,
2009)
2.2 Struktura aplikacije u Androidu
Vaţna značajka Androidove aplikacije je da moţe koristiti elemente druge
aplikacije (ako se definiraju dozvole od strane prve aplikacije). Time se smanjuje
potreba za pisanjem istih dijelova u različitim aplikacijama, jer je moguće pokrenuti
samo dio aplikacije koji jepotreban drugoj. Android to omogućava na način da ne
postoji samo jedna točka ulaska za svaku komponentu aplikacije, ne postoji
metoda main(), već je svaka aplikacija napravljena od osnovnih komponenti
koje sustav moţe instancirati i pokrenuti po potrebi.
Postoje četiri vrste takvih komponenti, to su:
o Activity,
o Service,
o BroadcastReceiver i
o ContentProvider.
18
2.2.1 Activity
Activity predstavlja grafičko korisničko sučelje, ekran kojeg korisnik u tom trenutku
vidi. To moţe biti, primjerice, lista s koje korisnik nešto treba odabrati, prikaz slika
u albumu ili ekran u kojem se namještaju postavke neke aplikacije. Aplikacija za
pisanje tekstualnih poruka mogla bi imati jedan activity u kojem se piše poruka,
drugi u kojem se prikazuju kontakti iz imenika i treći za pregled poslanih poruka.
Svaki od njih je nezavisan dio aplikacije iako rade zajedno i dio su iste aplikacije.
Svaki od njih je podklasa osnovne klase Activity. Koliko će aplikacija imati
activityja ili bilo kojih drugih osnovnih komponenti i kako će one suraĎivati, stvar je
dizajna i namjene aplikacije. Obično aplikacija ima početni activity koji se prikazuje
korisniku kada pokrene aplikaciju. Prelazak s jednog na drugi izvodi se tako da
trenutni activity pokrene onaj koji je potreban. Pri izradi activityja svakom je
dodijeljen njegov vlastiti prozor, koji je inicijalno postavljen da pokrije cijeli ekran,
no to se, naravno, moţe promijeniti. Svaki activity moţe koristiti dodatne elemente
prikaza kao što su primjerice pop-up prozori koji zahtijevaju korisnikovu interakciju
ili prozor u koje se prikaţu detaljnije informacije o elementu koji je korisnik trenutno
odabrao. Vizualni sadrţaj prozora ima hijerarhijski organiziran sadrţaj elemenata
prikaza koji su svi izvedeni iz osnovne klase View. Svaki element pripada
odreĎenom prostoru pravokutnog oblika unutar prozora. Pojam hijerarhijski odnosi
se na elemente prikaza, pa tako element prikaza roditelj organizira i sadrţi izgled i
raspored elemenata prikaza djece. Postoji skup gotovih elemenata prikaza
sadrţanih u Androidu kao što su gumbi, polja za unos teksta, izbornici, check-
boxovi i drugi. Hijerarhija tih elemenata organizira se metodom
Activity.setContentView(). (Android Developers, 2010)
Ţivotni ciklus activityja
Postoje tri stanja u kojima se activity moţe naći:
o aktivno stanje ili stanje izvoĎenja – kada je prikazan na ekranu (to je stanje
kada korisnik koristi njegove mogućnosti);
o pauzirano stanje – još uvijek je vidljiv korisniku, no trenutno ga ne koristi. To
je slučaj kada je drugi activity „iznad“ njega, koji je transparentan ili ne
19
pokriva cijeli ekran. U slučaju da operacijski sustav ima premalo slobodne
memorije taj activity se moţe i ugasiti;
o zaustavljeno stanje – drugi activity ga je potpuno prekrio. Još uvijek su
sačuvane sve informacije o stanju. Ovakvi activityji se često gase kada
sustavu treba memorije.
Prelazak iz jednog stanja u drugo dogaĎa se pozivom jedne od ovih metoda:
o void onCreate()
o void onStart()
o void onRestart()
o void onResume()
o void onPause()
o void onStop()
o void onDestroy()
Sve prethodno navedene metode mogu se nadjačati (eng. override) te se tako
moţe definirati što treba učiniti kada se promijeni stanje. Jedina nuţna metoda je
onCreate() jer se u njoj definiraju početne postavke.
Ţivotni ciklus activitya prikazan je na slici (Slika 2.2.1):
20
Slika 2.2.1 Dijagram stanja activityja (Android Developers, 2010)
Na dijagramu moţemo vidjeti tri vaţna puta:
o cijeli ţivotni ciklus activityja – odvija se izmeĎu prvog poziva onCreate()
metode do prvog poziva onDestroy() metode. Obuhvaćeno je sve od
definiranja početnih postavki na početku do oslobaĎanja zauzetih resursa.
o vidljivi ciklus activityja – odvija se izmeĎu metoda onStart() i onStop().
Korisnik vidi activity na ekranu, što obuhvaća slučajeve kada je korisnik s
njime u interakciji i kada je activity vidljiv iako trenutno nije aktivan.
21
o aktivni ciklus activityja – odvija se izmeĎu poziva metoda onResume() i
onPause(). U tom je slučaju korisnik u neposrednoj interakciji s
activityjem.
Activity se dakle stvara metodom onCreate(), a pokreće metodom onStart().
Tada activity radi, tj. u aktivnom je stanju. Metodom onPause() prelazi u
pauzirano stanje iz kojega se u aktivno moţe vratiti pozivom metode
onResume(). Da bi se vratio u prvi plan iz stanja kada se ne vidi na ekranu, mora
se pozvati metoda onRestart(). Gasi se metodom onDestroy().
Operacijski sustav se brine za pohranu stanja activityja ako ga treba ugasiti kako
bi oslobodio memoriju. Da bi to bilo moguće, treba implementirati metodu
onSaveInstanceState(), koju Android poziva kada postoji mogućnost da će
activity biti ugašen, dakle prije poziva onPause() metode. Stvara se Bundle
objekt u koji se pohranjuje trenutno stanje activityja u obliku parova ime-vrijednost.
Kada se taj activtiy ponovo pokrene Bundle objekt se predaje metodama
onCreate() i onRestoreInstanceState() (koja se izvršava nakon
onStart() metode) kako bi se moglo vratiti stanje u kojem je activity bio prije
nego je srušen.
2.2.2 Service
Komponenta service nema grafičko sučelje nego radi u pozadini. Njen ţivotni
ciklus nije ograničen trenutnim prikazom sučelja na ekranu kao kod activityja, ona
radi u neodreĎenom vremenskom razdoblju. Koristi se za zadatke koji se mogu
izvoditi u pozadini, kao na primjer sviranje glazbe u pozadini dok korisnik radi
nešto drugo. Moţe se koristiti za dohvat podataka preko mreţe ili za izračun nekih
podataka koje moţe isporučiti activityju koji ih treba.
Svaki service je podklasa osnovne klase Service. Dobar primjer je media player
aplikacija, koja reproducira pjesme poredane u listu. Aplikacija bi imala nekoliko
activityja u kojima bi se mogle praviti liste, pokretati reprodukcija i mijenjati
postavke, no samu reprodukciju ne bi bilo pametno izvesti unutar activityja jer se
pretpostavlja da ih korisnik često mijenja, a od takve aplikacije se očekuje da se
glazba moţe nastaviti reproducirati i kada korisnik promijeni activity ili pokrene
neku drugu aplikaciju. To se moţe izvesti tako da activity aplikacije pokrene
22
service koji se izvodi u pozadini. Kada korisnik napusti activity u kojemu je
pokrenuo reprodukciju, ona se nastavlja i dalje jer service još uvijek radi. Moguće
je povezati se s već pokrenutim serviceom. Za vrijeme te veze moţe se s njime
komunicirati putem sučelja koje pruţa. U tom sučelju bi se, primjerice, moglo
omogućiti da korisnik pauzira, zaustavi ili započne reprodukciju ispočetka. Kao i
activity i ostale komponente, i service se izvodi u glavnoj niti procesa aplikacije.
Kako u ovakvim slučajevima ne bi blokirali druge komponente korisničkog sučelja,
mogu stvoriti novu nit za radnje za koje se zna da zahtijevaju više vremena.
(Android Developers, 2010)
Service će biti ključna komponenta u izradi ovo diplomskog zadatka. Unutar nje će
biti potrebno implementirati funkcionalonost protokola SIP, točnije: registraciju
korisnika, pretplatu na prisutnost kontakta, slanje vlastite pristunosti te slanje i
primanje poruka.
Service se moţe koristiti na dva načina:
o Moţe se pokrenuti i pustiti da radi dok ju netko ne zaustavi ili dok se sama
ne zaustavi. U tome slučaju moguće ju je pozvati metodom
Context.startService() a zaustaviti pozivom metode
Context.stopService(). Sama će se zaustaviti pozivom metode
Service.stopSelf() ili Service.stopSelfResult(). Za
zaustavljanje servicea je dovoljno samo jednom pozvati metodu
stopService(), bez obzira koliko je puta bila pozvana metoda
startService().
o Moţe biti upravljana programski koristeći sučelje. Korisnik tada uspostavlja
vezu sa Service objektom i koristeći tu vezu moţe upravljati sa serviceom.
Ona se uspostavlja pozivom metode Context.bindService(), a gasi se
pozivom metode Context.unbindService(). Na istu service je
moguće spojiti više korisnika.
Kao i activitya, service ima svoj ţivotni ciklus i metode koje omogućuju prijelaz iz
jednog stanja u drugo te praćenje promjena pojedinih stanja. To su slijedeće
metode:
23
o void onCreate(),
o void onStart(Intent intent) i
o void onDestroy()
Kombinacijom navedenih metoda service prolazi kroz dva ţivotna ciklusa:
o cijeli ţivotni ciklus – odvija od trenutka kad je pozvana metoda
onCreate() do trenutka kad je pozvana metoda onDestroy()
o aktivni ţivotni ciklus – počinje od trenutka kad se pozove metoda
onStart(), koja je preko metode startService dobila odgovarajući Intent
objekt.
Kod servica, za razliku od activitya, ne postoje posebne metode koje se pozivaju
kad se service ugasi – ne postoji metoda onStop().
Metode onCreate() i onDestroy() se pozivaju uvijek i za sve service bez
obzira da li su oni pokrenuti metodom Context.startService()ili
Context.bindService(), dok se metoda onStart() poziva jedino za service
pokrenute metodom startService().
Service moţe dozvoliti drugima da se veţu na nju (eng. bind) i tada je potrebno
implementirati dodatne metode:
o IBinder onBind(Intent intent),
o boolean onUnbind(Intent intent) i
o void onRebind(Intent intent)
Metoda onBind() preuzima Intent objekt koji joj je predan metodom
bindService() a metoda onUnbind() prezima objekt od metode
unbingService(). Ako service dozvoljava vezanje,metoda onBind() vraća
komunikacijski kanal kojeg klijenti mogu korisiti kao bi ostvarili komunikaciju s
njom. Metoda onUnbind() moţe pozvati metodu onRebind() u trenutku kada
se novi korisnik poveţe s serviceom.
Na slici (Slika 2.2.2) su prikazana oba ţivotna ciklusa servica, jedan kreiran
pomoću startService() a drugi pomoću bindService(). Iako su ova dva
ciklusa prikazana odvojeno moguće moguće je svakoj service, bez obzira kojom je
metodom ona kreirana, dozvoliti povezivanje s drugim klijenitima.
24
2.2.2 Dijagram stanja servica (Android Developers, 2010)
2.2.3 Broadcast receiver
Zadatak komponenti ovog tipa je da primaju obavijesti o višeodredišnom
razašiljanju (eng. broadcast) i reagiraju na njih. U radu aplikacija i sustava
pojavljuje se mnogo takvih obavijesti, npr. obavijest da ponestaje napona u
bateriji, da se promijenila vremenska zona, da su, aplikacijama koje ih trebaju,
dostupni podaci prikupljeni s Interneta. Aplikacija moţe imati bilo koji broj
broadcast receivera koji mogu odgovarati na sve informacije koje se smatraju
vaţnima. Osnovna klasa svakog od njih je BroadcastReceiver. Ove
komponente takoĎer nemaju grafičko sučelje, ali mogu pokrenuti odreĎeni activity
kao odgovor na informaciju koju su dobili ili umjesto toga mogu koristiti upravitelja
obavijesti. Takve obavijesti mogu se prikazati na različite načine – kao treperenje
pozadinskog svjetla, vibracija pokretnog urenaja, reprodukcija odreĎenog zvuka.
Na traci stanja pojavi se ikona koju korisnik moţe odabrati kako bi pročitao
obavijest (eng. notification). (Android Developers, 2010)
U ovom diplomskom zadatku će uz pomoć broadcast receivera biti prikazano kao
prikazati obavijest o primljenoj poruci ili o promjeni prisutnosti kontakta.
25
2.2.4 Content provider
Ova komponenta se koristi za isporuku skupa podataka aplikacije drugim
aplikacijama. Ti podaci mogu se pohraniti u datotečni sustav kao datoteka ili u
obliku SQLite baze podataka. Osnovna klasa je ContentProvider koja sadrţi
standardni skup metoda koje omogućuju aplikacijama preuzimanje ili pohranu
tipova podataka s kojima rade. Aplikacije ne pozivaju te metode izravno, nego
pomoću objekta ContentResolver. Taj objekt moţe komunicirati sa svakim content
providerom na način da on upravlja komunikacijom. Operacijski sustav se brine o
tome je li proces pokrenut ili ga treba pokrenuti svaki puta kada se pojavi zahtjev
koji treba obraditi aplikacija koja trenutno nije aktivna. TakoĎer, ako ne postoje
instance koje su potrebne, a dio su aplikacije koja treba obraditi zahtjev, Android ih
sam stvara. (Android Developers, 2010)
2.2.5 Datoteka manifest
Da bi se komponenta aplikacije mogla pokrenuti, Android mora znati da ta
komponenta postoji. To je izvedeno na način da aplikacija deklarira svoje
komponente u manifest datoteci koja je povezana s paketom Android aplikacije
.apk. Ta datoteka je strukturirana XML datoteka i uvijek se zove
AndroidManifest.xml, za sve aplikacije. U njoj je definirano još mnogo drugih
stvari kao što su imena biblioteka s kojima aplikacija treba biti povezana i dozvole
koje se dodjeljuju aplikaciji. Android ne vidi komponente koje nisu deklarirane u
manifest datoteci te se one stoga ne mogu izvoditi.
2.2.6 Aktivacijska komponenta – Intent
Asinkrona poruka kojom se aktivira pojedina komponenta naziva se intent. To je
objekt klase Intent u kojemu je sadrţaj poruke. Za activity i service ta poruka,
izmeĎu ostalog, sadrţi ime radnje koja se zahtijeva i URI (Uniform Resource
Identifier) datoteke nad kojom ta radnja treba biti obavljena, dok za broadcast
receiver sadrţi ime radnje koja je objavljena (npr. moţe obavijestiti strane koje ga
osluškuju da je pritisnut gumb za pokretanje kamere). Za aktivaciju svake od
komponenti postoje različite metode. Activity se pokreće tako da se intent objekt
pošalje metoda Context.startActivity() ili
26
Activity.startActivityForResult(). Česta je situacija da jedan activity
pokreće drugi. Ako očekuje neki rezultat od activityja kojeg poziva, koristi drugu
navedenu metodu. Rezultat se takoĎer vraća kao intent objekt. Activity koji reagira
na intent, moţe provjeriti koji intent ga je pokrenuo metodom getIntent().
Service se pokreće metodom Context.startService(). Metodom
Context.bindService() moţe se uspostaviti veza izmenu pozivajuće
komponente i servicea. Višeodredišno razašiljanje pokreće se tako da se intent
objekt pošalje metodi Context.sendBroadcast(),
Context.sendOrderedBroadcast() ili
Context.sendStickyBroadcast(). Intent objekt moţe eksplicitno navesti ime
ciljane komponente – u tom slučaju Android pronalazi tu komponentu na temelju
deklaracija u datoteci manifest i aktivira je. U slučaju da ciljana komponenta nije
imenovana, Android pronalazi najbolju komponentu koja odgovara tom intentu. To
čini tako da intent objekt usporenuje s intent filtrom potencijalnih ciljnih
komponenti. Filtri obavještavaju operacijski sustav o tome koje vrste intenta mogu
obraditi, što je zapisano u manifest datoteci. Komponenta moţe imati neograničen
broj intent filtara. Ako nema nijedan, moguće ju je aktivirati jedino intentom koji
eksplicitno imenuje tu komponentu kao ciljnu.
27
3 Idejno rješenje diplomskog rada
Zadatak diplomskog rada bio je proučiti prisutnost uz pomoć protokola SIP i ispitati
mogućnosti njenog korištenja na operacijskom sustavu Android. To obuhvaća
izradu posluţiteljske i korisničke strane sustava koji bi pruţio navedenu uslugu, a
usluga prisutnosti je na korisničkoj strani izvedena u sklopu programa za trenutno
poručivanje kao njegov sastavni dio.
Za izvršenje ovog rada potrebno je bilo izvršiti slijedeće zadatke:
o Kreirati posluţitelja koji će primati i slati SIP zahtjeve i poruke te tako
korisniku omogućiti: prijavu preko korisničkog imena i SIP URI-a,
povezivanje s drugim korisnicima, slanje i primanje kratkih poruka, pretplatu
na tuĎe informacije o prisutnosti te slanje vlastitih informacija o prisutnosti.
o Preko spomenutog posluţitelja povezati dva SIP-telefona (u ovom slučaju
dva X-lite telefona) te tako provjeriti ispravnost posluţitelja te proučiti tijek
komunikacije izmeĎu ta dva korisnika.
o Izraditi korisničku aplikaciju na operacijskom sustavu Android koja će se
ponašati kao aplikacija trenutnog poručivanja s informacijama o prisutnosti.
o Unutar aplikacije implementirati protokol SIP uz pomoć knjiţnice MJsip te
tako omogućiti punu funkcionalnost aplikacije: registracija korisnika na
posluţitelja, slanje i primanje prouka te slanje i primanje informacija o
prisutnosti.
28
4 Implementacija posluţiteljske strane – projekt
PresenceServer
Posluţiteljska strana realizirana je unutar Netbeans projekta PresenceServer, a
temelji se na Salifin posluţitelju kojeg je moguće preuzeti sa stranice:
http://sailfin.dev.java.net.
4.1 Opis osnovnih metoda
Projekt sadrţi šest klasa unutar paketa hr.fer.tel.sip kako je prikazano na slici
(Slika 4.1.1).
Slika 4.1.1 Klase PresenceServera
Osnovna klasa je klasa MainSipServlet i ona sadrţi metode koje se pozivaju
ovisno o tijeku komunikacije.
U trenutku kada se korisnik ţeli registrirati on prema posluţitelju šalje zahtjev
REQUEST i tada se poziva metoda doRegister() koja je definirana unutar
osnovne klase:
@Override
protected void doRegister(SipServletRequest req) throws
ServletException, IOException {
registrar.doRegister(req);
if(sf == null) {
Logger.getLogger(MainSipServlet.class.getName())
.log(Level.SEVERE, "SipFactory Value is null", sf);
}
}
29
Ona zatim poziva metodu doRegister iz klase Registar kojom će se izvršiti
registracija korisnika.
protected void doRegister(SipServletRequest request)
throws ServletException, IOException {
/**
* Process the registration request : find/create the Person
* object corresponding to the incoming request.
*/
processRegistration(request);
/**
* Send 200 OK for the REGISTER request.
*/
SipServletResponse resp =
request.createResponse(SipServletResponse.SC_OK);
resp.send();
}
Pošto se zahtjev REQUEST šalje i u slučaju registracije i deregistracije metoda
poziva se prvo metoda processRegistration() koja će prvo provjeriti o kojem
se slučaju registracije radi. Ako se zahtjeva registracija provjerit će da li je taj
korisnik već bio registriran, ako nije registrirat će ga i dodat na svoj popisa
korisnika, a ako je već bio registriran obnovit će njegove podatke.
Korisnik, nakon što se registrirao na posluţitelju, ima mogućnost pretplate na
prisutnost svog kontakta. Ona se pokreće slanjem zahtjeva REQUEST i tada se
poziva metoda doSubscribe() koja je definirana u glavnoj klasi.
@Override
protected void doSubscribe(SipServletRequest request) throws
ServletException, IOException {
String friendID = ((SipURI) request.getRequestURI()).getUser();
/** Add FRIEND to the Person's friend's list. Also, store the
* SipSession of this request, so that we can send the NOTIFY
* using this SipSession.*/
Person person = Registrar.findPerson(request);
if (person != null && !person.getId().equals(friendID)) {
person.addFriendID(friendID);
person.setSubscriptionSession(friendID,
request.getSession());
}
/** Send 200 OK. */
SipServletResponse resp =
request.createResponse(SipServletResponse.SC_OK);
resp.send();
/** SUBSCRIBE for the presence information of this user.*/
subscribeForPresenceEvents(request);
/** If the friend is currently online, send his presence
30
*information to this person.*/
if (person != null && person.getStatus()==Person.Status.ONLINE){
sendPresenceInformation(PersonDB.findPersonById(friendID),
person);
}
}
Unutar ove metode se prvo pohrane podaci o kontaktu na kojeg se korisnik ţeli
pretplatiti, a zatim se pohranjuju podaci o SIP sjednici kao bi se kasnije mogli slati
odgovarajući NOTIFY zahtjevi. Nakon toga je moguće nastaviti s pretplatom na tog
kontakta i to pozivom metode subscribeForPresenceEvents(), a ako je taj
kontakt prisutan slanje njegovih informacija o prisutnosti prema korisniku inicira se
pozivom metode sendPresenceEvents().
Nakon uspješne registracije i izvršenih pretplata korisnici imaju mogućnost
mjenjati svoje statuse i o tome obavijestiti one kontakte koji su se na njih pretplatili.
Prilikom svake promjene statusa šalje se zahtjev NOTIFY, a on tada inicira poziv
metode doNotify(). Metoda doNotify() je opisana u glavnoj klasi
MainSipServlet.
@Override
protected void doNotify(SipServletRequest request) throws
ServletException, IOException {
try {
/** Retrieve the presence information from request and store
* it in Person object. */
Person person = storePresenceInformation(request);
/** Send 200 OK. */
SipServletResponse resp =
request.createResponse(SipServletResponse.SC_OK);
resp.send();
/** Notify the presence information to all friends
* who are currently online. */
sendPresenceInformationToAllFriends(person);
} catch (Exception e) {
e.printStackTrace();
throw new ServletException(e);
}
}
Ona je zaduţena za primanje i pohranu informacija o prisutnosti i to je prvo što se
izvrši. Nakon toga ima zadaću slanja te informacije svima koji su se na nju
pretplatili i to se inicira pozivom metode
sendPresenceInformationToAllFriends().
31
4.2 Opis komunikacije
Komunikacija prikazana na slici (Slika 4.2.1)
Slika 4.2.1 Komunikacija dva telefona Xlite telefona
počinje tako da prvi korisnik ostvari vezu s posluţiteljem i to na način da odabere
svoje korisničko ime te IP adresu računala na kojem se nalazi posluţitelj. Adresa
posluţitelja je 192.168.1.9, a prvi korisnik neka bude Alice. Da bi se komunikacija
ostvarila korisnik se prvo mora registrirati, to se postiţe slanjem zahjeva
REGISTER kojeg Alice šalje prema posluţitelju PresenceServer.
Primjer REGISTER zahtjeva kojeg je Alice poslala posluţitelju:
REGISTER sip:192.168.1.9 SIP/2.0
Content-Length: 0
From: "alice"<sip:[email protected]>;tag=942a3f2b
Max-Forwards: 70
User-Agent: X-Lite release 1104o stamp 56125
Expires: 3600
Cseq: 1 REGISTER
Contact: <sip:[email protected]:13654;rinstance=83bbd4fd9521d4d0>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE,
SUBSCRIBE, INFO
To: "alice"<sip:[email protected]>
Call-Id: MDBjNzhiYzkyY2Y5YThiZTA1NjMwM2VhNjBlMDZiNGM.
Via: SIP/2.0/UDP 127.0.0.1:13654;branch=z9hG4bK-d8754z-d47bdf5b29127910-
1---d8754z-;rport=13654;received=192.168.1.9
From polje prenosi informaciju koja sadrţi ime korisnika koji se ţeli (alice)
pretplatiti te SIP adresu na koju se ţeli prijaviti (sip:[email protected]). U
Contact polju se nalaze detalji o Alice, tj. SIP adresa na kojoj se Alice nalazi.
Kako su u ovom slučaju Alice i posluţitelj na istom računalu Alicina je adresa tako
32
sip:[email protected], dok će Bobova adresa sadrţavati IP drugog računala
što ćemo vidjeti u slijedećoj poruci.
Primjer zahtjeva REGISTER zahtjeva kojeg je Bob šalje posluţitelju:
REGISTER sip:192.168.1.9 SIP/2.0
Content-Length: 0
From: "bob"<sip:[email protected]>;tag=eb06790d
Max-Forwards: 70
User-Agent: X-Lite release 1104o stamp 56125
Expires: 3600
Cseq: 1 REGISTER
Contact: <sip:[email protected]:31930;rinstance=23f0826357fab658>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE,
SUBSCRIBE, INFO
To: "bob"<sip:[email protected]>
Call-Id: ZDFiZWZlNzE1MDE0ZDdkODg4NjU0ODVhZTkzYWIzMzM.
Via: SIP/2.0/UDP 192.168.1.8:31930;branch=z9hG4bK-d8754z-
0e274756f83ad00c-1---d8754z-;rport=31930;received=192.168.1.8
Ovdje takoĎer u From polju dobivamo ime (bob) i SIP adresu
(sip:[email protected]) na koje se korisnik ţeli registrirati, a u Contact polju
vidimo SIP adresu gdje se Bob zapravo nalazi, i to je adresa:
sip:[email protected].
Ako je registracija uspješno izvršena korisnik je pohranjen u bazu podataka, a
posluţitelj mu šalje poruku 200 OK i time mu je omogućena komunikacija.
Slijedeći korak komunikacije moţe biti aktiviranje usluge prisutnosti. Ona se inicira
tako što jedan od korisnika, recimo Alice, u svoju listu kontakata doda novog
člana, tj. Boba. Tada Alice zapravo prema posluţitelju pošalje zahtjev SUBSCRIBE
i time od posluţitelja zatraţi da joj pošalje NOTIFY za svaku Bobovu promjenu
statusa.
Ovako izgleda primjer SUBSCRIBE zahtjeva kojeg je Alice poslala posluţitelju:
SUBSCRIBE sip:[email protected] SIP/2.0
From: "alice"<sip:[email protected]>;tag=cf20d40f
User-Agent: X-Lite release 1104o stamp 56125
To: "bob"<sip:[email protected]>
33
Via: SIP/2.0/UDP 127.0.0.1:51948;branch=z9hG4bK-d8754z-5b14c074ca308523-
1---d8754z-;rport=51948;received=192.168.1.9
Accept: multipart/related, application/rlmi+xml, application/pidf+xml
Content-Length: 0
Max-Forwards: 70
Expires: 3600
Cseq: 1 SUBSCRIBE
Contact: <sip:[email protected]:51948>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE,
SUBSCRIBE, INFO
Subject:
Event: presence
Call-Id: MTg0OTRhNjQ4MjA1MDNlNWI0NmE3YzZlNTI1MmE1ZTE.
Na samom početku zahtjeva SUBSCRIBE prenosi se Bobova SIP adresa na kojoj
je on registriran (sip:[email protected]). Polje From kaţe tko se ţeli pretplatiti
na Bobov status, u ovom slučaju je to Alice. Ovdje sad vidimo i novo polje Event
unutar kojeg je dan opis dogaĎaja na koji se Alice ţeli pretplatiti i to je presence.
Sličan je sadrţaj i zahtjeva SUBCRIBE kojeg šalje Bob kad se ţeli pretplatiti na
Alice:
SUBSCRIBE sip:[email protected] SIP/2.0
From: "bob"<sip:[email protected]>;tag=fa4d9765
User-Agent: X-Lite release 1104o stamp 56125
To: "alice"<sip:[email protected]>
Via: SIP/2.0/UDP 192.168.1.8:7166;branch=z9hG4bK-d8754z-df3ccc54d862614b-
1---d8754z-;rport=7166;received=192.168.1.8
Accept: multipart/related, application/rlmi+xml, application/pidf+xml
Content-Length: 0
Max-Forwards: 70
Expires: 3600
Cseq: 1 SUBSCRIBE
Contact: <sip:[email protected]:7166>
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE,
SUBSCRIBE, INFO
Subject:
Event: presence
Call-Id: ZmMxMWEyNjIwODZmNjcyZTM1YzQ5NDhlY2Y3MzNiYWY
Sada kad su oba korisnika prijavljena imaju mogućnost razmjene informacija o
statusu. Te se informacije razmijenjuju zahtjevima NOTIFY i ovo je primjer kao one
izgledaju trenutak nakon što Bob promjeni svoj status u “idle”:
34
NOTIFY sip:192.168.1.9:5060;transport=TCP;fid=server_1 SIP/2.0
Content-Length: 480
From: <sip:[email protected]:50970;transport=TCP>;tag=b83a3d3c
Max-Forwards: 69
User-Agent: X-Lite release 1104o stamp 56125
Cseq: 3 NOTIFY
Contact: <sip:[email protected]:50970;transport=TCP>
Event: presence
To: <sip:[email protected]>;tag=g7v8my23-s
Content-Type: application/pidf+xml
Subscription-State: active;expires=3592
Call-Id: 192.168.1.9_9_6457866684076875503
Via: SIP/2.0/TCP 192.168.1.8:50899;branch=z9hG4bK-d8754z-
3243ee6a5f791117-1---d8754z-;rport=50970;received=192.168.1.8
<?xml version='1.0' encoding='UTF-8'?><presence
xmlns='urn:ietf:params:xml:ns:pidf'
xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model'
xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid'
xmlns:c='urn:ietf:params:xml:ns:pidf:cipid'
entity='sip:[email protected]'><tuple
id='tb9676d02'><status><basic>open</basic></status><rpid:user-
input>idle</rpid:user-input></tuple><dm:person
id='peb32f031'><rpid:activities><rpid:unknown/></rpid:activities><dm:note
>Idle</dm:note></dm:person></presence>
NOTIFY sip:[email protected]:4850;transport=TCP SIP/2.0
Content-Length: 480
Max-Forwards: 70
From: "bob"<sip:[email protected]>;tag=g7v8jiq0-i
Cseq: 5 NOTIFY
Contact: <sip:192.168.1.9:5060;fid=server_1;transport=TCP>
Event: presence
To: "alice"<sip:[email protected]>;tag=a141580f
Content-Type: application/pidf+xml
Subscription-State: active;expires=3592
Call-Id: OGIzMzVkZWE1ZDRjZTQxNDNhNjNkMDgwYmZhMjk5YTg.
<?xml version='1.0' encoding='UTF-8'?><presence
xmlns='urn:ietf:params:xml:ns:pidf'
xmlns:dm='urn:ietf:params:xml:ns:pidf:data-model'
xmlns:rpid='urn:ietf:params:xml:ns:pidf:rpid'
xmlns:c='urn:ietf:params:xml:ns:pidf:cipid'
entity='sip:[email protected]'><tuple
id='tb9676d02'><status><basic>open</basic></status><rpid:user-
input>idle</rpid:user-input></tuple><dm:person
id='peb32f031'><rpid:activities><rpid:unknown/></rpid:activities><dm:note
>Idle</dm:note></dm:person></presence>
Tada se šalju dva zahtjeva NOTIFY zahtjeva. Prvi zahtjev se šalje samo na
adresu posluţitelja, a šalje ga onaj tko je promjenio status, u ovom slučaju je to
Bob i stoga se njegova SIP adresa nalazi u polju From. Unutar ovog zahtjeva se
šalju i podaci o promjeni statusa i oni se prenose unutar XML dokumenta, tj. kao
PIDF dokument. U njemu moţemo pronaći redak
entity='sip:[email protected]' koji sadrţi podatak o korisniku koji
35
promjenio status, te blok <basic>open</basic> koji kaţe da je taj Bob
trenutno prisutan a detalji o njegovoj prisutnosti su vidljivi u bloku
<dm:note>Idle</dm:note> iz kojeg je moguće očitati da je njegovi trenutni
status “Idle”. Ta je informacija sada pohranjena na posluţitelju i potrebno ju je
proslijediti korisnicima koji su se na nju pretplatili.
Na tu informaciju je pretplaćena Alice i zato joj posluţitelj šalje ovaj drugi zahtjev
NOTIFY. On je sadrţaja sličnog kao i prvi zahtjev, razlika je u prvom retku gdje
sada stoji SIP adresa od Alice jer je ona ta kojoj ne zahtjev upućen.
36
5 Implementacija korisničke strane – projekt
AndroidSIPChat
Korisničku stranu predstavlja Android aplikacija koja je izvedena u sklopu
Andoridovog projekta AndroidSIPChat. To je aplikacija koja nudi uslugu
trenutnog poručivanja i primanja informacija o prisutnosti.
Sastoji se od više radnih aktivnosti (eng. activity) i namjera (eng. intent) koje
pozivaju sljedeću aktivnost i smještene su unutar paketa fer.tel. Uz njih
implementirana je i jedne usluge (eng. service),a nalazi se unutar paketa
fer.tel.service. Osim klasa aktivnosti aplikacija sadrţi klase i metode
potrebne za implementiranje protokola SIP pri čemu smo koristili knjiţnicu MjSip, i
one su organizirane unutar zasebnih paketa (Slika 5.1.1).
Uz spomenute klase aplikacija sadrţi i automatski kreiranu klasu R.java,
datoteku Manifest.xml, te podatkovne resurse obuhvaćene u mapi res. U
podatkovne resurse ubrajaju se korištene slike i ikone (unutar podmapa
drawable), datoteke koje opisuju grafički izgled pojedine aktivnosti (unutar
podmape layout), te konstantne vrijednosti znakovnih nizova (unutar podmape
values).
5.1 Knjiţnica MJsip
Kako Android nema u sebi ugraĎenu podršku za protokole SIP i RTP u ovom
diplomskom radu koristili smo MjSip - Java bazirani otvoreni kod (eng. open
source) koji implementira stog protokola SIP, a moţe se preuzeti sa stranice:
http://www.mjsip.org.
MjSip sadrţi sve klase i metode potrebne za kreiranje aplikacija baziranih na
protokolu SIP i potpuno poštuje specifikaciju definiranu unutar RFC 3261.
(mjsip.org, 2006). One su rasporeĎene unutar šesnaest paketa koje smo izravno
dodali u src mapu Androidovog projekta, kao što je prikazano na slici (Slika
6.1.1). Pri izradi aplikacije je korišten izvorni kod, jedine izmjene koje su uvedene
tiču se načina kreiranja Log datoteka i izvorne naredbe su zamijenje i prilagoĎene
Androidovom okruţenju na način kako je to prikazano ovim kodom:
37
//stare naredbe
//event_log=new
RotatingLog(filename+"_events.log",null,SipStack.debug_level,SipStack.max
_logsize*1024,SipStack.log_rotations,SipStack.rotation_scale,SipStack.rot
ation_time);
//message_log=new
RotatingLog(filename+"_messages.log",null,SipStack.debug_level,SipStack.m
ax_logsize*1024,SipStack.log_rotations,SipStack.rotation_scale,SipStack.r
otation_time);
//nove naredbe
event_log = new AndroidEventLog(SipStack.debug_level);
message_log = new AndroidMessageLog(SipStack.debug_level);
Slika 5.1.1 Prikaz MJsipovih paketa unutar AndroidSIPChat projekta
Metode i klase MJsipovih paketa su korištene unutar servica koji je opisan klasom
IMService (paket fer.tel.services) i tako su ostvarene usluge registracije,
slanja i primanja poruka te primanja informacija o prisutnosti. Unutar klase
IMService implementirane su MJsipove klase: RegisterAgentListener,
UserAgentListener, MessageAgentListener i PresenceAgentListener
38
te predstavljaju sučelja za istoimene agente a svi se nalaze unutar paketa
local.ua.
public class IMService extends Service implements RegisterAgentListener,
UserAgentListener, MessageAgentListener,
PresenceAgentListener, IAppManager {
private static final String TAG = "MyService";
private RegisterAgent registerAgent;
private UserAgent userAgent;
private MessageAgent messageAgent;
private PresenceAgent presenceAgent;
private UserAgentProfile user_profile;
private SipProvider sip_provider;
Nakon kreiranja pojedinih agenata potrebno je inicijalizirati SIPov stog prema
specifikacijama koje odreĎuje MJsip, te je potrebno kreirati SipProvidera te SIP
promet usmjeriti prema sučelja emulatora čija je adresa 10.0.2.15, a vrata 6060
su tipična vrata koja koristi UDP protokol.
SipStack.init();
SipStack.debug_level = 5;
SipStack.log_path = ".";
sip_provider = new SipProvider("10.0.2.15", 6060);
5.1.1 Agent za registraciju
Objekt RegisterAgent je tada u mogućnosti kreirati agenta za registraciju koji
će pozivom metode register() izvršiti registraciju korisnika. U nastavku se
nalazi dio koda koji opisuje tijek registracije:
user_profile = new UserAgentProfile();
user_profile.do_register = true;
user_profile.username = usernameText;
user_profile.from_url = "sip:" + usernameText +
"@192.168.1.4";
user_profile.contact_url = "sip:" + usernameText +
"@192.168.1.4:7000";
userAgent = new UserAgent(sip_provider, user_profile, this);
registerAgent = new RegisterAgent(sip_provider,
user_profile.from_url,
user_profile.contact_url, user_profile.username,
user_profile.realm, user_profile.passwd, this);
registerAgent.register();
Log.d(TAG, "nakon register()");
39
Daljnji proces registracije dodatno nadziru registracijske metode
onUaRegistrationFailure() i onUaRegistrationSuccess() koje su
implementirane kao ako dio RegisterAgentListener sučelja. Prva se poziva
u slučaju da registracija ne uspije (kao rezulatat pogrešno upisane adresa,
nedostupnosti posluţitelja i sl.) dok se druga poziva nakon što se registracija
uspješno izvrši.
// RegisterAgentListener methods
public void onUaRegistrationFailure(RegisterAgent ra, NameAddress
target,NameAddress contact, String result) {
registred = "0";
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
public void onUaRegistrationSuccess(RegisterAgent ra, NameAddress
target,NameAddress contact, String result) {
registred = "1";
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
5.1.2 Agent za slanje i primanje poruka
Slično kako je kreiran agent za registraciju kreira se i agent za slanje i primanje
poruka MessageAgent. Metode koje on potom moţe pozivati su receive() i
send():
messageAgent = new MessageAgent(sip_provider, user_profile,
this);
// primanje poruka
messageAgent.receive();
// slanje poruka
messageAgent.send(friendUserURL, "naslov", "text/html",
poruka);
Sučelje MessageAgenta takoĎer sadrţi metode koje tijek slanja i primanja poruka
te ih je potrebno implementirati unutar IMService klase. Metode
onMaDeliveryFailure() i onMaDeliverySuccess() se pozivaju ovisno o
tome da li je poruka uspješno isporučena posluţitelju ili nije, dok je metoda
40
onMaReceivedMessage() zaduţena za primanje poruka. Unutar te metode
poruka se analizira i šalje dalje kroz aplikaciju.
// MessageAgentListener metode
public void onMaDeliveryFailure(MessageAgent ma, NameAddress
recipient,String subject, String result) {
sent = "0";
try {
barrier2.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
public void onMaDeliverySuccess(MessageAgent ma, NameAddress
recipient, String subject, String result) {
sent = "1";
try {
barrier2.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
public void onMaReceivedMessage(MessageAgent ma, final NameAddress
sender, NameAddress recipient, String subject, String
content_type,final String body) {
if (content_type.equals("text/html")) {
}
// analiza primljene poruke
// proslijeđivanje poruke aplikaciji
}
}
5.1.3 Agent prisutnosti
Slijedeći agent koji se stvara je agent prisutnosti, PresenceAgent, i to na način
kao što su bili kreirani i prethodni agenti a on raspolaţe s metodama za pretplatu
na prisutnosti (metoda subscribe()) i slanje informacije o vlastitoj prisutnosti
(metoda notify()). Unutar metode subscribe()prenosi se SIP adresa
kontakta na kojeg se korisnik ţeli pretplatiti. Metoda notify() se poziva u
trenutku kada korisnik ţeli poslati informacije o prisutnosti i ona tada izgleda
ovako: presenceAgent.notify(state, expires, content_type,
body). Argument state opisuje stanje pretplate i moţe imati vrijednost
SubscriptionStateHeader.ACTIVE ili null. Argument expires se postavlja
na vrijednost 3600 koja je uobičajena unutar SIP protokola. Zadnja dva argumenta
41
se odnose na vrstu infomacije koja se šalje, tj one opisuju prijenos PIDF
dokumenta koji u sebi sadrţi ţeljene informacije. Argumet content_type je
potrebno postaviti kao application/pidf+xml i tako definirati a argumentom
body potrebno je poslati odgovarajući PIDF dokument u XML obliku koji je
specificiran unutar RFC 3863 (Sugano, 2004).
presenceAgent = new PresenceAgent(sip_provider, user_profile,
this);
// pretplata na tuđu prisutnost
presenceAgent.subscribe("sip:[email protected]", 3600);
// slanje informacija o vlastitoj prisutnost
// presenceAgent.notify(SubscriptionStateHeader.ACTIVE, 3600,
"application/pidf+xml", body);
Spomenuta metoda za slanje informacija o prisutnosti trenutno nije u potpunosti
implementirana u ovom diplomskom radu iz razloga što njenim pozivom dolazi
grešaka koje tad uzrokuju prekid rada korisničke aplikacije. Ona je usko vezana i
za posluţiteljsku stranu koja takoĎer javlja greške prilikom rada i to prilikom
primanje i slanja informacija o prisutnosti.
U trenutnoj stadiju razvoja diplomskog rada uzroci tih grešaka nisu u potpunosti
istraţeni i to bi tek trebalo biti detaljno proučeno.
Kreiranjem agenta za prisutnost potrebno je implementirati i metode sučelja
PresenceAgentListener. Metode onPaNotificationFailure(),
onPaNotificationRequest() se pozivaju ovisno o tijeku slanja i primanja
informacija o prisutnosti te je unutar njih potrebno pozvati metode accept() i
activate() koje dozvoljaju i prihvaćaju primanje informacija kao bi se one dalje
mogle analizirati i proslijeĎivati kroz aplikaciju. Preostale metode su
onPaSubscriptionRequest(), onPaSubscriptionSuccess() i
onPaSubscriptionTerminated(). A one se pozivaju ovisno o stanju
pretplate.
// presenceAgentListener metode
public void onPaNotificationFailure(PresenceAgent pa,
NameAddress recipient, String reason) {
pa.accept();
pa.activate();
}
public void onPaNotificationRequest(PresenceAgent pa,
42
NameAddress recipient, NameAddress notifier, String
event,String content_type, String body) {
// primljena informacija o prisutnosti
pa.accept();
pa.activate();
}
public void onPaSubscriptionRequest(PresenceAgent pa,
NameAddress presentity, NameAddress watcher) {
}
public void onPaSubscriptionSuccess(PresenceAgent pa, NameAddress
presentity) {
try {
subscriptionBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
public void onPaSubscriptionTerminated(PresenceAgent pa,
NameAddress presentity, String reason) {
try {
subscriptionBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
5.2 Ţivotni ciklus aplikacije
Aplikacija se sastoji od više activitya i intenta te jednog servicea. Za
ispravan rad aplikacije sve ih potrebno opisati unutar Manifest.xml datoteke
kao je to prikazano slikom (Slika 5.2.1).
Na njoj je grafičkim elementima prikazana struktura klasa i odgovarajućih namjera.
Uz simbol A navedeno je ime aktivnosti i njoj su pridruţene namjere koju ju mogu
aktivirati i one su opisane uz simbol I. Tako moţemo vidjeti da su svim activityma
dodjeljeni intenti Main i Normal što znači da su im dodjeljna osnovna
funkcionalnost kao to Androidova aplikacija i zahtjeva. Activity koji se razlikuje od
ostalih je activity HelloScreen razlikuje koje je dodjeljen intent Launcher i time
je odreĎeno da to bude prva aktivnost koja se aktivira prilikom pokretanja
43
aplikacije. Uz simbol S je navedena service IMService kao sastavni dio
aplikacije, te vidimo da njoj nije potrebno pridjeliti dodatne intente.
Slika 5.2.1 Opis aktivnosti, namjera i usluga unutar Manifest.xls datoteke
Ovo je primjer kako se datoteka Manifest.xml se dakle moţe kreirati preko
grafičkog sučelja no se je moguće i direktnim unosom koda koji tada izgleda
ovako:
<application android:label="@string/app_name"
android:icon="@drawable/icon">
<activity android:name=".FriendList">
<intent-filter>
<action
android:name="android.intent.action.MAIN"></action>
<category
android:name="android.intent.category.NORMAL">
</category>
</intent-filter>
</activity>
<service android:name=".service.IMService"></service>
5.2.1 Početni ekran i Glavni izbornik
Prva aktivnost aplikacije je jednostavni pozdravni ekran kojeg prikazuje grafički
predloţak HelloScreen.xml, a njegovo otvaranje je definirano u datoteci
Manifest.xml pozivanjem klase HelloScreen.
44
Klasa HelloScreen sadrţi dretvu halloScreenTimer koja je zaduţena za
pauziranje prikaza početnog ekrana neko konačno vrijeme, te nakon isteka tog
vremena pokreće se iduća aktivnost, a trenutna se aktivnost gasi pozivom metode
finish(). Da bi s pokrenula iduća aktivnost potrebno je stvoriti namjeru tj.,
instancu klase Intent i to naznačiti u datoteci Manifest.xml te preko Intent
Filtera povezati ju s novom klasom MainMenu. Sljedeća aktivnost se tad moţe
pokrenuti pozivom metode startActivity().
Thread halloScreenTimer = new Thread() {
public void run() {
try {
// Wait loop
long ms = 0;
while (helloScreenActive && ms <
helloScreenTime) {
sleep(100);
if (!paused) ms += 100;
}
// Go to the next screen - main menu.
startActivity(new Intent("CLEARSCREEN"));
} catch (Exception e) {
Log.e("HelloScreen", e.toString());
} finally {
finish();
}
Novo pokrenuta aktivnost je dakle opisana u klasi MainMenu i ona je zaduţena za
prikazivanje predloška MainMenu.xml što je zapravo glavni izbornik aplikacije s
tri gumba: Start Android Chat, About Android Chat, Exit. U toj su klasi opisani ti
gumbi i svakom od njih je pridruţena odgovarajuća aktivnost koja se pokreće
pritiskom tog gumba. Za svaki gumb definirana je metoda
setOnClickListener()
View startChatButton =
this.findViewById(R.id.start_chat_button);
startChatButton.setOnClickListener(this);
koja osluškuje da li je gumb kliknut i zatim se poziva metoda onClick() u kojoj
je opisana radnja pojedinog gumba.
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.start_chat_button:
Log.d(TAG, "onClick: starting new intent, SignUp");
Intent iSignUp = new Intent(this, SignUp.class);
startActivity(iSignUp);
45
break;
case R.id.about_button:
Intent iAbout = new Intent(this, About.class);
startActivity(iAbout);
break;
case R.id.exit_button:
finish();
break;
}
Pritiskom gumba Start Android Chat kreira se nova instanca klase Intent kako bi
se mogle pokrenuti aktivnosti vezane za registraciju korisnika i druge aktivnosti
vezne za uspostavu komunikacije, a koje su opisane u klasi SignUp.
Gumb About Android Chat otvara prozor koji daje kratak opis aplikacije, a
pritiskom trećeg gumba, Exit aplikacija se gasi.
5.2.2 Registracija korisnika
Registracija korisnika počinje klasom SignUp a njen klasni dijagram prikazan je
slikom(Slika 5.2.2).
Slika 5.2.2 Klasni dijagram klase SignUp
Unutar klase SignUp se otvara grafički predloţak sign_up_screen.xml koji
sadrţi gumbe Sign Up i Cancel te teksutalne okvire unutar kojih korisnik mora
46
upisati svoje korisničko ime i SIP URL. Za gumbe postoje definirane metode
setOnClickListener() i onClick().
Registracija je ostvarena korišetnjem servica koji je implementiran klasom
IMService a nalazi se unutar paketa fer.tel.service i definiran je u datoteci
Manifest.xml. Metode koje service nudi omogućene su preko sučelja IAppManager
a koje se nalazi u paketu fer.tel.interfaces. Za uspješno povezivanje sa servicom
potrebno je dakle stvoriti odgovarajući objekt:
private IAppManager imService;
Prije no što se poveţemo sa serviceom potrebno je implementirati slijedeći dio koda: private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
imService = ((IMService.IMBinder)service).getService();
Log.d(TAG, "onServiceConnected");
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Log.d(TAG, "onServiceDisconnected");
Toast.makeText(SignUp.this,
R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
Prva se metoda poziva u trenutnku kad se uspostavi veza sa serviceom i predaje
service objekt pomoću kojega se tada ostvaruje interakcija s uslugom. Druga se
metoda poziva u slučaju da se service neočekivano prekine, tj ako se proces
ugasi.
Sada je moguće pokrenuti service i povezati se s njim a to se vrši pozivom metode
startService() i to čim se aktivnost pokrene, dakle unutar glavne,
onCreate() metode, kao što je prikazano kodom:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
* Start and bind the imService
*/
startService(new Intent(SignUp.this, IMService.class));
47
Nakon kreiranja i povezivanja sa serviceom opisuju se grafički elemetni, teksutalni
okviri i gumbi kao je što je već spomenuto. Prvo je opisana onClick() metoda za
gumb Sign Up, a pritiskom na njega korisnik pokreće registraciju.
Prije nego što se pozove metoda signUpUser() potrebno je provjeriti da li
postoji veza s ţeljenom uslugom u slučaju da se onda neočekivano prekinula te je
o tome potrebno obavijestiti korisnika prikazom dijaloškog okvira što se ostvaruje
pozivom metode showDialog().
public void onClick(View v) {
switch (v.getId()) {
case R.id.signup:
if (imService == null) {
showDialog(NOT_CONNECTED_TO_SERVICE);
return;
} else if (imService.isNetworkConnected() == false) {
showDialog(NOT_CONNECTED_TO_NETWORK);
Primjer dijaloškog okvira je dan na slici (Slika 5.2.3).
Slika 5.2.3 Dijaloški okvir
Ako je veza s uslugom ispravna tada se vrši provjera podataka koje korisnik unio
te se kreira nit signUpThread koja je zaduţena za poziv registracijske metode
signUpUser().
Thread signUpThread = new Thread() {
@Override
public void run() {
final String result =
imService.signUpUser(usernameText
.getText().toString(),
urlText.getText().toString());
48
Kao argumente metoda signUpUser()prenosi korisničko ime i SIP adresu koje
je korisnik sam upisao preko korisničkog sučelja a vratit će String vrijednost koja
će sprema u objekt result. Ako je registracija uspješno realizirana result će imati
vrijednost “1” i tada će korisnik o tome biti obavješten kratkom toast obavjesti kao
jedan od načina slanja obavijesti koje Andoid podrţava. Naredba kojom se toast
obavijesti kreira izgleda ovako:
Toast.makeText(SignUp.this, R.string.signup_successfull,
Toast.LENGTH_LONG).show();
Izgled toast obavijest vidljiv je na slici (Slika 5.2.4).
Slika 5.2.4 Primjer toast obavijesti
U slučaju da registracija ne uspije vrijednost objekta result će biti “0” i korisnik će
o tome biti obavješten dijaloškim okvirom.
Nakon što je registracija završena aplikacija prelazi u slijedeću aktivnost i to
kreiranjem nove Intent instance te novoj aktivnosti prenosi odreĎene parametre,
kao što su ime korisnika koji se upravo registrirao te njegova SIP adresa. To se
postiţe pozivom metode putExtra(). Sljedeća aktivnost se pokreće je opisana u
klasi FriendList.
Intent i = new Intent(SignUp.this, FriendList.class);
i.putExtra("usernameText", usernameText
.getText().toString());
i.putExtra("urlText", urlText.getText()
.toString());
startActivity(i);
49
Kako sam proces registracije traje neko odreĎno vrijeme, za to vrijeme nije
poţeljno da korisnik pokreće neke dodatne akcije te je zato kreniran jednostavan
ProgressDialog koji će doći u prvi plan i tako korisniku dati do znanja što
aplikacija trenutno izvršava.
ProgressDialog se kreira na slijedeći način:
myProgressDialog = ProgressDialog.show(SignUp.this, "",
"Connecting...", false, true);
Izgled jednostavnog ProgressDialoga vidljiv je na slici (Slika 5.2.5).
Slika 5.2.5 Primjer ProgressDialoga
5.2.3 Popis kontakta i prisutnost
Sljedeća aktivnost koja se pokreće opisana je u klasi FriendList te otvara
grafički predloţak friend_list.xml a izvedena je iz klase ActivityList.
public class FriendList extends ListActivity {
Njome je omogućen prikaz jednostavne lista nad čijim elementima se mogu
definirati OnListItemClick() metoda koja se pokreće ovisno koji je element
liste pritisnut.
Prvo što se izvršava unutar ove aktivnosti je preuzimanje podataka poslanih iz
prethodne aktivnosti, a to su korisničko ime i SIP adresa. Preuzimanje podataka
od druge aktivnosti se vrši pozivom metoda getStringExtra().
Intent i = getIntent();
usernameText = i.getStringExtra("usernameText");
urlText = i.getStringExtra("urlText");
50
Unutar te liste kontakata prikazane su SIP adrese kontakata s kojima je moguće
komunicirati. Uz njihovo ime dodane su i ikone koje predstavljaju različite statusa
pojedinog kontakta. A na vrhu liste je dodan padajući dijalog koji korisiku
omogućuje postavljanje vlastitog statusa. (Slika 5.2.6)
Slika 5.2.6 Lista kontakata
Kako su tijekom rada uočene greške prilikom slanja i primanja informacija o
prisutnosti ovoj listi nije pridruţena puna funkcionalnost. Stoga je pokraj imena
svih kontakata pojavljuje zelana ikona koja indicira da su svi dostupni, dok korisnik
u padajućem dijalogu moţe birati izmeĎu tri statusa (Slika 5.2.7), no te informacije
se ne proslijeĎuju dalje prema posluţitelju prisutnosti.
Slika 5.2.7 Padajući dijalog za postavljanje statusa
51
Komunikacija s ţeljenim kontakom se ostvaruje pritiskom na njegovu SIP adresu.
To je omogućeno unutar OnListItemClick() metode koja dobavlja podatke o
odabranom kontaktu i pohranjuje ga unutar String varijable friendURL koja se
zajedno s korisničkim imenom i SIP URL-om dalje proslijeĎuju idućoj aktivnosti.
@Override
protected void onListItemClick(ListView l, View v, int position,
long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
Object o = this.getListAdapter().getItem(position);
String friendURL = o.toString();
Intent i = new Intent(this, Messaging.class);
i.putExtra("friendURL", friendURL);
i.putExtra("usernameText", usernameText);
i.putExtra("urlText", urlText);
startActivity(i);
}
Nova aktivnost pokreće se nakon kreiranja nove Intent instance koja je
povezana se s klasom Messaging.
5.2.4 Chat prozor
Metode potrebne za razmijenu poruka s odabranim kontaktom opisani su unutar
klase Messaging. Unutar nje prvo se preuzimanje podaci od prethodne aktivnosti
i to su: usernameText – korisničko ime, urlText – SIP adresa korisnika te
friendUserURL – SIP adresa odabranog.
Intent i = getIntent();
usernameText = i.getStringExtra("usernameText");
urlText = i.getStringExtra("urlText");
friendUserURL = i.getStringExtra("friendURL");
String delimiter = "[@]";
friendUserName = friendUserURL.split(delimiter)[0];
delimiter = "[:]";
friendUserName = friendUserName.split(delimiter)[1];
Log.d(TAG, "!!!!!!!! friendUserName: "+friendUserName);
52
Od friendUserURL se zatim parsira samo prvi dio Stringa kako bi dobili
friendUserName, tj samo korisničko ime kojeg ćemo tako jednostavnije koristiti
u samom chat prozoru.
Klasa Messaging pokreće otvara grafički predloţak messaging_screen.xml
unutar kojeg su opisani glavni tekstualni okvir u kojem će se prikazivati poslane i
primljene poruke zajedno s imenom pošiljatelja, zatim manji tekstualni okvir unutar
kojeg korisnik upisuje poruke te gumb Send koji će upisanu poruku poslati. Njen
klasni dijagram je prikazan na slici (Slika 5.2.8).
Slika 5.2.8 Klasni dijagram klase Messaging
Kako bi usluga slanja i primanja poruka bila uspješno imlementirana aktivnost je
nuţnu povezati s servicom, i to na isti način kako je to objašnjeno za uslugu
registracije korisnika.
Slanje poruke kreće nakon pristiska na gumb Send, a prije no što se pozove
metoda zaduţena za slanje poruka izvrši se provjera da li je korisnik upisao barem
jedan znak kako ne bi slali praznu poruku.
sendMessageButton.setOnClickListener(new OnClickListener() {
CharSequence message;
public void onClick(View arg0) {
53
message = messageText.getText();
if (message.length() > 0) {
Metoda za slanje poruka je metoda sendMessage() a opisana je unutar servicea
u klasi IMService. Nju je potrebno pozvati unutar niti i u je svrhu kreirana nit
sendingThread. Kao argumente prenosi SIP adresu korisnika kome je poruka
namjenjena te sam sadrţaj poruke, a kao rezlutat vraća vrijednost “1“ ili “0“ i on
se pohranjuje unutar parametra sent.
Thread sendingThread = new Thread() {
@Override
public void run() {
final String sent = imService.sendMessage(friendUserURL,
message.toString());
Ovisno o primljenoj vrijednosti moguće je znati da li je poruka uspješno
dostavljena posluţitelju. Ako je vrijednost “1”, znači da je slanje uspjelo te je tu
poruku potrebno upisati u glavni tekstualni okvir koji ima ulogu chat prozora.
Upisaivanje poruke u glavni okvir vrši se pozivom metode
appendToMessageHistory(). Ona kao argumente uzima ime pošiljatelja i
sadrţaj poruke i takve dodaje u chat prozor.
public void appendToMessageHistory(String username, String message)
{
if (username != null && message != null) {
messageHistoryText.append(username + ": ");
messageHistoryText.append(message + "\n");
}
}
Na taj način je implemenitrano slanje poruka, no primanje poruka je nešto
dugačije. Primanje poruka se dijeli na dva moguća slučaja: primanje poruke od
trenutnog kontakta ili primanje poruke od novog kontakta. Pod trenutni kontakt
misli se na kontakta s kojim je chat komunikacija već započela i taj chat prozor je
trenutno aktivan. A pod novi kontakt podrazumjeva se slučaj kad korisnik dobije
poruku od novog kontakta i tek tada ostvaruje komunikaciju s njim putem chat
prozora.
54
I slučaja počinju na jednak način. Kad posluţitelj usmjeri neku poruku prema
korisničkoj aplikaciji tada se pozove metoda onMaReceivedMessage() koja je
implementirana kao dio servicea i nalazi se unutar IMService klase.
Ona tada kao argumente preuzme ime i adresu pošiljatelja i poruku te ih “objavi”, tj
pomoću sendBroadcast() pošalje ga svim aktivnim Broadcast Receiverima.
public void onMaReceivedMessage(MessageAgent ma, final NameAddress
sender, NameAddress recipient, String subject, String
content_type,final String body) {
if (content_type.equals("text/html")) {
String delimiter = "</SPAN>";
receivedMessage = body.toString();
receivedMessage = receivedMessage.split(delimiter)[0];
delimiter = ">";
receivedMessage = receivedMessage.split(delimiter)[1];
String address = sender.getAddress().toString();
String friendName = sender.getDisplayName().toString();
Intent i = new Intent(TAKE_MESSAGE);
i.putExtra("friendURL", address);
i.putExtra("friendName", friendName);
i.putExtra("receivedMessage", receivedMessage);
sendBroadcast(i);
String activeFriend = FriendControl.getActiveFriend();
if (activeFriend == null ||
activeFriend.equals(address) == false) {
showNotification(friendName, address,
receivedMessage);
}
}
}
Broadcast Receiver zainteresiran za ovu poruku se nalazi unutar Messaging
klase i opisan je kao MessageReceiver. Nakon što se neka inframacija “objavi”
metodom sendBroadcast() kao rezlutat se pokrene odgovarajuća metoda
onReceive(). Unutar te metode je moguće preuzeti poslanu informaciju, u ovom
slučaju su to korisničko ime i adresa pošiljatelja i primljena poruka te se dodaju u
glavni chat prozor.
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle extra = intent.getExtras();
String friendURL = extra.getString("friendURL");
String friendName = extra.getString("friendName");
55
String receivedMessage =
extra.getString("receivedMessage");
if (friendURL != null && receivedMessage != null) {
if (friendUserURL.equals(friendURL)) {
appendToMessageHistory(friendName,
receivedMessage);
...
};
Nakon “objave” poruke kreće provjera pošiljatelje, točnije, provjera se da li poruku
posao trenutni ili novi kontakt. Informacije o kontaktu se nalaze unutar klase
FriendControl a aktivni kontakt se dobijem pozivom metode
getActiveFriend().
U slučaju da je to novi kontakt korisniku se šalje obavijest (notification) koja se
prikazauje kao mala ikona s tekstom unutar linije za obavijesti, pri vrhu ekrana.
(Slika 5.2.9) Pritiskom na taj notification kreira se novi Intent i povezuje s
klasom Messaging i tako se krerira novi chat prozor za komunikaciju s tim novim
kontaktom.
Slika 5.2.9 Notification
56
6 Instalacija i pokretanje aplikacije
Aplikacija je izvedena u sklopu Androidovog projekta AndroidSIPChat i sadrţi
sve potrebe klase i podatkovne resurse, a moguće ju je pokrenuti iz razvojnog
okruţenja Eclipse. Prije pokretanja same aplikacije potrebno je kreirati Androidov
emulator te mu preusmjeriti vrata (eng. port). Za izradu ovog diplomskog rada
korištena je AVD platforma 1.5. Nakon pokretanja AVD-a moguće je povezati se s
njegovom konzolom i to na način da se pokrene komandna linija i upiše naredba:
> telnet localhost <console port>
Kao <console port> potrebno je upisati broj konzole s kojom se ţelimo
povezati, a to je broj koji se nalazi u naslovoj traci prozora u kojem je AVD
prikazan. Najvjerojatnije je to broj: 5554. Naredba tada glasi:
> telnet localhost 5554
Nakon toga otvara se prozor unutar kojeg je potrebno upisati naredbu za
preusmjeravanje vrata:
> redir add <protocol>:<host-port>:<guest-port>
Pod <protocol> treba upisati protokol čiji promet ţelimo preusmjeriti, u našem
slučaju je to protokol UDP. Parametar <host-port> predstavlja proizvoljna
slobodna vrata ureĎaja na kojem je emulator pokrenut (za potrebe ovog
diplomskog rada kao <host-port> su odabrana vrata 7000), a <guest-port>
su vrata na emulatoru na koja ţelimo usmjeriti promet.
Nakon ovih postavki moguće je pokrenuti aplikaciju AndroidSIPChat.
Prvo što se prikazuje je početni ekran kao što je to prikazano na slici (Slika 6.2.1).
57
Slika 5.2.1 Početni ekran
Početni ekran se prikazuje sve par sekundi te se odmah nakon njega otvara glavni
izbornik unutar kojeg se moţe pritisnuti na jedan od ponuĎenih gumba (Slika
6.2.2).
Slika 5.2.2 Glavni izbornik
58
Glavni izbornik sadrţi tri gumba. Pritiskom prvog gumb pokreće se novi prozor koji
pokreće aplikaciju, drugi gumb otvara prozor s kraćim opisom aplikacije a treći
gumb ju gasi.
Odabirom prvog gumba (Start Andorid Chat) otvara se Sign Up prozor (Slika
6.2.3) unutar kojeg je potrebno upisati korisničko ime (polje Username) i SIP URL
(polje SIP URL) na način kako je opisano unutar teksutalnih okvira. Korisničko
imena i korisničkog dio SIP URLa se moţe odabrati prema ţelji, dok je za domenu
nuţno upisati 10.0.0.2.
Primjer korisničkog imena: android
Primjer SIP URLa: [email protected]
Slika 5.2.3 Sign up prozor
Za registraciju je potrebno upisati oba podatka te pritisnuti gumb Sign Up. U
slučaju da korisnik ne upiše oba podatka pojavit će se dijaloški okvir koji će ga
dodatno upozoriti na to.
Nakon pritiska na gumb Sign Up pokreće se postupak registracije. Za to vrijeme u
prvi plan dolazi Progress Dialog (Slika 6.2.4).
59
Slika 5.2.4 Process Dialog
Po završetku procesa registracije Progress Dialog se gasi Ako je registracija
uspješno izvršena pojavit će se prozor kao što je prikazan na slici (Slika 6.2.5)
Slika 5.2.5 Uspješno izvršena registracija
60
Nakon registracije korisnika otvara se sljedeći prozor unutar kojeg je prikazan
popis SIP adresa kontakata s kojima je moguće komunicirati. (Slika 6.2.6)
Slika 5.2.6 Lista kontakata
Komunikacija se inicira pritiskom na ţeljeni kontakt i tada se prelazi u prozor za
razmjenu poruka (Slika 6.2.7).
Slika 5.2.7 Prozor za razmjenu poruka
61
On se sastoji od većeg tekstualnog okvira u kojem će se ispisivati cijeli tijek
komunikacije (primljene i poslane poruke, s imenima pošiljatelja) i od manjeg
tekstualnog okvira unutar kojeg korisnik upisuje poruke koje ţeli poslati. Slanje
poruke se inicira pritiskom guma Send.
Na taj način se ostvaruje komunikacija s trenutnim poručivanjem. Na slici je
primjer komunikacije izmeĎu Androidove aplikacije i i SIP telefona X-lite. (Slika
6.2.8).
U dosadašnjem primjeru prikazan je tijek komunikacije za slučaj kada je
Androidova aplikacija inicira tu komunikaciju. Drugi slučaj bi bio da komunikaciju
inicira telefon X-lite slanjem poruke prema Androidovoj aplikaciji. Aplikacija tada
kreira obavijest (eng. notification) i pomoću nje obavijesti korisnika da drugi
korisnik ţeli ostvariti komunikaciju s njim. Te obavijesti se prikazuju unutar retka za
obavijesti, pri vrhu ekrana. Primjer obavijesti je prikazan slikom (Slika 6.2.9).
Slika 5.2.8 Primjer komunikacije s trenutnim poručivanjem
62
Slika 5.2.9 Prikaz obavijesti (eng. notification)
Primljenu obavijest je moguće potom otvoriti kao što je prikazano na slici (Slika
6.2.10) i pritiskom a nju pokreće se novi prozor za razmjenu poruka.
Slika 5.2.10 Otvaranje primljene obavijesti
63
Zaključak
Prilikom izrade diplomskog rada bilo je potrebno upoznati se s načinom
programiranja aplikacija namjenjenih ureĎajima s operacijskim sustavom Android,
te s radom Androidovog emulatora. TakoĎer, potrebno je bilo proučiti protokol SIP
te ga implemenirati unutar posluţiteljske i korisničke strane aplikacije.
Posluţiteljska je strana uspješno realizirana i ona omogućuje povezivanje dva ili
više SIP telefona (u ovom diplomskom korišten je SIP telefon X-lite) koji tada
mogu razmjenjivati kratke tekstualne poruke i informacije o prisutnosti.
Za implementaciju protokola SIP unutar Andorida od velike je koristi bila gotova
biblioteka MJsip i njome je uspješno realizirana usluga registracije korisnika te
slanje i primanje poruka. Što se tiče slanja i primanja inforamacija o prisutnosti
trenutno je uspješno realizirana usluga pretplate na ţeljenog korisnika te primanje
informacija o njegovoj prisnutnoti dok slanje vlastitih informacija o prisutnosti nije
podrţano. Taj bi se dio funkcionalnosti aplikacije trebao još dodatno proučiti.
Ovime radom je tako dan primjer izrade Androidove aplikacije s primjenom
protokola SIP kojim je ostvare komunikacija s trenutnim poručivanjem i razmjenom
informacija o prisutnosti. Time je prikazan samo manji dio funkcionalnosti koju
nam Android i SIP nude te moţe posluţiti kao pomoć pri izradi i kompliciranijih
aplikacija.
_______________________
Marta Tinodi
64
Literatura
[1] Chat, Chat, http://hr.wikipedia.org/wiki/Chat, 2010.
[2] Rosenberg J., RFC 3261, 2002, SIP: Session Initiation Protocol,
http://www.ietf.org/rfc/rfc3261.txt, 2010.
[3] SIP requests, 2008, List of SIP request methods,
http://en.wikipedia.org/wiki/List_of_SIP_request_methods, 2010.
[4] Rosenberg J., RFC 3856, 2008, A Presence Event Package for the Session
Initiation Protocol (SIP), http://www.ietf.org/rfc/rfc3856.txt, 2010.
[5] Day M., RFC 2778, 2000, A Model for Presence and Instant Messaging,
http://www.ietf.org/rfc/rfc2778.txt, 2010.
[6] Sugano H., RFC 3863, 2004, Presence Information Data Format (PIDF),
http://www.ietf.org/rfc/rfc3863.txt, 2010.
[7] Stipica, T., 2006., SIP - Session Initiation Protocol,
http://sistemac.srce.hr/fileadmin/user_root/Session_Initiation_Protocol.pdf,
2010.
[8] Camarillo G., García-Martín M.A. The 3G IP Mutimedia Subsystem (IMS),
Merging the Internet and the Cellular Worlds: The Presence Service on the
Internet. West Sussex, Engleska, 2004.
[9] mjsip.org, 2006., MjSip Features, http://www.mjsip.org, 2010.
[10] Čarapina, M., Praćenje tramvajskog prometa na operacijskom sustavu
Android, diplomski rad, Fakultet elektrotehnike i računarstva, 2009.
[11] Android Developers, The Developer’s Guid, Application Fundaments,
http://developer.android.com/guide/topics/fundamentals.html, 2010.
65
Popis skraćenica
IM Instant Messaging
SIP Session Initiation Protocol
IETF the Internet Engineering Task Force
RFC Request for Comments
IP Internet Protocol
RTP Real-time Transport Protocol
SDP Session Description Protocol
HTTP HyperText Transfer Protocol
SIP URI SIP Uniform Resource Identifier
SIP URL SIP Uniform Resource Locator
PSTN Public Switched Telephone Network
PDA Personal Data Assistant
UA User Agents
UAS User Agent Server
UAC User Agent Client
AoR Address of Record
UDP User Datagram Protocol
PUA Presence User Agent
PA Presence Agent
PS Presence Server
PIDF Presence Information Data Format
XML Extensible Mark-up Language
MIME Multipurpose Internet Mail Extension
RPID Rich Presence Information Data Format
API Application Programming Interface
SDK Software Development Kit