Secția Cibernetică, Statistică si Informatică Economică [623489]
1
Universitatea Babeș -Bolyai
Facultatea de Ș tiinte Economice si Gestiunea Afacerilor
Secția Cibernetică, Statistică si Informatică Economică
Cluj -Napoca 2017
Aplicație de tip mobile “Reminder App” pe platformele iOS si
Android
Profesor coordonator: Student: [anonimizat].univ.dr. Sergiu JECAN Mădă lin MUNTEANU
2
Cuprins
1. Introducere ………………………….. ………………………….. ………………………….. ………………………… 5
2 Scopul lucrării ………………………….. ………………………….. ………………………….. ……………………. 6
2.1 Conectarea dispozitivelor multiple prin Internet ………………………….. ………………………… 6
2.2 Analiza și proiectarea aplicatiei ………………………….. ………………………….. ………………….. 6
2.3 Soluții cross -platform ………………………….. ………………………….. ………………………….. ……. 8
2.4 Aplicarea cunoștiințelor de programare web ………………………….. ………………………….. … 8
3. Metodologia abordată ………………………….. ………………………….. ………………………….. …………. 9
3.1 Studiu de caz pe aplicații existente pe Android si iOS ………………………….. ……………….. 9
3.2 Chestionar ………………………….. ………………………….. ………………………….. ………………….. 17
4. Ce aduce în plus aplicația prezentată? ………………………….. ………………………….. ……………… 18
5. Arhitectura aplicatiei ………………………….. ………………………….. ………………………….. …………. 20
6. Tehnologiile utilizate ………………………….. ………………………….. ………………………….. ………… 22
6.1 Despre PhoneGap API ………………………….. ………………………….. ………………………….. … 22
6.2 Introducere spre alternative ………………………….. ………………………….. ………………………. 23
6.2.1 Layx ………………………….. ………………………….. ………………………….. …………………… 23
6.2.2 Dart ………………………….. ………………………….. ………………………….. ……………………. 23
7. Etapa de analiză ………………………….. ………………………….. ………………………….. ……………….. 24
7.1 Preliminarii ………………………….. ………………………….. ………………………….. ………………… 24
7.2 Publicul target al aplicației ………………………….. ………………………….. ……………………….. 24
7.3 Utilizarea aplicației ………………………….. ………………………….. ………………………….. …….. 24
7.4 Setările și detaliile tehnice ………………………….. ………………………….. ………………………… 24
8. Proiectarea ………………………….. ………………………….. ………………………….. ……………………….. 25
8.1 Tratarea erorilor ………………………….. ………………………….. ………………………….. ………….. 25
3
9. Implementarea ………………………….. ………………………….. ………………………….. ………………….. 27
9.1 Crearea siteului web ………………………….. ………………………….. ………………………….. ……. 27
9.2 Setarea bazei de date ………………………….. ………………………….. ………………………….. …… 27
9.2.1 Conectarea codului PHP la baza de date ………………………….. ………………………….. . 30
9.2.2 Folosirea TotalCommander pentru a accesa mai ușor partea de FTP ………………… 31
9.3 Algoritmii folosiți în cadrul aplicației ………………………….. ………………………….. ………… 34
9.3.1 Conectarea la baza de date ………………………….. ………………………….. …………………. 34
9.3.2 Înregistrarea utilizatorului (Sign Up) ………………………….. ………………………….. …… 35
9.3.3 Conectarea utilizatorului (Login) ………………………….. ………………………….. ………… 39
9.3.4 Schimbarea temei (zi/noapte) ………………………….. ………………………….. …………….. 45
9.3.5 Actualizarea tabelului cu mementourile listate ………………………….. ………………….. 46
9.3.6 Conectarea funcției pentru reactualizarea tabelului ………………………….. ……………. 47
9.3.7 Funcțiile de ștergere a mementourilor ………………………….. ………………………….. …. 47
9.3.8 Adăugarea mementourilor ………………………….. ………………………….. …………………. 49
9.3.9 Deconectarea ………………………….. ………………………….. ………………………….. ……….. 55
9.3.10 Funcția de ajutor accountSelectLogged ………………………….. ………………………….. .. 55
9.3.11 Codul pentru inițializare din JavaScript ………………………….. ………………………….. .. 56
10. Validarea și testarea ………………………….. ………………………….. ………………………….. ……….. 60
11. Prezentarea aplicației ………………………….. ………………………….. ………………………….. ……… 61
11.1 Ghidul utilizatorului ………………………….. ………………………….. ………………………….. … 61
11.2 Diagrama de stare ………………………….. ………………………….. ………………………….. ……. 72
11.3 Workflow ………………………….. ………………………….. ………………………….. ……………….. 73
11.4 Use case ………………………….. ………………………….. ………………………….. …………………. 74
11.5 Diagrame de clase ………………………….. ………………………….. ………………………….. ……. 75
12 Concluzii și perspective. Posibilități de îmbunătățire ………………………….. ……………………… 76
4
12.1 Dincolo de iOS si Android ………………………….. ………………………….. ……………………. 76
12.2 Dezvoltarea propriului API ………………………….. ………………………….. …………………… 76
12.3 Internaționalizarea aplicației ………………………….. ………………………….. ………………….. 77
12.4 Deschidere spre comunitatea open -source ………………………….. ………………………….. . 77
13 Glosar de termeni ………………………….. ………………………….. ………………………….. ………………… 78
14. Bibliografie ………………………….. ………………………….. ………………………….. …………………… 79
5
1. Introducere
În cadrul acestei lucrări am dezvoltat o aplicație care generează alerte(tip reminder) . Concep tul
este unul simplu – se definește un mesa j pentru reminder, precum si date -time pentru alerte
utilizatori.
Pentru început prezentă m scopul lucrării, apoi vom descrie metodologia abordată,aplicații
asemănătoare deja existente dar și explicâ nd ce aduce nou aplicația dezvoltată . Vom vorbi de
asemenea despre arhitectura fo losită și tehnologiile folosite , comparându -le cu alte tehnologii.
Lucrarea va fi descrisă în amănunt , cu toate etape le aferente proiectului de dezvoltare . În cadrul
etapei de analiză și proiectare veți înțelege ce pași am făcut pentru a ajunge la specificațiile și
funcțiile aplicației prezentate. Imple mentarea va fi det aliată ; valida rea și testarea au fost importante
in proiect . Veți avea și un ghid de utilizare a aplicației dezvoltate, dar vom arăta și aspecte mai
tehnice, cum ar fi diagramele de stare, use case, diagrame de clase și workflow.
În înche ierea lucrării vom pre zenta concluziile impreună cu o scurtă descri ere a posibilităților de
îmbunătăț ire.
6
2 Scopul lucrării
Aceas tă lucrare a necesitat mult studiu pentru îmbunătățirea cunoș tiintelor de programare ,dar ș i a
etapelor specifice unui proiect IT.
2.1 Conectarea dispozitivelor multiple prin Internet
În societatea de azi suntem conectați la Internet aproape zilnic. România are acces la conexiu ne de
internet, iar populația tânără (dar nu numai ) folosește din ce în ce mai mult aceste resurse care sunt
în continuă creștere și expansiune.
Având posibilitatea de a accesa internetul de pe diferite dispozitive ( calculatoare, laptopuri,
televizoare inteligente, ceasuri inteligente, telefoane inteligente, dispozitive GPS) a apărut
necesitatea de a conecta /accesa mai multe dispozitive via Internet. Un exemplu foarte simplu este
acela de a ne conecta de pe un laptop de acasă pe un server de la servici u si invers(in sc opul de a
lucra la acelaș i proiect. Pentru acest exemplu se pot aplica mai multe metode de a sin croniza datele
(fișierele necesare pentru muncă în acest caz) prin Internet.
2.2 Analiza și proiectarea aplicatiei
Analiza și proiectarea sunt etape importante în cadrul unui proiect IT. N ecesită timp și resurse dar
sunt mijloace eficiente de a finaliza c onform scopului. Este importantă respe ctarea metodologiilor
aferente ( adică nu este același lucru dacă se respectă pașii recomandați sau dacă se folosesc pași
aleatorii, aleși după idei sau pr esupuneri).
Analiza si proiectarea asigură eliminarea paș ilor de repetare/refacere a unor paș i din
proiect(schimbarea specificaț iilor,refacere cod,re -testare,…).Se cunosc mai multe metodologi i de
analiză si proiectare. In cadrul lucră rii noastre am ales modelul cascadă .
Avantaje:
1. Sistemul este bine documentat ;
2. Permite u n bun management al proiectului;
3. Planificarea resurselor pe etape;
4. Estimă ri de cost mai exacte.
7
Dezavantaje:
1. Un produs executabil, care să demonstreze funcț ionarea sistemu lui este disponibil destul de
târziu, dupa integrare. Până atunci s -au produs numai documente;
2. Deoarece modelul este secv ențial, există numai un feedback l ocal, la tranzițiile î ntre faze;
3. Multe erori sunt descoperite tâ rziu cost crescut ;
4. Toate riscurile sunt incluse intr -un singur ciclu de dezvoltare .
Cerințe
Design
Implementare
Testare
MentenanțăModelul cascadă
8
2.3 Soluții cross -platform
În 2017 este foarte important ca o soluție software să nu fie legată doar de un singur sistem de
operare. De exemplu, dacă un editor de text merge doar pe Windows, poate fi foarte bun, dar
nimeni din tre utilizatorii care nu fo losesc Windows nu o să beneficieze de existența acestuia.
Soluțiile cross -platform sunt aplicaț iile care pot rula pe mai multe platfo rme (pe mai m ulte sisteme
de operare ). Am ales dezvoltarea în PhoneGap, în scopul posibilităț ii de extindere a aplicației. Cu
alte cuvinte, ap licația dezvoltată poate rula atât pe platformele Android, cat si pe iOS.
Aceste sisteme de operare sunt folosite la nivel mondial.
Folos ind PhoneGap,putem extinde cu ușurință pe alte dispozitive cu sisteme de operare.
2.4 Aplicare a cunoștiințelor de programare web
PhoneGap este bazat pe programare web, iar dezvoltatorul va putea crea aplicații mobile fără
cunoștiințe avansate în această zonă de programare . Folosind doar HTML, CSS și JavaScript
putem dezvolta aplicații complete în PhoneGap.
9
3. Metodologia abordată
Aplicația prezentată gestionează mementouri create de utilizatori. Pentru a crea această aplicație,
am avut nevoie de o metodologie bine stabilită, pe care o prezentăm în acest capitol.
Diagrama Gantt
ID Task Name Start Finish DurationMar 2017 Apr 2017 Feb 2017 May 2017
9/4 19/2 23/4 14/5 2/4 26/2 26/3 16/4 19/3 12/3 7/5 30/4 5/3Jun 2017
21/528/54/611/6
1 3d 17.02.2017 15.02.2017 Planificarea aplicației
2 4d 20.02.2017 17.02.2017 Cerințe de sistem
3 28d 3/20/2017 2/21/2017 Analiză proiect
4 82d 6/10/2017 3/21/2017 Dezvoltarea aplicației
5 4d 6/19/2017 6/16/2017 Testarea și finalizarea aplicației
3.1 Studiu de caz pe aplicații existente pe Android si iOS
Întrebarea initiala este ce s -a făcut deja. Aplicațiile existente pe piață trebuie să devină indicatori
a ceea ce putem face ca să aducem ceva în plus față de ce există. Pen tru a răspunde la această
întrebare am studiat cateva dintre aplicațiile sugerate de Google Play Store si App Store la termenul
de căutare ”reminder”.
To Do Reminder with Alarm
Pagină aplicație : https://play.google.com/store/apps/details?id=com.ToDoReminder.gen
Funcțiile principale sunt :
Creare rapidă și ușoara de mementouri
10
Personalizare cu opțiuni de repetare (minute, ore, zilnic, săptămânal, lunar, anual)
Setarea alert elor de dinainte de memento
Alerta poate fi setată ca alarmă sau ca notificare
Va folosi melodia ta preferată
Având Speech -to-Text poți crea mementoul fără să mai scrii
Sincronizarea aniversărilor și zilelor de naștere ale prietenilor tăi de pe Facebook,
Phoneb ook, Google Calendar sau adăuga te manual
Widget pentru home screen
Funcții de backup & restore (copie de siguranță și restabilire)
Temă de zi și noapte
Just Reminder
Pagină aplicație : https://play.google.com/store/apps/details?id=in.smsoft.justremind
Funcțiile principale sunt :
Setarea mementourilor cu doar câteva clickuri
Speech -to-Text – comenzi vocale, c reare de memento fără a scrie
Personalizare cu opțiuni de repetare (minute, ore, zilnic, săptămânal, lunar, anual)
Fiecare memento poate fi personalizat cu imagine, ton de apel sau ton de Talking Alarm
Setarea alertelor de dinainte de memento
Funcții de ba ckup & restore (copie de siguranță și restabilire)
Mementouri pentru facturi (ce ai de plătit și când)
11
Any.do : To-do list & Calendar
Pagină aplicație : https://play.google.com/store /apps/details?id=com.anydo
Funcțiile principale sunt :
Dezvoltatorii aplicației spun că aplicația este numărul 1 pentru aplicații gen ”to do list” pe
Android
Sincro nizare în timp real între dispoz itive multiple (mobil, calculator, web și tabletă)
Meme ntour i pentru un timp programat sau o locație specific a
Personalizare cu opțiuni de repetare
Opțiunea de a avea mementouri pentru mai multe persoane care pot colabora ca și grup,
astfel ușurând munca
Widget pentru home screen
Vizualizare pe calendar – eveniment ele pe toată luna se pot vedea foarte repede și simplu
Sincronizare cu calendarul telefonului, cu calendarul Google, cu evenimentele Facebook,
cu calendarul Outlook
12
Reminder
Pagină aplicație : https://play.google.com/store/apps/details?id=com.arthurivanets.reminder
Funcțiile principale sunt :
Mementouri pentru termeni de livrare
Mementouri cu repetare săptămân ală pentru întâlniri
Mementouri pentru teme de casă și alte atribuiri
Mementouri pentru zile de naștere, aniversări
Mementouri pentru facturi (când se plătesc)
Mementouri pentru a pelurile importante sau pentru medicamente (când se iau)
Alerte zilnice pentr u a-ți aduce aminte ce ai de făcut pe ziua respectivă
Comenzi vocale (Speech -to-Text)
Google Keep
13
Pagină aplicație : https://play.google.com/store/apps/details?id=com.g oogle.android.keep
Funcțiile principale sunt :
Comenzi vocale (Speech -to-Text) – înregistrare audio, după care aplicația va transcrie în
cuvinte mai târziu
Organizare prin culori și etichete pe mementouri
Mementouri pentru evenimente surpriză
Sincronizare automată pe toate dispozitivele – telefon, tabletă, calculator și dispozitive
Android
Memento bazat pe locație – de exemplu, îți va reaminti de lista de cumpărături când ai
ajuns la magazin
BZ Reminder
Pagină aplicație : https://play.google.com/store/apps/details?id=com.bzzzapp
Funcțiile principale sunt :
Personalizare cu opțiuni de repetare
Zile de naștere, alerte
Marcarea mementourilor cu culori
Notițe, widgeturi personalizate
Calendar cu mementouri
Mementouri pentru apelurile pierdute
Compatibil cu ceas inteligent Android – comenzi vocale direct de pe ceasul inteligent
14
Alarmed
Funcț iile principale sunt :
-Adăugare reminder cu doar câ teva apăsă ri
-Alarme uș or de configurat
-Afișarea locației de unde s -a adă ugat reminder -ul respectiv
-Personalizarea soneriei cu peste 140 de tonuri.
-Adăugarea de timere
-Timere supra -dimensionat e pentru o vizibilitate mai bună .
15
Remind me App
Funcț ii principale :
-Ușor de utilizat
-Auto -snooze
-Posibilitatea adă ugării unei imagini pentru o identificare cât mai ușoară
-Conexiu nea la internet nu este necesară
16
Reminder App
Funcț ii principale :
-Snooze
-Filtru de categorii
-Categorii speciale : „Ur gent”; „Calendar”; „Birthday”
17
3.2 Chestionar
Pe lângă analiza aplicațiilor deja făcute, care sunt toate aplicații pentru mementorui, am ales și să
testăm potențiala piață de utilizatori prin folosirea unor chestionare cu întrebări speficice. Am ales
întrebările astfel încât să fie de ajutor în analiza și proiectarea soluției.
Întrebările au avut loc de răspuns liber, ceea ce înseamnă că nu am limitat opțiunile de răspuns la
unele predefinite. Chestionarul a avut următoarele întrebări :
1. Folosești aplicații de alerte sau mementouri pe Android sau iOS? Dacă da, care?
2. Care ar fi funcțiile tale preferate în tr-o aplicatie de acest tip ?
3. Ce anume ai schimba la o astfel de aplicație ?
4. Ai considera utilă o aplicație de mementouri în care accentul se pune pe
simplitate?
5. Ce apreciezi mai mult? A plicațiile care au foarte multe funcții incluse sau cele
care au mai puține – doar ”strictul necesar”?
6. Ai folosi o aplicație de memento dacă ac easta ar avea un design simplu si nu ar
avea deloc reclame?
Aceste într ebări au fost alese pentru că nu doar testează piața (care aplicații s unt cele mai folosite),
dar și arată ce ar crede oamenii despre aplicația prezentată în lucrarea de față.
La chestionar au răspuns 20 de persoane de la facultate ș i aceste ră spunsuri au stat la baza decizi ei
de a face o astfel de aplicaț ie.
18
4. Ce aduce în plus aplicația prezentată?
Conform metodologiei, analizând aplicațiile existente, putem să afirmăm că următoarele funcții
sunt aproa pe standard, adică incluse (în general) în orice aplicație de memento :
Alerte repetitive pe mementourile deja create
Mementouri dedicate pentru zile de naștere, facturi, întâlniri
Widget pentru home screen
Comenzi vocale (Speech -to-Text)
Vizualizare stil calendar
Alerte setate de dinainte pent ru mementourile create
Memento pentru apeluri pierdute
Marcare prin culori a mementourilor existente
Funcții de backup & restore (copie de siguranță și restabilire)
Datorită limitării resurselor ( timp și scop gener al), aplicația prezentată nu merge pe principul de a
aduce cât mai multe funcții posibile. Principiul abordat este de a oferi simplitate in utilizare si
stabilitate.
Un lucru in plus pe care aplicația noastră îl aduce este lipsa reclamelor si adăugare nelimita ta de
remindere.
Deși utilizatorii experimentați s -ar putea descurca ușor cu orice aplicație pe iOS sau Android
(oricât de complexă ar fi) știm că utilizatorul obișnuit nu dispune de cunoștiințe tehnice(sub nivel
mediu). Utilizatorul obișnuit știe doar min imul necesar din tot ce înseamnă iOS sau Android. De
aceea, dacă nu ne orientăm pe principiul de profesionalism general (adică pe principiul de a oferi
ceva solid până și celor mai pricepuți utilizatori) , atunci aplicația prezentată este foarte utilă pent ru
scopul ei.
Un alt beneficiu este că aplicația având o interfață foarte simplă , sunt mari șansele ca nici un
utilizator să nu aibe nevoie de manual de utilizare . Nu putem ști exact în ce măsură (cât la sută din
utilizatori) aplicația se poate folosi făr ă instrucțiuni, sau fără ca cineva să spună cum se folosește.
19
Pentru a afla date exacte ar trebui mai mult timp și mai multe resurse :
1. Chestionare la care să răspundă cel puțin 5000 de persoane din țări diferite și clase sociale
diferite. Din cei 5000 de persoane, 2500 ar trebui să fie fără experiență tehnică, iar 2500 cu
multă experiență, pentru a putea compara rezultatele eficient.
2. Să se observe cum se descurcă cei 5000 de utilizatori cu aplicația fără să l e arătăm cum s –
ar folosi. Adică am putea măsur a rata de succes pentru:
a. Crearea de mementouri
b. Crearea contului de utilizator
c. Logarea de pe alt dispozitiv decât cel de pe care s -a creat contul .
Scopul lucrării nu cuprinde cele menționate mai sus din cauza lipsei resurselor.
20
5. Arhitectura aplicatiei
Ca să înțelegem arhitectura trebuie să luăm în considerare arhitectura PhoneGap. Graficul de mai
jos prezintă vizual această arhitectură:
Sursă: https://stackoverflow.com/questions/26648378/phonegap -basic -architecture
În primul rând , aplicația este dezvoltată ca orice aplicație web. Cu alte cuvinte, programatorul
scrie HTML, CSS și JavaScript. Această abordare este foarte utilă în cazul în care vr em ca o
interfaț ă grafică să fie folosită pentru o aplicație pe dispozitive mobile (Android, iOS), dar nu știm
programare pentru acele dispozitive sau nu avem dispozitivele pentru a putea scrie codul sursă .
Totodată, dacă cineva scrie o aplicație Android, codul sursă nu prea este util pentru a rula aceeași
aplicație pe iOS.
21
Având aplicația dezvoltată ca o aplicație web, treb uie să ne imaginăm că este o pagină web fără
ecranul (cadrul) browserului ( adică ne putem folosi de tot spațiul de pe ecran ). Din co dul web
rezultă o v izualizare (interfață grafică) care se obține prin API -urile specifice HTML -ului și API –
urile de JavaScript ale PhoneGap.
De la pasul anterior , folosind API -urile PhoneGap și plugin -urile disponibile, se obține accesul la
sistemul de op erare mobil, adică servicii, senzori, intrare și grafică. La acest nivel al arhitecturii
aplicația este gata de utilizare pentru oricare sistem de operare suportat de PhoneGap.
Ca arhitectură de programare, modelul PhoneGap se aseamănă cu modelul MVC (Mode l-View –
Controller). MVC -ul presupune un model, o interfață gr afică și o unitate de control ( partea de unde
vin comenzile, evenimentele, legătura dintre model și interfață grafică ).
În cazul proiectului p rezentat, interfața grafică rezultă în urma interpret ării codului HTML, CSS,
JavaScript.
Modelul este c omponenta aplicației realizate –funcționalitațile pe care trebuie să le includă
aplicația. Unitatea de control în acest caz se face prin comenzi de JavaScript care vor accesa și
părți din API -ul PhoneGap – de aici vin evenimentele, transmiterea datelor, legătura dintre model
(conceptul aplicației) și interfața grafică (cum arată vizual aplicația pe iOS& Android).
22
6. Tehnologiile utilizate
Pentru realizarea ace stei aplicații s -au folosit următoarele tehnolo gii:
PhoneGap API
HTML/HTML5
CSS/CSS3
JavaScript
CORS
MySQL
6.1 Despre PhoneGap API
PhoneGap API trebuie înțeles ca interfață pentru accesa rea anumitor componente ale
dispozitivelor mobile. Dacă nu ar fi ace astă interfață , totul ar fi doar programare web fără vreo
funcționalitate specifică dispozi tivelor Android si iOS . PhoneGap API poate accesa:
Camera
Contactele
Geolocația
Compasul
Media
Rețeaua
Notificările
Stocarea
Accelerometrul
Cu ajutorul acestui API vizualizarea web este una extinsă, permițând u-se acces la funcțiile
specifice doar dispozitivelor care de altfel nu sunt accesibile niciunui site din browserul deschis
de pe aceste dispozitive.
23
6.2 Introducere spre alternative
Prima întrebare este: există oare alternative? Nu toate paginile web folosesc în prin cipiu HTML,
CSS, Java Script și derivatele acestora , adică platforme sau limbaje născute din acestea?
Răspunsul este nu! Deja cu ani în urmă, mai mulți oameni au avut dorința de a avea ceva mai solid,
mai bun decât aceste standarde cu care ne -am obișnuit c a și când ar fi singurele disponibile. Deși
încă nu este vreo alternativă puternică pe scară largă, se lucrează la mai multe proiecte și concepte,
dintre care unele chiar open -source, permițând oricui să contribuie cu ce poate.
Vă vom prezenta câteva alter native, comparându -le cu HTML, CSS și JavaScript.
6.2.1 Layx
Layx a pornit ca un proiect promiță tor, dar pe moment stagnează din 28 Ianuarie 2015. Codul sursă
al acestui proiect se află pe GitHub la adresa https://github.com/layxlang/layx . Siteul oficial
(http://www.layx.org/ ) prezintă limbajul Layx în sine.
Acest limbaj este bazat pe straturi (layers), având o abordare s implistă cu ajutorul unor coordo nate
în plan. Limbajul suportă și JavaScript, și CSS, dar a fost const ruit să fie de sine stătător, neavând
nevoie de HTML, CSS sau JavaScript.
Avantaj: Este o alternativă adevărată la HTML, CSS și JavaScript
Dezavantaj: Nu se mai lucrează la acest proiect .
6.2.2 Dart
Spre de osebire de Layx, Dart este un proiect in derulare la care se lucrează. Nu doar că se lucrează
în continuare la acest proiect, dar în momentul de față până și gigantul Google folosește Dart pentru
a crea aplicații foarte mari.
Dart este un limbaj de program are, asemănător cu C++, Java și C#.
24
7. Etapa de analiză
7.1 Preliminarii
Pentru aplicația prezentată am intenționat să implementăm următoarele funcții:
Crearea unui cont de utilizator ;
Crearea de mementouri pe bază de text și dată/oră ;
Tema de zi/noapte;
Vizua lizarea ușoară a mementourilor
Notificări locale
Sonerie standard
Stergea alarmelor in asteptare/efectuate
Conturile vor fi stocate pe un server pentru a putea fi accesibile de oriunde.
Funcționalitățiile sunt unele simple.
Costuri, accesul la un server de calitate co stă , depinzând de alegere. Se pot alege și soluții gratis
sau foarte ieftine care nu însă garan tează calitatea (viteza, securitat ea, accesibilitatea) .
7.2 Publicul target al aplicației
Serverul va găzdui baza de date, iar utilizatori i pot fi persoane de diferite vârste și c lase sociale
care au nevoie de organizare cu ajutorul memento -urilor.
7.3 Utilizarea aplicației
Cum am specificat în capitolele precedente, această aplicație își propune să fie simplă, utilizarea
fiind ușoară și pentru c ei care nu cunosc aproape deloc sistemul de operare Android sau iOS , și
nici dispozitivele mobile pe care acestea rulează .
7.4 Setările și detaliile tehnice
Aplicația folosește o bază de date care este stocată pe un server. Atat b aza de date, cât și serverul
trebuie să fie configurate corect, astfel încât să se poată accesa în orice moment 24/7.
Utilizatorul trebuie să fie conectat la internet și să aibă aplicația instalată pe dispozitivul mobil
pentru a putea folosi funcțiile acesteia.
25
Fiind ales mediul de de zvoltare PhoneGap, este nevoie de programare în HTML, CSS, JavaScript.
Pentru crearea si administrarea bazei de date folosim MySQL.
MySQL se poate folosi în multiple versiuni,depinde de serverul ales( dacă dispune de vreo aplicație
de acces simplificat sau nu). Dacă se folosesc programe dedicate operațiilor cu MySQL , acestea
trebuie instalate și configurate , iar conexiunea cu baza de date de pe serve r trebuie stabilită, creată
și testată.
8. Proiectarea
Odată finalizată analiza se poate trece la etapa de proiectare . O bună proiectare ne ajută în
dezvoltarea aplicației, nefiind existente probleme legate de interpretare, analiză necunoscută, mod
de utilizare neștiut, și nici alte probleme posibile în cazul în care nu s -ar face analiză.
8.1 Tratarea erorilor
În orice aplicație este important să ne ocupăm de posibile erori și să le tratăm. Dacă o aplicație are
o eroare pe baza căre ia nu ar face ceea ce utilizatorul vrea, nu este suficient că aplic ația se închide
automat și nu execute funcționalitate a. Utilizatorul trebuie info rmat despre existența problemei.
Pentru a trata erorile, trebuie doar să știm care erori se pot preîntâmpina în decursul execuției
aplicației.
26
Următoarele erori sunt posibile:
1) Nu există conexiune de internet
2) Conexiunea de internet are întreruperi, pierderi, sau viteză slabă
3) Serverul este suprasolicitat sau este inaccesibil din orice alt motiv (mentenanță, pană de
curent, schimbarea unei componente electrice)
4) Baza de date devine inaccesibilă (prea multe date, date salvate în format g reșit din cauza
erorilor logice din codul sursă)
5) Utilizatorul introduce valori nepermise (introducerea textului în câmpul destinat datei
calendaristice, format de dat ă invalidă, oră inexistentă, orice alte valori care produc eroare)
6) Dispozitivul are proble mă de software sau de hardware, astfel nefiind posibilă funcționarea
corectă a aplicației
7) Erori logice
Pentru a trata erorile eficient este nevoie să analizăm cu atenție codul sursă. Fiecare linie din codul
sursă care execută o comandă tre buie analizată . De exemplu, dacă avem o aplicație care calculează
A+B, trebuie să presupunem că utilizatorul poate introdu ce texte în loc de numere sau numere prea
mari pentru a fi stocate în memorie.
27
9. Implementarea
9.1 Crearea siteului web
Pentru crearea acestui program și funcționarea conform planificării, vom crea un site web prin
serviciul gratuit 000webhost. Este discutabilă calitatea acestui serviciu, dar pentru scopul de a
demonstra tehnologiile folosite și corectitudinea proi ectului prezentat, am optat acest serviciu .
9.2 Setarea bazei de date
Pentru a folosi toate funcțiile legate de sign in (conectare) sau sign up (înscriere), care să
funcționeze și prin alte dispozitive decât cel local (cel de pe care s -a creat contul), a trebuit să avem
o bază de date online. Este convenabil că pagina creată pe 000webhost.com ne permite și folosirea
tehnicilor PHP, dar și folosirea bazei de date, ambele rămân găzduite online.
Este important de știut că PhoneGap nu suportă PHP – de aceea, nu se putea seta un website local,
pentru că atunci și folosirea aplicației PhoneGap ar fi fost limitată la calculatorul pe care este
găzduit site -ul web, iar și pe acel calculator am fi putut folosi doar simulator/emulator de Android
sau de iOS.
Vom accesa partea de ”Manage database”:
După aceea, trebuie să dăm click pe ”New Database”:
Acest buton se găsește pe ace eași pagină mai jos (Manage database). După ce completăm datele
pe formularul de mai jos vom apăsa ”Create”.
28
În cazul nostru rezultatul se va vedea mai jos. Vom folosi Manage/PhpMyAdmin pentru a avea o
interfață de control a bazelor de date prietenoasă și puternică (PhpMyAdmin), prin care vom putea
adăuga tabelele folosite și (în caz de nevoie) pentru corecta anumite greșeli di n baza de date.
Este foarte important că deși anterior la numele bazei de date și la numele utilizatorului am
completat doar ”reminderapp”, numele real al utilizatorului va fi acel ”id1931071_reminderapp”
din imaginea de mai jos.
29
După conectare, vom ved ea interfața PhpMyAdmin, dar deocamdată totul este gol:
În următorul pas vom crea tabelul pentru utilizatori:
Setările tabelului vor arăta în felul următor:
30
Vom vedea tabelul deja creat:
9.2.1 Conectarea codului PHP la baza de date
Daca ne accesăm adresa
https://www.000webhost.com/members/website/reminderapp2017/database ni se spune cum să ne
conectăm corect!
Astfel, p utem folosi codul PHP care poate conecta la baza noastră de date găzduită pe server:
<?php
header("Access -Control -Allow -Origin: *");
$con =
mysqli_connect("localhost","id1931071_reminderapp","123456","id1931071_reminderapp") or
die ("could not connect database");
31
?>
9.2.2 Folosirea TotalCommander pentru a accesa mai ușor partea de FTP
Dacă accesăm linkul următor ( ), vom vedea următoarele detalii FTP:
Deci, exclusiv datele de conexiune sunt:
32
Aceste date sunt cele de interes pentru a seta din TotalCommander.
După ce deschidem TotalCom mander, accesăm meniul relevant:
De aici accesăm New connection:
După ce completăm corect datele apăsăm pe OK.
33
Acum n e putem conecta apăsând connect.
Prin TotalCommander ne conectăm :
34
Încărcând fișierele noastre :
Partea de JSON es te importantă, pentru că noi de fapt așa realizăm comunicarea între PhoneGap
și baza de date de pe server!
9.3 Algoritmii folosiți în cadrul aplicației
Crearea aplicației în Ph oneGap și conectarea acesteia la serverul online pentru partea de PHP și
bază de dat e necesită anumiți algoritmi .
Menționăm că s-au făcut pe calculator capturile de ecran (screenshots), adică accesând partea web
generată de PhoneGap.
9.3.1 Conectarea la baza de date
Dacă se folosesc aplicații dedicate, cum ar fi aplicația web PhpMyAdmin, conect area la baza de
date e relativ simplă – se introduce utilizatorul și parola, neavând de -a face cu al te setări. În cazul
nostru baza de date este setată pe un server care nu este local (nu -l vom avea pe dispozitiv și nici
pe calculator în cazul în care am testa local înainte de a compila pentru dispozitivul mobil). Deși
serviciul de găzduire (hosting) ne -ar permite accesul prin PhpMyAdmin, acest lucru nu ne ajută,
fiindcă aplicația PhoneGap nu poate comunica cu PhpMyAdmin prea simplu (de fapt a realiza
acest lucru ar fi foarte complicat și ar dura mult timp, necesitând cunoștiințe de programare foarte
avansată).
De aceea, conexiunea cu baza de date se face printr -un script PHP pe server . Este importantă
testarea scriptului, pentru că fără o conexiune bună, celelalte părți ale aplicației nu vor funcționa.
35
Scriptul folosit pentru conectarea la baza de date este următorul:
<?php
header("Access-Control-Allow-Origin: *" );
$con =
mysqli_connect ("localhost" ,"id1931071_reminderapp" ,"123456" ,"id1931071_remind
erapp") or die ("could not connect database" );
?>
Listare cod sursă 1 – conectare la bază de date prin cod PHP
Este interesantă conectarea, și probabil se pune întrebarea: de ce localhost dacă am precizat că nu
ne conectăm local, ci pe un server? Scriptul de mai sus este î ncărcat pe serverul folosit, și relativ
la server, și conexiunea la baza de date, și baza de dat e efectivă dar și celelalte scripturi PHP sunt
toate locale, pe aceeași gazdă, acel localhost care în acest caz e serverul. Am permis originea *
pentru testare ca să vedem manual dacă și conexiunea în sine este corectă.
Restul parametrilor, adică numele de utilizator, parola și baza de date sunt date de gazdă, cum am
precizat în această documentație. Doar parola putea fi setată de utilizator când s -au făcut toate
setările pentru server.
9.3.2 Înregistrarea utilizatorului (Sign Up)
Pentru a înregistra utilizatorul , cerem un email, o parolă și un nume de utilizator. Înainte de a
începe descrierea algoritmului este important de precizat cum se poate valida o adresă de email.
Deși aparent emailul e doar ”ceva caractere”, un arond (@) și iarăși ”ceva caractere” punct ( .)
”ceva domeniu valid”, nu este ușor de validat.
Există un stan dard pentru adresele de email (care adrese ar putea fi valide) ,dar și dacă am scrie
un RegEx pentru toate (care ar fi foarte lung), tot nu garantează că emailul este vali d. Motive
pentru ace ste aspecte:
1. Se pot înregistra emailuri care nu sunt șablon – un domeniu care arată ciudat nu este și
invalid .
36
2. Se pot crea aliasuri pentru emailuri. Dacă un alias ar fi e.mailul@meu, nu înseamnă că e
invalid. Dar, în același timp, mas.ina@mea ar putea fi un email invalid.
3. Singura verificare completă ar putea fi prin server, dacă am trimite un email de test,
verificând dacă recipientul chiar a primit sau nu emailul trimis.
Acestea fiind spuse, să analizăm codul sursă.
function validateEmail (email) {
var chrbeforAt = email.substr(0, email.indexOf('@'));
if (!($.trim(email).length > 127)) {
if (chrbeforAt .length >= 2) {
var re =
/^(([^<>() \[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@(( \[[0-
9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a -zA-Z\-0-9]+\.)+[a-zA-
Z]{2,}))$/ ;
return re.test(email);
}
return false;
}
return false;
}
Listare cod sursă 2 – validare de email în JavaScript
Acest regex este unul complicat. Confor m sursei http://emailregex.com/ această verificare acoperă
99.99% din cazuri.
Conform m ai multor surse, validarea emailurilor cu regex oricum nu este recomandată. Se
recomandă doar validarea pe server, cea de regex fiind considerată doar orientativă pentru
utilizatorul care scrie datele personale într -un formular.
Partea de înregistrare o an alizăm pas cu pas. Definim funcția :
function handleRegister ()
La început, vom verifica datele transmise prin formular.
var form = $("#registerForm" );
//disable the button so we can't resubmit while we wait
$("#submitButton" ,form).attr("disabled" ,"disabled" );
var u = $(".username" , form).val();
var p = $(".password" , form).val();
var e = $(".email" , form).val();
37
var c = $(".confirm -password" , form).val();
if(u === '' || p === '' || e === '' || c === '') {
showToast ("You must enter all fields" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
if(p !== c) {
showToast ("You must enter matching passwords" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
După ce am salvat toate datele în variabile, verif icăm să nu fie goale. Dacă sunt goale, terminăm
execuția funcției și anunțăm prin mesaj de eroare. În mod similar, dacă parola nu corespunde cu
parola confirmată, dăm mesaj de eroare și ne oprim.
Validarea începe abia acum, folosind expresiile regulare și funcția prezentată mai sus.
var regex_u = new RegExp("^[a-zA-Z0-9\\_\\-]{4,30}$" );
if(!regex_u.test(u)) {
showToast ("Invalid username! \r\nCan contain: letters, numbers, _
and -\r\nMin length: 4 \r\nMax length: 30" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
var regex_p = new RegExp("^[a-zA-Z0-9\\_\\-\\!\\^\\(\\)\\.]{6,30}$" );
if(!regex_p.test(p)) {
showToast ("Invalid password! \r\nCan contain: letters, numbers, _,
-, !, ^, (, ), . \r\nMin length: 6 \r\nMax length: 30" );
$("#submitButton" ).removeAttr("disabled" );
return false;
}
if(validateEmail (e) === false) {
showToast ("Invalid email! Please enter a valid email address." );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
Aceste expresii vor determina dacă un nume de utilizator, o parolă respectiv un email sunt valide.
Validarea de email a fost deja prezentată. Validarea utilizatorului se face verificând că are minim
4, maxim 30 de caractere lungime, iar oricare caracter poa te fi literă (mică sau mare), cifră,
caracterul _ sau caracterul -.
Similar, validarea parolei înseamn ă să aibă minim 6, maxim 30 de caractere lungime, iar oricare
caracter poate fi ca oricare caracter de la numele de utilizator. În plus, mai sunt accepta te și
caracterele : !, ^, (, ) și . (punctul).
Se observă că după fiecare verificare este o clauză if – dacă nu a trecut de verificare, vom da un
mesaj de eroare și vom opri execuția funcției de înregistrare.
38
$.post("https://reminderapp2017.000webhostapp.com/register.php ", {user:u,
email:e, pass:p},
function (res) {
if (res.success === true) {
showToast ("You have successfully registered as " + u +" !");
$.mobile.changePage ("index.html" );
$("#loginStatus" ).text("You are logged in as " +u);
localStorage .setItem("isLogged" , true);
accountSelectLogged ();
} else {
localStorage .setItem("isLogged" , false);
showToast (res.message);
}
$("#submitButton" ).removeAttr ("disabled" );
},"json");
return false;
Requestul de POST dat prin JS ON este unul simplu – dăm ca parametri valorile user, email și
parolă . Parola se trimite doar o dată – validarea nu se face pe server în cazul nostru. Dacă răspunsul
dat de server e pozi tiv (are success setat pe true), atunci se arată mesajul aferent și revine aplicația
pe index.html. În caz contrar se afișează mesajul de eroare relevant.
39
9.3.3 Conectarea utilizatorului (Login)
function handleLogin () {
var form = $("#loginForm" );
//disable the button so we can't resubmit while we wait
$("#submitButton" ,form).attr("disabled" ,"disabled" );
var u = $("#username" , form).val();
var p = $("#password" , form).val();
if (u === '' || p === '') {
showToast ("You must enter a username and password" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
var regex_u = new RegExp("^[a-zA-Z0-9\\_\\-]{4,30}$" );
if(!regex_u.test(u)) {
showToast ("Invalid username! Can contain: letters, numbers, _ and
-\r\nMin length: 4 \r\nMax length: 30" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
var regex_p = new RegExp("^[a-zA-Z0-9\\_\\-\\!\\^\\(\\)\\.]{6,30}$" );
if(!regex_p.test(p)) {
showToast ("Invalid password! Can contain: letters, numbers, _, -,
!, ^, (, ), . \r\nMin length: 6 \r\nMax length: 30" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
$.post("https://reminderapp2017.000webhostapp.com/login.php ",
{user:u,pass:p}, function (res) {
if (res.success == true) {
localStorage .setItem("isLogged" , true);
showToast ("Welcome back " + u +", you're logged in now!" );
$.mobile.changePage ("index.html" );
$("#loginStatus" ).text("You are logged in as " +u);
accountSelectLogged ();
} else {
localStorage .setItem("isLogged" , false);
showToast (res.message);
}
$("#submitButton" ).removeAttr ("disabled" );
},"json");
return false;
}
Listare cod sursă 3 – funcția de conectare (parte client în JavaScript)
Această funcție se ocupă – pe partea de client – de funcția de conectare.
40
În primul rând, ajungem la partea de formular, adică prin jQuery salvăm accesul la formular într-
o variabilă. După aceea, butonul de trimitere (submitButton) este setat pe dezactivat (disabled)
pentru a împiedica cererile multiple către server.
În variabilele u și p salvăm numele de uti lizator și parola.
var u = $("#username" , form).val();
var p = $("#password" , form).val();
if (u === '' || p === '') {
showToast ("You must enter a username and password" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
După ce au fost salvate, verificăm să nu fie variabilele fără valoare (goale). Dacă vreo variabilă nu
are valoare dată, arătăm un mesaj de eroare și execuția funcției este întreruptă prin return false.
Dacă aplicația a trecut de verificarea de mai sus, trecem printr -o verificare cu expresii regulare
(Regular Expressi ons) care ne ajută să permitem doar un anumit format pentru nume de utilizator,
dar și pentru parolă. Să vedem în detalii verificarea și cum funcționează.
var regex_u = new RegExp("^[a-zA-Z0-9\\_\\-]{4,30}$" );
if(!regex_u.test(u)) {
showToast ("Invalid username! Can contain: letters, numbers, _ and
-\r\nMin length: 4 \r\nMax length: 30" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
În mod normal, ca expresie regulară simplă (nu prin JavaScript), cea de sus are fi: ”^[a -zA-Z0-
9\_\-]{4,30}”. Adică, orice caracter de la a -z, sau orice caracter de la A -Z sau orice cifră de la 0 –
9 sau caracterul _ sau caracterul – repetate de minim 4 ori, maxim 30 de ori redau ceea ce permite
expresia regulară. Deci, așa permitem doar nume de utilizator care îndeplinește exact a ceste
condiții. În caz de eșec a testului, se primește mesajul de eroare, după care se activează butonul de
trimitere (cel care zice Login) și fun cția nu mai este executată (se dă un return false). În mod
similar verificăm parola:
var regex_p = new RegExp("^[a-zA-Z0-9\\_\\-\\!\\^\\(\\)\\.]{6,30}$" );
if(!regex_p.test(p)) {
showToast ("Invalid password! Can contain: letters, numbers, _, -,
!, ^, (, ), .\r\nMin length: 6 \r\nMax length: 30" );
$("#submitButton" ).removeAttr ("disabled" );
return false;
}
41
Aici sunt doar câteva diferențe. Marea parte se înțelege datorită exemplului anterior, ce este în plus
sunt caracterele !, ^, (, ) și . (punct ul). Aceste caractere, precum și _ și – sunt trecute cu escape
(adică un backslash \) pentru că nu vrem să fie interpreteze altfel (aceste caractere reprezintă
instrucțiuni în sintaxa regex).
Dacă variabilele au fost validate, verificăm și dacă acestea su nt goale (fără valoare). Dacă au
valoare (orice, dar nu valoare goală), atunci printr -un jQuery post request trimitem la server, direct
la un script în PHP, în format JSON. Este important de știut că PhoneGap comunică cel mai ușor
cu JSON. Desigur, nu este exclusă comunicarea simplă, adică text neformatat (adică fără formatare
JSON).
Observăm că există o funcție cu un parametru, care prelucrează rezultatele. Rezultatul fiind un
obiect JSON, are setat un parametru ”success” care este de tip boolean (true sau false). Dacă este
setat pe true știm că cererea a fost finalizată. În acest caz pe stocarea internă salvăm o variabilă
pentru a ști că utilizatorul s -a conectat deja. După aceea, afișăm un mesaj de întâmpinare și setăm
un text viz ibil utilizatorului prin care va ști că s -a conectat.
În caz de eșec arătăm mesajul (cauza) aferent requestului. La urmă submitButton nu mai rămâne
dezactivat.
Pentru a vedea clar cum s -a realizat conectarea, ne trebuie o privire și la server, unde este codul
PHP care face toate verificările și conexiunea cu baza de date.
42
<?php
header('Access-Control-Allow-Origin: *' );
header('Access-Control-Allow-Credentials: true' );
header('Access-Control-Allow-Headers: x -requested -with');
include "db.php" ;
if(isset($_REQUEST ['user'])&&isset($_REQUEST ['pass']))
{
$utilizator =$_REQUEST ['user'];
$parola=$_REQUEST ['pass'];
$q=mysqli_query ($con,"SELECT COUNT(*) FROM `utilizatori` WHERE
`parola`=PASSWORD(' $parola') AND `user`=' $utilizator '");
if($q)
{
$count=0;
if($row = mysqli_fetch_array ($q))
{
$count = $row[0];
}
if($count==1)
{
$message = array(
"success" => true,
"message" => "Successful login"
);
}
else
{
$message = array(
"success" => false,
"message" => "Wrong user and/or password"
);
}
}
else
{
$message = array(
"success" => false,
"message" => "SQL error"
);
}
}
else
{
$message = array(
"success" => "false",
"message" => "Request error"
);
}
echo json_encode ($message );
?>
Listare cod sursă 4 – conectarea (PHP, cod de pe server)
43
Primele trei linii de cod reprezintă o parte foarte importantă:
header('Access-Control-Allow-Origin: *' );
header('Access-Control-Allow-Credentials: true' );
header('Access-Control-Allow-Headers: x -requested -with');
Practic aici comunicăm și setăm pe server cross -origin requests (CORS). Altfel spus, permitem
conectarea de oriunde (*), permitem credențiale (adică cookies) și permitem și requesturile care
vin prin jQuery, care de obicei sunt trimise cu parametrul ”x -requested -with”. Fără această parte,
nu ar merge aplicația deloc, fiindcă comunicarea cu serverul ar fi oprită automat din cauza
nerespectării politicilor de conectare.
include "db.php" ;
Linia de mai sus include de fapt partea de conexiune la baza de date. Deci, aici se execută deja
codul din fișierul db.php, care (cum am prezentat mai înainte) face conexiunea cu baza de date.
if(isset($_REQUEST ['user'])&&isset($_REQUEST ['pass']))
{
$utilizator =$_REQUEST ['user'];
$parola=$_REQUEST ['pass'];
$q=mysqli_query ($con,"SELECT COUNT(*) FROM `utilizatori` WHERE
`parola`=PASSWORD(' $parola') AND `user`=' $utilizator '");
Mai sus se verifică dacă în r equest au venit sau nu parametr i denumiți user și pass. Dacă acestea
nu au venit, nu se execută cealaltă parte din cod (interiorului clauzei if). În caz că acestea sunt
setate, adică au fost trimise scriptului de PHP, se preiau val orile și se salvează în variabile. Apoi,
prin variabila $q facem interogarea SQL care, după cum se vede, numără câți utilizatori există în
baza de date cu userul și parola respectivă.
if($q)
{
$count=0;
if($row = mysqli_fetch_array ($q))
{
$count = $row[0];
}
if($count==1)
{
$message = array(
"success" => true,
"message" => "Successful login"
);
}
else
{
44
$message = array(
"success" => false,
"message" => "Wrong user and/or password"
);
}
}
Aceste linii se execută doar dacă interogarea a fost cu succes. Am creat o variabilă $count, care e
inițializată cu 0 . În continuare se preia rezu ltatul interogării și se verifică dacă este egal cu unu.
Dacă este egal cu unu, înseamnă că există acel utilizatorul, în caz contrar nu avem acel utilizator
în baza noastră de date.
Se setează parametrul ”success” pentru a indica dacă a r eușit rularea scriptului sau nu și parametrul
”message” va conține mesajul aferent.
else
{
$message = array(
"success" => false,
"message" => "SQL error"
);
}
Aceste linii setează mesajul și valoarea de succes pentru cazul în care a fost o eroare de SQL.
else
{
$message = array(
"success" => false,
"message" => "Request error"
);
}
echo json_encode ($message );
?>
Ultimele linii din scriptul PHP se ocupă de cazul în care requestul nu a avut toate datele necesare
pentru a se conecta un utilizator. La urmă, se codifică în format JSO
În esență, această arhitectură a conectării garantează că utilizatorul s -ar putea conecta de pe orice
dispozitiv, chiar dacă contul de utilizator nu a fost creat de pe dispozitivul respectiv. Cu alte
cuvinte, dacă baza de date ar fi fost st ocată pe dispozitiv, nu se putea conecta nimeni de pe alt
dispozitiv, nici dacă ar fi instalat aplicația ReminderApp. Prezența bazei de date pe un server
asigură accesul de oriunde, cu condițiile:
1. Să fie dispozitiv cu conexiune la internet, suportat de Pho neGap
45
2. Să fie instalată aplicația ReminderApp
9.3.4 Schimbarea temei (zi/noapte)
Schimbarea temei, pe interfața grafică, este simplă (un slider pe ON/OFF). Partea de cod sursă e ste
scrisă în felul următor :
$.mobile. changeGlobalTheme = function (theme) {
// These themes will be cleared, add more
// swatch letters as needed.
var themes = " a b c d e" ;
// Updates the theme for all elements that match the
// CSS selector with the specified theme class.
function setTheme (cssSelector, themeClass, theme) {
$(cssSelector)
.removeClass( themes.split(" ").join(" " + themeClass + "-"))
.addClass(themeClass + "-" + theme)
.attr("data-theme", theme);
}
// Add more selectors/theme classes as needed.
setTheme (".ui-mobile-viewport" , "ui-overlay" , theme);
setTheme ("[data-role='page']" , "ui-body", theme);
setTheme ("[data-role='header']" , "ui-bar", theme);
setTheme ("[data-role='listview'] > l i", "ui-bar", theme);
setTheme (".ui-btn", "ui-btn-up", theme);
setTheme (".ui-btn", "ui-btn-hover", theme);
};
Listare cod sursă 5 – schimbarea temei zi/noapte (JavaScript)
Temele acestea sunt luate automat din parte a de stil care provine din jQuery, adică stilul CSS care
era deja inclus:
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile –
1.4.5.min.css" >
Dacă ne uităm la codul de JavaScript, la schimbare temei se vor schimba automat selectorii de
CSS, adică de exemplu în loc de ui -body vom avea ui -body -a. În esență acest cod , având clasel e
și setările de CSS, fiecare element de pe pagină să folosească tema aleasă din designul CSS care e
dat deja de jQuery mobile, un fișier preluat de pe internet.
46
9.3.5 Actualizarea tabelului cu mementourile listate
refresh_table = function (page) {
if (!info) {
$("table" + page + "Table tbody" ).empty();
return;
}
info = JSON.parse(localStorage .getItem("rp_data" ));
if (!info.data) {
$("table" + page + "Table tbody" ).empty();
return;
}
var html = '';
for (var count = 0; count < info.data.length; count++) {
var scheduleTime = new Date(info.data[count][3]).getTime();
var currentTime = new Date().getTime();
var customTime = new Date(info.data[count][3]).toLocaleTimeString ('en-US', {
year: 'numeric' ,
month: 'long',
day: 'numeric' ,
hour: '2-digit',
minute: '2-digit'
});
if (currentTime < scheduleTime ) {
// pending notifications
html = html + "<tr><td>" + info.data[count][1] + "</td><td>" + customTime
+
"</td><td><a href='#' data -role='button' data -mini='true' data –
inline='true' onclick='cancel(" + info.data[count][0] + ");'>Cancel</a></td></tr>" ;
} else {
if (page == '#all') {
// triggered notifications
html = html + "<tr><td>" + info.data[count][1] + "</td><td>" +
customTime +
"</td><td><a href='#' data -role='button' data -mini='true' data –
inline='true' onclick=' clearSingle (" + info.data[count][0] +
");'>Clear</a></td> </tr>";
}
}
}
$("table" + page + "Table tbody" ).empty();
$("table" + page + "Table tbody" ).append(html).closest( "table" + page +
"Table").table("refresh" ).trigger( "create" );
};
Listare co d sursă 6 – actualizarea tabelului cu mementourile listate din aplicație
Acest cod est e responsabil pentru listarea mementourilor (în format tabelar) în paginile de ”Pending
reminders” și ”All reminders”. Dacă ne uităm la cod, se folosește stocarea internă, adică datele
locale din care aplicația va ști de toate mementourile. Pentru afișare se folosește elementul <table>,
care este cel mai simplu de folo sit pentru scopul aplicației. O alternativă ar fi fost cu elemente div
dar atunci am fi avut nevoie de mai multe setări din CSS.
47
Dease menea, acest cod verifică fiecare memento sa vadă dacă acesta este din ”viitor ”. De
exemplu, dacă am setat ieri un memen to, astăzi nu se va mai vedea, pentru că a trecut deja
evenimentul respectiv. Pentru simplitate, am ales formatul timpului en -US, adică cel standard
american.
9.3.6 Conectarea funcției pentru reactualizarea tabelului
$(document ).on("pagebeforeshow" , "#all, #pending" , function () {
refresh_table (window.location .hash);
});
Listare cod sursă 7 – conectarea funcției de reactualizare a tabelului
Acest eveniment simplu, un cod de doar 3 linii, este responsabil pentru ”chemarea” reactualizării
tabelului. În jQuery, evenimentul pagebeforeshow se petrec e înainte de a schimba pagina. Adică,
în cazul aplicației prezentate, în momentul în care dăm click pe Pending reminders sau pe All
reminders , mai întâi se apelează funcția refresh_table pe care am prezentat -o mai sus în
document.
Astfel, nu se va putea î ntâmpla să nu apară mementouri adăugate cu doar cu câteva clipe în urmă,
pentru că tabelul pe care -l vom vedea va fi deja actualizat.
9.3.7 Funcțiile de ștergere a mementourilor
cancel = function (id) {
if (cordova.plugins.notification !== undefined ) {
cordova.plugins.notification.local. cancel(id, callback );
}
remove_item (id);
};
clearSingle = function (id) {
if (cordova.plugins.notification !== undefined ) {
cordova.plugins.notification.local.clear(id, callback );
}
remove_item (id);
};
clearAll = function () {
if (cordova.plugins.notification !== undefined ) {
cordova.plugins.notification.local.clearAll( callback );
}
remove_items ();
};
Listare cod sursă 8 – funcții folosite pentru a șterge mementouri
48
La o analiză mai apropiată, se vede că cele trei fun cții sunt aproape identice. Dar atunci, de fapt,
care este diferența? Pr imele două funcții, adică funcția cancel și clearSingle sunt identice. Ele fac
același lucru, adică apelează funcția remove_item cu un ID aferent, funcție care va fi prezentată
mai jos în acest document, având rolul de a șterge un singur memento.
Funcția clear all pe de altă parte are rolul de a șterge fiecare memento. În continuar e vom vedea
cum acționează aceste funcții remove_item(id) respectiv remove_items() .
remove_item = function (id) {
var items = JSON.parse(localStorage .getItem("rp_data" )).data;
items.splice(id, 1);
var data = {data: items};
localStorage .setItem("rp_data" , JSON.stringify (data));
refresh_table (window.location .hash);
};
Listare cod sursă 9 – funcția remove_item
Această funcție citește rp_data , care stochează toate mementourile, și șterge cel ca re are ID -ul
aferent cu cel dată , iar apoi salvează rezultatele înapoi în stocarea locală. Această mulțime rp_data
se stochează în format de mulțime JSON. Funcția JSON.stringify transformă mulțimea în format
text, pe când func ția JSON.parse citește acel text și reconstruiește formatul JSON original.
remove_items = function () {
info = null;
var rp_data = {data: []};
localStorage .setItem("rp_data" , JSON.stringify (rp_data));
info = JSON.parse(localStorage .getItem("rp_data" ));
$.mobile.changePage( "index.html" );
var u = localStorage .getItem("loggedInUser" );
localStorage .setItem("isLogged" , true);
$("#loginStatus" ).text("You are logged in as " + u);
accountSelectLogged ();
$("#submitButton" ).removeAttr( "disabled" );
};
Listare cod sursă 10 – funcția remove_items
49
Acestă funcție face o revenire la o stare inițială în care nu era nici un memento setat. Din cauza
faptului că am creat în aplicație această opțiune de a șterge toate mementourile și am vrut o revenire
la ecranul principal, am scris codul de mai sus.
În primul rând, ștergem conținutul variabilei info care conținea da te despre mementouri. După
aceea, am creat o mulțime vidă rp_data , pe care o salvăm în variabila info. O dată ce am terminat
cu resalvarea stării curente (fără mementouri), revenim la pagina inițială unde va trebui să se vadă
cine este utilizatorul conecta t. Pentru acesta, trebuie să setăm conținutul loginStatus și să activăm
din nou butonul submitButton .
9.3.8 Adăugarea mementourilor
function add_reminder () {
var date = document .getElementById ("date").value;
var time = document .getElementById ("time").value;
var title_value = document.getElementById ("title").value;
var message_value = document .getElementById ("message" ).value;
if (date === "" || time === "" || title_value === "" || message_value === "") {
// navigator.notification.alert("Please enter all details");
showToast ("Please enter all details" );
return;
}
var scheduleTime = new Date((date + " " + time).replace(/-/g, "/")).getTime();
scheduleTime = new Date(scheduleTime );
var id = 1;
if (info.data) {
id = info.data.length;
}
if (cordova.plugins.notification !== undefined ) {
cordova.plugins.notification.local.hasPermission( function (granted) {
if (granted === true) {
schedule (id, title_value , message_value , scheduleTim e);
doAddReminderHack (date, time, title_value , message_value );
return false ;
} else {
cordova.plugins.notification.local.registerPermission( function
(granted) {
if (granted === true) {
schedule (id, title, message, scheduleTime );
doAddReminderHack (date, time, title_value , message_value );
return false ;
} else {
// navigator.notification.alert("Reminder cannot be added
because app doesn't have permission");
showToast ("Reminder cannot be added because app doesn't have
permission" );
}
});
}
});
} else {
// fallback option
schedule (id, title_value , message_value , scheduleTime );
doAddReminderHack (date, time, title_value , message_value );
return false ;
}
}
Listare cod sursă 11 – funcția principală responsabilă de adăugare mementourilor
50
Această funcție care adaugă mementouri este un pic mai complexă și se folosește de alte 2 funcții,
și de aceea vom explica mai în amănunte toate aceste detalii
În primul rând, cu următoarele comenzi, salvăm datele despre memento în variabile:
var date = document .getElementById ("date").value;
var time = document .getElementById ("time").value;
var title_value = document .getElementById ("title").value;
var message_value = document .getElementById ("message" ).value;
O dată ce au fost salvate, verificăm să nu fie date goale, iar dacă nu sunt date goale, setăm timpul
aferent mementoului – pe când a vrut utilizatorul să fie reamintit de evenimentul adăugat:
if (date === "" || time === "" || title_value === "" || message_value === "") {
// navigator.notification.alert("Please enter all details");
showToast ("Please enter all detail s");
return;
}
var scheduleTime = new Date((date + " " + time).replace(/-/g, "/")).getTime();
scheduleTime = new Date(scheduleTime );
Următorul pas este să aflăm id -ul pentru mementoul creat. Fiindcă mulțimile sunt numerotate de
la 0 în JavaScript, dacă nu avem nici un memento, primul creat ar avea ID -ul de zero.
var id = 0;
if (info.data) {
id = info.data.length;
}
Dacă avem plugin -ul pentru notificări și JavaScript recunoaște existența lui, atunci putem adăuga
mementoul. Totuși, trebuie să avem permisiuni (granted), pentru că altfel nu se poate adăuga. Dacă
nu avem instant permisiunea granted, încercăm să o înregistrăm (regis terPermission), iar dacă nici
așa nu merge, înștiințăm utilizatorul despre faptul că nu s -a putut.
51
if (cordova.plugins.notification !== undefined ) {
cordova.plugins.notification.local.hasPermission( function (granted) {
if (granted === true) {
schedule (id, title_value , message_value , scheduleTime );
doAddReminderHack (date, time, title_value , message_value );
return false ;
} else {
cordova.plugins.notification.local.registerPermission( function (granted) {
if (granted === true) {
schedule (id, title, message, scheduleTime );
doAddReminderH ack(date, time, title_value , message_value );
return false ;
} else {
showToast ("Reminder cannot be added because app doesn't have
permission" );
}
});
}
});
} else {
// fallback option
schedule (id, title_value , message_value , scheduleTime );
doAddReminderHack (date, time, title_value , message_value );
return false ;
}
Observăm că avem un fallback, adică în cazul în care nu avem plugin -ul de notificări. În toate
cazurile de creare, se fo losesc funcțiile schedule și doAddReminderHack . În continuare
prezentăm aceste 2 funcții importante.
52
function schedule (id, title, message, scheduleTime) {
if (cordova.plugins.notific ation !== undefined ) {
cordova.plugins.notification.local.schedule({
id: id,
title: title,
message: message,
at: scheduleTime
});
}
var array = [id, title, message, scheduleTime];
if (info) {
if (info.data) {
info.data[info.data.length] = array;
}
else {
var rp_data = {data: array};
localStorage .setItem("rp_data" , JSON.stringify (rp_data));
info = JSON.parse(localStorage .getItem("rp_data" ));
}
}
else {
var rp_data = {data: array};
localStorage .setItem("rp_data" , JSON.stringify (rp_data));
info = JSON.parse(localStorage .getItem("rp_data" ));
}
localStorage .setItem("rp_data" , JSON.stringify (info));
showToast ("Reminder " + title + " successfully added!" );
// Clear the inputs
document .getElementById ("date").value = '';
document .getElementById ("time").value = '';
document .getElementById ("title").value = '';
document .getElementById ("message" ).value = '';
}
Listare cod sursă 12 – funcția schedule (programare pe dată/timp)
Această funcție, prin pluginul de notificări, încearcă să programeze mementoul. Și în cazul în care
pluginul nu merge sau nu a fost instalat, pe stocarea locală salvează mementoul ca utilizatorul să
poată vedea ulterior că acesta există.
În același timp, la urmă, înștiinț ăm utilizatorul despre adăugarea mementoului și ștergem datele de
pe formular ca la un nou memento să începem cu o foaie albă – să se completeze datele de la zero.
Este impor tantă partea de verificare. Structura de mai sus cu if -else este menită pentru a evita
cazurile de null reference (referință pe null). Dacă variabila i nfo ar fi ștearsă, nu putem scrie în
JavaScript ”info.data” pentru că un null (nimic) nu are parametru pe nume ”data”, și ar da eroare
iar apl icația nu va putea funcționa.
53
function doAddReminderHack (date, time, title_value, message_value) {
var userid = localStorage .getItem("loggedInID" );
$.post("https://reminderapp2017.000webhostapp.com/addreminder.php" , {
d: date,
t: time,
title: title_value,
message: message_value,
uid: userid
},
function (res) {
if (res.success === true) {
showToast ("Reminder added for " + date + " " + time + " !");
} else {
showToast (res.message);
}
$.mobile.changePage( "index.html" );
var u = localStorage .getItem("loggedInUser" );
//showToast("Logged in user: " + u);
localStorage .setItem("isLogged" , true);
$("#loginStatus" ).text("You are logged in as " + u);
accountSelectLogged ();
$("#submitButton" ).removeAttr( "disabled" );
}, "json");
}
Listare cod sursă 13 – funcția doAddReminderHack pentru salvare în baza de date online
Funcția doAddReminderHack va salva în baza de date online datele despre memento. În primul
rând accesăm un jQuery post pe URL -ul dat, a dică datele noastre vor merge spre un script PHP pe
care îl vom prezenta mai jos. Prelucrarea rezultatelor este una simplă, și parcurge următorii pași:
1. Se citește variabila de succes – dacă avem succes, înștiințăm utilizatorul că a fost adăugat
un memento pe data aleasă de el , iar dacă nu, vom afișa mesajul de eroare.
2. Se trece înapoi pe ecranul principal
3. Se citește cine e utilizatorul conectat.
4. Se apelează funcția accountSelectLogged()
5. Se reactivează butonul submitButton
În continuare vom vedea ce se face pe server, pe parte a de PHP.
54
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true' );
header('Access-Control-Allow-Headers: x -requested -with');
include "db.php" ;
if(isset($_REQUEST ['title'])&&isset($_REQUEST ['message' ])&&isset($_REQUEST ['d'])
&&isset($_REQUEST ['t'])&&isset($_REQUEST ['uid']))
{
$title=$_REQUEST ['title'];
$message =$_REQUEST ['message' ];
$d=$_REQUEST ['d'];
$t=$_REQUEST ['t'];
$uid=$_REQUEST ['uid'];
//title message date time userid
$q=mysqli_query ($con,"INSERT INTO `reminders`
(`title`,`message`,`date`,`time`,`userid`) VALUES
('$title','$message ','$d','$t','$uid')");
if($q)
{
$message = array(
"success" => true,
"message" => "Reminder added successfully" ,
"userid" => $uid
);
}
else
{
$message = array(
"success" => false,
"message" => "SQL error"
);
}
}
else
{
$message = array(
"success" => false,
"message" => "Request error"
);
}
echo json_encode ($message );
?>
Listare cod sursă 14 – codul PHP de pe server pentru adăugarea unui memento
În primul rând, se setează parametrii pentru CORS, iar apoi se conectează baza de date. Verificăm
dacă mulțimea $_REQUEST conține toate datele necesare adăugării unui memento. În cazul în
care datele sunt prezent e, le salvăm în variabile PHP.
55
$q va fi scriptu l SQL pentru INSERT INTO (adăugare), iar apoi verificăm rezultatul rulării acestui
script. În cazul în care avem succes , scriem înapoi mesajul, true, și ID -ul userului logat. În caz de
eroare, vom înș tiința utilizatorul că este o eroare de SQL sau de Reque st.
La urmă, scriptul afișează totul în format JSON ca JavaScript să poată interpreta ușor rezultatele.
9.3.9 Deconectarea
function handleLogout () {
localStorage .removeItem ("username" );
localStorage .removeItem ("password" );
localStorage .setItem("isLogged" , false);
$.mobile.changePage( "index.html" );
$("#loginStatus" ).text("You are logged out" );
}
Listare cod sursă 15 – codul JS pentru deconectare
Pentru deconect are, codul este unul scurt și simplu. Ștergem datele despre utilizator și parolă, și
setăm variabila isLogged pe false, după care revenim pe pagina principală și înștiințăm utilizatorul
că s-a deconectat.
9.3.10 Funcția de ajutor accountSelectLogged
Funcția accou ntSelectLogged() este o funcție de ajutor în cazul în care un utilizator este conectat.
var accountSelectLogged = function () {
var logged = localStorage .getItem("isLogged" );
if (logged !== true) {
var accountSelect = $('#select -custom-21');
accountSelect .find('[value="#signin"]' ).remove();
accountSelect .find('[value="#signup"]' ).remove();
if (accountSelect .find('[value="#signout"]' ).length) {
accountSelect .selectmenu( 'refresh' , true);
return;
}
accountSelect .append($('<option>' , {value: '#signout' , text: 'Log Out '}));
accountSelect .selectmenu( 'refresh' , true);
}
};
Listare cod sursă 16 – codul sursă pentru accountSelectLogged
56
În primul rând, această funcție citește variabila isLogged . Dacă observăm că utilizatorul este
conectat, vom șterge elementele din meniul de cont care ar fi Si gn in și Sign up ( conectarea și
înregistrarea ). În locul lor adăugăm opțiunea de Log out (deconec tarea ).
Această funcție este importantă, pentru că altfel deși am setat toți parametrii necesari când
utilizatorul s -a conectat.A cești parametri nu vor modifica meniul afișat. În schimb, această funcție
de ajutor își face treaba cu modificarea meniului afi șat!
9.3.11 Codul pentru inițializare din JavaScript
Ca toate funcțiile prezentate să meargă, este nevoie de o inițializare corectă. Vom parcurge pașii
pentru inițializare, explicând ce face fiecare parte de cod.
var info = null;
document .addEventListener ("deviceready" , function () {
localStorage .setItem("isLogged" , false);
if (!localStorage .getItem("rp_data" )) {
var rp_data = {data: []};
localStorage .setItem("rp_data" , JSON.stringify (rp_data));
}
// https: //github.com/phonegap/phonegap -app-desktop/issues/351
// https://forums.adobe.com/thread/2179667
if (cordova.plugins.notification !== undefined ) {
cordova.plugins.notification.local.on( 'cancel' , function (notification) {
showToast('Reminder ' + notification.title + ' was canceled' );
});
cordova.plugins.notification.local.on( 'clear', function (notification) {
showToast ('Reminder ' + notification.title + ' was eraased' );
});
}
if (localStorage .getItem("rp_data" ) !== "undefined" ) {
info = JSON.parse(localStorage .getItem("rp_data" ));
}
Listare cod s ursă 17 – inițializare
La început declarăm variabila info cu valoarea null. Tot restul inițializării este leg at de evenimentul
deviceready , ceea ce este important, fiindcă am programat o aplicație PhoneGap. Până nu este
gata dispozitivul , nu putem include nici un cod de JavaScript. De aceea, dacă nu am fi legat codul
de acest eveniment, nimic nu ar fi putut garanta că acest cod ar fi rulat vreodată.
57
Setăm variabila isLogged pe fals, pentru că la început nimeni nu este conectat. Apoi setăm o
mulțime goală în variabila rp_data , unde ulterior vom salva mementourile.
Dacă avem plugin -ul cordova notification adăugăm înștiințarea automată a utilizatorului în cazul
evenimentului de cancel sau clear – adică ștergerea reminderului . Dacă rp_data există, salvăm
datele în variabila info.
if (localStorage .getItem("theme") == 'dark') {
var mySwitch = $("#flip-mini");
mySwitch [0].selectedIndex = 1;
if (location.hash === '' || location.hash === '#home') {
mySwitch .slider( "refresh" );
}
$.mobile. changeGlobalTheme ("b");
}
$("#flip-mini").slider({
stop: function (event, ui) {
if ($('.ui-slider-handle').attr('aria-valuenow' ) == 'on') {
$.mobile. changeGlobalTheme ("b");
localStorage .setItem("theme", 'dark');
} else {
$.mobile. changeGlob alTheme("a");
localStorage .setItem("theme", 'white');
}
}
});
Dacă tema este setată pe noapte (dark), atunci setăm sliderul pe poziția corectă și reîncărcăm
pagina pe tema globa lă b care are stilul de CSS pentru tema de noapte.
Când se declanșează evenimentul stop pe slider, verificăm dacă avem pe moment tema de zi sau
de noapte. În cazul nostru, on va însemna că avem temă de noapte, iar off va însemna temă de zi.
//on homepage change dinamically account select
if (location.hash === '' || location.hash === '#home') {
var accountSelect = $('#select -custom-21');
if (localStorage .getItem("isLogged" ) === true) {
//accountSelect.html('');
accountSelect .append($('<option>' , {value: '#signout' , text: 'Log Out' }));
} else {
accountSelect .append($('<option>' , {value: '#signin' , text: 'Sign In' }));
accountSelect .append($('<option>' , {value: '#signup' , text: 'Sign Up' }));
}
accountSelect .selectmenu( 'refresh' , true);
}
58
Aceste rânduri se ocupă de afișare, în cazul în care utilizatorul a revenit de pe vreo altă pagină pe
pagina principală. Pentru utilizatorul conectat, se afișează în meniu doar Log Out , pe când pentru
cei care nu s -au conectat se afiș ează opțiunile Sign In și Sign Up .
//refresh account select when we're going back to home from login/register
$('.ui-icon-home').on('click', function () {
$('#select -custom-21').val("choose-one").selectmenu( 'refresh' );
});
$('#select -custom-21').change( function () {
if ($(this).val() == '#signout' ) {
handleLogout ();
showToast ('You were logged out!' );
window.location = '';
window.location .reload();
} else if ($(this).val() == '#signin' || $(this).val() == '#signup' ) {
$.mobile.changePage( "index.html" + $(this).val());
}
});
Dacă utilizatorul dă click pe butonul Home care apare în meniurile Pending reminders și All
reminders , atunci se va da un refresh pentru a afișa corect meniul pentru utilizatorii conec tați sau
neînregistrați.
Pe urmă, la schimbarea stării (change), se verifică dacă utilizatorul este conectat sau dacă abia s -a
deconectat. În fiecare caz, se face o reîncărcare a paginii pentru reactualizarea afișajului.
59
// browsers alternative to notification
// once a minute check notifications that should be triggered
if (device.platform == 'browser' || cordova.plugins.notification === undefined ) {
setInterval (function () {
if (localStorage .getItem("rp_data" )) {
reminders = JSON.parse(localStorage .getItem("rp_data" ));
for (var count = 0; count < reminders .data.length; count++) {
var scheduleTime = new Date(reminders .data[count][3]);
var currentTime = new Date();
scheduleTime .setSeconds (0, 0);
currentTime .setSeconds (0, 0);
var diff = compareMinutesBetweenDates (currentTime , scheduleTime );
console.log( 'recurring check' );
// check all comming
if (diff === 0) {
var msg = 'You have a reminder: ' + reminders .data[count][1] + ' –
' + reminders .data[count][2];
navigator. notification .alert(msg, null, 'ReminderApp' , 'Confirm');
navigator. notification .beep(1);
}
}
}
}, 60000);
// redirect to index.html if we request a direct link
if (location. pathname == "/" && device.platform == 'browser' ) {
location. pathname = "/index.html" ;
}
}
Această funcție este scrisă pentru par tea de browser. Ea se folosește, fie dacă folosim browser -ul
pentru a rula aplicația noastră, fie dacă nu avem pluginul de notificari locale instalat. Mai întâi se
încarcă mementourile din stocarea internă (browser sau dispozitiv), iar apoi pentru fiecare
memento în parte se parcurg următorii pași:
1. Se setează data și ora planificată
2. Se verifică cât timp a trecut între timpul “prezent ” și cel al mementoului .
3. Dacă mementoul era setat pe acum, îl afișăm și înștiințăm ut ilizatorul
Verificarea se face o dată pe minut.
//bind submit function
$("#loginForm" ).on("submit" , handleLogin );
$("#registerForm" ).on("submit" , handleRegister );
$("#clearAllButton" ).on("click", remove_items );
La urmă legăm evenimentele de funcțiile aferente pe butoanele folosite în aplicație.
60
Funcția de ajutor compareMinutesBetweenDates(startDate, endDate) a fost def inită în felul
următor:
var compareMinutesBetweenDates = function (startDate, endDate) {
var diff = endDate. getTime() – startDate. getTime();
return (diff / 60000);
};
Defapt se socotește diferența dintre două structuri de tip dată (care conțin da ta și ora), iar rezultatul
se va afișa în minute. Acest rezultat este folosit de funcția de mai sus, care face parte din
inițializare.
10. Validarea și testarea
Pentru validare vom considera un principiu simplu care este eficient în cazul în care vrem să
validăm ceea ce am dezvoltat.
Principiul este: dacă la procesul/funcția/metoda A (input) ne așteptăm la rezultatul B (output) ,
atunci procesul/funcția/metoda este validă doar în cazul în care va produce exact rezultatul B.
Crearea contului de utilizator
Input: Un utilizator încearcă să creeze un cont pe aplicația dezvoltată.
Output: Contul de utilizator salvat în baza de date, acces ibil ulterior de pe orice dispozitiv care are
aplicația instalată.
Testare: Am testat de 3 ori, cu date diferite, crearea unui cont de utilizator.
Rezultate: VALIDAT
Crearea unui memento
Input: Utilizatorul logat creează un memento pentru ora 6 PM, pe astă zi.
Output: Memento își va face efectul la ora 6 PM.
Testare: Am testat crearea mementoului .
Rezultate: VALIDAT
61
11. Prezentarea aplicației
11.1 Ghidul utilizatorului
1.Ins talarea aplicaț iei pe platforma Android .
Instalarea aplicaț iei pe platforma Android se face după următorii pași :
I Se downloadează din link-ul de mai jos fiș ierul cu extensia “apk”.
https://drive.google.com/file/d/0B2zT69xbGhXUQktwbnZDT05GR3c/view?usp=sharing
II După ce s -a downloadat,se instalează fiș ierul respectiv.
III Dupa instalar e,aplicaț ia se poate rula.
2.Instalarea aplicaț iei pe platforma iOS.
Din păcate,nu s -a reuș it importa rea fisierului „sdk” neces ar instală rii aplicatiei pe iOS din lipsa
resurselor financiare,dar o alta solutie ar fi sa instalam aplicatia „PhoneGap” pe PC si pe iOS.
După instalarea acesteia pe PC,se va importa proiectul:
62
După ce proiectul va fi importat,acesta va porni automat:
Observă m ca acesta deja ruleaza pe unul dintre ip -uri.
Pasul urmă tor: Vom porni aplicaț ia PhoneGap pe un iOS device si vom introduce IP -ul valid. După
aceea,vo m apă sa pe butonul „Connect”.
63
După conectare,vo m observa că aplicația rulează :
64
Utilizarea aplicaț iei:
Adăugare Reminder :
65
In secț iunea „Pending Reminders” se pot vedea Reminderele în aș teptare:
66
Secțiunea „All reminders” conține toate reminderele adăugate de utilizator.
67
Alegerea temei de zi/noapte se poate face apăsâ nd(glisând) pe butonul din chenarul de mai jos:
68
Înregistrarea/Logarea se face apăsâ nd pe butonul „Account”:
69
Formularul de înregistrare:
Formularul de logare:
70
Delogarea se poate face apăsân d pe butonul „Account”
71
Ștergea unui singur „Reminder” se poate face apăsâ nd butonul „Cancel” .Ștergerea tututor
reminderelor se poate face apăsâ nd pe butonul „Clear all” situat in dreap ta sus iar după aceea va
mai apă rea un buton „Clear all reminders” care va șterge toate reminderele.
72
11.2 Diagrama de stare
Deschiderea aplicației
Setarea datei și orei de afișare
[data curen tă < data amintit ă
[data curent ă >= data amintit ă]
Afișarea mesajului
Confirmarea mesajului
73
11.3 Workflow
UserSign Up
Log In
Delete the
reminders
View the
remindersCreate
RemindersReminder
Database
74
11.4 Use case
UtilizatorCreează reminder <<extend >> Șterge reminder
Înregistrare <<extend >> Logare
<<uses>>
Actualizare Bază de dateAlege temă
75
11.5 Diagrame de clase
registerForm
+handleRegister (): var-user : String
-parola : String-email : String-id: String {id}
loginForm
-username : String
-password : String
+handleLogin (): var
+handleLogout (): var+validateEmail (email ): varadd-reminder
-date : Date
-time : Time-title: String
-message : String
+add_reminder (): var
+getElementById (): var-id: String {id}
+remove _item (id): var
+getTime (): var
+remove _item (): var
+remove _items (): var
76
12 Concluzii și perspective. Posibilități de îmbunătățire
În concluzie am reușit să implementăm ceea ce am proiectat. Aplicația prezentată dispune de toate
funcțiile intenționate la planificare, încadrându -se în resursele disponibile.
Sunt multe posibilități de îmbunătățire – după orice îmbunătățire implementată se pot găsi soluții
pentru alte îmbunătățiri – dar vom aminti câteva din cele mai interesante variante.
12.1 Dincolo de iOS si Android
Cea mai imediată posibilitate de îmbunătăți re este să o implementăm pentru a rula pe alte
dispozitive mobile, pe Blackberry, Windows Phone, și pe orice alt sistem mobil de operare.
Această îmbunătățire ar face ca a plicația să devină mai flexibilă . Utilizatorii nu ar mai fi doar cei
care dețin dispozitive cu iOS sau Android.
12.2 Dezvoltarea propriului API
O altă opțiune poate fi dezvoltarea propriului API. În mod ideal, acest API ar trebui să fie găzd uit
pe un server și să permită multe requesturi (cereri). Un API ar permite multe lucruri, printre care:
Integrarea funcțiilor acestei aplicații în orice altă aplicație pentru dispozitivele mobile
Integrare pentru aplicații desktop
Integrare pe pagini web
Pentru dezvoltarea APIului este importantă documentația, care trebuie să fie elaborată, ușor de
înțeles și specifi când toate condițiile utilizării normale. Deasemenea, manualul de utilizare al
APIului ar trebui să vorbească despre po sibilele erori și depanarea lor.
77
12.3 Internaționalizarea aplicației
Un lucru simplu dar eficient ar fi ca aplicația prezentată să fie trad usă în toate limbile frecvent
utilizate și astfel utilizatorii din diferite țări s -ar bucura de aplicație. Internaționalizarea trebuie
făcută după standarde, ca orice modificări ulterioare să fie simple de făcut.
12.4 Deschidere spre comunitatea open -source
Dacă acest proiect ar fi deschis pentru comunitatea open -source, ar putea să devină mult mai
puternică. În general, oamenii care au pasiune pentru programare vor participa la îmbunătățirea
unor programe open -source. Pentru acest proiect, implicarea experțilo r ar aduce doar beneficii,
cum ar fi:
Tratarea problemelor în mod eficient (erori de logică sau de funcționalitate)
Implementarea rapidă funcțiilor care ar fi utile, dar nu există
Discuții între membrii comunității care aduc idei și soluții noi
Atenție din partea unor comunități online care evaluează aplicații pentru dispozitive mobile
78
13 Glosar de termeni
Termenul folosit Ce înseamnă
API Interfața de programare a aplicațiilor. De obicei, această
interfață este o librărie având un set de funcții documentate,
accesibile cu parametrii corecți
Utilizator Persoana (sau programul) care folosește aplicația
Open -source Proiecte soft și web la care codul sursă este disponibil, vizibil
public, fiind posibilă modificarea acesteia respectând anumite
condiții
Implementare Aplicarea teoriei – cu alte cuvinte, teoria este algoritmul sau
metoda/funcția care ar îndeplini o sarcină, iar aplicarea este
programul în care această teorie devine practică, executată,
vizibilă
Internaționalizare Traducerea textelor în mai multe limbi
Cross -platform Soluții de programare care pot rula pe mai multe sisteme de
operare
Sistem de operare Programul care face posibilă folosirea hardwareului dintr -un
dispozitiv
Software / soft Comenz ile date sistemului de operații și hardwareului pentru a
realiza o aplicație capabilă de funcționalitatea pentru care a fost
proiectată
Hardware Componentele electronice dintr -un dispozitiv (microprocesor,
placă de sunet, placă de rețea, placă video, memo rie și multe
alte componente)
79
14. Bibliografie
AJAX JSONP call automatically adding callback parameter. How to remove that? (2017, June
16). Preluat de pe Stackoverflow: "https://stackoverflow.com/questions/10955213/ajax -jsonp –
call-automatically -adding -callback -parameter -how-to-remove -that"
How do you display code snippets in MS Word preserving format and syntax highlighting? (2017,
June 16). Preluat de pe Stackoverflow: "https://stackoverflow.com/questions/387453/how -do-
you-display -code -snippets -in-ms-word -preserving -format -and-syntax -highlig"
How To Fix SQL Injection: PHP. (2017, June 16). Preluat de pe SANS Software Securit y:
"https://software -security.sans.org/developer -how-to/fix -sql-injection -in-php-using -prepared –
statements"
Login & signup forms in panel. (2017, June 16). Preluat de pe Bootsnipp:
"https://bootsnipp.com/snippets/featured/login -amp-signup -forms -in-panel"
On the Third Day of PhoneGapping: Getting Data from a Server. (2017, June 16). Preluat de pe
Simon MacDonald: "http://simonmacdonald.blogspot.ro/2011/12/on -third -day-of-phonegapping –
getting.html"
PhoneGap Tutorial
Sursă: „ https://www.youtube.com/watch?v=sSr1s19gND8 ”
PhoneGap App Development Tutorial
Sursă : „https://www.youtube.com/watch?v=ydQeT5aM7aA ”
Making your first PhoneGap App
Sursă: „https://www.youtube.com/watch?v=yWmWGwOjWKk”
Create HTML Web App for iPhone/Android – PhoneGap Desktop
Sursă : https://www.youtube.com/watch?v=P7wtBBdW7UA
How to Install PhoneGap Desktop App and Use the Developer App
80
Sursă : https://www.youtube.com/watch?v=sstEPqL8eMk
Install PhoneGap mobile app
Sursă : „http://docs.phonegap.com/getting -started/2 -install -mobile -app/”
Create your app
Sursă : „http://docs.phonegap.com/getting -started/3 -create -your-app/desktop/ ”
„Eloquent JavaScript: A Modern Introduction to Programming by Marijn Haverbeke”
„JavaScript: The Definitive Guide by David Flanagan ”
„Learning PHP, MySQL & JavaScript: With JQuery, CSS & HTML5 by Robin Nixon ”
„Modern JavaScript: Develop and Design by Larry Ullman”
How to code in HTML5 and CSS3
Sursă : http://howtocodeinhtml.com/#toc
„HTML & CSS: Design and Build Web Sites by Jon Duckett”
Implement database in PhoneGap app
Sursă :„https://stackoverflow.com/questions/16369532/how -to-implement -database -in-phonegap –
app”
How to connect a PhoneGap Mobile App to a remote MySQL Database
Sursă : ”https://stackoverflow.com/questions/28917860/how -to-connect -a-phonegap -mobile -app-
to-a-remote -mysql -database/28999870 ”
Integrating Local Notifications in Cordova Apps
Sursă : „https://www.sitepoint.com/integrating -local -notifications -in-cordova -apps/ ”
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Secția Cibernetică, Statistică si Informatică Economică [623489] (ID: 623489)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
