69
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.

Prisutnost korisnika na operacijskom sustavu Android [2 MiB] - FER-a

  • Upload
    others

  • View
    2

  • 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.

Mentor rada: Doc.dr.sc. Mario Kušek

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

66

OHA Open Handset Alliance

HAL Hardware Abstraction Layer

IDE Integrated development enviroment

ADT Android Development Tools

DDMS Dalvik Debug Monitoring Service)

AAPT Android Asset Packaging Tool

ADB Android Debug Bridge

AAPT Android Asset Packaging Tool