Aplicație de socializare într -un grup restrâns de utilizatori [611948]

Universitatea “Politehnica ” din București
Facultatea de Electronică, Telecomunicații și Tehnologia Informației

Aplicație de socializare într -un grup restrâns de utilizatori

Proiect de diplomă
prezentat ca cerință parțială pentru obținerea titlului de
Inginer în domeniul Inginerie electronică Юi telecomunicații
programul de studii de licență Tehnologii Юi sisteme de telecomunicații

Conducător științific Absolvent
Э.l.dr.ing. Alexandru VULPE George Alexandru DAMIAN

2017

2

3

4

5
Declarație de onestitate academică

Prin prezenta declar că lucrarea cu titlul “ Aplica ție de socializare într -un grup
restrâns de utilizatori ”, prezentată în cadrul Facultății de Electronică,
Telecomunicații și Tehnologia Informației a Universității “ Politehnica ” din București
ca cerință parțială pentru obținerea titlului de Inginer în domeniul Inginerie
Electronică și Telecomunicații , programul de studii Tehnologii Юi Sisteme de
Telecomunicații este scrisă de mine și nu a mai fost prezentată niciodată la o facultate
sau instituție de învățământ superior din țară sau străinătate.

Declar că toate sursele utilizate, inclusiv cele de pe Internet, sunt indicate în
lucrare, ca referințe bibliografice. Fragmentele de text din alte surse, reprodu se exact,
chiar și în traducere proprie din altă limbă, sunt scrise între ghili mele și fac referință
la sursă. Reformularea în cuvinte proprii a textelor scrise de către alți autori face
referință la sursă. Înțeleg că plagiatul constituie infracțiune și se sa ncționează
conform legilor în vigoare.

Declar că toate rezultatele simulărilor, experimentelor și măsurătorilor p e care
le prezint ca fiind făcute de mine, precum și metodele prin care au fost obținute, sunt
reale și provin din respectivele simulări, experimente și măsurător i. Înțeleg că
falsificarea datelor și rezultatelor constituie fraudă și se sancționează conform
regulamentelor în vigoare.

Bucure ști, Septembrie 2017

Absolvent: [anonimizat]

_________________________

6

7
Cuprins
Listă de figuri ……………………………………………………………………………………………………. 9
Listă de tabele …………………………………………………………………………………………………. 11
Listă de acronime …………………………………………………………………………………………….. 13
Introducere ……………………………………………………………………………………………………… 15
Sistemul de operare Android ……………………………………………………………………………. 17 Capitolul 1
1.1 Istoric ………………………………………………………………………………………………………………… 17
1.2 Evoluția sistemului de operare Android ………………………………………………………………….. 19
1.3 Arhitectura Android …………………………………………………………………………………………….. 21
Kernel-ul Linux ……………………………………………………………………………………………….. 22 1.3.1
Bibliotecile ……………………………………………………………………………………………………… 22 1.3.2
Android Runtime……………………………………………………………………………………………… 22 1.3.3
Framework-ul Android …………………………………………………………………………………….. 23 1.3.4
Nivelul Aplica ție ……………………………………………………………………………………………… 23 1.3.5
Tehnologii utilizate ………………………………………………………………………………………… 25 Capitolul 2
2.1 Java……………………………………………………………………………………………………………………. 25
Limbajul de programare Java …………………………………………………………………………….. 25 2.1.1
Mașina virtuală Java …………………………………………………………………………………………. 25 2.1.2
Platforma Java …………………………………………………………………………………………………. 26 2.1.3
2.2 XML ………………………………………………………………………………………………………………….. 27
2.3 Tehnologia Wi- Fi ………………………………………………………………………………………………… 28
Principalele standarde din familia 802.11 ……………………………………………………………. 28 2.3.1
Nivelul MAC…………………………………………………………………………………………………… 29 2.3.2
Wi-Fi Direct ……………………………………………………………………………………………………. 29 2.3.3
Mediul de dezvoltare ………………………………………………………………………………………. 31 Capitolul 3
3.1 Android Studio ……………………………………………………………………………………………………. 31
Instant Run ……………………………………………………………………………………………………… 32 3.1.1
Emulatorul Android …………………………………………………………………………………………. 32 3.1.2
Cloud Test Lab ………………………………………………………………………………………………… 33 3.1.3
App Indexing…………………………………………………………………………………………………… 34 3.1.4
GPU Debugger ………………………………………………………………………………………………… 35 3.1.5
3.2 SDK …………………………………………………………………………………………………………………… 35
Dezvoltarea aplicației ……………………………………………………………………………………… 37 Capitolul 4
4.1 Descrierea proiectului ………………………………………………………………………………………….. 37
4.2 Crearea unei conexiuni P2P prin Wi-Fi în Android ………………………………………………….. 37
Permisiunile necesare Wi-Fi P2P ……………………………………………………………………….. 38 4.2.1
Configurarea unui Broadcast Receiver și a unui P2P Manager ………………………………. 39 4.2.2
Inițializarea descoperirii dispozitivelor pereche …………………………………………………… 41 4.2.3
Obținerea unei liste de dispozitive pereche ………………………………………………………….. 41 4.2.4
Conectarea la un dispozitiv pereche……………………………………………………………………. 42 4.2.5
Crearea unui grup …………………………………………………………………………………………….. 43 4.2.6
4.3 Structura proiectului …………………………………………………………………………………………….. 43
Dosarul manifests …………………………………………………………………………………………….. 43 4.3.1
Dosarul Java ……………………………………………………………………………………………………. 45 4.3.2
Dosarul res ……………………………………………………………………………………………………… 46 4.3.3
4.4 Descrierea funcționării …………………………………………………………………………………………. 47
Concluzii ………………………………………………………………………………………………………… 53
Bibliografie …………………………………………………………………………………………………….. 55

8

9
Listă de figuri
Figura 1.1 Telefonul inteligent T-Mobile G1 ………………………………………………………………………… 17
Figura 1.2 Răspândirea versiunilor Android în iunie 2017 ………………………………………………………. 18
Figura 1.3 Logo-ul oficial pentru sistemul de operare Android. ………………………………………………. 19
Figura 1.4 Arhitectura Android ……………………………………………………………………………………………. 21
Figura 2.1 – Exemplu XML…………………………………………………………………………………………………. 27
Figura 2.2 – Exemplu Layout.xml ………………………………………………………………………………………… 28
Figura 2.3 – Logo-ul Wi- Fi …………………………………………………………………………………………………. 28
Figura 2.4 – Emblemă Wi -Fi Direct în sistemul de operare Android ………………………………………… 30
Figura 3.1 – Logo Android Studio ………………………………………………………………………………………… 31
Figura 3.2 – Butoanele specifice Instant Run …………………………………………………………………………. 32
Figura 3.3 – Emulatorul Android ………………………………………………………………………………………….. 33
Figura 3.4- Interfață teste Cloud Test Lab …………………………………………………………………………….. 34
Figura 3.5 – Testare Google App Indexing ……………………………………………………………………………. 34
Figura 3.6- GPU Debugger …………………………………………………………………………………………………. 35
Figura 4.1 – Permisiunile necesare Wi-Fi P2P ……………………………………………………………………….. 38
Figura 4.2 – Intent-urile necesare stabilirii conexiunii Wi-Fi P2P …………………………………………….. 39
Figura 4.3 – Obținerea obiectului WifiP2pManager.Channel …………………………………………………… 39
Figura 4.4 – Metoda onReceive() …………………………………………………………………………………………. 40
Figura 4.5 – Metodele onResume() și onPause() ……………………………………………………………………. 40
Figura 4.6 – Metoda discoverPeers() …………………………………………………………………………………….. 41
Figura 4.7 – Popularea unei liste cu dispozitive pereche disponibile …………………………………………. 41
Figura 4.8 – Cererea listei de dispozitive pereche disponibile ………………………………………………….. 42
Figura 4.9 – Metoda connect() ……………………………………………………………………………………………… 42
Figura 4.10 – Metoda createGroup() …………………………………………………………………………………….. 43
Figura 4.11 – Structura aplicației ………………………………………………………………………………………….. 43
Figura 4.12 – Structura dosarului java …………………………………………………………………………………… 45
Figura 4.13 – Fișierul de tip enum ………………………………………………………………………………………… 46
Figura 4.14 – Structura dosarului res …………………………………………………………………………………….. 46
Figura 4.15 – Ecran inițial aplicație ………………………………………………………………………………………. 48
Figura 4.16 – Căutare dispozitive pereche …………………………………………………………………………….. 48
Figura 4.17 – Crearea unui grup …………………………………………………………………………………………… 49
Figura 4.18 – Trimiterea unei invitații de conectare ………………………………………………………………… 49
Figura 4.19 – Invitație de conectare ……………………………………………………………………………………… 50
Figura 4.20 – Chat utilizator 1 ……………………………………………………………………………………………… 51
Figura 4.21 – Chat utilizator 2 ……………………………………………………………………………………………… 51

10

11
Listă de tabele
Tabel 1.1 – Versiuni Android ………………………………………………………………………………………………. 21
Tabel 2.1 – Principalele standarde din familia 802.11 …………………………………………………………….. 29

12

13
Listă de acronime
Acronim Semnificația inițialelor Traducere română
AOT Ahead of Time Compilarea înainte de timp
API Application Programming
Interface IŶterfață de prograŵare peŶtru
apliĐații
APK Android Application Package Fișier paĐhet al apliĐației AŶdroid
BSS Bulettin Board System –
CCK Complementary Code Keying Codare ĐoŵpleŵeŶtară
CPU Central Processing Unit UŶitate ĐeŶtrală de proĐesare
CSMA/CA Carrier Sense Muliple Access with
Collision Avoidance Acces multiplu cu deteĐție de
purtătoare și eǀitare a Đoli ziunii
DCF Distributed Coordination Function FuŶție de ĐoordoŶare distriďuită
DVM Dalvik Virtual Machine MașiŶa ǀirtuală Dalǀik
GPU Graphics Processing Unit UŶitate de proĐesare grafiĐă
HTC High Tech Computer –
HTML HyperText Markup Language Limbaj de marcare HyperText
IDE Integrated Development
Environment Mediu integrat de dezvoltare
IEEE Institute of Electrical and
Electronics Engineers Institutul Inginerilor
EleĐtrotehŶiști și EleĐtroŶiști
JDK Java Development Kit Trusă de dezǀoltare Jaǀa
JIT Just in Time Compilarea la timp
JRE Java Runtime Environment Mediul de dezvoltare Java
JVM Java Virtual Machine MașiŶa ǀirtuală Jaǀa
MAC Media Access Control Controlul accesului media
NFC Near-field communication CoŵuŶiĐație de Đâŵp apropiat
OFDM Orthogonal Frequency Division
Multiplexing Multiplexare cu divizare în
freĐǀeŶță ortogoŶală
P2P Peer to Peer –
PCF Point Coordination Function FuŶĐție de ĐoordoŶare puŶĐtuală
RAM Random Access Memory Memorie cu acces aleator
SD Secure Digital –
SDK Software Development Kit Trusă de dezǀoltare softǁare
SGML Standard Generialized Markup
Language Limbaj de marcare standard
generalizat
SSL Secure Sockets Layer –
TDD Time Division Duplex CoŵuŶiĐație duplex diǀizată îŶ
timp
URL Uniform Resourse Locator Localizator uniform de resurse
W3C World Wide Web Consortium –
WPA2 Wi-Fi Protected Access Acces protejat la Wi- Fi
XML Extensible Markup Language Limbaj de marcare extensibil

14

15
Introducere
Posibilitatea de a transmite mesaje la distanță a influențat și a modelat enorm societatea
umană . De la semnalele de fum din epoca preistorică , telegraful electric , telefonia prin cablu până
la internet , toate au avut un rol definitoriu pentru felul cum socializăm in ziua de astăz i prin
capacitatea de a comunica fără a fi nevoie să fim în imediata vecinătate.
Odată cu dezvoltarea internetului au apărut ceea ce au fost numite rețele de socializare,
medii prin care utilizatorii cu un interes comun pot comunica facil unii cu alții și pot partaja date
sau resurse. Datorită interconectivității globale oferite de internet , persoanele din toate părțile lumii
pot fi în contact în timp real , ceea ce reprezintă un avantaj major al acestui concept, fie că este
vorba de colegi de muncă , colegi de studiu din cadrul unei școli sau facultăți , prieteni , împărtășind
date utile tuturor sau simple conversații.
Astfel de medii au fost valabile încă din anii ’ 70 prin intermediul BBS sau Bulettin Board
Sistem care era practic un calculator server la care se puteau conecta mai mulți utilizatori folosind
un program terminal. A fost una din primele rețele care ducea cu gândul la ceea ce a fost
implementat mai târziu, cum ar fi Craigslist , LinkedIn , MySpace și bineînțeles cele mai cunoscute
din ziua de azi precum Twitter, Instagram sau Facebook. Toate au avut un succes aparte la timpul
lor, datorită nevoii tot mai mari a societății de a comunica și a sta permanent conectată.
Următorul pas a fost aducerea acestei posibilități pe platformele mobi le prin ap ariția
telefoanelor inteligente . Telefoanele mobile se puteau deja conecta la internet , dar datorită
tehnologiei de înaintea erei smartphone- urilor, erau limitate în capacitatea lor de a susține creșterea
din telecomunicații. Când tehnica a făcut posibilă fabricarea unui telefon inteligent , a apărut nevoia
creării unui sistem de operare care să fie convenabil, cele mai cunoscute și utilizate fiind iOS și
Android. Amândouă au avut un rol deosebit în evoluția rețelelor de socializare , aducând cu succes
aplicațiile, până acum disponbile în mare parte doar pe web, pe platformele mobile și adaptându -le
la mediul respectiv.
Am ales să dezvolt o aplicație pentru sistemul de operare Android pentru a îmi înmulți
cunoștințele despre programarea în Android și datorită rolului important pe care acesta îl are în
prezent, fiind cel mai popular sistem de operare pentru dispozitivele mobile, foarte răspândite în
ziua de astăzi. Posibilitatea de a împărți aplicația cu o multitudine de utilizatori constituie un a lt
punct important în alegerea temei.
Lucrarea de față își propune prezentarea unei aplicații de socializare pe o platformă mobilă,
care va permite utilizatorilor săi să intre în contact unii cu alții, fără a -și cunoaște datele de contact
în prealabil. Numărul utilizatorilor va fi unul restrâns, cum ar fi persoanele dintr-o cafenea,
restaurant sau o sală de conferințe. Aceasta se va realiza fără a fi nevoie de access la internet sau de
conectarea la un punct de access intermediar și se adresează utilizatorilor care folosesc un dispozitiv
mobil care suportă tehnologia Wi -Fi Direct.
În prezent se pune foarte mare accent pe a fi mereu conectat la internet și majoritatea
aplicațiilor implementează opțiuni pentru aceasta. Prin alegerea utilizării tehnologiei Wi -Fi Direct
am dorit să ofer posibilitatea utilizatorilor să intre în contact unii cu alții fără a avea nevoia unui
terț.
Majoritatea aplicațiilor de comunicație peste Wi -Fi, precum Wi-Fi Talkie sau WeChat, nu
folosesc funcția de Wi -Fi Direct și au nevoie de un dispozitiv intermediar pentru a funcționa, iar
aplicații precum Wi -Fi Social, care utilizează această tehnologie, au o interfață dificil de utilizat ,
spre deosebire de aplicația dezvoltată în această lucrare care are o interfață minimalistă și intuitivă.
Lucrarea va începe prin prezentarea sistemului de operare Android, istoricul acestuia și
câteva informații esențiale pentru a introduce cititorul în lumea celui mai popular sistem de operare
pentru dispozitive mobile inteligente. Se va continua cu detalii despre tehnologiile utilizate care au
ajutat la crearea și funcționarea corectă a aplicației Android propusă în această lucrare, urmat ă de
prezentarea mediului de dezvoltare Android Studio și se încheie cu descrierea funcționării aplicației
și concluziile a ferente.

16

Sistemul de operare Android Capitolul 1

Android este un sistem de operare bazat pe nucleul Linux folosit pentru dispozitive și
telefoane mobile, în principal cu ecran tactil, cum ar fi telefoanele inteligente și tabletele. Interfața
Android se bazează în principal pe manipulare directă a ecranului folosind gesturi care corespund
cu unele naturale pentru diferitele interacțiuni pe care utilizatorul le are cu dispozitivul ceea ce îl
face ușor de folos it pentru utilizatorul comun. În prezent Android este prezent pe o multitudine de
dispozitive, de la televizoare până la ceasuri inteligente, console de jocuri, camere digitale și chiar și
automobilie prin varianta sa Android Auto.

1.1 Istoric

Toată lumea asociază Android cu compania de care este deținut în prezent, dar este demn de
precizat că acesta nu a fost un proiect inițiat de Google, ci de către Andy Rubin, un inginer Apple,
împreună cu Rich Miner, Nick Sears și Chris White. Aceștia au fondat Android Inc. în luna
Octombrie a anului 2003. Compania era una de software cu nici un produs de vânzare pentru doi
ani, dar cu un plan de a crea și de a revoluționa următoarea generație de software pentru telefoa ne
inteligente. Aceștia s -au concentrat pe a oferi u tilizatorului o experiență de a fi cât mai conectat la
internet și în special de a face mediul Android unul în care orice dezvoltator de aplicații să poată să
creeze și să se acomodeze într -un timp cât mai scurt.
Răbdarea le -a fost răsplătită în anul 2005 când mai mulți investitori au relizat potențialul pe
care îl avea Android Inc. Compania a fost cumpărată în același an de către Google care dorea să
intre pe piața telefoanelor inteligente spre a rivaliza cu Microsoft și Blackberry și pentru a se
asigura c ă motorul de căutare preferat pentru dispozitivele mobile va fi cel deținut de ei. Platforma
Android le- a oferit celor de la Google exact ce aveau nevoie. La sfârșitul anului 2005, Rubin și
echipa sa lucrau în birourile din Mountain View, California pentru a aduce la viață viziunea pe care
o împărtășea cu cei de la Google.
Software nu înseamnă nimic fara hardware, așa că cei de la Google împreună cu partenerii
lor de la HTC s- au îmabarcat în misiunea lor de a crea o platformă fizică pentru sistemul de opera re
Android. După un număr de prototipuri, a fost lansat în anul 2008 telefonul T -Mobile G1,
reprezentat în Figura 1.1.

Figura 1.1 Telefonul inteligent T-Mobile G1

T-Mobile G1, care mai târziu a fost vândut sub numele HTC Dream, rula prima versiune de
Androi d ( 1.0 ) care este singura versiune fără un nume de cod. Aceasta a pornit revoluția care s -a

18
concretizat în cel mai răspândit sistem de operare pentru terminalele mobile inteligente, cu vânzări
mai mari decât Windows și iOS la un loc. [1]
Versiunile de Android care au urmat poartă numele unor deserturi și acestea sunt după cum
urmează:
 Android 1.5 – Cupcake
 Android 1.6 – Donut
 Android 2.0 – Éclair
 Android 2.2 – Froyo
 Android 2.3 – Gingerbread
 Android 3.0 – Honeycomb
 Android 4.0 – Ice Cream Sandwich
 Android 4.4 – KitKat
 Android 5.0 – Lollipop
 Android 6.0 – Marshmallow
 Android 7.0 – Nougat

Răspândirea acestor versiuni în prezent este reprezentat în Figura 1.2.

Figura 1.2 Răspândirea versiunilor Android în iunie 2017

În prezent sunt peste 2.8 milioane de aplicații pe Google Play Store , magazinul online prin
care Google oferă access la aplicații pentru sistemul de operare Android. Acest număr extraordinar
este datorat faptului că sistemul a pornit cu ideea de a încuraja dezvoltatorii să își creeze propriil e
aplicații, lucru susținut de oferirea publică a codului sursă pe care poate lucra și peste care poa te
aduce îmbunătățiri oricine.[3]

Sistemul de operare avea nevoie și de un logo pentru a pune o amprentă grafică pe ceea ce
se numește Android, iar acesta a fost creat de către Irina Blok. Inițial logo -ul era destinat doar către
dezvoltatorii de aplicații, dar a fost foarte bine primit și de către comunitatea de utilizatori încât a Gingerbread
1% Ice Cream
Sandwich
1% Jelly Bean
9%
KitKat
18%
Lollipop
31% Marshmallow
31% Nougat
9% Răspândirea versiunilor Android în
iunie 2017
Gingerbread
Ice Cream Sandwich
Jelly Bean
KitKat
Lollipop
Marshmallow
Nougat

19
fost adoptat ca logo oficial. Speculațiile spun ca logo -ul a fost inspirat fie dintr -un joc pentru
consola Atari , numit „ Gauntlet: The Third Encounter”, fie după imaginea popularului R2 -D2 din
seria de filme Star Wars. Cu toate acestea, Irina a explicat că au existat multe schițe până la
adoptarea sa și că logo -ul actual este chiar unul din primele sale idei. [2]
Logo -ul Android este reprezentat în Figura 1.3 .

Figura 1.3 Logo-ul oficial pentru sistemul de operare Android.

1.2 Evoluția sistemului de operare Android

Așa cum am descris în subcapitolul precedent, există mai multe versiuni al sistemului de
operare, versiuni care vor fi detaliate în subcapitolul curent.

Figura 1.4 – Evoluția Android

Primei versiuni ( Android 1.0 ) nu i-a fost dat nici un nume . Aceasta a apărut pentru prima
oară în anul 2008 pe platforma fizică HTC T -Mobile G1 și conținea opțiuni precum Gmail,
Bluetooth, Google Maps, o fereastră de notificări care se putea trage din partea de sus a ecranului și
cea mai importantă dintre toate, Android Market. Deși cea din urmă, la momentul respectiv, avea
doar 35 de aplicații, a atras atenția dezvoltatorilor, moment din care Android a început sa își pună
amprenta.
Mai târziu în februarie, anul 2009, a fost lansat Android 1.1, prima actualizare de software
care a adus cu sine rezolvarea unor bug- uri, precum și opțiunea de a salva documente atașate.

20
Android 1.5 a fost prima versiune de software căreia i -a fost dat un nume și astfe l a început
tradiția de a fi numite după deserturi, acesta fiind Cupcake. A fost lansat în anul 2009 cu API de
nivel 3 și a adus cu sine înregistrarea video și posibilitatea de a încărca filmele pe Youtube,
capabilitatea pentru widget- uri și efecte de tranziție animate,iar ta statura de pe ecran a primit
opțiunea de prezice re text.
Următoarea versiune a fost Android 1.6 , Donut, lansată în septembrie 2009 cu un număr
mare de îmbunătățiri, cele mai importante fiind un Android Market optimizat și capabilitatea de a
funcționa cu ecrane de rezoluție 800×480.
Una dintre cele mai populare versiuni, Android 2.0 – Éclair , a fost lansată în octombrie a
aceluiași an, aducând cu sine o multitudine de opțiuni orientate către camera foto/video. Dintre
acestea merită a fi enumerate magnificarea digitală, blitz -ul, modul decor, echilibrarea albului și
diferite efecte de culoare. De asemenea, a fost introdusă capabilitatea de atingere multiplă, care a
adus îmbunătățiri sporite pentru gesturile cu care utilizatorul interacționa cu dispozitivul.
În mai 2010 a fost lansat Android 2.2 – Froyo care permitea instalarea aplicațiilor pe un card
SD, precum și utilizarea ecranelor 720p, și integrarea cu Adobe Flash 10.1, ceea ce făcea posi bil
urmărirea de filme pe internet, nu doar prin intermediul aplicaț iei YouTube. Un pas important venit
odată cu această versiune este eliberarea SDK -ului pentru Android 2.2 , bazat pe Linux Kernel
2.6.32.
Următoarea generație de Android a fost Android 2.3, numit Gingerbread, lansat în
decembrie 2010, care a continuat să aducă îmbunătățiri rezoluției pe care era capabil să lucre ze
sistemul de operare, precum și introducerea tehnologiei NFC.
Februarie 2011 a marcat apariția Android 3.0 Honeycomb care a avut o orientare către a crea
o interfață specializată pentru dispozitive de tip tabletă. Astfel, elementele grafice au fost
restructurate pentru a îndeplini cât mai bine acest nou scop.
Android 4.0 – Ice Cream Sandwich a fost scos pe piață în octombrie 2011 și a adus cu sine
o interfață grafică mult îmbunătățită, împreună cu capacitatea de a suporta procesoare cu mai multe
nuclee, ceea ce a dus la capabilități sporite de procesare și de multi -tasking. Această versiune a avut
un impact major odată cu eliberarea patch-urilor 4.0.1 și 4.0.4 care au adus cu sine îmbunătățiri ale
performanței.
Android 4.4, numit KitKat, a fost eliberat publicului pe 3 septembrie 2013 și s -a bazat pe
optimizarea performanței pe terminalele mobile cu resurse fizice limitate. Împreună cu această
versiune a venit și Google Now, asistentul digital al celor de la Google. Utilizatorul, în loc să fie
nevoit să deschidă aplicații separate, poate să folosească comenzi vocale pentru diferite acțiuni,
funcție care este activată în momentul pronunțării frazei “ OK Google ”.
Android Lollipop, versiunea 5.0, a fost l ansat în anul 2014, pe 12 noiembrie și a adus cu sine
schimbări ale interfeței grafice și a notificărilor. Ceea ce merită menționat este faptul că odată cu
această versiune platforma internă, Dalvik, a fost înlocuită de Android Runtime, mai multe
informații despre aceasta găsindu -se în subcapitolul 1.3.3.
Versiunea 6.0, Android Marshmallow, lansată pe 5 octombrie 2015, implementează un mai
bun sistem de gestionare a energiei, care reduce activitatea de fundal atunci când dispozitivul nu
este fizic utilizat, precum și suport nativ pentru utilități pe bază de recunoașterea amprentei și
conectori USB Type- C.

21
Ultima versiune de Android eliberată , la data de 22 august 2016, este Android 7.0 Nougat.
Aceasta introduce schimbări notabile sistemului de operare și platformei de dezvoltare, incluzând
afișarea pe ecran a multiple aplicații în același timp prin împărțirea acestuia în diferite ferestre
destinate fiecăreia. Android Nougat a fost bine primit de utilizator în special datorită schimbărilor
aduse formatului notificărilor și a capacității de multi -tasking.[5]

Nume de cod Versiune Data lansării
Fără nume de cod 1.0 23 septembrie 2008
Fără nume de cod 1.1 9 februarie 2009
Cupcake 1.5 27 aprilie 2009
Donut 1.6 15 septmebrie 2009
Éclair 2.0 26 octombrie 2009
Froyo 2.2 20 mai 2010
Gingerbread 2.3 6 decembrie 2010
Honeycomb 3.0 22 februarie 2011
Ice Cream Sandwich 4.0 18 octombrie 2011
KitKat 4.4 3 septembrie 2013
Lollipop 5.0 12 noiembrie 2014
Marshmallow 6.0 5 octombrie 2015
Nougat 7.0 22 august 2016
Tabel 1.1 – Versiuni Android

1.3 Arhitectura Android

Android este o stivă de componente software împărțită în cinci secțiuni și în patru straturi
principale. Un mecanism de structurare a elementelor componente ale unui sistem software este
arhitectura stratificată. Nivelele alocă responsabilități în aplicație iar fiecare strat este un grup de
module care îndeplinesc aceleași funcții specifice.

Figura 1.5 Arhitectura Android

22

Componentele principale ale arhitecturii Android sunt reprezentate în Figura 1.5:

 Kernel-ul Linux
 Bibliotecile
 Motorul Android – Android Runtime
 Cadrul pentru aplicații – Application Framework
 Aplicațiile

Kernel -ul Linux 1.3.1
În acesta sunt conținute driver -ele pentru componentele hardware cum ar fi ecranul, camera
foto, antena WiFi, memoria flash, dispozitivele audio, etc. Acesta este responsabil de gestiunea
proce selor, a memoriei și a dispozitivelor periferice.
Kernel- ul Linux utilizat de Android diferă față de cel al sistemului de operare Linux utilizat
pe calculatoare, o diferență importantă fiind faptul că utilizatorii de terminale mobile nu au acces de
tip root, spre deosebire de utlizatorii de Linux de pe PC.
Alte îmbunătățiri au fost implementate pe parcursul timpului pentru a adapta cât mai bine
kernel-ul pentru scopul pe care acesta îl are :
 Binder – sistemul de comunicație interproces.
 Logger – sistemul ce facilitează stocarea de log-uri.
 Wave Locks – sistemul prin care se previne transferul sistemului de operare într- o
stare de latență.
 Viking Killer – mecanism prin care memoria utilizată este revendicată de sistemul de
operare atunci când aceasta ajunge la un anumit prag.
 YAFFS2 – sistem de fișiere adecvat cipurilor flash de memorie.
Bibliotecile 1.3.2
Componentele bibliotecilor se comportă ca un nivel de comunicare între kernel și
framework- ul aplicației și conțin codul care oferă principalele funcționalități ale sistemului de
operare Android. Librăriile sunt scrie în C/C++ dar sunt la dispoziția dezvoltatorilor software prin
intermediul unui Java API. Dezvoltatorii pot folosi framework- ul aplicației Java pentru a accesa
codul de bază C/C++ al librăriilor .
Principalele biblioteci:
 Media framework – conține o mulțime de drivere media
 SQLite – folosită ca spațiu de stocare și pentru partajarea datelor
 WebKit- motorul de căutare folosit pentru a afișa conținut HTML
 biblioteci SSL – pentru as igurarea securității pe Internet
 biblioteca libc – biblioteca de sistem C
Android Runtime 1.3.3
Android Runtime este o mașină virtuală, implementată odată cu versiunea 5.0, care folosește
tipul de compilare “Ahead of Time ”, în care bytecode-ul este transpus în cod mașină la momentul
instalării și astfel este executat direct de către mediul dispozitivului mobil.
Predecesorul acestuia este Dalvik Virtual Machine (DVM) , o mașină virtuală proprie
Android care este optimizată pentru a lucra cu telefoanele mobile, și din Bibliotecile de bază, care
permit dezvoltarea de aplicații Android folosind limbajul de programare Java.

23
Pentru fiecare tip de platformă hardware pe care rulează sistemul Android există o mașina
virtuală Dalvik care transformă codul în instrucțiuni native. Programele sunt compilate în fișiere de
tip .dex care sunt transferate pe dispozitive în fișiere de tip .apk.
DVM este dotată cu un compilator JIT (just -in-time) ceea ce permite ca executabilul obținut
să fie modificat în momentul instalării pe terminalul mobil, de asemenea arhitectura mașinii virtuale
este una bazată pe registre.
Odată cu introducerea mașinii virtuale ART s -a trecut la compilarea AOT (Ahead of Time)
care presupune compilarea întregii aplicații în cod mașină nativ, ceea ce a dus la creșterea eficienței
globale de execuție, la reducerea consumului de energie, îmbunătățind simțitor autonomia bateriei și
o alocare mai eficientă a memoriei. [6]

Framework-ul Android 1.3.4
Un framework este o abstractizare în care software- ul care oferă funcționalitate generică
poate fi modificat selectiv printr-un cod suplimentar scris de utilizator, oferind astfel software-ul
necesar unei aplicații specifice.
Toate opțiunile sistemul de operare Android sunt puse la dispoziția dezvoltatorului printr -un
set de API-uri scrise în limbajul de programare Java. Un API (Application Programming Interface)
reprezintă un set de definiții de sub -programe, protocoale și unelte pentru programarea de aplicații
și software. Acestea frunizează cărămizile de bază pentru a crea aplicații Android simplific ând
utilizarea componentelor și serviciilor de bază.
Framework-ul include :
 managerul activității – serviciul controlează toate aspectele timpului de viață al
aplicației și stiva de navigare a utilizatorului
 furnizorii de conținut – acest serviciu permite aplicațiilor să publice și să împartă date
cu alte aplicații (exemplu: cont actele din telefon)
 managerul de resurse – acest serviciu oferă acces la resurse încorporate fără cod cum
ar fi: strigs, setările de culoare, layout -ul interfeței cu utilizatorul
 managerul de notificări – acest serviciu permite aplicațiilor să afișeze alerte și
notificări utilizatorului
 sistemul de vizualizare – acest serviciu oferă un set extensibil de views care sunt
folosite pentru a crea interfețele cu utilizatorul

Nivelul Aplica ție 1.3.5
La acest nivel sunt rulate toate aplicațiile și aici, folosind toate cele de mai sus, se execută
produsele dezvoltatorilor.
Componenta aceasta a arhitecturii Android este cea mai apropiată cu care are contact
utilizatorul.

24

25
Tehnologii utilizate Capitolul 2

2.1 Java

Java a fost lansată de compania Sun Microsystems în anul 1995 și a avut un impact
remarcabil asupra dezvoltatorilor de software.
Atunci când vorbim despre Java este important să facem diferența dintre limbajul de
programare Java, mașina virtuală Java și platforma Java.
Limbajul de programare Java este limbajul în care aplicațiile Java sunt scrise. Programele
scrise în limbaj Java sunt formate din fișiere cu extensia .java care conțin codul sursă. Codul sursă
este codul format din instrucțiunile scrise de programator. Aceste fișiere sunt compilate și rezultă un
set de instrucțiuni în cod mașină ce se vor executa pe procesorul virtual Java si poartă numele de
bytecode. Acest cod se găsește într -un fișier cu același nume ca cel sursă dar cu extensia .class. La
rulare mașina virtuală execută codul cuprins în acest fișier.
Codul numit bytecode este o formă de cod portabil scris special pentru mașina virtuală Java
– JVM (Java Virtual Machine). Această mașină virtuală poate fi implementată direct pe hardware
dar este de obicei implementată sub forma unui program software care interpretează si execută cod
de tip bytecode.
Platforma Java este distinctă de limbajul de programare Java si de mașina virtuală Java.
Aceasta este formată dintr -un set de clase Java predefinite care există la orice instalare Java și pot fi
folosi te de orice program Java. Platforma Java este de asemenea referită ca JRE – Java Runtime
Environment sau ca nucleul API- urilor Java. Această platformă poate fi extinsă cu anumite extensii
standard opționale. Aceste extensii există doar în anumite instalări Java, existența lor nefiind
garantată pe toate. [11]

Limbajul de programare Java 2.1.1

Limbajul de programare Java este un limbaj modern, orientat pe obiecte și are o sintaxă
similară cu cea a limbajului de programare C. Creatorii limbajului au țintit să facă un limbaj de
programare puternic dar în același timp au încercat să evite caracteristicile mult pr ea complexe care
au tras în jos alte limbaje orientate pe obiecte cum ar fi C++. Menținând limbaj simplu, aceștia au
permis programatorilor să facă programe mult mai complicate mai ușor. Ca rezultat, limbajul Java a
devenit foarte popular în rândul programatorilor.
Acest limbaj a fost creat inițial de Sun Microsystems c a parte a unui proiect de dezvoltare a
unui software pentru echipament electronice casnice – televizoare, toastere și tot felul de alte
dispozitive casnice. Astfel limbajul a fost creat sa fie mic, eficient si ușor de transpus pe o gamă
mare de dispozitive hardware. Tocmai aceste lucruri au făcut din acest limbaj un adevărat succes
pentru că a fost perfect pentru a crea programe eficiente și a fost ușor de implementat pe mai multe
sisteme de operare.

Mașina virtuală Java 2.1.2

Mașina virtuală Java, notată de mu lte ori ca JVM – Java Virtual Machine este o piesă
cruciala pentru orice instalare Java.
Programele Java sunt portabile dar acest lucru este permis numai pe platforme care au un
interp retor Java la dispoziție.
Deși în general interpretorii nu sunt considerați sisteme cu performanțe înalte, mașina
virtuală Java are performanțe foarte bune și este extrem de stabilă. Un mare plus este tehnologia

26
JIT-just in time utilizată pentru compilare. Aceasta permite codului Java de tip bytecode sa fie
convertit în limbaj nativ pentru orice sistem într-un timp foarte scurt mai ales pentru un cod care
este rulat în mod repetat.
Mașina virtuală Java are trei componente principale:
 Subsistemul de încărcare a claselor – acest subsistem încarcă clasele programelor în
memorie
 Motorul de execuție – execută instrucțiunile din cadrul claselor încărcate în mașina
virtuală Java
 Zona de rulare a datelor – memorează componentele în timpul rulării programelor

Toate obiectele create în cadrul JVM se plasează într -o zonă de memorie care poartă
denumirea de Heap. Obiectele care nu mai sunt referite în cadrul programului ce se afl ă în execuție
se șterg cu ajutorul unei componente ce poartă numele de Garbage Collector.
Astfel programatorul nu trebuie să elibereze obiectele nefolositoare. Un alt avantaj este
acela că mecanismul nu permite ștergerea accidentală a obiectelor sau zonelor de memorie, lucru ce
ajută la menținerea integrității programului.

Platforma Java 2.1.3

Platforma Java este la fel de importantă ca și limbajul de programare si mașina virtuală.
Toate programele scrise în limbajul Java se bazează pe setul de clase predefinite care
compun platforma Java. Clasele Java sunt organizate în anumite grupuri sub formă de pachete.
Platforma Java definește pachetele după funcționalități cum ar fi grafica, crearea de interfețe,
securitatea, input/output și multe altele.
Un mare plus pentru platforma Java a fost lansarea Java 1.2. Aceasta a triplat numărul de
clase conținute de aceasta și a introdus funcționalități importate. Pentru a arăta acest lucru Sun a
numit această versiune Platforma Java 2. Acesta este un nume recunoscut și are importanță mai
mult din punct de vedere al marketing-ului.
Este important de înțeles ce înseamnă termenul de platformă. Pentru un programator o
platformă este definită de API -urile folosite pentru a scrie programele. Aceste API-uri sunt definite
de obicei de sistemul de operare al calculatorului. Deci un programator care scrie un progra m pe un
calculator cu sistemul de operare Microsoft Windows poate folosi un set diferit de API- uri față de
un programator care scrie același program pentru un calculator cu Unix. Din acest punct de ve dere
putem spune ca Windows, Machintosh si Unix au 3 platforme diferite.
Java nu este un sistem de operare. Cu toate acestea platfor ma Java conține API -uri care pot
fi comparabile cu cele definite de un sistem de operare. Cu ajutorul platformei poți scrie programe
Java fără a sacrifica anumite caracteristici esențiale disponibile programatorilor care scriu pr ograme
în limbaje native pe ntru un anumit sistem de operare. O aplicație scrisă pe platforma Java poate rula
pe orice sistem de operare care suportă această platformă. Asta înseamnă ca nu trebuie să creezi
câte un program distinct pentru Windows, Machintosh si Linux. Un singur program poate rula pe
toate aceste sistem de operare de unde a apărut si motto -ul companiei Sun pentru Java – Write once,
run anywhere.
Asta explică de ce unele companii precum Microsoft se pot simți amenințate de Java.
Platforma nu este un sistem de operare da r pentru programatori este o țintă de dezvoltare. Platforma
Java permite programatorilor să nu depindă de sistemul de operare pe care o să ruleze programele si
astfel crește libertatea utilizatorului de a alege un sistem de operare.

27
În funcție de versiune a de Java trebuie ales kitul de dezvoltare potrivit JDK – Java
Development Kit. De la versiunea Java 1.2 JDK a fost redenumit în SDK – Software Development
Kit.
Nu trebuie sa facem confuzia între JDK si JRE – Java Runtime Environment. JRE conține
tot ce e ste necesar pentru a rula programe Java dar nu conține instrumentele necesare pentru a
dezvolta aplicații Java .

2.2 XML

Extensible Markup Language (XML) , o versiune mai simplă și mai ușor de folosit a
Standard Generalized Markup Language (SGML), este un limbaj folosit pentru a descrie date.
Standardul este o metodă flexibilă de a crea formate de informație și de a distribu i electronic aceste
date structurate.
XML este o recomandare formală din partea World Wide Web Consortium (W3C) și este
similar limbajului HTML, Hypertext Markup Language. Ambele conțin simboluri marcate pentru a
descrie pagini sau conținutul unor fișiere. Codul HTML descrie conținutul unei pagini Web doar în
termenii în care aceasta este afișată și felul cum se interacționează cu aceasta, da tele XML sunt
cunoscute ca descriindu- se și definindu -se pe sine însuși, asta însemnând că nu este nevoie de o
compilare a limbajului scris, acesta este înțeles dinamic în cadrul XML. [7]
Celula de bază în cadrul unui document XML este elementul definit prin etichete. Un astfel
de element are o etichetă la început și una la final, ceea ce permite o ierarhizare a elementelor.
Altfel spus, un element poate conține mai multe elemente, care la rândul lor pot conține alte
elemente, toate cuprinse între etichetele lor proprii. Numele acestor elemente descriu conținutul, iar
structura ierarhiei descrie relația dintre elemente. Un exemplu de cod XML este prezentat în Figura
2.1.

Figura 2.1 – Exemplu XML

În cadrul Android sunt folosite mai multe fișiere XML, fiecare cu un scop propriu :
 Layout.xml – fișier folosit pentru a defini interfața grafică a aplicației Android.
 Manifest.xml – fișier în care sunt definite componentele aplicației, precum numele
pachetelor folosite, clasele, serviciile și permisiunile necesare funcționării aplicației .
 Strings.xml – în cadrul acestui fișier se pot defini o serie de cuvinte sub forma unui
singur string, la care se pot face referire doar prin acel string.
 Styles.xml – acest fișier este folosit pentru a defini diferite stiluri în ceea ce privește
interfața grafică a aplicației.
 XML-uri Drawable – fișier folosit pentru a integra diferite elemente grafice în
elemente ale aplicației.

28
Figura 2.2 conține un exemplu de L ayout.xml.

Figura 2.2 – Exemplu Layout.xml

2.3 Tehnologia Wi- Fi

Numele de Wi- Fi este o prescurtare a Wireless Fidelity, tehnologie bazată pe familia de
standarde IEEE 802.11. Sistemele curente de Wi- Fi permit o rată de date de peste 433 Mbps la
nivelul fizic, o rată de date mai mare decât sistemele 4G curente. Rețelele Wi-Fi sunt sisteme TDD
(Time division duplex), sisteme în care uplink-ul este separat de downlink prin alocarea de diferite
sloturi temporale în cadrul aceeași benzi de frecvență, largimea de bandă fiind între 20 de MHz și
25 de MHz în funcție de standard ul IEEE folosit.

Figura 2.3 – Logo-ul Wi- Fi
Principalele standarde din familia 802.11 2.3.1

802.11a este capabil de un transfer de date maxim de 54 Mbps și are o rază de aproximativ
30 de metri. Acesta folosește banda de frecvență de 5 GHz și ca metodă de codare OFDM
(Multiplexare divizată în frecvență ortogonală). Semnalul radio este compus din 52 de
subpurtătoare, dintre care 48 sunt folosite pentru transmisie de date, iar 4 sunt subpurtătoare pilot.
Lățimea de banda utilizată este de 20 MHz, iar separarea dintre subpurtătoare de 0.3125 MHz
obținându -se prin împărțirea lățimii de banda la 64. Diferența de la 52 la 64 este folosită ca bandă
de gardă.
802.11b este un standard aprobat în anul 1999 și are un trans fer de date maxim de 11 Mbps
deoarece folosește banda de frecvențe din jurul a 2.4 GHz și ca metodă de modulație este utilizat
CCK (complementary Code Keying).

29
802.11g ocupă o lățime de bandă de 22 MHz în banda de 2.4 GHz. Folosește ca metodă de
modulație atât OFDM cât și CCK pentru a fi în continuare compatibil cu 802.11b.
802.11n ca și 802.11g folosește atât ODFM cât și CCK, dar cu posibilitatea utilizării unei
lungimi de bandă de 40 de MHz și a unor îmbunătățiri aduse implementării OFDM, în cadrul
acestu i standard se poate ajunge la o rată maximă de date de 600 Mbps.
802.11ac sau Gigabit Wi- Fi a crescut mult lățimea de bandă utilizată până la 160 de MHz în
banda de 5 GHz, ceea ce a dus la creșterea ratei maxime de date la un teoretic 6.93 Gbps. [8]

Standardul
IEEE 802.11a 802.11b 802.11g 802.11n 802.11ac
Anul aprobării 1999 1999 2003 2009 2014
Frecvența 5 GHz 2.4 GHz 2.4 GHz 2.4 GHz/5
GHz 5 GHz
Rata maximă
de date 54 Mbps 11 Mbps 54 Mbps 600 Mbps 1 Gbps
Rază în
interior 30 m 30 m 40 m 70 m 27 m
Rază în
exterior 120 m 140 m 140 m 250 m 300 m
Tabel 2.1 – Principalele standarde din familia 802.11

Nivelul MAC 2.3.2

Pentru rețelele wireless definite în cadrul IEEE 802.11 există două opțiuni când vine vorba
de nivelul MAC (Medium Access Control), nivel care gestionează comunicarea din rețea, PCF
(Point Coordination Function) și DCF (Distrubuted Coordination Function). Majoritatea
producătorul au ales sa folosească a doua soluție.
DCF utilizează Carrier Sense Multiple Access with Collision Avoidance (CSMA/CA) în
cadrul căruia nivelul MAC instructează receptorul să caute dacă există o transmisiune în
desfășurare. În cazul în care acesta nu dectează o astfel de transmisiune, se trimite pachetul pentru
care se așteaptă un mesaj de confirmare. Dacă mesajul de confirmare nu a fost recepționat, după o
perioadă de timp, se ia de la capăt procesul până la o transmisiune reușită. [8]

Wi-Fi Direct 2.3.3

Wi-Fi Direct, numit la început Wi-Fi P2P (peer- to-peer) este un standard care permite
conectarea dispozitivelor fără a avea nevoie de un punct de acces separat. Spre deosebire de re țelele
fără fir ad hoc care folosesc comunicații multihop, Wi -Fi Direct est e un mod de comunicație fără fir
cu un singur hop.
Această tehnologie apare pentru utilizatorul obișnuit asemănătoare cu cea Bluetooth, doar că
permite rate de transfer de date și rază de acțiune mult mai mari. Mai mult decât atât, spre deosebire
de Bluet ooth, nu e nevoie ca ambele dispozitive care se conectează să fie capabile de Wi -Fi Direct,
e de ajuns doar unul din ele să posede această opțiune, iar celălalt tehnologia Wi -Fi standard.
Prin Wi-Fi Direct punctul de acces este înlocuit de unul virtual, un punct de acces software
(SoftAP) , creat pe dispozitivul capabil de această tehnologie. [9]

30
Wi-Fi Direct a fost implementat în sistemul de operare Android odată c u versiunea 4.0 Ice
Cream Sandwhich, în Figura 2.4 fiind reprezentată emblema utilizată pentru a informa utilizatorul
că are această opțiune activă.

Figura 2.4 – Emblemă Wi -Fi Direct în sistemul de operare Android

31
Mediul de dezvoltare Capitolul 3

Pentru dezovoltarea aplicațiilor Android se poate folosi orice editor de Java, cele mai
cunsocute și utilizate fiind IDE -urile Android Studio și Eclipse.
Un mediu integrat de dezovoltare (IDE – Integrated development environment) este o
aplicație software care furnizează facilități cuprinzătoare pentru programarea pe ca lculator și
dezvoltarea de aplicații. În general, un IDE este format dintr -un editor de cod sursă, o unealtă care
construiește programul și un debugger, dar poate veni și cu un interpretor și un compilator.
Eclipse este cel mai răspândit și popular IDE când vine vorba de Java . Cu ajutorul unor
plug- in-uri poate fi folosit și cu alte limbaje de programare cum ar fi C, C++, C#, Haskell,
JavaScript, etc.
Android Studio este IDE-ul recomandat de cei de la Google pentru a dezvolta aplicatii
Android și datorită interfeței grafice ușor de înțeles, faptul ca a fost dezvoltat special pentru
Android și a umeroaselor tutoriale pe care cei de la Google le oferă, am ales să folosesc ac est mediu
de dezvoltare.

3.1 Android Studio

Android Studio reprezintă cea mai rapidă metodă de a crea aplicați i pentru platforma
Android, aceasta incluzând telefoane, tablete, Android Auto, Android Wear și Android TV. Fiind
IDE- ul oficial de la Google, Android Studio include tot ce este nevoie pentru a crea o aplicație,
incluzând un editor de cod, un instrument de analiză a codului, emulatoare și multe altele. [10]

Figura 3.1 – Logo Android Studio

Android Studio este creat în coordonare cu platforma Android, așadar oferă toate API -urile
la zi și oferă urmatoarele opțiuni :
 Instant Run – cu această opțiune se pot face schimbări în cadrul aplicației și acestea
vor fi reflectate imediat în aplicația care deja rulează. Aceasta face să fie mult mai
ușor observabil și înțeles impactul pe care îl are o schimbare în cadrul aplicației.
 Android Emulator – cu această opțiune nu este nevoie de un suport fizic pentru a rula
aplicațiile create, ele pot fi rulate pe un dispozitiv virtual care utilizează resursele
fizice ale pltaformei pe care se lucrează pentru a emula un dispozitiv Android.
 Cloud Test Lab Integration – aplicațiile pot fi rulate pe o varietate mare de
dispozitive Android conținute în cadrul Android Test Lab, de asemenea pro iectele
vor fi salvate pe cloud și pot fi accesate de oriunde.
 App Indexing Code Generation & Test – vizibilitatea aplicațiilor în Google Search
poate fi îmbunătățită adăugând URL -uri autogenerate
 GPU Debugger Preview – pentru dezvoltatorii de aplicații s au jocuri folosind
OpenGL ES, aceștia pot vedea fiecare cadru și starea GL
 IntelliJ 15 – Android Studio este construit pe platforma de codare IntelliJ

32
Instant Run 3.1.1

În ziua de astăzi platformele mobile sunt centrate în jurul vitezei și agilității și totuși
construirea unei aplicații pentru o platformă mobilă poate fi uneori lentă. Instant Run este soluția
celor care au dezvoltat Android Studio pentru o dezvoltare rapidă și fluidă.
Această opțiune crește productivitatea accelerând ciclurile de editare, construire și rulare a
aplicațiilor. Prin apăsarea butonului de Instant Run, acesta va analiza schimbările care au fost făcute
și va determina cum poate să introducă noul cod în cea mai rapidă metodă posibilă.

Figura 3.2 – Butoanele specifice Instant Run

De fiecare dată când este posibil, va injecta schimbările din cod în aplicația care deja
rulează, astfel evitându -se o reconstruire a proiectului și o reinstalare a APK -ului, reducând timpul
necesar pentru a vizualiza schimbările.
Pentru anumite schimbări un restart al activității sau a aplicației este necesar, proces ca re tot
este mai rapid decât înainte.
Instant Run funcționează pentru orice dispozitiv cu sistem de operare Android sau emulator
care ruleaza API 14 sau mai mult ( Ice Cream Sandwich ). [10]

Emulatorul Android 3.1.2

Emulatorul Android este de trei ori mai rapid când vine vorba de CPU, RAM și operații de
introducere și producere de date în comparație cu versiunile sale anterioare. În cele mai multe
situații folosind emulatorul Android este chiar mai rapid decât utilizarea unui dispozitiv real, acesta
folosind la maxim performanțtele sistemului pe care este rulat cu performanțe mult mai bune decât
cele alea unui dispozitiv mobil comun.
Pe lângă viteză și performanță, emulatorul Android oferă o nouă interfață grafică pentru
utilizator și control al senzorilor.

33
Pentru instalări rapide ale aplicațiilor, APK -urile se pot trage peste fereastra cu emulatorul
pentru a îndeplini această acțiune. De asemenea acesta oferă opțiunile de a redimensiona fere astra și
oferă posibilitatea de a utiliza acțiuni multi -atingere.

Figura 3.3 – Emulatorul Android

Pentru a utiliza emulatorul Android este nevoie ca utilizatorul să aibe instalat SDK Tools
versiunea 25.1.1 sau mai nouă.
Pentru a crea un dispozitiv virtual Android Studio pune la dispoziție o listă de dispozitive
reale ale căror caracteristici vor fi oferite dispozitivului emulat, dar un utilizator își și poate
configura un dispozitiv cu caracteristicile dorite de acesta. [10]

Cloud Test Lab 3.1.3

Cloud Test Lab este un serviciu care permite ca aplicațiile dezvoltate să fie testate pe o
bandă largă de dispozitive și configurații de dispozitive prezente în cloud. Odată ce o testare inițială
a fost facută, dezvoltatorul are ocazia să compare rezultatele obținute cu un portofoliu întreg de
dispozitive fizice găzduite de centrele de date Google.
Chiar dacă nu există un test creat de dezvoltator, Cloud Test Lab conține o listă de teste
genrice care pot fi folosite pen tru a testa stabilitatea aplicației create.

34
Interfața Android Studio permite configurarea unei liste de astfel de teste și poate prezenta
rezultatele acestora într-un mod prietenos pentru utilizator. [10]

Figura 3.4- Interfață teste Cloud Test Lab

App Indexing 3.1.4

Cu ajutorul acestei opțiuni este mai ușor pentru utilizatori să găsească, cu ajutorul Google
Search, aplicația creată, Android Studio creând o structură URL în cadrul codului aplicației și
adăugând atributele necesare în fișierul AndroidManifest.xml care lucrează îndeaproape cu serviciul
Google App Indexing.
Dupa adăugarea URL -urilor, codul de ind exare al aplicației poate fi testat ca în Error!
Reference source not found. .

Figura 3.5 – Testare Google App Indexing

35
GPU Debugger 3.1.5

Pentru dezvoltatorii de aplicații care sunt mai intensive din punct de vedere al resurselor
grafice, GPU Debugger permite explorarea aplicației cadru cu cadru pentru identificarea
eventualelor erori de redare.

Figura 3.6- GPU Debugger

3.2 SDK

SDK – Software Development Kit este în mod tipic un set de unelte de dezvoltare a
programelor pe calculator. Pentru a aduce funcționalități avansate aplicațliei create, fiecare
dezvoltator impl ementează SDK -uri specifice pentru sistemul de operare căruia îi este destinată
aplicația sau specifice fiecărui limbaj de programare.
Pentru aplicații destinate iOS există iOS SDK, pentru Universal Windows Platform există
.NET Framework SDK, iar pentru Android este utilizat Java Development Kit ( JDK ).

Java Development Kit oferă o varietate de librării și clase gata implementate care ajută
dezvoltatorul în crearea unei aplicații fără a fi nevoie să implementeze de la zero anumite funcții
comune.

36

37
Dezvoltarea aplicației Capitolul 4

4.1 Descrierea proiectului

Așa cum spune și titlul lucrării, „Aplicație de socializare într -un grup restrâns de utilizatori ”,
proiectul își propune dezvoltarea unei aplicații destinat e sistemului de operare Android cu ajutorul
căreia utilizatorii se pot conecta unii la alții direct, fără a își cunoaște detaliile de contact în
prealabil, aceștia descoperindu -se unii pe alții în momentul când doresc să facă acest lucru.
Aplicația se folosește de tehnologia Wi -Fi Direct pentru a comunica, neavând nevoie de un
punct de acces intermediar (un router wireless) sau de o conexiune de date mobile. Conexiunea are
loc peste Wi- Fi, suprafața de acoperire limitându -se la capacitățile menționate în sub capitolul 2.3, în
funție de standardul folosit, astfel creând o rețea destinată unui număr restrâns de utilizatori.
Decizia alegerii acestei teme de licență a fost dorința de a îmi dezvolta cunoștințele despre
dezvoltarea de aplicații pe platforma Android și despre limbajul de programare Java.
Datorită faptului că aplicația nu are nevoie de conexiune la internet sau de un punct de acces
intermediar, aceasta poate fi utilizată oriunde fără ca utilizatorii să își facă griji de consumul de date
sau de conectarea la un router wireless, gestionarea rețelei fiind făcute chiar de propriile lor
dispozitive.
Aplicația implementează o interfață prietenoasă pentru utilizator, care nu necesită o
pregătire premergătoare utilizării acesteia. Navigația în cadrul aplicației se face cu ajutorul
butoanelor definite, care au etichete corespunzătoare funcției lor, ceea ce le fac intuitive și ușor de
înțeles.
Utilizatorii vor comunica uni i cu alții prin mesaje text în cadrul unui grup creat de unul din
ei, toți având acces la mesajele transmise atâta timp cât sunt conectați la deținătorul grupului.
Aceștia pot comunica și într -un mod privat conectându- se la persoana dorită. Informațiile pe care
aceștia le au la dispoziție în momentul descoperirii altor utilizatori sunt doar numele dispozitivului
utilizat de respectiva persoană și daca o conexiune se poate face, astfel încurajând pe cei c are
folosesc aplicația să trimită o invitație la o conversație pentru a cunoaște persoana respectivă.
Avantajul unei astfel de abordări pentru o aplicație de socializare este posibilitatea de a intra
în contact cu oricine din vecinătate oricând și oriunde fără a avea nevoie de o componentă terță care
să faciliteze acest lucru, atâta timp cât măcar unul din utilizatori are un dispozitiv capabil de Wi-Fi
Direct. Acest ultim punct ar putea fi considerat un dezavantaj, necesitatea unei capabilități
tehnologice anume, însă în ziua de astăzi majoritatea dispozitivelor dispun de această opțiune.
Numele aplicației este Coffee Partner, un nume sugestiv pentru scopul pentru care a fost
dezvoltată.

4.2 Crearea unei conexiuni P2P prin Wi- Fi în Android

Wi-Fi P2P permite aplicațiilor să găsească rapid și să interacționeze cu dispozitive
apropriate intr- o rază de acoperire mult mai mare față de capabilitățile tehnologiei Bluetooth.

API-ul Wi-Fi peer- to-peer permite conectarea la dispozitive apropriate fără a fi nevoie de
conectarea la o rețea sau a unui punct de acces separat, framework-ul Android Wi-Fi P2P fiind în
conformitate cu certificarea Wi-Fi Direct.

38

Wi-Fi Direct este o alegere potrivită pentru a aplicație care face parte dintr -o rețea de rază
mică și securizată datorită următoarelor motive :
 Criptarea WPA2 – Wi-Fi Protected Access II este un protocol de securitate dezvoltat
de Wi- Fi Alliance și a apărut pentru a umple neajunsurile WEP (Wired Equivalent
Privacy). Wi-Fi este capabil de astfel de criptare.
 Dispozitivele pot difuza serviciile pe care le oferă, ceea ce ajută alte dispozitive să
descopere dispozitive pereche adecvate.
 Când se determină ce dispozitiv ar trebui să fie deținătorul grupului pentru rețea, Wi –
Fi Direct examineaz ă pentru fiecare dispozitiv administrarea sa a energiei, interfața
grafică și capabilitățile de servicii și folosește aceste informații pentru a alege care
dispozitiv poate funcționa pe post de server cel mai eficient.
 Android nu oferă posibilitatea creării unei rețele Wi -Fi ad-hoc.

Permisiunile necesare Wi-Fi P2P 4.2.1

Pentru a folosi Wi- Fi P2P este necesar să fie adăugate în fișierul AndroidManifest.xml
permisiunile de ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE,
ACCESS_WIFI_STATE și INTERNET.
În cadrul Wi-Fi P2P nu este necesară o conexiune la internet, totuși sunt folosite socket -ele
standard Java, care au nevoie de permisiunea INTERNET. [17]

Figura 4.1 – Permisiunile necesare Wi-Fi P2P

39
Configurarea unui Broadcast Receiver și a unui P2P Manager 4.2.2

Pentru a folosi Wi- Fi P2P este necesară informarea aplicației de anumite evenimente care au
avut loc. Aceasta se implem entează prin configurarea unor unelte numite Intents, care sunt o
descriere abstractă a unei operații ce urmează să fie facută.
Este nevoie de crearea unui IntentFilter care să asculte pentru următoarele :
 WIFI_P2P_STATE_CHANGED_ACTION – indică dacă Wi -Fi P2P este pornit.
 WIFI_P2P_PEERS_CHANGED_ACTION – indică faptul că lista de dispozitive
pereche s-a schimbat.
 WIFI_P2P_CONNECTION_CHANGED_ACTION – indică faptul că starea
conectivității Wi -Fi P2P s-a schimbat.
 WIFI_P2P_THIS_DEVICE_CHANGED_ACTION – indică faptul că detaliile de
configurare ale dispozitivului s-au schimbat.

Figura 4.2 – Intent-urile necesare stabilirii conexiunii Wi-Fi P2P

La sfârșitul metodei onCreate() trebuie obținută o instanță a clasei WifiP2pManager și
apoi accesată metoda sa, initialize() pentru a obține un obiect WifiP2pManager.Channel,
obiect folosit mai târziu pentru a conecta aplicația la framework -ul Wi-Fi P2P. [17]

Figura 4.3 – Obținerea obiectului WifiP2pManager.Channel

40

Clasa BroadcastReceiver va fi creată pentru a asculta pentru schimbările în stările Wi -Fi
P2P, iar în metoda onReceive() se vor adăuga condiții pentru a trata fiecare din acestea.

Figura 4.4 – Metoda onReceive()

În cele din urmă se adaugă doua metode, onResume() și onPause() pentru a înregistra
intent- ul când activitatea este activă sau a anula înregistrarea când aceasta este inactivă.

Figura 4.5 – Metode le onResume() și onPause()

41
Inițializarea descoperirii dispozitivelor pereche 4.2.3

Pentru a căuta dispozitive apropiate se va accesa metoda discoverPeers() . Această
metodă are nevoie de două argumente WifiP2pManager.Channel și
WifiP2pManager.ActionListener.

Figura 4.6 – Metoda discoverPeers()

Obținerea unei liste de dispozitive pereche 4.2.4

Pentru a obține o listă de dispozitive pereche este necesar implementării unei interfețe
WifiP2pManager.PeerListListener , care oferă informații despre dispozitivele pereche care au fost
detectate și înștiințează aplicația.

Figura 4.7 – Popularea unei liste cu dispozitive pereche disponibile

42

După implementarea acestei interfețe, cu ajutorul metodei requestPeers() în interiorul
metode onReceive() se va cere lista de dispozitive pereche disponibile. [17]

Figura 4.8 – Cererea listei de dispozitive pereche disponibile

Conectarea la un dis pozitiv pereche 4.2.5

Pentru conectarea la un dispozitiv per eche trebuie mai întâi să i se cunoască adresa. Aceasta
se realizează creând un obiect WifiP2pConfig, apoi se adresează metoda connect().

Figura 4.9 – Metoda connect()

43

Crearea unui grup 4.2.6

Crearea unui grup presupune ca mai multe dispozitive să se conecteze la unul singur care va
fi considerat deținătorul grupului. Pentru aceasta se vor urma aceeași pași ca și până acum, cu
excepția faptului ca în loc de metoda connect() se va utliza metoda createGroup() .

Figura 4. 10 – Metoda createGroup()

4.3 Structura proiectului

Proiectul este împărțit în trei module, dosarul manifests, dosarul java și dosarul res, structură
reprezentată în Figura 4.11.

Figura 4. 11 – Structura aplicației

Dosarul manifests 4.3.1

Manifests coține fișierul AndroidManifest.xml în care sunt informații esențiale pentru
sistemul Android despre aplicație pe care sistemul trebuie să le cunoască înainte de rula codul
aplicației.

44

Funcțiile sale principale sunt :
 Indică pachetul Java pentru aplicație.

 Decla ră permisiunile pe care aplicația trebuie să le aibă pentru a funcționa.

 Descrie componentele aplicației care includ activitățile și serviciile folosite.

45
Dosarul Java 4.3.2

Acesta conține codul Java și structura acestuia este reprezentată în Figura 4.12.

Figura 4. 12 – Structura dosarului java

Dosarul conține o singură activitate P2PcommunicationActivity.java . O activitate în
Android este clasă care se ocupă de crearea ferestrei în care dezvoltatorul își va implementa
interfața grafică. O aplicație poate implementa în același proiect mai multe astfel de activități pentru
a avea mai multe ecrane diferite pentru a interacționa cu funcțiile aplicației.
În proiectul de față am folosit o singură activitate, trecerea de la un ecran la altul fă cându -se
cu ajutorul unor fragmente, ce vor fi detaliate mai jos.
În această clasă creează interfața grafică, pe baza informațiilor din fișierele xml, interfa ță cu
care utilizatorul va interacționa. De asemenea, tot aici, se va obține o instanță a unui
WifiP2pBroadcastReceiver, descris în subcapitolul 4.2.2 , care va asculta pentru schimbările de stare
ale Wi-Fi P2P.

Dosarul fragment conține două fișiere java CommunicationFragment.java și
DiscoveryAndConnectionFragment.java care gestioneză funcționalitatea celor două fragmente
din singura activitate a aplicației.
Un fragment reprezintă comportamentul dintr -o porțiune din interfața grafică a aplicației
dintr- o activitate specifică. Prin combinarea a mai multor fragmente se dă impresia utilizatorul ui de
activități multiple care de fapt sunt toate sub aceeași activitate.
Fragmentele au fost introduse în Android 3.0 pentru a crea interfețe grafice mai dinamice și
mai flexibile, în special pentru dispozitivele cu ecrane mari, cum ar fi tabletele, dator ită posibilității
ca pe același ecran afișat să existe un număr mai mare de ferestre cu opțiuni care aparțin fie căreia și
a nu fi nevoie să se treacă de la un ecran la altul pentru a accesa opțiuni în afara capabilităților
ecranului curent.
Dosarul broadcastreceiver conține fișierul WifiP2pBroadcastReceiver.java care a mai fost
descris mai sus.

46
În pachetul multicast sunt conținute fișiere care gestionează serviciul de chat, transmiterea
și recepționarea de mesaje text, odată ce o conexiune între utilizatori este realizată, prin crearea de
socketuri de rețea în care mesajul este scris și din care este citit.
Un socket de rețea este un capăt de linie pentru transmiterea și recepționarea de mesaje
căruia îi este asociat o adresă de rețea și un număr de port.
Dosarul adapter conține clase care gestionează ajustarea elementelor de interfață grafică din
fiecare fragment pentru acțiunea care a avut loc. Astfel interfața va fi actualizată cu informațiile
necesare.
Pachetul utils conține un subpachet n umit button care la rândul său conține fișiere care
gestionează evenimentele care au loc prin apăsarea celor două butoane și de asemenea schimbă
starea acestora și eticheta lor în funcție de aceasta. Stările sunt definite într -un fișier de tip Enum
reprezentat în Figura 4. 13 . Un fișier Enum în Java este un tip special de fișier care îi permite unei
variabile să aibă valoarea a unor constante predefinite.

Figura 4. 13 – Fișierul de tip enum

Tot în pachetul utils se găsește fișierul NetworkUtil.java care are rolul de a obține
informații despre adresa IP pe care o folosesc utilizatorii și definirea unui Port, informații asignate
socketurilor descrise mai sus în pachetul multicast.

Dosarul res 4.3.3

Acest dosar conține fișierele xml care sunt utilizate pentru definierea elementelor de
interfață grafică, precum și fișiere de tip imagine care sunt folosite drept diverse iconițe în cadrul
aplicației. Structura acestuia este prezentată în Figura 4.14.

Figura 4. 14 – Structura dosarului res

47

Pachetul drawable conține fișierele de format imagine descrise mai sus.

Dosarul layout conține fișierele care descriu interfața grafică a celor trei secțiuni alea
ecranului :
 Main – cel din partea de sus a ecranului, cu informații despre dispozitivul propriu,
 fragmentul de descoperire și conectare – partea de jos inițială a ecranului inițial,
 fragmentul de comunicare – reprezentat de chat-ul propriu-zis.
În pachetul values se găsesc fișiere xml care sunt folosite pentru a defini valori pentru
variabile String, codul culorilor folosite în cadrul interfeței grafice a aplicației și dimensiunile
elementelor de interfață grafică.

4.4 Descrierea funcționării

Subcapitolul acesta își propune descrierea funcționării aplicației cu ajutorul unor capturi de
ecrani obținute de pe trei dispozitive mobile cu capabilități de Wi -Fi Direct.
În figura de mai jos este prezentată o schemă logică a funcționării aplicației. Am realizat
această diagramă utilizând resursele oferite de draw.io, un software online gratuit special conceput
pentru crearea de diagrame logice, organigrame, scheme de rețea sau scheme de circuite electronice
și electrice.

48

La deschiderea aplicației singura activitate din cadrul aplicației va construi interfața grafică
cu ajutorul informațiilor din main.xml și va arăta ca în Figura 4.15.

Figura 4. 15 – Ecran inițial aplicație

Ecranul va conține detaliile despre dispozitivul propriu și fragmentul definit în
DiscoveryAndConnectionFragment.java .

Prin apăsarea butonului Descoperă se va face un apel către metoda onRequestPeers()
și se începe căutarea de dispozitive pereche pentru a popula lista din fragmentul menționat. De
asemenea butonul își schimbă starea și eticheta, devenind Stop cum este prezentat în Figura 4.16.

Figura 4. 16 – Căutare dispozitive pereche

49

Lista din cadrul fragmentului va fi populată cu dispozitivele pereche identificate așa cum se
poate observa în Figura 4.16 . Acestea vor dobândi o poziție în cadrul fragmentului, poziție ce va
trebuie memorată pentru când va veni momentul ca utilizatorul să încerce să se conecteze la unul
din dispozitivele din listă.
Unul din utilizatori are acum posibilitatea de a crea un grup apăsând pe butonul Creează
Grup și apoi de a trimite invitații de conectare celorlalți prin selectarea lor din listă, așa cum este
îndemnat prin textul Atinge pentru a te conecta.

Figura 4. 17 – Crearea unui grup
Figura 4. 18 – Trimiterea unei invitații de conectare

În momentul creării unui grup se face apel la metoda onCreateGroup() din activitate,
după ce butonul din drea pta jos își va schimba starea din CREATE_GROUP în DISCONNECT și
eticheta sa se va schimba în Deconectează -te pentru a facilita această opțiune în caz că utilizatorul
dorește să o folosească. Textul din partea de sus a ecranului se va actualiza și va menționa dacă
dispozitivul curent este sau nu deținătorul grupului, precum și adresa IP. Verificarea dacă un
utilizator este deținătorul grupului are loc în activitatea principală folosind metoda
onGroupHostInfoChanged().
În momentul trimiterii unei invitații starea dispozitivului selectat va fi actualizată cu textul
Invitat, precum și butonul din dreapta jos, trecând în starea CANCEL_INVITATION, iar etich eta
acestuia va afișa textul corespunzător. Invitația se trimite către dispozitivul de la poziția adecvată,
poziție memorată în prealabil, care identifică dispozitivul în lista ArrayList din fragment.

50

Utilizatorul invitat are posibilitatea să accepte sau să refuze invitația ca în figura de mai jos.

Figura 4. 19 – Invitație de conectare

Accesarea celui de-al doilea fragment se face prin glisarea spre stânga. Mesajele pot fi
trimise imediat după crearea grupului și vor fi trimise cu succes, chiar dacă nu este nici un alt
utilizator care să le recepționeze.
În momentul realizării conexiunii sau atunci când un grup este creat, chiar dacă singurul
participan t este deținătorul, un socket este creat cu ajutorul serviciului definit în fișierul
MulticastMessageReceiverService .java din pachetul multicast cu informațiile obținute din
NetworkUtil.java.
Mesajele se vor scrie în caseta de introducere text, implementat în
communication_fragment.xml și adăgat în fragmentul definit în CommunicationFragment.java .
Prin apăsarea butonului din dreapta jos, textul va fi preluat și scris în socket ul creat spre a fi trimis
către socketul fiecărui dispozitiv conectat, din care acesta extrage mesajul și actualizează interfa ța
grafică din fragmentul CommunicationFragment.
Administrarea creării socketu rilor și a transmiterii și recepționării de mesaje este realizată de
clasele d efinite în fișierele din dosarul multicast.
Interfața grafică va fi actualizată la fiecare mesaj trimis sau recepționat. Dacă mesajul a fost
trimis atunci se va actualiza cu layout-ul message_sent_layout.xml , iar în caz contrat cu
message_received_layout.xml.

51

Mesajele vor apărea pentru toți utilizatorii precum în Figura 4.20 și Figura 4.21.

Figura 4. 20 – Chat utilizator 1
Figura 4. 21 – Chat utilizator 2

Pentru ca un utilizator să se deconecteze de la grup este nevoie ca acesta să navigheze înapoi
la p rimul fragment și să utilizeze butonul Deconectează -te și s e va apela metoda
onDisconnect() din activitate.

52

53
Concluzii

În ziua de astăzi se pune din ce în ce mai mult accent pe a fi permanent conectat la internet,
iar dezvoltarea puternică și rapidă a tehnologiei telecomunicațiilor creează un mediu foarte bun
pentru dezvoltatorii de aplicații de socializare care permit conectarea utilizatorilor săi pe distanțe
foarte mari, limitate doar de raza de acoperire a operatorului de telefonie care furnizează
conexiunea de date sau de raza de acoperire a celui mai apropiat punct de acces la internet.
Coffe Partner este o încercare de a face ceva diferit, oferind posibilitatea de a intra în contact
cu persoane din apropiere fără a depinde de un terț.
Aplicația implementează un serviciu de chat, o opțiune esențială fiecărei aplicații de
socializare, folosind pentru conectarea utilizatorilor tehnologia Wi- Fi Direct fără nevoia conectării
la un punct de acces intermediar ceea ce face ca utilizarea ei să fie pentru un număr mic de
utilizatori pe o suprafață limitată de capabilitățile tehnologiei Wi -Fi a fiecărui dispozitiv pe care
aceasta este instalată.
Necunoașterea detaliilor de contact în prealabil, descoperirea dispozitivelor făcându -se la un
moment specific în timp și opțiunea de a crea un grup în care se pot transmite și primi mesaje la
care toți participanții la grup au acces încurajează ca persoanele să intre în contact unele cu altele.
Mai multe opțiuni pot fi implementate pe viitor cum ar fi posibilitatea de a trimite și
recepționa imagini și fișiere sau o opțiune de localizare a dispozitivelor conectate la grup sub forma
unei hărți în jurul deținătorului grupului. Acestea ar duce la creșterea complexității aplicației și
utilizarei ei aducând mai multe avantaje.

54

55
Bibliografie

[1] Android Pre-History, Alex Dobie, Russell Holly, Jerry Hildenbrand, Andrew Martonik,
Android Central, https://www.androidcentral.com/android-pre-history
[2] Povestea din spatele Logo-ului Android, Marc Knoll, http://trendblog.net/the-story-of-the-
android-logo/
[3] Număr de aplicații Google Play Store, https://www.statista.com/statistics/266210/number-
of-available-applications- in-the-google-play-store/
[4] Statistica aplicații descărcate din Google Play Store,
https://www.statista.com/statistics/281106/number-of-android-app-downloads-from-
google-play/
[5] Evoluția sistemului de operare Android, Spinfold, http://www.spinfold.com/evolution-of-
android-os/
[6] Arhitectura Android, Android Developers Guides
https://developer.android.com/guide/platform/index.html
[7] XML, Margaret Rouse, Tamas E. Doszkocs, Gerhard Hill, Fredrik Lindgren, Neil
Yashinsky, http://searchmicroservices.techtarget.com/definition/XML-Extensible-Markup-
Language
[8] Standardele Wi-Fi IEEE 802.11, http://www.radio-electronics.com/info/wireless/wi-fi/ieee-
802-11-standards-tutorial.php
[9] Wi-Fi Direct, Wi-Fi Alliance, https://www.wi-fi.org/discover- wi-fi/wi- fi-direct
[10] Android Studio 2.0, Jamal Eason, Android Developers Blog https://android-
developers.googleblog.com/2016/04/android-studio-2-0.html
[11] Java in a nutshell – O ’Reilly & Associates, Inc., 1005 Gravenstein Highway North,
Sebastopol, CA 95472.
[12] App Manifest, Android Developers Guides
https://developer.android.com/guide/topics/manifest/manifest-intro.html
[13] Activity, Android Developers Guides
https://developer.android.com/reference/android/app/Activity.html
[14] Fragment, Android Developers Guides
https://developer.android.com/guide/components/fragments.html
[15] Adapter, Android Developers Guides
https://developer.android.com/reference/android/widget/Adapter.html
[16] Comunicarea cu interfața grafică, Android Developers Guides
https://developer.android.com/training/multiple-threads/communicate-ui.html
[17] Crearea unei conexiuni P2P prin Wi-Fi în Android, , Android Developers Guides
https://developer.android.com/training/connect-devices-wirelessly/wifi-direct.html
[18] Unealtă software de creat diagrame logice https://www.draw.io/

57
ANEXA 1 Codul Java
P2pCommunicationActivity.java

package com.george.cofeepartner;

import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import
android.net.wifi.WifiManager.MulticastLoc
k;
import
android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;
import
android.net.wifi.p2p.WifiP2pManager;
import
android.net.wifi.p2p.WifiP2pManager.Conne
ctionInfoListener;
import
android.net.wifi.p2p.WifiP2pManager.PeerL
istListener;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import
android.support.v4.app.FragmentActivity;
import
android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import butterknife.ButterKnife;
import butterknife.InjectView ;
import
com.george.cofeepartner.adapter.P2pCommun
icationFragmentPagerAdapter;
import
com.george.cofeepartner.broadcastreceiver
.WifiP2pBroadcastReceiver;
import
com.george.cofeepartner.fragment.Communic
ationFragment;
import
com.george.cofeepartner.fragment.Discover
yAndConnectionFragment;
import
com.george.cofeepartner.listener.discover
y.DiscoveryStateListener;
import
com.george.cofeepartner.listener.invitati
on.InvitationToConnectListener;
import
com.george.cofeepartner.listener.multicas
t.MulticastListener;
import
com.george.cofeepartner.listener.onpagech
ange.ViewPagerOnPageChangeListener;
import
com.george.cofeepartner.listener.wifip2p.
WifiP2pListener;
import
com.george.cofeepartner.wifip2p.P2pCommun
icationWifiP2pManager;

public class P2PCommunicationActivity
extends FragmentActivity implements WifiP2pListener, MulticastListener {

public static final String TAG =
P2PCommunicationActivity. class.getSimpleN
ame();
private
P2pCommunicationWifiP2pManager
p2pCommunicationWifiP2pManager ;
private WifiP2pBroadcastReceiver
wifiP2pBroadcastReceiver ;
private
P2pCommunicationFragmentPagerAdapter
p2pCommunicationFragmentPagerAdapter ;
private boolean wifiP2pEnabled ;

@InjectView (R.id.view_pager )
ViewPager viewPager ;

@InjectView (R.id.my_device_name_text_view
) TextView myDeviceNameTextView ;

@InjectView (R.id.my_device_status_text_vi
ew) TextView myDeviceStatusTextView ;

@InjectView (R.id.am_i_host_question_text_
view) TextView amIHostQuestionTextView ;
@InjectView (R.id.host_ip_text_view )
TextView hostIpTextView ;

@Override
protected void onCreate(Bundle
savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout. main);

ButterKnife. inject(this);
createAndAcquireMulticastLock();
p2pCommunicationWifiP2pManager =
new
P2pCommunicationWifiP2pManager(getApplica
tionContext());
wifiP2pBroadcastReceiver = new
WifiP2pBroadcastReceiver(getApplicationCo
ntext(), this);

p2pCommunicationFragmentPagerAdapter =
new
P2pCommunicationFragmentPagerAdapter(getS
upportFragmentManager(),
getFragmentList());
setViewPager( viewPager ,
p2pCommunicationFragmentPagerAdapter );
}

@Override
public void onResume() {
super.onResume();

registerReceiver( wifiP2pBroadcastReceiver
, createWifiP2pIntentFilter());
}

@Override
public void onPause() {
super.onPause();

unregisterReceiver( wifiP2pBroadcastReceiv
er);
}

58

@Override
public void onWifiP2pStateEnabled() {
wifiP2pEnabled = true;
}

@Override
public void onWifiP2pStateDisabled()
{
wifiP2pEnabled = false;
}

@Override
public void onStartPeerDiscovery() {
if (wifiP2pEnabled ) {
DiscoveryStateListener
discoveryStateListener =
p2pCommunicationFragmentPagerAdapter .getD
iscoveryAndConnectionFragment();

p2pCommunicationWifiP2pManager .startPeerD
iscovery(discoveryStateListener);
} else {
Toast. makeText (this,
R.string. wifi_p2p_disabled_please_enable ,
Toast.LENGTH_SHORT ).show();
}
}

@Override
public void onStopPeerDiscovery() {
DiscoveryStateListener
discoveryStateListener =
p2pCommunicationFragmentPagerAdapter .getD
iscoveryAndConnectionFragment();

p2pCommunicationWifiP2pManager .stopPeerDi
scovery(discoveryStateListener);
}

@Override
public void onRequestPeers() {
PeerListListener peerListListener
=
p2pCommunicationFragmentPagerAdapter .getD
iscoveryAndConnectionFragment();

p2pCommunicationWifiP2pManager .requestPee
rs(peerListListener);
}

@Override
public void onConnect(WifiP2pDevice
wifiP2pDevice) {
InvitationToConnectListener
invitationToConnectListener =
p2pCommunicationFragmentPagerAdapter .getD
iscoveryAndConnectionFragment();

p2pCommunicationWifiP2pManager .connect(wi
fiP2pDevice,
invitationToConnectListener);
}

@Override
public void onCancelConnect() {

p2pCommunicationWifiP2pManager .cancelConn
ect();
}
@Override
public void onDisconnect() {

p2pCommunicationWifiP2pManager .disconnect
();
}

@Override
public void onIsDisconnected() {

p2pCommunicationFragmentPagerAdapter .getD
iscoveryAndConnectionFragment().reset();

p2pCommunicationFragmentPagerAdapter .getC
ommunicationFragment().reset();
onGroupHostInfoChanged( null);
}

@Override
public void onCreateGroup() {

p2pCommunicationWifiP2pManager .createGrou
p();
}

@Override
public void onRequestConnectionInfo()
{
ConnectionInfoListener
connectionInfoListener =
p2pCommunicationFragmentPagerAdapter .getD
iscoveryAndConnectionFragment();

p2pCommunicationWifiP2pManager .requestCon
nectionInfo(connectionInfoListener);
}

@Override
public void
onThisDeviceChanged(WifiP2pDevice
wifiP2pDevice) {

myDeviceNameTextView .setText(wifiP2pDevic
e.deviceName );

myDeviceStatusTextView .setText(getDeviceS
tatus(wifiP2pDevice. status));
}

@Override
public void
onGroupHostInfoChanged(WifiP2pInfo
wifiP2pInfo) {
if (wifiP2pInfo != null &&
wifiP2pInfo. groupFormed &&
wifiP2pInfo. isGroupOwner ) {

amIHostQuestionTextView .setText(getString
(R.string. am_i_host_question ) + " " +
getResources().getString(R.string. yes));

hostIpTextView .setText(getString(R.string
.ip_capital_letters ) + ": " +
wifiP2pInfo. groupOwnerAddress .getHostAddr
ess());
} else if (wifiP2pInfo != null &&
wifiP2pInfo. groupFormed ) {

amIHostQuestionTextView .setText(getString

59
(R.string. am_i_host_question ) + " " +
getResources().getString(R.string. no));
hostIpTextView .setText( "");
} else {

amIHostQuestionTextView .setText( "");
hostIpTextView .setText( "");
}
}

@Override
public void
onStartReceivingMulticastMessages() {

p2pCommunicationFragmentPagerAdapter .getC
ommunicationFragment().startReceivingMult
icastMessages();
}

private void
createAndAcquireMulticastLock() {
WifiManager wifiManager =
(WifiManager)
getSystemService( WIFI_SERVICE );
if (wifiManager != null) {
MulticastLock multicastLock =
wifiManager.createMulticastLock( TAG);
multicastLock.acquire();
}
}

private void setViewPager(ViewPager
viewPager, PagerAdapter pagerAdapter) {

viewPager.setOnPageChangeListener( new
ViewPagerOnPageChangeListener(viewPager))
;

viewPager.setAdapter(pagerAdapter);
}

private List<Fragment>
getFragmentList() {
List<Fragment> fragmentList = new
ArrayList<>();

fragmentList.add(DiscoveryAndConnectionFr
agment.newInstance ());

fragmentList.add(CommunicationFragment. ne
wInstance ());
return fragmentList;
}

private IntentFilter
createWifiP2pIntentFilter() {
IntentFilter wifiP2pIntentFilter
= new IntentFilter();

wifiP2pIntentFilter.addAction(WifiP2pMana
ger.WIFI_P2P_STATE_CHANGED_ACTION );

wifiP2pIntentFilter.addAction(WifiP2pMana
ger.WIFI_P2P_PEERS_CHANGED_ACTION );

wifiP2pIntentFilter.addAction(WifiP2pMana
ger.WIFI_P2P_CONNECTION_CHANGED_ACTION );

wifiP2pIntentFilter.addAction(WifiP2pMana
ger.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION ); return wifiP2pIntentFilter;
}

private String getDeviceStatus( int
deviceStatus) {
switch (deviceStatus) {
case WifiP2pDevice. AVAILABLE :
return
getString(R.string. available );
case WifiP2pDevice. INVITED:
return
getString(R.string. invited);
case WifiP2pDevice. CONNECTED :
return
getString(R.string. connected );
case WifiP2pDevice. FAILED:
return
getString(R.string. failed);
case
WifiP2pDevice. UNAVAILABLE :
return
getString(R.string. unavailable );
default:
return
getString(R.string. unknown);
}
}

}

P2pCommunicationWifiP2pManager.java

package com.george.cofeepartner.wifip2p;

import android.content.Context;
import android.net.wifi.WpsInfo;
import
android.net.wifi.p2p.WifiP2pConfig;
import
android.net.wifi.p2p.WifiP2pDevice;
import
android.net.wifi.p2p.WifiP2pManager;
import
android.net.wifi.p2p.WifiP2pManager.PeerL
istListener;
import
android.net.wifi.p2p.WifiP2pManager.Chann
el;
import
android.net.wifi.p2p.WifiP2pManager.Conne
ctionInfoListener;

import com.george.cofeepartner.R;
import
com.george.cofeepartner.listener.invitati
on.InvitationToConnectListener;
import
com.george.cofeepartner.listener.discover
y.DiscoveryStateListener;
import
com.george.cofeepartner.listener.wifip2p.
action.WifiP2pCancelConnectActionListener
;
import
com.george.cofeepartner.listener.wifip2p.
action.WifiP2pConnectActionListener;
import
com.george.cofeepartner.listener.wifip2p.
action.WifiP2pCreateGroupActionListener;

60
import
com.george.cofeepartner.listener.wifip2p.
action.WifiP2pDisconnectActionListener;
import
com.george.cofeepartner.listener.wifip2p.
action.WifiP2pStartPeerDiscoveryActionLis
tener;
import
com.george.cofeepartner.listener.wifip2p.
action.WifiP2pStopPeerDiscoveryActionList
ener;

public class
P2pCommunicationWifiP2pManager {

private Context context;
private WifiP2pManager
wifiP2pManager ;
private Channel wifiP2pChannel ;

public
P2pCommunicationWifiP2pManager(Context
context) {
this.context = context;
this.wifiP2pManager =
getWifiP2pManager();
this.wifiP2pChannel =
initializeWifiP2pChannel();
}

public void
startPeerDiscovery(DiscoveryStateListener
discoveryStateListener) {

wifiP2pManager .discoverPeers( wifiP2pChann
el, new
WifiP2pStartPeerDiscoveryActionListener( c
ontext, discoveryStateListener));
}

public void
stopPeerDiscovery(DiscoveryStateListener
discoveryStateListener) {

wifiP2pManager .stopPeerDiscovery( wifiP2pC
hannel, new
WifiP2pStopPeerDiscoveryActionListener( co
ntext, discoveryStateListener));
}

public void
requestPeers(PeerListListener
peerListListener) {

wifiP2pManager .requestPeers( wifiP2pChanne
l, peerListListener);
}

public void connect(WifiP2pDevice
wifiP2pDevice,
InvitationToConnectListener
invitationToConnectListener) {

wifiP2pManager .connect( wifiP2pChannel ,
createWifiP2pConfig(wifiP2pDevice), new
WifiP2pConnectActionListener( context,
invitationToConnectListener));
}

public void disconnect() {
wifiP2pManager .removeGroup( wifiP2pChannel
, new
WifiP2pDisconnectActionListener( context))
;
}

public void createGroup() {

wifiP2pManager .createGroup( wifiP2pChannel
, new
WifiP2pCreateGroupActionListener( context)
);
}

public void
requestConnectionInfo(ConnectionInfoListe
ner connectionInfoListener) {

wifiP2pManager .requestConnectionInfo( wifi
P2pChannel , connectionInfoListener);
}

public void cancelConnect() {

wifiP2pManager .cancelConnect( wifiP2pChann
el, new
WifiP2pCancelConnectActionListener( contex
t));
}

public static String
getFailureReason(Context context, int
reasonCode) {
switch (reasonCode) {
case WifiP2pManager. BUSY:
return
context.getString(R.string. busy);
case WifiP2pManager. ERROR:
return
context.getString(R.string. internal_error
);
case
WifiP2pManager. P2P_UNSUPPORTED :
return
context.getString(R.string. wifi_p2p_unsup
ported);
default:
return
context.getString(R.string. unknown_error )
;
}
}

private WifiP2pManager
getWifiP2pManager() {
return (WifiP2pManager)
context.getSystemService(Context. WIFI_P2P
_SERVICE );
}

private Channel
initializeWifiP2pChannel() {
return
wifiP2pManager .initialize( context,
context.getMainLooper(), null);
}

private WifiP2pConfig
createWifiP2pConfig(WifiP2pDevice

61
wifiP2pDevice) {
WifiP2pConfig wifiP2pConfig = new
WifiP2pConfig();
wifiP2pConfig. deviceAddress =
wifiP2pDevice. deviceAddress ;
wifiP2pConfig. wps.setup =
WpsInfo. PBC;
return wifiP2pConfig;
}
}
ConnectionButton.java
package
com.george.cofeepartner.util.button;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;

import butterknife.ButterKnife;
import butterknife.OnClick ;
import com.george.cofeepartner.R;
import
com.george.cofeepartner.listener.wifip2p.
WifiP2pListener;

public class ConnectionButton extends
Button {

private WifiP2pListener
wifiP2pListener ;
private
DiscoveryAndConnectionButtonState
buttonState ;

public ConnectionButton(Context
context) {
super(context);
}

public ConnectionButton(Context
context, AttributeSet attrs) {
super(context, attrs);
}

public ConnectionButton(Context
context, AttributeSet attrs, int
defStyleAttr) {
super(context, attrs,
defStyleAttr);
}

public void
initialize(WifiP2pListener
wifiP2pListener) {
this.wifiP2pListener =
wifiP2pListener;
setStateCreateGroup();
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife. inject(this);
}

@OnClick
public void onClick() {
if (buttonState ==
DiscoveryAndConnectionButtonState. CANCEL_INVITATION ) {

wifiP2pListener .onCancelConnect();
} else if (buttonState ==
DiscoveryAndConnectionButtonState. CREATE_
GROUP) {

wifiP2pListener .onCreateGroup();
} else if (buttonState ==
DiscoveryAndConnectionButtonState. DISCONN
ECT) {

wifiP2pListener .onDisconnect();
}
}

public void
setStateCancelInvitation() {

setText(getContext().getString(R.string. c
ancel_invitation ));
buttonState =
DiscoveryAndConnectionButtonState. CANCEL_
INVITATION ;
}

public void setStateCreateGroup() {

setText(getContext().getString(R.string. c
reate_group ));
buttonState =
DiscoveryAndConnectionButtonState. CREATE_
GROUP;
}

public void setStateDisconnect() {

setText(getContext().getString(R.string. d
isconnect ));
buttonState =
DiscoveryAndConnectionButtonState. DISCONN
ECT;
}

}

DiscoveryAndCOnnectionButtonState.java

package
com.george.cofeepartner.util.button;

public enum
DiscoveryAndConnectionButtonState {

START_DISCOVERY ,
STOP_DISCOVERY ,
CANCEL_INVITATION ,
CREATE_GROUP ,
DISCONNECT ;

}

DiscoveryButton.java

package
com.george.cofeepartner.util.button;

import android.content.Context;

62
import android.util.AttributeSet;
import android.widget.Button;

import butterknife.ButterKnife;
import butterknife.OnClick ;
import com.george.cofeepartner.R;
import
com.george.cofeepartner.listener.wifip2p.
WifiP2pListener;

public class DiscoveryButton extends
Button {

private WifiP2pListener
wifiP2pListener ;
private
DiscoveryAndConnectionButtonState
buttonState;

public DiscoveryButton(Context
context) {
super(context);
}

public DiscoveryButton(Context
context, AttributeSet attrs) {
super(context, attrs);
}

public DiscoveryButton(Context
context, AttributeSet attrs, int
defStyleAttr) {
super(context, attrs,
defStyleAttr);
}

public void
initialize(WifiP2pListener
wifiP2pListener){
this.wifiP2pListener =
wifiP2pListener;
setStateStartDiscovery();
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife. inject(this);
}

@OnClick
public void onClick() {
if (buttonState ==
DiscoveryAndConnectionButtonState. START_D
ISCOVERY ) {

wifiP2pListener .onStartPeerDiscovery();
} else if (buttonState ==
DiscoveryAndConnectionButtonState. STOP_DI
SCOVERY) {

wifiP2pListener .onStopPeerDiscovery();
}
}

public void setStateStartDiscovery()
{

setText(getContext().getString(R.string. d
iscover)); buttonState =
DiscoveryAndConnectionButtonState. START_D
ISCOVERY ;
}

public void setStateStopDiscovery() {

setText(getContext().getString(R.string. s
top));
buttonState =
DiscoveryAndConnectionButtonState. STOP_DI
SCOVERY;
}
}

NetworkUtil.java

package com.george.cofeepartner.util;

import android.util.Log;

import
org.apache.http.conn.util.InetAddressUtil
s;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;

public class NetworkUtil {

private static final String TAG =
NetworkUtil. class.getSimpleName();
private static final String
MULTICAST_GROUP_IP = "239.255.1.1" ;
private static final String
NETWORK_INTERFACE_NAME = "p2p-wlan0-0" ;
private static final String
ALTERNATE_NETWORK_INTERFACE_NAME = "p2p-
p2p0";
private static final int PORT =
40000;

public static int getPort() {
return PORT;
}

public static InetAddress
getMulticastGroupAddress() throws
UnknownHostException {
return
InetAddress. getByName (MULTICAST_GROUP_IP )
;
}

public static NetworkInterface
getWifiP2pNetworkInterface() throws
SocketException {
Enumeration<NetworkInterface>
networkInterfaceEnumeration =
NetworkInterface. getNetworkInterfaces ();
while
(networkInterfaceEnumeration.hasMoreEleme
nts()) {
NetworkInterface
networkInterface =
networkInterfaceEnumeration.nextElement()

63
;
if
(isWifiP2pInterface (networkInterface)) {
return networkInterface;
}
}
return null ;
}

public static String
getMyWifiP2pIpAddress() {
try {
Enumeration<InetAddress>
inetAddressEnumeration =
getWifiP2pNetworkInterface ().getInetAddre
sses();
while
(inetAddressEnumeration.hasMoreElements()
) {
InetAddress inetAddress =
inetAddressEnumeration.nextElement();
if
(isIpv4Address (inetAddress)) {
return
inetAddress.getHostAddress().toString();
}
}
} catch (SocketException e) {
Log. e(TAG, e.toString());
}
return null ;
}

private static boolean
isWifiP2pInterface(NetworkInterface
networkInterface) throws SocketException
{
return networkInterface.isUp() &&
(networkInterface.getDisplayName().equals
(NETWORK_INTERFACE_NAME) ||
networkInterface.getDisplayName().contain
s(ALTERNATE_NETWORK_INTERFACE_NAME));
}

private static boolean
isIpv4Address(InetAddress inetAddress) {
return
!inetAddress.isLoopbackAddress() &&
InetAddressUtils.isIPv4Address(inetAddres
s.getHostAddress());
}

}

UserInputHandler.java

package com.george.cofeepartner.util;

public interface UserInputHandler {

String
getMessageToBeSentFromUserInput();

void clearUserInput();
}

MulticastMessage.java

package
com.george.cofeepartner.multicast;

public class MulticastMessage {

private String text;
private String senderIpAddress;
private boolean sentByMe ;

public MulticastMessage(String text,
String senderIpAddress) {
this.text = text;
this.senderIpAddress =
senderIpAddress;
}

public MulticastMessage(String text,
String senderIpAddress, boolean sentByMe)
{
this.text = text;
this.senderIpAddress =
senderIpAddress;
this.sentByMe = sentByMe;
}

public String getText() {
return text;
}

public String getSenderIpAddress() {
return senderIpAddress;
}

public boolean isSentByMe() {
return sentByMe ;
}

public void setSentByMe( boolean
sentByMe) {
this.sentByMe = sentByMe;
}
}

MulticastMessageReceivedHandler.java

package
com.george.cofeepartner.multicast;

import android.os.Handler;
import android.os.Message;

import
com.george.cofeepartner.listener.multicas
t.MulticastMessageReceivedListener;
import
com.george.cofeepartner.util.NetworkUtil;

public class
MulticastMessageReceivedHandler extends
Handler {

public static final String
RECEIVED_TEXT = "RECEIVED_TEXT" ;
public static final String
SENDER_IP_ADDRESS = "SENDER_IP_ADDRESS" ;
private
MulticastMessageReceivedListener

64
multicastMessageReceivedListener ;

public
MulticastMessageReceivedHandler(Multicast
MessageReceivedListener
multicastMessageReceivedListener) {

this.multicastMessageReceivedListener =
multicastMessageReceivedListener;
}

@Override
public void handleMessage(Message
messageFromMulticastMessageReceiverServic
e) {
MulticastMessage multicastMessage
=
createMulticastMessage(messageFromMultica
stMessageReceiverService);

multicastMessageReceivedListener .onMultic
astMessageReceived(multicastMessage);
}

private MulticastMessage
createMulticastMessage(Message
messageFromMulticastMessageReceiverServic
e) {
String receivedText =
getReceivedText(messageFromMulticastMessa
geReceiverService);
String senderIpAddress =
getSenderIpAddress(messageFromMulticastMe
ssageReceiverService);
MulticastMessage multicastMessage
= new MulticastMessage(receivedText,
senderIpAddress);
if
(senderIpAddress.equals(NetworkUtil. getMy
WifiP2pIpAddress ())) {

multicastMessage.setSentByMe( true);
}
return multicastMessage;
}

private String
getSenderIpAddress(Message
messageFromReceiverService) {
return
messageFromReceiverService.getData().getS
tring(SENDER_IP_ADDRESS );
}

private String
getReceivedText(Message
messageFromReceiverService) {
return
messageFromReceiverService.getData().getS
tring(RECEIVED_TEXT );
}
}

MulticastMessageReceiverService.java

package
com.george.cofeepartner.multicast;

import android.app.IntentService; import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;

import
com.george.cofeepartner.util.NetworkUtil;

public class
MulticastMessageReceiverService extends
IntentService {

public static final String TAG =
MulticastMessageReceiverService. class.get
SimpleName();
public static final String
ACTION_LISTEN_FOR_MULTICAST =
"ACTION_LISTEN_FOR_MULTICAST" ;
public static final String
EXTRA_HANDLER_MESSENGER =
"EXTRA_HANDLER_MESSENGER" ;
public static boolean isRunning =
false;

public
MulticastMessageReceiverService() {

super(MulticastMessageReceiverService. cla
ss.getSimpleName());
}

@Override
protected void onHandleIntent(Intent
intent) {
final String action =
intent.getAction();
if
(action.equals( ACTION_LISTEN_FOR_MULTICAS
T)) {
isRunning = true;
try {
MulticastSocket
multicastSocket =
createMulticastSocket();
while (isRunning ) {
DatagramPacket
datagramPacket = createDatagramPacket();

multicastSocket.receive(datagramPacket);

sendReceivedDataToMulticastMessageReceive
dHandler(getHandlerMessenger(intent),
datagramPacket);
}
} catch (IOException |
RemoteException e) {
Log. e(TAG, e.toString());
}
}

65
}

@Override
public void onDestroy() {
isRunning = false;
super.onDestroy();
}

private void
sendReceivedDataToMulticastMessageReceive
dHandler(Messenger handlerMessenger,
DatagramPacket datagramPacket) throws
RemoteException {
Message handlerMessage =
createHandlerMessage(getReceivedText(data
gramPacket),
getSenderIpAddress(datagramPacket));

handlerMessenger.send(handlerMessage);
}

private Message
createHandlerMessage(String
receivedMessage, String senderIpAddress)
{
Bundle receivedData = new
Bundle();

receivedData.putString(MulticastMessageRe
ceivedHandler. RECEIVED_TEXT ,
receivedMessage);

receivedData.putString(MulticastMessageRe
ceivedHandler. SENDER_IP_ADDRESS ,
senderIpAddress);
Message handlerMessage = new
Message();

handlerMessage.setData(receivedData);
return handlerMessage;
}

private Messenger
getHandlerMessenger(Intent intent) {
return (Messenger)
intent.getExtras().get( EXTRA_HANDLER_MESS
ENGER);
}

private String
getSenderIpAddress(DatagramPacket
datagramPacket) {
return
datagramPacket.getAddress().getHostAddres
s();
}

private String
getReceivedText(DatagramPacket
datagramPacket) {
return new
String(datagramPacket.getData(), 0,
datagramPacket.getLength());
}

private MulticastSocket
createMulticastSocket() throws
IOException {
MulticastSocket multicastSocket =
new MulticastSocket(getPort());
multicastSocket.setNetworkInterface(getNe
tworkInterface());
multicastSocket.joinGroup( new
InetSocketAddress(getMulticastGroupAddres
s(), getPort()), getNetworkInterface());
return multicastSocket;
}

private NetworkInterface
getNetworkInterface() throws
SocketException {
return
NetworkUtil. getWifiP2pNetworkInterface ();
}

private InetAddress
getMulticastGroupAddress() throws
UnknownHostException {
return
NetworkUtil. getMulticastGroupAddress ();
}

private int getPort() {
return NetworkUtil. getPort();
}

private DatagramPacket
createDatagramPacket() {
byte[] buffer = new byte [1024];
return new DatagramPacket(buffer,
buffer.length);
}
}

SendMulticastMessageAsyncTask.java

package
com.george.cofeepartner.multicast;

import android.os.AsyncTask;
import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;

import
com.george.cofeepartner.listener.multicas
t.MulticastMessageSentListener;
import
com.george.cofeepartner.util.NetworkUtil;
import
com.george.cofeepartner.util.UserInputHan
dler;

public class
SendMulticastMessageAsyncTask extends
AsyncTask<Void, String, Boolean> {

public static final String TAG =
SendMulticastMessageAsyncTask. class.getSi
mpleName();
private MulticastMessageSentListener

66
multicastMessageSentListener ;
private UserInputHandler
userInputHandler ;

public
SendMulticastMessageAsyncTask(MulticastMe
ssageSentListener
multicastMessageSentListener,
UserInputHandler userInputHandler) {
this.multicastMessageSentListener
= multicastMessageSentListener;
this.userInputHandler =
userInputHandler;
}

@Override
protected Boolean
doInBackground(Void… params) {
boolean success = false;
try {
MulticastSocket
multicastSocket =
createMulticastSocket();
String messageToBeSent =
userInputHandler .getMessageToBeSentFromUs
erInput();
DatagramPacket datagramPacket
= new
DatagramPacket(messageToBeSent.getBytes()
, messageToBeSent.length(),
getMulticastGroupAddress(), getPort());

multicastSocket.send(datagramPacket);
success = true;
} catch (IOException ioException)
{
Log. e(TAG,
ioException.toString());
}
return success;
}

@Override
protected void onPostExecute(Boolean
success) {
if (!success) {

multicastMessageSentListener .onCouldNotSe
ndMessage();
}

userInputHandler .clearUserInput();
}

private MulticastSocket
createMulticastSocket() throws
IOException {
MulticastSocket multicastSocket =
new MulticastSocket(getPort());

multicastSocket.setNetworkInterface(getNe
tworkInterface());
multicastSocket.joinGroup( new
InetSocketAddress(getMulticastGroupAddres
s(), getPort()), getNetworkInterface());
return multicastSocket;
}

private NetworkInterface getNetworkInterface() throws
SocketException {
return
NetworkUtil. getWifiP2pNetworkInterface ();
}

private InetAddress
getMulticastGroupAddress() throws
UnknownHostException {
return
NetworkUtil. getMulticastGroupAddress ();
}

private int getPort() {
return NetworkUtil. getPort();
}

}

DiscoveryStateListener.java

package
com.george.cofeepartner.listener.discover
y;

public interface DiscoveryStateListener {

void onStartedDiscovery();

void onStoppedDiscovery();

}

InvitationToConnectListener.java

package
com.george.cofeepartner.listener.invitati
on;

public interface
InvitationToConnectListener {

void onSentInvitationToConnect();

}

MulticastListener.java

package
com.george.cofeepartner.listener.multicas
t;

public interface MulticastListener {

void
onStartReceivingMulticastMessages();

}

MulticastMessageReceivedListener.java

package
com.george.cofeepartner.listener.multicas
t;

67
import
com.george.cofeepartner.multicast.Multica
stMessage;

public interface
MulticastMessageReceivedListener {

void
onMulticastMessageReceived(MulticastMessa
ge multicastMessage);
}

MulticastMessageSentListener.java

package
com.george.cofeepartner.listener.multicas
t;

public interface
MulticastMessageSentListener {

void onCouldNotSendMessage();

}

ViewPagerOnPageChangeListener.java

package
com.george.cofeepartner.listener.onpagech
ange;

import android.support.v4.view.ViewPager;
import
android.support.v4.view.ViewPager.OnPageC
hangeListener;

public class
ViewPagerOnPageChangeListener implements
OnPageChangeListener {

private ViewPager viewPager ;

public
ViewPagerOnPageChangeListener(ViewPager
viewPager) {
this.viewPager = viewPager;
}

@Override
public void onPageScrolled( int
position, float positionOffset, int
positionOffsetPixels) {
}

@Override
public void onPageSelected( int
position) {

viewPager .setCurrentItem(position);
}

@Override
public void
onPageScrollStateChanged( int position) {
}
}
WifiP2pCancelConnectActionListener.java

package
com.george.cofeepartner.listener.wifip2p.
action;

import android.content.Context;
import
android.net.wifi.p2p.WifiP2pManager.Actio
nListener;
import android.util.Log;
import android.widget.Toast;

import com.george.cofeepartner.R;
import
com.george.cofeepartner.wifip2p.P2pCommun
icationWifiP2pManager;

public class
WifiP2pCancelConnectActionListener
implements ActionListener {

private static final String TAG =
WifiP2pCancelConnectActionListener. class.
getSimpleName();
private final Context context;

public
WifiP2pCancelConnectActionListener(Contex
t context) {
this.context = context;
}

@Override
public void onSuccess() {
Toast. makeText (context,
context.getString(R.string. successfully_c
ancelled_connection ),
Toast.LENGTH_SHORT ).show();
Log. i(TAG,
context.getString(R.string. successfully_c
ancelled_connection ));
}

@Override
public void onFailure( int reasonCode)
{
String reason =
context.getString(R.string. could_not_canc
el_connection ) + ": ";
reason +=
P2pCommunicationWifiP2pManager. getFailure
Reason(context, reasonCode);
Toast. makeText (context, reason,
Toast.LENGTH_SHORT ).show();
Log. w(TAG, reason);
}
}

WifiP2pConnectActionListener.java

package
com.george.cofeepartner.listener.wifip2p.
action;

import android.content.Context;
import
android.net.wifi.p2p.WifiP2pManager;
import android.util.Log;

68
import android.widget.Toast;

import com.george.cofeepartner.R;
import
com.george.cofeepartner.listener.invitati
on.InvitationToConnectListener;
import
com.george.cofeepartner.wifip2p.P2pCommun
icationWifiP2pManager;

public class WifiP2pConnectActionListener
implements WifiP2pManager.ActionListener
{

private static final String TAG =
WifiP2pConnectActionListener. class.getSim
pleName();
private Context context;
private InvitationToConnectListener
invitationToConnectListener ;

public
WifiP2pConnectActionListener(Context
context, InvitationToConnectListener
invitationToConnectListener) {
this.context = context;
this.invitationToConnectListener
= invitationToConnectListener;
}

@Override
public void onSuccess() {

invitationToConnectListener .onSentInvitat
ionToConnect();
Log. i(TAG,
context.getString(R.string. successfully_s
ent_invitation_to_connect ));
}

@Override
public void onFailure( int reasonCode)
{
String reason =
context.getString(R.string. could_not_send
_invitation_to_connect ) + ": ";
reason +=
P2pCommunicationWifiP2pManager. getFailure
Reason(context, reasonCode);
Toast. makeText (context, reason,
Toast.LENGTH_SHORT ).show();
Log. w(TAG, reason);
}
}

WifiP2pCreateGroupActionListener.java

package
com.george.cofeepartner.listener.wifip2p.
action;

import android.content.Context;
import
android.net.wifi.p2p.WifiP2pManager.Actio
nListener;
import android.util.Log;
import android.widget.Toast;

import com.george.cofeepartner.R; import
com.george.cofeepartner.wifip2p.P2pCommun
icationWifiP2pManager;

public class
WifiP2pCreateGroupActionListener
implements ActionListener {

private static final String TAG =
WifiP2pCreateGroupActionListener. class.ge
tSimpleName();
private final Context context;

public
WifiP2pCreateGroupActionListener(Context
context) {
this.context = context;
}

@Override
public void onSuccess() {
Log. i(TAG,
context.getString(R.string. successfully_c
reated_group ));
}

@Override
public void onFailure( int reasonCode)
{
String reason =
context.getString(R.string. could_not_crea
te_group );
reason +=
P2pCommunicationWifiP2pManager. getFailure
Reason(context, reasonCode);
Toast. makeText (context, reason,
Toast.LENGTH_SHORT ).show();
Log. w(TAG, reason);
}
}

WifiP2pDisconnectActionListener.java

package
com.george.cofeepartner.listener.wifip2p.
action;

import android.content.Context;
import
android.net.wifi.p2p.WifiP2pManager;
import android.util.Log;
import android.widget.Toast;

import com.george.cofeepartner.R;
import
com.george.cofeepartner.wifip2p.P2pCommun
icationWifiP2pManager;

public class
WifiP2pDisconnectActionListener
implements WifiP2pManager.ActionListener
{

private static final String TAG =
WifiP2pDisconnectActionListener. class.get
SimpleName();
private Context context;

public

69
WifiP2pDisconnectActionListener(Context
context) {
this.context = context;
}

@Override
public void onSuccess() {
Log. i(TAG,
context.getString(R.string. successfully_d
isconnected ));
}

@Override
public void onFailure( int reasonCode)
{
String reason =
context.getString(R.string. could_not_disc
onnect) + ": ";
reason +=
P2pCommunicationWifiP2pManager. getFailure
Reason(context, reasonCode);
Toast. makeText (context, reason,
Toast.LENGTH_SHORT ).show();
Log. w(TAG, reason);
}

}

WifiP2pStartPeerDiscoveryListener.java

package
com.george.cofeepartner.listener.wifip2p.
action;

import android.content.Context;
import
android.net.wifi.p2p.WifiP2pManager.Actio
nListener;
import android.util.Log;
import android.widget.Toast;

import com.george.cofeepartner.R;
import
com.george.cofeepartner.listener.discover
y.DiscoveryStateListener;
import
com.george.cofeepartner.wifip2p.P2pCommun
icationWifiP2pManager;

public class
WifiP2pStartPeerDiscoveryActionListener
implements ActionListener {

private static final String TAG =
WifiP2pStartPeerDiscoveryActionListener. c
lass.getSimpleName();
private final Context context;
private DiscoveryStateListener
discoveryStateListener ;

public
WifiP2pStartPeerDiscoveryActionListener(C
ontext context, DiscoveryStateListener
discoveryStateListener) {
this.context = context;
this.discoveryStateListener =
discoveryStateListener;
}
@Override
public void onSuccess() {

discoveryStateListener .onStartedDiscovery
();
Log. i(TAG,
context.getString(R.string. successfully_s
tarted_discovery ));
}

@Override
public void onFailure( int reasonCode)
{
String reason =
context.getString(R.string. could_not_star
t_discovery ) + ": ";
reason +=
P2pCommunicationWifiP2pManager. getFailure
Reason(context, reasonCode);
Toast. makeText (context, reason,
Toast.LENGTH_SHORT ).show();
Log. w(TAG, reason);
}

}

WifiP2pStopPeerDiscoveryActionListener.
java

package
com.george.cofeepartner.listener.wifip2p.
action;

import android.content.Context;
import
android.net.wifi.p2p.WifiP2pManager.Actio
nListener;
import android.util.Log;
import android.widget.Toast;

import com.george.cofeepartner.R;
import
com.george.cofeepartner.listener.discover
y.DiscoveryStateListener;
import
com.george.cofeepartner.wifip2p.P2pCommun
icationWifiP2pManager;

public class
WifiP2pStopPeerDiscoveryActionListener
implements ActionListener {

private static final String TAG =
WifiP2pStopPeerDiscoveryActionListener. cl
ass.getSimpleName();
private final Context context;
private DiscoveryStateListener
discoveryStateListener ;

public
WifiP2pStopPeerDiscoveryActionListener(Co
ntext context, DiscoveryStateListener
discoveryStateListener) {
this.context = context;
this.discoveryStateListener =
discoveryStateListener;
}

70
@Override
public void onSuccess() {

discoveryStateListener .onStoppedDiscovery
();
Log. i(TAG,
context.getString(R.string. successfully_s
topped_discovery ));
}

@Override
public void onFailure( int reasonCode)
{
String reason =
context.getString(R.string. could_not_stop
_discovery ) + ": ";
reason +=
P2pCommunicationWifiP2pManager. getFailure
Reason(context, reasonCode);
Toast. makeText (context, reason,
Toast.LENGTH_SHORT ).show();
Log. w(TAG, reason);
}
}

WifiP2pListener.java

package
com.george.cofeepartner.listener.wifip2p;

import
android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;

import
android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;

public interface WifiP2pListener {

void onWifiP2pStateEnabled();

void onWifiP2pStateDisabled();

void onStartPeerDiscovery();

void onStopPeerDiscovery();

void onRequestPeers();

void onConnect(WifiP2pDevice
wifiP2pDevice);

void onCancelConnect();

void onDisconnect();

void onIsDisconnected();

void onCreateGroup();

void onRequestConnectionInfo();

void
onThisDeviceChanged(WifiP2pDevice
wifiP2pDevice);

void
onGroupHostInfoChanged(WifiP2pInfo wifiP2pInfo);

}

CommunicationFragment.java

package com.george.cofeepartner.fragment;

import android.content.Intent;
import android.os.Bundle;
import android.os.Messenger;
import android.support.v4.app.Fragment;
import
android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import butterknife.ButterKnife;
import butterknife.InjectView ;
import butterknife.OnClick ;
import com.george.cofeepartner.R;
import
com.george.cofeepartner.adapter.ChatListA
dapter;
import
com.george.cofeepartner.adapter.P2pCommun
icationFragmentPagerAdapter;
import
com.george.cofeepartner.listener.multicas
t.MulticastMessageReceivedListener;
import
com.george.cofeepartner.listener.multicas
t.MulticastMessageSentListener;
import
com.george.cofeepartner.multicast.Multica
stMessage;
import
com.george.cofeepartner.multicast.Multica
stMessageReceivedHandler;
import
com.george.cofeepartner.multicast.Multica
stMessageReceiverService;
import
com.george.cofeepartner.multicast.SendMul
ticastMessageAsyncTask;
import
com.george.cofeepartner.util.UserInputHan
dler;

public class CommunicationFragment
extends ListFragment implements
MulticastMessageReceivedListener,
MulticastMessageSentListener,
UserInputHandler {

public static final String TAG =
CommunicationFragment. class.getSimpleName
();
private boolean viewsInjected ;
private Intent
multicastReceiverServiceIntent ;
private ChatListAdapter
chatListAdapter ;

@InjectView (R.id.user_input_edit_text )

71
EditText userInputEditText ;

public static Fragment newInstance()
{
CommunicationFragment
communicationFragment = new
CommunicationFragment();

communicationFragment.setArguments( getFra
gmentArguments ());
return communicationFragment;
}

@Override
public View
onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle
savedInstanceState) {
View communicationFragmentView =
inflater.inflate(R.layout. communication_f
ragment, null);
ButterKnife. inject(this,
communicationFragmentView);
viewsInjected = true;
return communicationFragmentView;
}

@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife. reset(this);
}

@Override
public void onActivityCreated(Bundle
savedInstanceState) {

super.onActivityCreated(savedInstanceStat
e);
chatListAdapter = new
ChatListAdapter(getActivity(),
R.layout. communication_fragment_list_row )
;
setListAdapter( chatListAdapter );
}

@OnClick (R.id.send_button )
public void sendMulticastMessage() {
new
SendMulticastMessageAsyncTask( this,
this).execute();
}

public void
startReceivingMulticastMessages() {
if
(!MulticastMessageReceiverService. isRunni
ng) {

multicastReceiverServiceIntent =
createMulticastReceiverServiceIntent();

getActivity().startService( multicastRecei
verServiceIntent );
Log. i(TAG,
getString(R.string. multicast_receiver_ser
vice_started ));
}
}
public void
stopReceivingMulticastMessages() {
if
(MulticastMessageReceiverService. isRunnin
g) {

getActivity().stopService( multicastReceiv
erServiceIntent );
Log. i(TAG,
getString(R.string. multicast_receiver_ser
vice_stopped ));
}
}

@Override
public void
onMulticastMessageReceived(MulticastMessa
ge multicastMessage) {

addMulticastMessageToChatList(multicastMe
ssage);
}

@Override
public void onCouldNotSendMessage() {
MulticastMessage multicastMessage
= new
MulticastMessage(getString(R.string. messa
ge_not_multicasted ), "", true);

addMulticastMessageToChatList(multicastMe
ssage);
}

@Override
public String
getMessageToBeSentFromUserInput() {
return
userInputEditText .getText().toString();
}

@Override
public void clearUserInput() {
userInputEditText .setText( "");
}

public void reset() {
if(viewsInjected ) {
chatListAdapter .clear();

chatListAdapter .notifyDataSetChanged();

stopReceivingMulticastMessages();
}
}

private static Bundle
getFragmentArguments() {
Bundle fragmentArguments = new
Bundle();

fragmentArguments.putString(P2pCommunicat
ionFragmentPagerAdapter. FRAGMENT_TITLE ,
"CHAT");
return fragmentArguments;
}

private Intent
createMulticastReceiverServiceIntent() {
Intent

72
multicastReceiverServiceIntent = new
Intent(getActivity(),
MulticastMessageReceiverService. class);

multicastReceiverServiceIntent.setAction(
MulticastMessageReceiverService. ACTION_LI
STEN_FOR_MULTICAST );
MulticastMessageReceivedHandler
multicastMessageReceivedHandler = new
MulticastMessageReceivedHandler( this);

multicastReceiverServiceIntent.putExtra(M
ulticastMessageReceiverService. EXTRA_HAND
LER_MESSENGER , new
Messenger(multicastMessageReceivedHandler
));
return
multicastReceiverServiceIntent;
}

private void
addMulticastMessageToChatList(MulticastMe
ssage multicastMessage) {

chatListAdapter .add(multicastMessage);

chatListAdapter .notifyDataSetChanged();

getListView().setSelection( chatListAdapte
r.getCount() – 1);
}
}

DiscoveryAndConnectionFragment.java

package com.george.cofeepartner.fragment;

import
android.net.wifi.p2p.WifiP2pDevice;
import
android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import
android.net.wifi.p2p.WifiP2pManager.Conne
ctionInfoListener;
import
android.net.wifi.p2p.WifiP2pManager.PeerL
istListener;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import
android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.RelativeLayout;

import butterknife.ButterKnife;
import butterknife.InjectView ;
import com.george.cofeepartner.R;
import
com.george.cofeepartner.adapter.Discovery
ListAdapter;
import
com.george.cofeepartner.adapter.P2pCommun
icationFragmentPagerAdapter;
import com.george.cofeepartner.listener.discover
y.DiscoveryStateListener;
import
com.george.cofeepartner.listener.invitati
on.InvitationToConnectListener;
import
com.george.cofeepartner.listener.multicas
t.MulticastListener;
import
com.george.cofeepartner.listener.wifip2p.
WifiP2pListener;
import
com.george.cofeepartner.util.button.Conne
ctionButton;
import
com.george.cofeepartner.util.button.Disco
veryButton;

public class
DiscoveryAndConnectionFragment extends
ListFragment implements
DiscoveryStateListener, PeerListListener,
InvitationToConnectListener,
ConnectionInfoListener {

public static final String TAG =
DiscoveryAndConnectionFragment. class.getS
impleName();
private boolean viewsInjected ;
private DiscoveryListAdapter
discoveryListAdapter ;
private WifiP2pListener
wifiP2pListener ;
private MulticastListener
multicastListener ;

@InjectView (R.id.search_layout )
RelativeLayout searchLayout ;

@InjectView (R.id.no_devices_available_lay
out) RelativeLayout
noDevicesAvailableLayout ;
@InjectView (R.id.left_bottom_button )
DiscoveryButton leftBottomButton ;
@InjectView (R.id.right_bottom_button )
ConnectionButton rightBottomButton ;

public static Fragment newInstance()
{
DiscoveryAndConnectionFragment
discoveryAndConnectionFragment = new
DiscoveryAndConnectionFragment();

discoveryAndConnectionFragment.setArgumen
ts(getFragmentArguments ());
return
discoveryAndConnectionFragment;
}

@Override
public View
onCreateView(LayoutInflater
layoutInflater, ViewGroup container,
Bundle savedInstanceState) {
View
discoveryAndConnectionFragmentView =
layoutInflater.inflate(R.layout. discovery
_and_connection_fragment , container,
false);
ButterKnife. inject(this,

73
discoveryAndConnectionFragmentView);
viewsInjected = true;
return
discoveryAndConnectionFragmentView;
}

@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife. reset(this);
}

@Override
public void onActivityCreated(Bundle
savedInstanceState) {

super.onActivityCreated(savedInstanceStat
e);

wifiP2pListener =
(WifiP2pListener) getActivity();
multicastListener =
(MulticastListener) getActivity();
discoveryListAdapter = new
DiscoveryListAdapter(getActivity(),
R.layout. discovery_and_connection_fragmen
t_list_row );

setListAdapter( discoveryListAdapter );

leftBottomButton .initialize( wifiP2pListen
er);

rightBottomButton .initialize( wifiP2pListe
ner);
}

@Override
public void onListItemClick(ListView
listView, View view, int position, long
id) {
super.onListItemClick(listView,
view, position, id);
WifiP2pDevice wifiP2pDevice =
discoveryListAdapter .getItem(position);

wifiP2pListener .onConnect(wifiP2pDevice);
}

@Override
public void onStartedDiscovery() {
clearDiscoveryList();

searchLayout .setVisibility(View. VISIBLE);

noDevicesAvailableLayout .setVisibility(Vi
ew.GONE);

leftBottomButton .setStateStopDiscovery();
}

@Override
public void onStoppedDiscovery() {

searchLayout .setVisibility(View. GONE);

leftBottomButton .setStateStartDiscovery()
;
}
@Override
public void
onPeersAvailable(WifiP2pDeviceList
wifiP2pDeviceList) {
clearDiscoveryList();

addAllDiscoveredDevicesToDiscoveryList(wi
fiP2pDeviceList);
if
(discoveryListAdapter .isEmpty()) {

noDevicesAvailableLayout .setVisibility(Vi
ew.VISIBLE);
}
}

@Override
public void
onSentInvitationToConnect() {

rightBottomButton .setStateCancelInvitatio
n();
}

@Override
public void
onConnectionInfoAvailable(WifiP2pInfo
wifiP2pInfo) {

wifiP2pListener .onStopPeerDiscovery();

wifiP2pListener .onGroupHostInfoChanged(wi
fiP2pInfo);

multicastListener .onStartReceivingMultica
stMessages();

rightBottomButton .setStateDisconnect();
}

public void reset() {
if (viewsInjected ) {

rightBottomButton .setStateCreateGroup();
Log. i(TAG,
getString(R.string. has_been_reset ));
}
}

private static Bundle
getFragmentArguments() {
Bundle fragmentArguments = new
Bundle();

fragmentArguments.putString(P2pCommunicat
ionFragmentPagerAdapter. FRAGMENT_TITLE ,
"DISPOZITIVE DISPONIBILE" );
return fragmentArguments;
}

private void
addAllDiscoveredDevicesToDiscoveryList(Wi
fiP2pDeviceList wifiP2pDeviceList) {

discoveryListAdapter .addAll(wifiP2pDevice
List.getDeviceList());

discoveryListAdapter .notifyDataSetChanged
();
}

74

private void clearDiscoveryList() {
if (discoveryListAdapter != null)
{
discoveryListAdapter .clear();

discoveryListAdapter .notifyDataSetChanged
();
}
}

}

WifiP2pBroadcastReceiver.java

package
com.george.cofeepartner.broadcastreceiver
;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import
android.net.wifi.p2p.WifiP2pDevice;
import
android.net.wifi.p2p.WifiP2pManager;
import android.util.Log;

import com.george.cofeepartner.R;
import
com.george.cofeepartner.listener.wifip2p.
WifiP2pListener;

public class WifiP2pBroadcastReceiver
extends BroadcastReceiver {

public static final String TAG =
WifiP2pBroadcastReceiver. class.getSimpleN
ame();
private final Context context;
private WifiP2pListener
wifiP2pListener ;

public
WifiP2pBroadcastReceiver(Context context,
WifiP2pListener wifiP2pListener) {
this.context = context;
this.wifiP2pListener =
wifiP2pListener;
}

@Override
public void onReceive(Context
context, Intent intent) {
String action =
intent.getAction();

if
(WifiP2pManager. WIFI_P2P_STATE_CHANGED_AC
TION.equals(action)) {

notifyWifiP2pStateChanged(intent);

} else if
(WifiP2pManager. WIFI_P2P_PEERS_CHANGED_AC
TION.equals(action)) {
notifyPeersChanged();
} else if
(WifiP2pManager. WIFI_P2P_CONNECTION_CHANG
ED_ACTION .equals(action)) {

notifyConnectionStateChanged(getNetworkIn
fo(intent));

} else if
(WifiP2pManager. WIFI_P2P_THIS_DEVICE_CHAN
GED_ACTION .equals(action)) {

notifyThisDeviceChanged(intent);
}
}

private void
notifyWifiP2pStateChanged(Intent intent)
{
int state =
intent.getIntExtra(WifiP2pManager. EXTRA_W
IFI_STATE , -1);
if (state ==
WifiP2pManager. WIFI_P2P_STATE_ENABLED ) {

wifiP2pListener .onWifiP2pStateEnabled();
Log. i(TAG,
context.getString(R.string. wifi_p2p_enabl
ed) + " (" + state + ")");
} else {

wifiP2pListener .onWifiP2pStateDisabled();
Log. i(TAG,
context.getString(R.string. wifi_p2p_disab
led) + " (" + state + ")");
}
}

private void notifyPeersChanged() {
wifiP2pListener .onRequestPeers();
Log. i(TAG,
context.getString(R.string. peers_requeste
d));
}

private NetworkInfo
getNetworkInfo(Intent intent) {
return
intent.getParcelableExtra(WifiP2pManager.
EXTRA_NETWORK_INFO );
}

private void
notifyConnectionStateChanged(NetworkInfo
networkInfo) {
if (networkInfo.isConnected()) {

wifiP2pListener .onRequestConnectionInfo()
;
Log. i(TAG,
context.getString(R.string. is_connected ))
;
} else {

wifiP2pListener .onIsDisconnected();
Log. i(TAG,
context.getString(R.string. is_disconnecte
d));
}
}

75
private void
notifyThisDeviceChanged(Intent intent) {
WifiP2pDevice wifiP2pDevice =
intent.getParcelableExtra(WifiP2pManager.
EXTRA_WIFI_P2P_DEVICE );

wifiP2pListener .onThisDeviceChanged(wifiP
2pDevice);
Log. i(TAG,
context.getString(R.string. this_device_ch
anged));
}
}

ChatListAdapter.java

package com.george.cofeepartner.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

import
com.george.cofeepartner.multicast.Multica
stMessage;

public class ChatListAdapter extends
ArrayAdapter<MulticastMessage> {

private Context context;
private int layoutResourceId ;

public ChatListAdapter(Context
context, int layoutResourceId) {
super(context, layoutResourceId);
this.context = context;
this.layoutResourceId =
layoutResourceId;
}

@Override
public boolean isEnabled( int
position) {
return false ;
}

@Override
public View getView( final int
position, View convertView, ViewGroup
parent) {
convertView =
ensureConvertView(convertView);
ChatListAdapterViewHolder
chatListAdapterViewHolder =
ensureChatListAdapterViewHolder(convertVi
ew);

MulticastMessage multicastMessage
= getItem(position);
if
(multicastMessage.isSentByMe()) {

chatListAdapterViewHolder. messageReceived
Layout.setVisibility(View. GONE);

chatListAdapterViewHolder. messageSentLayo
ut.setVisibility(View. VISIBLE);
chatListAdapterViewHolder. messageSentText
View.setText(multicastMessage.getText());
} else {

chatListAdapterViewHolder. messageReceived
Layout.setVisibility(View. VISIBLE);

chatListAdapterViewHolder. messageSentLayo
ut.setVisibility(View. GONE);

chatListAdapterViewHolder. messageReceived
TextView .setText(multicastMessage.getSend
erIpAddress() + ":\n" +
multicastMessage.getText());
}

return convertView;
}

private LayoutInflater
getLayoutInflaterService() {
return (LayoutInflater)
context.getSystemService(Context. LAYOUT_I
NFLATER_SERVICE );
}

private View ensureConvertView(View
convertView) {
if (convertView == null) {
convertView =
getLayoutInflaterService().inflate( layout
ResourceId , null);
}
return convertView;
}

private ChatListAdapterViewHolder
ensureChatListAdapterViewHolder(View
convertView) {
if (convertView.getTag() == null)
{
convertView.setTag( new
ChatListAdapterViewHolder(convertView));
}
return
(ChatListAdapterViewHolder)
convertView.getTag();
}
}

ChatListAdapterViewHolder.java

package com.george.cofeepartner.adapter;

import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

import butterknife.ButterKnife;
import butterknife.InjectView ;
import com.george.cofeepartner.R;

public class ChatListAdapterViewHolder {

@InjectView (R.id.message_received_layout )
RelativeLayout messageReceivedLayout ;

76
@InjectView (R.id.message_received_text_vi
ew) TextView messageReceivedTextView ;
@InjectView (R.id.message_sent_layout )
RelativeLayout messageSentLayout ;

@InjectView (R.id.message_sent_text_view )
TextView messageSentTextView ;

public ChatListAdapterViewHolder(View
view) {
ButterKnife. inject(this, view);
}
}

DiscoveryListAdapter.java

package com.george.cofeepartner.adapter;

import android.content.Context;
import
android.net.wifi.p2p.WifiP2pDevice;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

import com.george.cofeepartner.R;

public class DiscoveryListAdapter extends
ArrayAdapter<WifiP2pDevice> {

private Context context;
private int layoutResourceId ;

public DiscoveryListAdapter(Context
context, int layoutResourceId) {
super(context, layoutResourceId);
this.context = context;
this.layoutResourceId =
layoutResourceId;
}

@Override
public View getView( final int
position, View convertView, ViewGroup
parent) {
convertView =
ensureConvertView(convertView);
DiscoveryListAdapterViewHolder
discoveryListAdapterViewHolder =
ensureDiscoveryListAdapterViewHolder(conv
ertView);

WifiP2pDevice wifiP2pDevice =
getItem(position);

discoveryListAdapterViewHolder. deviceName
TextView .setText(wifiP2pDevice. deviceName
);

discoveryListAdapterViewHolder. deviceStat
usTextView .setText(getDeviceStatus(wifiP2
pDevice. status));

return convertView;
}

private View ensureConvertView(View
convertView) { if (convertView == null) {
convertView =
getLayoutInflaterService().inflate( layout
ResourceId , null);
}
return convertView;
}

private
DiscoveryListAdapterViewHolder
ensureDiscoveryListAdapterViewHolder(View
convertView) {
if (convertView.getTag() == null)
{
convertView.setTag( new
DiscoveryListAdapterViewHolder(convertVie
w));
}
return
(DiscoveryListAdapterViewHolder)
convertView.getTag();
}

private LayoutInflater
getLayoutInflaterService() {
return (LayoutInflater)
context.getSystemService(Context. LAYOUT_I
NFLATER_SERVICE );
}

private String getDeviceStatus( int
deviceStatus) {
switch (deviceStatus) {
case WifiP2pDevice. AVAILABLE :
return
context.getString(R.string. tap_to_connect
);
case WifiP2pDevice. INVITED:
return
context.getString(R.string. invited);
case WifiP2pDevice. CONNECTED :
return
context.getString(R.string. connected );
case WifiP2pDevice. FAILED:
return
context.getString(R.string. failed);
case
WifiP2pDevice. UNAVAILABLE :
return
context.getString(R.string. unavailable );
default:
return
context.getString(R.string. unknown);
}
}

}
DiscoveryListAdapterViewHolder.java

package com.george.cofeepartner.adapter;

import android.view.View;
import android.widget.TextView;

import butterknife.ButterKnife;
import butterknife.InjectView ;
import com.george.cofeepartner.R;

77
public class
DiscoveryListAdapterViewHolder {

@InjectView (R.id.discovered_device_name_t
ext_view ) TextView deviceNameTextView ;

@InjectView (R.id.discovered_device_status
_text_view ) TextView
deviceStatusTextView ;

public
DiscoveryListAdapterViewHolder(View view)
{
ButterKnife. inject(this, view);
}

}

P2pCommunicationFragmentPagerAdapte
r.java

package com.george.cofeepartner.adapter;

import android.support.v4.app.Fragment;
import
android.support.v4.app.FragmentManager;
import
android.support.v4.app.FragmentPagerAdapt
er;

import java.util.List;

import
com.george.cofeepartner.fragment.Communic
ationFragment;
import
com.george.cofeepartner.fragment.Discover
yAndConnectionFragment;

public class
P2pCommunicationFragmentPagerAdapter
extends FragmentPagerAdapter {

public static final String
FRAGMENT_TITLE = "FRAGMENT_TITLE" ;
private List<Fragment> fragmentList ;

public
P2pCommunicationFragmentPagerAdapter(Frag
mentManager fragmentManager,
List<Fragment> fragmentList) {
super(fragmentManager);
this.fragmentList = fragmentList;
}

@Override
public Fragment getItem( int i) {
return fragmentList .get(i);
}

@Override
public int getCount() {
return fragmentList .size();
}

@Override
public CharSequence getPageTitle( int
position) { return
fragmentList .get(position).getArguments()
.getString( FRAGMENT_TITLE );
}

public DiscoveryAndConnectionFragment
getDiscoveryAndConnectionFragment() {
return
(DiscoveryAndConnectionFragment)
getItem( 0);
}

public CommunicationFragment
getCommunicationFragment() {
return (CommunicationFragment)
getItem( 1);
}
}

78

79
ANEXA 2 XML
communication_fragment.xml

<LinearLayout
xmlns:android="http://schemas.android.com
/apk/res/android"

xmlns:tools="http://schemas.android.com/t
ools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical"

tools:context= ".P2PCommunicationActivity"
>

<ListView
android:id="@android:id/list"
android:layout_height= "0dip"

android:layout_width= "match_parent"
android:layout_weight= "1"
android:visibility= "visible"
android:divider= "@null"
android:dividerHeight= "0dp"/>

<LinearLayout

android:layout_width= "fill_parent"

android:layout_height= "wrap_content"
android:orientation= "horizontal" >

< EditText

android:id="@+id/user_input_edit_text"
android:layout_width= "0dp"

android:layout_height= "fill_parent"
android:layout_weight= "1"

android:layout_marginLeft= "@dimen/side_ma
rgin"

android:layout_marginRight= "@dimen/side_m
argin"

android:inputType= "textMultiLine"
android:ems="10"

android:hint="@string/write_a_message" />

< ImageButton
android:id="@+id/send_button"

android:layout_width= "wrap_content"

android:layout_height= "wrap_content"

android:padding= "@dimen/side_margin"

android:background= "@drawable/send_button
_click_animation"

android:src= "@drawable/ic_action_send_now
"

style="?android:attr/buttonBarButtonStyle
"/>
</LinearLayout >

</LinearLayout >

Communication_fragment_list_row.xml

<?xml version= "1.0" encoding= "utf-8"?>
<LinearLayout
xmlns:android= "http://schemas.android.com
/apk/res/android"
android:orientation= "horizontal"
android:layout_width= "match_parent"

android:layout_height= "?android:listPrefe
rredItemHeight" >

<RelativeLayout

android:id= "@+id/message_received_layout"

android:layout_width= "wrap_content"

android:layout_height= "fill_parent" >

< LinearLayout

android:layout_width= "wrap_content"

android:layout_height= "fill_parent"

android:orientation= "horizontal"

android:layout_alignParentLeft= "true">

< ImageView

android:layout_width= "wrap_content"

android:layout_height= "wrap_content"

android:layout_marginRight= "@dimen/side_m
argin"

android:layout_gravity= "top"

android:src= "@drawable/ic_action_person"
android:focusable= "false"

android:clickable= "false"/>

< TextView

android:id= "@+id/message_received_text_vi
ew"

android:layout_width= "wrap_content"

android:layout_height= "wrap_content"

android:layout_gravity= "center"

android:background= "@drawable/chat_bubble
_received"

android:paddingTop= "@dimen/chat_bubble_pa
dding"

80
android:paddingBottom= "@dimen/chat_bubble
_padding"

android:paddingRight= "@dimen/chat_bubble_
padding"

android:paddingLeft= "@dimen/chat_bubble_d
ouble_padding"

android:textColor= "@android:color/primary
_text_light" />

</ LinearLayout >

</RelativeLayout >

<RelativeLayout

android:id= "@+id/message_sent_layout"

android:layout_width= "wrap_content"

android:layout_height= "fill_parent"
android:visibility= "gone">

< LinearLayout

android:layout_width= "wrap_content"

android:layout_height= "fill_parent"

android:orientation= "horizontal"

android:layout_alignParentRight= "true">

< TextView

android:id= "@+id/message_sent_text_view"

android:layout_width= "wrap_content"

android:layout_height= "wrap_content"

android:layout_gravity= "center"

android:layout_margin= "5dip"

android:background= "@drawable/chat_bubble
_sent"

android:paddingTop= "@dimen/chat_bubble_pa
dding"

android:paddingBottom= "@dimen/chat_bubble
_padding"

android:paddingRight= "@dimen/chat_bubble_
double_padding"

android:paddingLeft= "@dimen/chat_bubble_p
adding"

android:textColor= "@android:color/primary
_text_dark" />

< ImageView

android:layout_width= "wrap_content"

android:layout_height= "wrap_content"
android:layout_gravity= "top"

android:layout_marginLeft= "@dimen/side_ma
rgin"

android:src= "@drawable/ic_action_person"
android:focusable= "false"

android:clickable= "false"/>

</ LinearLayout >

</RelativeLayout >

</LinearLayout >

Discovery_and_connection_fragment.xml

<LinearLayout
xmlns:android="http://schemas.android.com
/apk/res/android"

xmlns:tools="http://schemas.android.com/t
ools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical"

tools:context= ".P2PCommunicationActivity"
>

<LinearLayout

android:layout_width= "fill_parent"

android:layout_height= "fill_parent"
android:orientation= "vertical" >

< ListView
android:id="@android:id/list"
android:layout_height= "0dip"

android:layout_width= "match_parent"
android:layout_weight= "1"
android:clickable= "true"

android:visibility= "visible" />

< RelativeLayout

android:id="@+id/no_devices_available_lay
out"

android:layout_width= "fill_parent"

android:layout_height= "?android:attr/list
PreferredItemHeight"

android:layout_alignParentBottom= "true"

android:background= "@color/black_opacity_
60"
android:visibility= "gone">

< TextView

android:layout_width= "wrap_content"

81
android:layout_height= "fill_parent"

android:layout_alignParentLeft= "true"

android:paddingLeft= "@dimen/activity_hori
zontal_margin"
android:gravity= "center"

android:text="@string/no_devices_availabl
e"

android:textColor= "@color/white"

android:textSize= "@dimen/abc_text_size_la
rge_material" />

</ RelativeLayout >

< RelativeLayout

android:id="@+id/search_layout"

android:layout_width= "fill_parent"

android:layout_height= "?android:attr/list
PreferredItemHeight"

android:layout_alignParentBottom= "true"

android:paddingLeft= "@dimen/activity_hori
zontal_margin"
android:gravity= "center|left"

android:background= "@color/black_opacity_
60"
android:visibility= "gone">

< LinearLayout

android:layout_width= "wrap_content"

android:layout_height= "wrap_content"

android:orientation= "horizontal" >

< ProgressBar

android:id="@+id/search_layout_progress_b
ar"

android:layout_width= "wrap_content"

android:layout_height= "wrap_content"

style="?android:attr/progressBarStyle" ></
ProgressBar >

< TextView

android:id="@+id/search_layout_text_view"

android:layout_width= "wrap_content"

android:layout_height= "fill_parent"

android:layout_alignParentLeft= "true"

android:gravity= "center"

android:text="@string/searching_dots"
android:textColor= "@color/white"

android:textSize= "@dimen/abc_text_size_la
rge_material" />

</ LinearLayout >

</ RelativeLayout >

< LinearLayout

style="?android:attr/buttonBarStyle"

android:layout_width= "match_parent"

android:layout_height= "wrap_content"

android:orientation= "horizontal"

android:background= "@color/teal_800" >

<com.george.cofeepartner.util.button.Disc
overyButton

android:id="@+id/left_bottom_button"

android:layout_width= "0dp"

android:layout_height= "wrap_content"
android:layout_weight= "1"

android:textColor= "@color/white"

style="?android:attr/buttonBarButtonStyle
"/>

<com.george.cofeepartner.util.button.Conn
ectionButton

android:id="@+id/right_bottom_button"

android:layout_width= "0dp"

android:layout_height= "wrap_content"
android:layout_weight= "1"

android:textColor= "@color/white"

style="?android:attr/buttonBarButtonStyle
"/>

</ LinearLayout >

</LinearLayout >

</LinearLayout >

Discovery_and_connection_fragment_list_
row.xml

<?xml version= "1.0" encoding= "utf-8"?>
<LinearLayout
xmlns:android= "http://schemas.android.com
/apk/res/android"
android:layout_width= "fill_parent"

82
android:layout_height= "?android:listPrefe
rredItemHeight"

android:background= "?android:attr/activat
edBackgroundIndicator"

android:padding= "@dimen/header_linear_lay
out_padding" >

<ImageView
android:id= "@+id/phone_icon"

android:layout_width= "wrap_content"

android:layout_height= "fill_parent"

android:layout_marginRight= "@dimen/side_m
argin"

android:src= "@drawable/ic_action_phone"
android:focusable= "false"
android:clickable= "false"/>

<LinearLayout
android:layout_width= "0dp"

android:layout_height= "fill_parent"
android:layout_weight= "1"
android:orientation= "vertical" >

< TextView

android:id= "@+id/discovered_device_name_t
ext_view"

android:layout_width= "fill_parent"
android:layout_height= "0dip"
android:layout_weight= "1"
android:focusable= "false"
android:clickable= "false"/>

< TextView

android:id= "@+id/discovered_device_status
_text_view"

android:layout_width= "fill_parent"
android:layout_height= "0dip"
android:layout_weight= "1"
android:focusable= "false"
android:clickable= "false"/>

</LinearLayout >

</LinearLayout >

Main.xml

<LinearLayout
xmlns:android="http://schemas.android.com
/apk/res/android"

xmlns:tools="http://schemas.android.com/t
ools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical"

tools:context= ".P2PCommunicationActivity">

<TextView

android:layout_width= "fill_parent"

android:layout_height= "wrap_content"
android:gravity= "center_vertical"

android:paddingLeft= "@dimen/activity_hori
zontal_margin"

android:paddingRight= "@dimen/activity_hor
izontal_margin"
android:paddingTop= "5dp"
android:paddingBottom= "5dp"

android:background= "@color/teal_800"

android:text="@string/me_capital_letters"

android:textSize= "@dimen/abc_text_size_me
dium_material"

android:textColor= "@color/white" />

<LinearLayout
xmlns:android="http://schemas.android.com
/apk/res/android"

android:layout_width= "fill_parent"

android:layout_height= "?android:attr/list
PreferredItemHeight"

android:background= "?android:attr/activat
edBackgroundIndicator"

android:padding= "@dimen/header_linear_lay
out_padding" >

< ImageView
android:id="@+id/phone_icon"

android:layout_width= "wrap_content"

android:layout_height= "fill_parent"

android:src="@drawable/ic_action_phone"
/>

< LinearLayout

android:orientation= "vertical"
android:layout_width= "0dp"
android:layout_weight= "1"

android:layout_height= "fill_parent" >

< TextView

android:id="@+id/my_device_name_text_view
"

android:layout_width= "fill_parent"

android:layout_height= "0dp"
android:layout_weight= "1"
android:gravity= "bottom"
/>

83

< TextView

android:id="@+id/my_device_status_text_vi
ew"

android:layout_width= "fill_parent"

android:layout_height= "0dp"
android:layout_weight= "1"
android:gravity= "top" />
</ LinearLayout >

< LinearLayout

android:orientation= "vertical"
android:layout_width= "0dp"
android:layout_weight= "1"

android:layout_height= "fill_parent" >

< TextView

android:id="@+id/am_i_host_question_text_
view"

android:layout_width= "fill_parent"

android:layout_height= "0dp"
android:layout_weight= "1"
android:gravity= "bottom"
/>

< TextView

android:id="@+id/host_ip_text_view"

android:layout_width= "fill_parent"

android:layout_height= "0dp"
android:layout_weight= "1"
android:gravity= "top" />
</ LinearLayout >

</LinearLayout >

<android.support.v4.view.ViewPager

android:layout_width= "wrap_content"

android:layout_height= "fill_parent"
android:id="@+id/view_pager" >

<android.support.v4.view.PagerTitleStrip

android:id="@+id/pager_title_strip"

android:layout_width= "match_parent"

android:layout_height= "wrap_content"
android:layout_gravity= "top"

android:background= "@color/teal_800"

android:textColor= "@color/white"
android:paddingTop= "5dp"
android:paddingBottom= "5dp"/>

</android.support.v4.view.ViewPager >
</LinearLayout >

Colors.xml

<?xml version= "1.0" encoding= "utf-8"?>
<resources >

<color name="white">#FFFFFF</ color>
<color
name="black_opacity_60" >#99000000</ color>
<color
name="blue_theme" >#005FBF</ color>

<!–
http://www.google.com/design/spec/style/c
olor.html#color-color-palette –>
<color
name="green_500" >#4CAF50</ color>
<color
name="green_900" >#1B5E20</ color>
<color
name="light_blue_900" >#01579B</ color>
<color
name="blue_900" >#0D47A1</ color>
<color
name="indigo_100" >#C5CAE9</ color>
<color
name="indigo_500" >#3F51B5</ color>
<color
name="indigo_700" >#303F9F</ color>
<color
name="teal_100" >#B2DFDB</ color>
<color
name="teal_500" >#009688</ color>
<color
name="teal_800" >#00695C</ color>

</resources >

strings.xml

<?xml version= "1.0" encoding= "utf-8"?>
<resources >

<string name="app_name" >Coffee
Partner</ string>
<string name="yes">Da</string>
<string name="no">Nu</string>
<string name="wifi_p2p_on_off" >WiFi
P2P On/Off</ string>
<string name="wifi_p2p_enabled" >WiFi
P2P Activat</ string>
<string name="wifi_p2p_disabled" >WiFi
P2P Dezactivat</ string>
<string
name="wifi_p2p_disabled_please_enable" >Wi
Fi P2P este dezactivat, vă rugăm porniți
opțiunea din Setări</ string>
<string
name="wifi_p2p_unsupported" >Dispozitivul
nu este compatibil Wi-Fi P2P</ string>
<string name="connect" >Conectează –
te</string>
<string
name="connected" >Conectat</ string>
<string
name="disconnect" >Deconectează –

84
te</string>
<string
name="disconnected" >Deconectat</ string>
<string
name="discover" >Descoperă</ string>
<string
name="message_not_multicasted" >Mesajul nu
a fost trimis</ string>
<string name="tap_to_connect" >Atinge
pentru a te conecta</ string>
<string
name="available" >Disponibil</ string>
<string
name="unavailable" >Indisponibil</ string>
<string
name="invited" >Invitat</ string>
<string name="busy">Ocupat</ string>
<string
name="internal_error" >Internal
error</string>
<string name="unknown_error" >Unknown
error</string>
<string name="failed" >Failed</ string>
<string
name="no_devices_available" >Nici un
dispozitiv disponibil</ string>
<string
name="unknown" >Unknown</ string>
<string
name="multicast_chat_capital_letters" >CHA
T</string>
<string
name="available_devices_capital_letters" >
DISPOZITIVE DISPONIBILE</ string>
<string
name="me_capital_letters" >DISPOZITIVUL
MEU</string>
<string
name="searching_dots" >Căutare…</ string>
<string name="send">Trimite</ string>
<string
name="am_i_host_question" >Deținătorul
grupului?</ string>
<string
name="received" >Primit</ string>
<string name="scan">Scan</string>
<string name="stop">Stop</string>
<string name="host">Host</string>
<string
name="ip_capital_letters" >IP</string>
<string name="create_group" >Creează
grup</string>
<string
name="data_has_been_reset" >Data has been
reset</string>
<string name="peers_requested" >Peers
requested</ string>
<string name="is_connected" >Este
conectat</ string>
<string name="is_disconnected" >Este
deconectat</ string>
<string
name="this_device_changed" >This device
changed</ string>
<string
name="successfully_sent_invitation_to_con
nect">Successfully sent invitation to
connect</ string>
<string
name="could_not_send_invitation_to_connect">Could not send invitation to
connect</ string>
<string
name="successfully_created_group" >Success
fully created group</ string>
<string
name="could_not_create_group" >Could not
create group</ string>
<string
name="successfully_disconnected" >Successf
ully disconnected</ string>
<string
name="could_not_disconnect" >Could not
disconnect</ string>
<string
name="successfully_started_discovery" >Suc
cessfully started discovery</ string>
<string
name="could_not_start_discovery" >Could
not start discovery</ string>
<string
name="successfully_stopped_discovery" >Suc
cessfully stopped discovery</ string>
<string
name="could_not_stop_discovery" >Could not
stop discovery</ string>
<string
name="successfully_cancelled_connection" >
Successfully cancelled
connection</ string>
<string
name="could_not_cancel_connection" >Could
not cancel connection</ string>
<string
name="cancel_invitation" >Cancel
invitation</ string>
<string
name="multicast_receiver_service_stopped"
>Multicast receiver service
stopped</ string>
<string
name="multicast_receiver_service_started"
>Multicast receiver service
started</ string>
<string name="write_a_message" >Scrie
un mesaj</ string>
<string name="has_been_reset" >Has
been reset</ string>

</resources >

AndroidManifest.xml

<?xml version= "1.0" encoding= "utf-8"?>
<manifest
xmlns:android="http://schemas.android.com
/apk/res/android"
package= "com.george.cofeepartner" >

<uses-permission
android:name="android.permission.ACCESS_W
IFI_STATE" />
<uses-permission
android:name="android.permission.CHANGE_W
IFI_STATE" />
<uses-permission
android:name="android.permission.CHANGE_N
ETWORK_STATE" />

85
<uses-permission
android:name="android.permission.INTERNET
" />
<uses-permission
android:name="android.permission.ACCESS_N
ETWORK_STATE" />
<uses-permission
android:name="android.permission.CHANGE_W
IFI_MULTICAST_STATE" />

<application
android:allowBackup= "true"

android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
< activity

android:name=".P2PCommunicationActivity"

android:label="@string/app_name" >
< intent-filter >
< action
android:name="android.intent.action.MAIN"
/>

< category
android:name="android.intent.category.LAU
NCHER" />
</ intent-filter >
</ activity >

< service

android:name=".multicast.MulticastMessage
ReceiverService"
android:exported= "false" >
</ service>

</application >

</manifest >

86

Similar Posts