Documente Academic
Documente Profesional
Documente Cultură
PROIECT DE DIPLOMĂ
Galați
2019
UNIVERSITATEA „DUNĂREA DE JOS” DIN GALAȚI
FACULTATEA DE AUTOMATICĂ, CALCULATOARE, INGINERIE
ELECTRICĂ ȘI ELECTRONICĂ
Coordonator științific,
Dr. Ing. Dan Munteanu
Absolvent,
Mihailov
Bogdan-Ionuț
Galați
2019
Departamentul __________________________________________________________________________
Str. Științei Nr. 2, cod poștal 800146, Galați, România, tel/fax: +0236 470 905, e-mail: aciee@ugal.ro, web: www.aciee.ugal.ro
UNIVERSITATEA „DUNĂREA DE JOS” DIN GALAȚI
FACULTATEA DE AUTOMATICĂ, CALCULATOARE, INGINERIE
ELECTRICĂ ȘI ELECTRONICĂ
Nr. _____/__________________
Str. Științei Nr. 2, cod poștal 800146, Galați, România, tel/fax: +0236 470 905, e-mail: aciee@ugal.ro, web: www.aciee.ugal.ro
UNIVERSITATEA „DUNĂREA DE JOS” DIN GALAȚI
FACULTATEA DE AUTOMATICĂ, CALCULATOARE, INGINERIE
ELECTRICĂ ȘI ELECTRONICĂ
Aprobat,
Decan
DOMNULE DECAN
Subsemnata/Subsemnatul,
_______________________________________________________________________, absolventă /absolvent
a/al Facultă ții de Automatică , Calculatoare, Inginerie Electrică și Electronică , din cadrul
Universită ții Dună rea de Jos din Galați, domeniul __________________________________,
specializarea (licență /master) ______________________________________
_____________________________________________________________________________________________________
________, promoția ______________, vă rog să -mi aprobați înscrierea la examenul de
licență /disertație sesiunea _________________________________________________.
Am ales proiectul de diplomă /lucrarea de disertație cu titlul
_________________________________________________
_____________________________________________________________________________________________________
________sub îndrumarea
___________________________________________________________________________.
Am citit cu atenție REGULAMENTUL DE ÎNTOCMIRE A PROIECTELOR DE
DIPLOMĂ ȘI LUCRĂ RILOR DE DISERTAȚ IE și l-am respectat integral.
Str. Științei Nr. 2, cod poștal 800146, Galați, România, tel/fax: +0236 470 905, e-mail: aciee@ugal.ro, web: www.aciee.ugal.ro
UNIVERSITATEA „DUNĂREA DE JOS” DIN GALAȚI
FACULTATEA DE AUTOMATICĂ, CALCULATOARE, INGINERIE
ELECTRICĂ ȘI ELECTRONICĂ
DECLARAŢ IE
Subsemnata (ul),
_________________________________________________________________________________
absolventă /absolvent a/al Facultă ții de Automatică , Calculatoare, Inginerie Electrică și
Electronică , din cadrul Universită ții “Dună rea de Jos” din Galați, promoția ________________,
specializarea
_____________________________________________________________________________________________, declar
pe proprie ră spundere că proiectul de diplomă /lucrare de disertație cu titlul
„____________________________________________________________________________________________________
_____________________________________________________________________________________________________
_______________”este elaborat/elaborată de mine și nu a mai fost prezentat/prezentată
niciodată la o altă facultate sau instituție de învă ță mâ nt superior din ţară sau
stră ină tate. De asemenea, declar că toate sursele utilizate, inclusive cele de pe Internet,
sunt indicate în proiect/lucrare, cu respectarea regulilor de evitare a plagiatului.
Str. Științei Nr. 2, cod poștal 800146, Galați, România, tel/fax: +0236 470 905, e-mail: aciee@ugal.ro, web: www.aciee.ugal.ro
UNIVERSITATEA „DUNĂREA DE JOS” DIN GALAȚI
FACULTATEA DE AUTOMATICĂ, CALCULATOARE, INGINERIE
ELECTRICĂ ȘI ELECTRONICĂ
Str. Științei Nr. 2, cod poștal 800146, Galați, România, tel/fax: +0236 470 905, e-mail: aciee@ugal.ro, web: www.aciee.ugal.ro
Anexa 5 la Regulamentul de întocmire a proiectelor de diplomă și a lucrărilor de disertație
Departamentul __________________________________________________________________________
Sesiunea:_________________________________________________________________________________
REFERAT DE EVALUARE
Notă:
* Se taie (bifează), după caz
Rezumat
În primul capitol s-a efectuat o analiză a industriei aplicațiilor de chat mobile, fiind
decrise câ teva aspecte ale aplicațiilor prezente pe piață în acest moment.
În cel de-al doilea capitol, sunt prezentate resursele aplicației care au fost folosite
în crearea acesteia și logica pe care am abordat-o în diferite situații,
În cel de-al treilea capitol, este prezentată aplicație din punctul de vedere al unui
utilizator și nu al unui programator.
CUPRINS
Cuprins
Introducere..........................................................................................................................................1
Capitolul 1. Analiza industriei aplicațiilor mobile de chat....................................................................2
1.2.2 Facebook Messenger....................................................................................................................5
1.2.3 Platforme pentru distribuția aplicațiilor mobile...........................................................................6
Capitolul 2. Resursele folosite și dezvoltarea aplicației.......................................................................8
2.1 Prezentare C#..................................................................................................................................8
2.2 Prezentare Xamarin.Forms..............................................................................................................9
2.3 Integrarea Firebase Database în proiectul de licență....................................................................11
2.4 Convertorii.....................................................................................................................................16
2.5 Mecanismul din spatele trimiterii mesajelor.................................................................................17
2.6 Cum funcționează înregistrarea?...................................................................................................25
2.7 Șablonul MVVM(Model-View-ViewModel)....................................................................................27
2.8 Life cycle-ul unei aplicații în cadrul platformei Android.................................................................31
2.9 Custom renderers..........................................................................................................................33
Capitolul 3. Descrierea aplicației........................................................................................................37
3.1 Înregistrarea..................................................................................................................................37
3.2 Logarea și utilizatorii......................................................................................................................39
3.3 Trimiterea mesajelor.....................................................................................................................40
Concluzie.............................................................................................................................................42
Bibliografie..........................................................................................................................................43
Lista figurilor
Figura 1. WhatsAppLogo........................................................................................................................3
Figura 2. WhatsApp Chat page..............................................................................................................4
Figura 3 SSL Asyncron............................................................................................................................4
Figura 4 Logo Messenger.......................................................................................................................5
Fig 5 Android, iOS chat..........................................................................................................................6
Fig 6 Stastici pe piață a platformelor.....................................................................................................6
Fig 7 Android OS....................................................................................................................................7
Fig 8 Ecosistemul Apple.........................................................................................................................8
Fig 9 Schemă compilare Xamarin.Forms..............................................................................................10
Fig 10 Firebase flow.............................................................................................................................12
Fig 11 Pagina de înregistrare...............................................................................................................15
Fig 12 Structura bazei de date în FireBase a userilor...........................................................................16
Fig 13 Structura bazei de date a conversațiilor....................................................................................17
Fig 14 Secțiunea de profil a utilizatorului.............................................................................................18
Fig 15 Logarea în aplicație...................................................................................................................19
Fig 16 Logarea pagina de HomePage...................................................................................................20
Fig 17 Pagina de chat a aplicației.........................................................................................................20
Fig 18 Chat-ul.......................................................................................................................................23
Fig 19 Înregistrarea..............................................................................................................................25
Fig 20 Logarea utililizatorului...............................................................................................................26
Fig 21 Pagina de înregistrare...............................................................................................................27
Fig 22 Schemă reprezentativă pentru patternul MVVM......................................................................28
Figura 23 Binding-ul din spatele paginilor(flow)..................................................................................29
Figura 24 Lifecycle-ul unei aplicații în Android....................................................................................33
Figura 25 Lifecycle-ul unei aplicații în iOS............................................................................................34
Fig 26 Custom Renders(Schemă).........................................................................................................35
Fig 27 Register Page.............................................................................................................................36
Fig 28 Cum se face logarea?................................................................................................................38
Fig 29 Înregistrarea unui utilizator nou................................................................................................39
Fig 30 Pagina de homepage a aplicației...............................................................................................40
Introducere
1
Capitolul 1. Analiza industriei aplicațiilor mobile de chat
Companie Whatsapp
Numele aplicației Whatsapp
Necesită conexiune constantă la internet Da
Mentenanță Da
Gratis Da
Protocol folosit XMPP
Transmiterea securizată a datelor folosind SSL Da
DBMS folosit Mnesia(SQL)
Platforme suportate Android, IOS, Windows Phone, Windows
Videocall Da
Audiocall Da
Comunicare prin text Da
Companie Facebook
Numele aplicației Messenger
Necesită conexiune constantă la internet Da
Mentenanță Da
Gratis Da
Protocol folosit Handover Protocol
Transmiterea securizată a datelor folosind SSL Da
Platforme suportate Android, iOS, Windows Phone, Windoww
Videocall Da
Audiocall Da
Comunicare prin text Da
1.2.1 WhatsApp
Whatsapp este o aplicație de mesagerie gratuită , cross-platform deținută de
Facebook. Aceasta permite utilizatorilor să trimită mesaje de tip text sau audio, să
efectueze apeluri video sau audio, trimiterea de fișiere: fișiere text, documente, locații
etc.
2
Figura 1. WhatsAppLogo
3
Figura 2. WhatsApp Chat page
Mesajele multimedia sunt mai întâ i transformate în Base64, apoi fiind trimise
că tre server și date mai departe. La primirea acestora se face decodarea din base64 în
fișierul trimis.
4
1.2.2 Facebook Messenger
5
Fig 5 Android, iOS chat
6
Cu timpul, au fost lansate mai multe versiune ale acestuia, purtâ nd numele unor
deserturi: Cupcake 1.5; Donut 1.6; Eclair 2.0; Froyo 2.2; Gingerbread 2.3; Honeycomb
3.0; Ice Cream Sandwich 4.0; Jelly Bean 4.1; KitKat 4.4; Lollipop 5.0; Marshmallow 6.0;
Nougat 7.0, Oreo 8.0 și ultima versiune 9.0 Pie.
În ceea ce privește customizarea, Android oferă o libertată infinită . Numă rul de
aplicații este mult mai mare și fiind Open Source, oricine poate avea acces la acesta și
modificâ nd OS-ul, putâ nd ca fiecare să își facă propria lor versiune de Android.
Fig 7 Android OS
Pe celă lalt front se află cei de la Apple cu sistemul lor de operar IOS. Diferența
dintre acesta și cel de la Google este customizarea. Cei de la Apple nu permit deblocarea
acestuia, singura metodă curată prin care se poate face update la o nouă versiune este
cea oficială , atunci câ nd Apple trimite că tre utilizatori o nouă versiune. Sistemul lor de
operare este valabil pe tablete, telefoane și smartwatch-uri. Apple a implementat prin
intermediul acestui sistem de operare un mic ecosistem. Toate informațiile sunt
sincronizate între device-uri de la mesaje la apeluri, la fișiere. O altă diferență o
reprezintă interfața celor două sisteme de operare. Unde Android oferă o interfață mai
friendly plină ce culori și animații, cei de la Apple oferă una mult mai profesională și mai
simplistă , mergâ nd pe o cale mai minimalistă .
Magazinul de aplicații reprezintă încă o diferență . În Android, toate aplicațiile pot
fi puse în market, neavâ nd parte de o testare precisă , fiind cazuri în care viruși au ajuns
acolo. În schimb, pe App Store așa ceva nu e posibil. La publicarea fiecă rei aplicații, un
om stă și testează aplicația asigurâ ndu-se că nu există nimic suspect în legă tură cu ea.
Cred că cea mai mare diferență dintre cele 2 sisteme de operare o reprezintă
performanța acestora. Unde Android e plin de instabilită ți în multe cazuri, nefiind
optimizat pentru toate tipurile de procesoare datorită faptului că există în acest
moment pe piață foarte mulți producă tori de telefoane cu propriile lor versiuni de
procesor, Apple își optimizează sistemul de operare pe procesorul produs de ei,
oferindu-le posibilitatea ca să livreze un OS optimizat ca la carte, avâ nd un numă r redus
de instabilită ți.
7
Fig 8 Ecosistemul Apple
8
utilizator sunt puse în Model, iar apoi trimise că tre viewModel unde le voi afișa sau le
voi trimite.
Xamarin.Forms mi-a oferit posibilitatea de a scrie un cod C#, care este apoi
transformat la compilare în codul nativ specific fiecă rei platforme în parte. Am folosit
această libră rie pentru a proiecta interfața. Aceasta îmi oferă posibilitatea ca, printr-un
fișier .xaml unde sunt stocate toate elementele de user control, să transmit date că tre și
din interfață .
De asemenea, Firebase Database m-a scutit de un lucru și acela de a face eu
management pe o bază de date și pe serverul acesteia. În cloud se află baza de date, eu
trebuind doar să îi specific un cod special care îmi oferă posibilitatea de a mă loga pe
acesta cu un user și o parolă (sau utilizatorului de a se loga după ce s-a înregistrat).
Datorită faptului că Xamarin.Forms este încă relativ nou, fiind lansate versiuni noi care
repară probleme, nu toate lucrurile merg bine sau sunt implementate într-un mod ok,
uneori neexistâ nd versiuni oficiale ale unor libră rii și trebuind astfel să recurg la third-
party-uri care nu mereu se comportau cum trebuie. De aseemenea, Firebase oferă
posibilitatea ca logarea sau înregistrarea să se facă folosind contul de Google sau de
Facebook, dar fiind un third-party, nu am avut posiblitatea de a implementa această
funcționalitate care ar fi ușurat munca unui utilizator.
2.1 Prezentare C#
9
Principiul de bază de funcționare al acestui framework este acesta: codul în C# este
transformat, la compilare, în cod nativ pentru fiecare platformă în parte. Elementele
grafice pot fi adă ugate folosind fie fișiere de tip XAML, avâ nd în spate o clasă parțială de
C#(acestea două împă rțind obiectele celuilalt), fie creâ nd clase C# separate ce conțin
elementele grafice respective.
<StackLayout>
<!-- Place new controls here -->
<Label x:Name="LabelDemo" Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Exemplu de clasă C# din spatele acestui XAML, putâ nd folosi elementele definite în
fișierul de mai sus:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace App4
{
public partial class MainPage : ContentPage
10
{
public MainPage()
{
InitializeComponent();
LabelDemo.TextColor = Color.Aqua;
}
}
}
Transmiterea datelor din fișierul de .xaml unde utilizatorul a efectuat câ teva acțiuni se
desfă șoară prin intermediul conceptului de Binding.
<flex:FlexButton x:Name="loginButton" Text="Login" ClickedCommand="{Binding
LoginCommand}"
WidthRequest="76"
HeightRequest="76"
CornerRadius="38"
ForegroundColor="#ffffff"
HighlightForegroundColor="#49516F"
BackgroundColor="#6279B8"
HighlightBackgroundColor="#8EA4D2"
IsEnabled="{Binding IsBusy}"
IsToggled="{Binding IsBusy}"
Clicked="UnfocusEntry"
FontFamily="LilitaOne-Regular.ttf#LilitaOne-Regular"
Grid.Row="2" Grid.Column="0"/>
Fiecare View are în componența sa un ViewModel de care se leagă care reprezintă o
clasă din care preia datele sau le introduce. Prin acest mod, diferite componente pot
avea proprietă ți diferite în funcție de câ mpurile viewmodel-ului. Acest binding poate fi
de mai multe tipuri. Voi exemplifica cele două tipuri care sunt cele mai folosite:
- OneWay- care doar preia datele din viewModel, neputâ nd transmite informații
înapoi la viewmodel, utilizatorul neputâ nd direct să afecteze acele date.
- TwoWay – care, la fel ca și numele permite schimbul de informații dintre view și
viewmodel.
În exemplul de mai sus, se află un astfel de concept, proprietă țile care au ca valori
Binding, fiind luate din viewmodel.
Datorită faptului că unele elemente grafice arată sau se comportă diferit în funcție de
fiecare platformă în parte, uneori este necesară crearea unui custom render. Acesta
reprezintă un element grafic, scris în subproiectele xamarin și folosind elemente
specifice acelei platforme. Astfel, la compilare, compilatorul știe să selecteze elementul
și să ruleze codul pentru fiecare platformă .
11
2.3 Integrarea Firebase Database în proiectul de licență
Firebase Auth este o soluție ce permite logarea userilor pe platformă folosind doar
codul din aplicație. Aceasta permite logarea prin intermediul rețelelor de socializare
cum ar fi Google, Facebook, Twitter, Google Play Games. De asemenea, în acest serviciu
este inclus și managementul de că tre programatori a utilizatorilor, permițâ nd logarea în
aplicație cu un email și o parolă , date ce sunt stocate în Firebase.
Bazele de date relaționale au apă rut la începutul anului 1970, permițâ nd stocarea
datelor și prelucrarea acestora folosind un limbrja de programare numit
SQL(Structured Query Language). În acea perioadă , stocarea datelor era scumpă și
schema de date era destul de simplă . În momentul câ nd Internetul a devenit mult mai
accesibil, cantitatea de informații legate de useri, obiecte și evenimente a explodat.
Datele, acum, sunt accesate mult mai frecvent și procesarea acestora a devenit cu mult
mai intensive. Să luă m ca exemplu rețelele de socializare ca Facebook ce crează sute de
milioane de pagini de noută ți pentru useri în funcție de activită țile acestora.
12
Bazele de date NoSQL au fost construite ca o soluție la această problemă , fiind
concepute în așa fel încâ t să permită introducerea de date fă ră o schemă anume.
Spre deosebire de cele relaționale, aici datele pot fi doar adă ugate sau șterse,
nefiind posibil o eventuală actualizare fă ră înlocuirea completă a acestora.
Astfel de alternative sunt folosite în domeniul:
-naval(prelucrarea datelor a sute sau mii de nave)
-aerian(prelucrare datelor avioanelor)
rețele de socializare/servicii de muzică (Spotify, Facebook, SoundCloud)
În esență , NoSQL este folosit în momentul câ nd este vorba de cantită ți imense de
date(Big Data).
Nefolosing o libră rie oficială , nu am acces la toate facilită țile oferite de cei de la
Google prin intermediul acestei baze de date. Facilitatea principală pe care am folosit-o
este stocarea mesajelor și subscribe-ul la inserarea unor date noi în aceasta, primind în
momentul câ nd se stochează informații noi, o notificare și afișâ nd-o pe ecran. Am folosit
această logică la implementarea mesajelor primite și trimise.
Acest lucru a fost posibil prin integrarea metodei de subscribe din interiorul
nuggetului folosit.
var observable = child.AsObservable<MessageModel>();
var subscription = observable
.Where(f => !string.IsNullOrEmpty(f.Key))
.Subscribe(f =>
{
if (f.Object.AuthorUuid == User.UserUUID)
{
if (!(messageUuids.Contains(f.Object.MessageUuid)))
{
//sorted.Add(f.Object);
MessageList.Add(f.Object);
MessagingCenter.Send(new ScrollToBottomMessage(),
"ScrollToBottomMessage");
messageUuids.Add(f.Object.MessageUuid);
}
}
});
Voi explica acum codul de mai sus pentru a înțelege mai bine cum funcționează
acestă funcționalitate de subscribe.
13
După cum se vede am creat o variabilă de tip observable, mai apoi stocâ nd în ea
informații. Acel subscribtion este defapt o listă , care prin intermediul LINQ din C# ce îmi
permite o parcurgere a listei sub o formă a asemă nă toare interogă rilor din SQL, reușesc
să îmi caut efectiv “tabelul” de la care vreau noile date. Subscribeul de mai sus este
pentru primirea mesajelor noi de la alt utilizator, neffind necesară crearea unor
requesturi continue pentru date noi. Ceea ce fac eu mai sus, este să îmi fac subscribe la
json-ul cu uuid-ul meu, ceilalți utilizatori, care atunci câ nd îmi scriu mesajele, stochează
datele în felul acesta Conversation/user-uuid/message-uuid. Partea de aici care mă
interesează pe mine este user-uuid.
În momentul câ nd am primit un mesaj nou, îl adaug într-o listă pe care o
ordonez după un timestamp.
Trecâ nd mai departe, voi ară ta structura sub care am stocat informațiile legate de
utilizatori și de mesajele acestora.
Voi începe mai întâ i cu partea de utilziatori. În momentul câ nd un user nou se
înregistrează , datele despre el sunt trecute în felul urmă tor:
14
Fig 11 Pagina de înregistrare
Primele două valori vor fi folosite la afișarea numelui acestuia în lista de utilizatori.
Emailul va fi folosit pentru a permite accesul acestuia în platformă .
Parola care va fi folosită împreună cu emailul la logare.
15
De precizat este faptul că atâ t mailul, câ t și parola nu sunt scrise în nicio structură , ci
reprezintă efectiv crearea unui utilizator care va permite accesul la serverul unde
este gă zduită baza de date.
Cele din urmă , uuid și imaginea de utilziator, sunt setate by-default.
Uuid-ul ajută la unicitatea unui utilziator și idendificarea acestuia cu succes, iar
imaginea reprezintă efectiv o simplă imagine din proiect care este mai întâ i fă cută în
base64 pentru a putea fi stocată în baza de date.
Aici, am pus o imagine default în proiect și am definit-o ca fiind resource. Folosing acel
string care îmi caută numele resursei cu acel nume și îmi face un stream, reușesc să fac
un array de byti și apoi îi convertesc în base64 datorită funcției de mai sus.
Voi exemplifica mai tâ rziu cum sunt aduse din format base64 în imagini propriu-zise.
Structura sub care am stocat conversațiile este urmă toarea:
Toate informațiile utilizatori sunt stocate sub acel uuid unic al lor pentru unicitate.
16
Ceea ce vedeți mai sus, în momentul câ nd fac un request, este adus ca și UserModel la
mine în aplicație, știind automat să își gă sescă câ mpurile necesare pe care să le
completeze cu informațiile nou venite.
Conversațiile au urmă toarea structură
Fiecare utilizator are scris în această structură , uuid-ul lui la care are subscribe și de la
care primește notifică ri noi în cazul venirii unui mesaj.
La fel ca și mai sus, aici câ nd vin informațiile din DB, este fă cut un bind automat la
modelul de mesaje, nefiind necesar ca eu să îi fac bindingul și scutindu-mă de acest
efort.
2.4 Convertorii
În Xamarin.Forms există termenul de converters? Ce sunt aceștia? Aceștia sunt clase cu
o metodă ca cea de mai jos
class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
if (!(string.IsNullOrEmpty(value.ToString())))
{
byte[] Base64Stream =
System.Convert.FromBase64String(value.ToString());
17
}
Aceștia sunt folosiți atunci câ nd, vrem să convertim o simplă valoare într-o proprietate
a unui element grafic cum ar fi sursa unei imagini.
<controls:CircleImage x:Name="image" Source="{Binding
CurrentUserImage, Converter={StaticResource imageConverter}}" Aspect="AspectFill"
Grid.Column="0" IsVisible="True">
După cum puteți vedea, am dat ca surcă a imaginii un string, care reprezintă
imaginea utilziatorului în base64 venită din baza de date. Apoi am folosit Converter,
care primește automat ca și parametru CurrentUserImage. Acesta știe automat să își ia
parametrii și să îi convertească , putâ nd adă uga diverse condiții.
Aveștia sunt definiți atunci câ nd se definesc în XAML toate resursele care urmează să fie
folosite(importul de clase efectiv)
<ContentPage.Resources>
<ResourceDictionary>
<cvrt:ImageConverter x:Key="imageConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
Ce face acest convertor? Prin intemrediul lui am reușit să obțin acest efect al imaginii de
utilizator.
În momentul randă rii paginii, acesta primește ca parametru imaginea în format base64,
apoi convertind-o într-o imagine propriu-zisă .
Convertorul primește 4 parametri, primul este valoarea care urmează să fie convertită ,
al doilea este tipul de element care este de așteptat să fie convertit, cel de-al treilea
parametru (puteți trece un parametru suplimentar la convertor), iar ultimul
informațiile despre cultură .
Sfat: este mai bine să adă ugați toate clasele de conversie într-un dosar pentru a fi
organizate.
Sfat: Pentru a numi convertorul este mai bine să folosiți un nume intuitiv, ca preferință
personală îmi place să pun un nume referitor la ceea ce face convertorul, de exemplu
dacă convertorul convertește un null la bool cu scopul de a fi folosit pe Isvisible
proprietatea este numită , NullToVisibilityConverter.
18
2.5 Mecanismul din spatele trimiterii mesajelor
19
Fig 16 Logarea pagina de HomePage
20
- Din lista utilizatorilor, acesta alege un user că ruia să îi trimită mesajul.
21
}
Lista este de tip observable pentru ca vizual aceasta să fie actualizată cu noile date venit
din rqeusturile fă cute la baza de date.
messageUuids.Add(message.Object.MessageUuid);
}
}
sorted = sorted.OrderBy(o => o.TimeStamp).ToList();//necessary for ordering
the messages when arriving
foreach (var item in sorted)
{
MessageList.Add(item);
}
sorted.Clear();
}
După cum puteți vedea, am folosit prima dată un connector pentru baza de date
pe care îl salvez în momentul câ nd îl creez la logare, apoi parcurg toate datele de
dedesubtul structurii care începe de la uuid-ul utilizatorului pe care îl contactez câ t și al
meu.
De ce am fă cut acest lucru? Trebuia să preiau atâ t mesajele lui câ t și pe alemele.
În momentul câ nd scriu un mesaj scriu și în structura mea și în structura utilziatorului
țintă .
După ce am preluat mesajele a trebuit să fac în așa fel încâ t să le ordonez după un
criteriu. Am ales timestamp. Mesajele sunt ordonate în ordine crescă toare începâ nd de
sus pâ nă jos în funție de timestampul acestora. Mai întâ i adaug mesajele în lista de
sorted, mai apoi le adaug în lista eventuală de mesaje direct sortate.
Acum că am trecut peste această list, așa arată un utilziator cu mesaje trimise și primite.
22
Fig 18 Chat-ul
Mesajele persoanei țină t este pe un fundal albastru. Am obținut acestl ucru folosin un
convertor care seta culoarea de background a fiecă rui frame în funcție de authoruuid-ul
dat. Dacă era la fel ca utilizatorul curent salvat la logare atunci era alb, altfel este
albastru.
La fel ca mai sus acesta este codul Convertorului.
public object Convert(object value, Type targetType, object parameter, CultureInfo
culture)
{
return value.ToString() == Helper.RetainedData.CurrentUser.UserUUID ?
"#F5F5F5" : "#03A9F4";
}
23
Ș i la această linie este setat backgroundul
<Frame BackgroundColor="{Binding AuthorUuid,
Converter={StaticResource colorConverter}}" WidthRequest="400">
<Frame.HasShadow>
Un alt lucru de precizat este faptul că ...de fiecare dată câ nd fac requestul...pentru
a nu lua aceleași mesaje de fiecare dată , afișâ ndu-le de două ori, fac în felul urmă tor:le
rețin pe cele pe care le-am luat, iar fiecare mesaj care îmi vine cu ceea ce am deja și apoi
îl adaug în listă . Prima dată m-am lovit de această problemă și am rezolvat-o astfel.
O altă problemă de care m-am lovit inițial a avut legă tură cu subscribeul la
structura uuid-ului utilizatorului propriului utilizator în tabela de conversații. Din
pă cate, nu se poate face subscribe la un lucru care inițial nu există și apoi să facă
automat acest lucru câ nd se crează . Dacă nu aș fi aplicat urmă toarea soluție, nu aș fi
putut să primesc mesajele de la alți utilizatori.
Care a fost soluția? În momentul înregistră rii
24
Fig 19 Înregistrarea
După ce utilziatorul a completat toate datele și a apă sat pe butonul de
înregistrare, atunci voi scrie în tabela de conversații a utilziatorului respectiv un mesaj,
pentru a crea structura și ap utea face subscribe cu succes.
MessageModel message = new MessageModel("abv", "abc",
Helper.RetainedData.UserUuid, "abc", "abc", DateTime.Now);
await firebaseClient
.Child("Users")
.Child(loginNewlyCreatedUser.User.LocalId)
.PutAsync(userToBeAdded);
await firebaseClient
.Child("Conversations")
.Child(loginNewlyCreatedUser.User.LocalId)
.Child(Helper.UUIDGenerator.UuidGenerator)
25
.PutAsync(message);
26
Fig 21 Pagina de înregistrare
Unde va fi rugat să își introducă datele de înregistrare. Ca și celelalte view-uri, acestă
pagină are în spate un ViewModel care se ocupă cu trimiterea de date că tre Firebase.
await
Connectors.Client.FireBaseAuthConfig.CreateUserWithEmailAndPasswordAsync(Email,
Password);
27
2.7 Șablonul MVVM(Model-View-ViewModel)
28
În principiu, acest model separă logica de business, pă strâ nd-o în clasele dedicate
acesteia de cea de UI.
Mai jos se află o figură mai detaliată al proceselor care au loc în spatele folosirii
acestui pattern.
Structura este urmă toarea: în componența proiectului se află două modele pe care le
folosesc pentru a actualiza, șterge sau introduce date.
MessageModel.cs
29
}
}
Voi explica fiecare field al clasei în parte. Stocarea în baza de date se face pe baza unui
JSON, o structură de date. Pentru a adă uga unicitate fiecă rui mesaj în parte și de a evita
suprascrierea mesajelor, am ales să ofer fiecă rui mesaj în parte pe care eu îl trimit un id
unic(uuid), avâ nd o metodă separată pentru generarea acestui id, folosindu-mă efectiv
de funcția de random. Printr-un loop for reușesc să convertesc un numă r de 10 numere
în char, generâ nd astfel acel UUID.
Împreună cu acest uuid, stochez în aceasă clasă numele autorului mesajului, uuid-ului
acestuia, timestampul și conținutul mesajului și uuidul utilizatorului că tre care îi trimit
mesajul respectiv.
Mai sus am oferit un exemplu. Voi explica în urmă toarele râ nduri cum am reușit să
adaptez acest pattern acestui proiect printr-un exemplu mult mai detaliat, acela fiind
preluarea listei de utilizatori existenți în platformă .
30
<ListView x:Name="List" ItemsSource="{Binding Userlist}"
RowHeight="60" ItemSelected="OnSelectedItem">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Margin="8">
<StackLayout Orientation="Horizontal">
<controls:CircleImage Source="{Binding UserImage,
Converter={StaticResource imageConverter}}" Aspect="AspectFill" Grid.Column="0"
IsVisible="True">
<controls:CircleImage.WidthRequest>
<OnPlatform x:TypeArguments="x:Double">
<On Platform="Android, iOS">50</On>
</OnPlatform>
</controls:CircleImage.WidthRequest>
<controls:CircleImage.HeightRequest>
<OnPlatform x:TypeArguments="x:Double">
<On Platform="Android, iOS">50</On>
</OnPlatform>
</controls:CircleImage.HeightRequest>
</controls:CircleImage>
<Label Text="{Binding FirstName}"
FontFamily="LilitaOne-Regular.ttf#LilitaOne-Regular"/>
<Label Text="{Binding LastName}"
FontFamily="LilitaOne-Regular.ttf#LilitaOne-Regular"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
În acest Xaml sunt mai multe cuvinte cheie de care trebuie să se țină cont. În primul
râ nd este acel ListView. ListView-ul reprezintă o listă grafică , care inițial este goală ,
urmâ nd ca ulterior informațiile să fie adă ugate în acesta și randate eventual pe ecran.
În primul râ nd i-am definit sursa, care este UserList. Această listă este definită în
ViewModel
31
userlist = value;
OnPropertyChanged("Userlist");
}
}
În mod normal, dacă nu aș fi adă ugat acel Observable la definitea listei de useri (în care
sunt aduși toți userii câ nd se face requestul la baza de date pentru aceștia), obiectele ar
fi fost randate pe ecran, însă dacă ar fi trebuit să actualizez lista, de exemplu câ nd se
adaugă un nou user, pe ecran nu ar fi apă rut noul utilizator, el fiind totuși prezent în
lista din viewmodel. Acel Observable, atunci câ nd sunt schimbă ri legate de datele din
interior, trimite o notificare la cei care au subscribe la această listă (în cazul nostru
listview-ul) și aceștia updatează lista cu informațiile nou venite. E asemă nă tor cu
patternul de Observable unde există obiecte ce, atunci câ nd sunt modifică ri, toți
subscriberii la acel obiect primesc o notificiare, putâ nd efectua diferite acțiuni în funcție
de aceasta.
Dar cum se face legarea la viewmodel? La fel cum am mai spus, în spatele acestui xaml
se află o clasă de C#, care inițial nu are decâ t câ teva linii de cod ce țin mai mult de
inițializarea acesteia.
InitializeComponent();
BindingContext = new MainPageViewModel();
this.viewModel = viewModel;
Mai sus este prezentată clasa din spatele pagini Main unde sunt ară tați utilizatorii
existenți. După cum vedem, se setează un BindingContext care stă efectiv la baza
transmiterii de date ale modelului prin viewmodel.
În Android, fiecare aplicație are un life cycle care începe din momentul câ nd aceasta a
fost lansată .
În figura ală turată este prezentat lifecycle-ul unei aplicații în Android.
32
Figura 24 Lifecycle-ul unei aplicații în Android
33
Figura 25 Lifecycle-ul unei aplicații în iOS
În momentul lansă rii aplicației, este apelată metoda de onCreate(), atunci câ nd se
face tranziție din background în foreground, este apelată metoda de onResume(), câ nd
este bă gată în background cea de onPause() și așa mai departe.
Programatorul trebuie să țină cont de aceste lucruri, deoarece unele lucruri ar
putea dispă rea câ nd se revine în aplicație, mai ales câ nd sunt puse requesturi de date în
metoda de onAppearing afiecă rei pagini. Această metodă se execută de fiecare dată câ nd
apare pagina respectivă pe ecran, astfel putâ nd avea loc un numă r considerabil de
operațiuni inutile care în mod normal ar trebui să se execute numai o singură dată .
Aceste metode sunt automat suprascrise de Xamarin.Forms la crearea
proiectului pentru fiecare platformă în parte. Aceste metode pot avea în interiorul lor
diferite acțiune în funcție de life cycle-ul curent. Un exemplu ar fi un request de date
atunci câ nd se revine în aplicație din background.
34
Fig 26 Custom Renders(Schemă )
35
Fig 27 Register Page
Ceea ce am fă cut pentru a ajunge la acest rezultat a fost urmă torul lucru: a fost necesară
crearea unei clase în proiectul de Xamarin.Forms(nu cel specific platformei) care
extindea clasa elementului grafic pe care voiam să îl folosesc.
public class CustomEntry : Entry
{
}
Dacă se dorește adă ugarea de proprietă ți noi, se poate face acest lucru foarte
ușor, dar am ales să merg pe calea mai simplă .
Apo a trebuit să creez clasa acestei componente în proiectul de Android.
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var gradientDrawable = new GradientDrawable();
gradientDrawable.SetCornerRadius(60f);
gradientDrawable.SetStroke(5, Android.Graphics.Color.DarkGray);
gradientDrawable.SetColor(Android.Graphics.Color.Transparent);
Control.SetBackground(gradientDrawable);
e.NewElement.PlaceholderColor = Color.Gray;
Control.SetPadding(50, Control.PaddingTop, Control.PaddingRight,
Control.PaddingBottom);
}
}
Această metodă este apelată în momentul câ nd este detectată , din fișierul .xaml
unde este folosită componenta modificată , o schimbare a comportamentului
componentei respective. Astfel se setează colțurile componentei(care dau acea
rotunjime a acestora), stroke-ul, culoarea și culoarea fundalului aplicației. De
assemenea poate fi adă ugat și un place holder care să îi ofere un indiciu utilizatorului în
legă tură cu informațiile cerute de la acesta. Pe iOS, codul acestei componente ar fi ară tat
complet diferit folosind metode specifice Swift-ului ce țin de elementele grafice ale
acestuia.
Pentru a folosi această componentă , am creat această componentă în fișierul
de .xaml unde sunt adă ugate toate elementele de grafică .
<Controls:CustomEntry x:Name="Email"
Grid.Row="0"
Grid.Column="0"
Placeholder="Email"
VerticalOptions="CenterAndExpand"
Text="{Binding UserEmail}"
TextColor="White"
FontFamily="LilitaOne-Regular.ttf#LilitaOne-Regular"/>
36
Importul clasei se face la fel ca în C#. Trebuie doar chemat obiectul, apă râ nd un
prompt de a adă uga folderul unde se află componenta respectivă .
37
Capitolul 3. Descrierea aplicației
Aplicație fă cută în cadrul proiectului de licență este o aplicație de chat care are ca scop
oferirea unei că i de comunicare între două persoane prin text.
Fiecare utilizator va trebui facă un cont pentru a putea avea acces la serviciile oferite de
că tre aplicație.
3.1 Înregistrarea
Prima dată , câ nd userul va intra în aplicație acesta va trebui să apese pe acest
buton în cazul în care nu are cont.
38
Urmâ nd ca mai apoi să fie dus în această pagină de înregistrare unde va trebui să
completeze câ mpurile cu urmă toarele date:
Numele de familie
Prenumele
Adresa de email
Parola
După apă sarea butonului de înregistrare acesta va fi adus în pagina de Logare unde va
trebui să introducă datele cu care va intra în sistem.
39
3.2 Logarea și utilizatorii
După ce utilizatorii s-au logat, aceștia vor avea o pagină de unde pot face urmă toarele
lucruri
Să selecteze un utilziator cu care să vorbească
Să își seteze o poză de profil
Să se delogheze
40
În această pagină , conversaționează doi utilizatori. Fiecare poate trimite mesaj,
backgroundul fiecă rui mesaj fiind în funcție de cine a trimis mesajul respectiv.
Culoarea albastră pentru mesajul venit de la celă lalt user și gri pentru cel care logat în
momentul acesta în aplicație
41
Concluzie
În final, această aplicație a avut două scopuri majore. Unul dintre ele a fost faptul
că am avut oportunitatea de a mă folosi de tehnologii noi pe care nu le-am mai folosit
înainte, care sunt în vogă și din ce în ce mai adoptate, suportul pentru ele fiind încă mic,
dar cu timpul va crește. Am avut ocazia să fac aplicația de la 0, neavâ nd o bază propriu-
zisă dintr-un tutorial.
Al doilea motiv, folosind aceste tehnologii am avut ocazia să aplic lucruri pe care
le știam deja și am reușit să le aprofundez, reușind de asemenea să deprind lucruri
noi(Xamarin.Forms, MVVM, Firebase).
În final, aplicația rezultată din acest efort reprezintă timpul pe care l-am acordat
învă ță rii acestor lucruri noi și a unor lucruri învă țate în cei 4 ani de facultate.
42
Bibliografie
https://en.wikipedia.org/wiki/C_Sharp_(programming_language)
https://www.telerik.com/blogs/what-is-xamarin-forms
https://en.wikipedia.org/wiki/Firebase
https://www.mongodb.com/nosql-inline
https://www.slideshare.net/VirginiaSgargi/whatsapp-project-work
43