Php, Mysql și Java Utilizate Pentru O Aplicatie Mobila cu Arhitectura Client Server

Lucrare de licență

PHP, mySQL și JAVA utilizate pentru o aplicație mobilă cu arhitectură client – server

Cuprins

Introducere

Capitolul 1 Analiza tehnologiilor utilizate

Protocolul de comunicare HTTP

PHP și mySQL în arhitectura aplicației server

Sistemul de operare Android

Clasa Activity

Clasa Intent

Clasa Service

Uneltele disponibile pentru dezvoltarea unei aplicații mobile

Capitolul 2 Proiectarea unei aplicații mobile cu arhitectura client – server

Descrierea serverului web APACHE

Realizarea conexiunii client – server. Servicii de comunicare WEB

Arhitectura de tip R.E.S.T.

Adresabilitate

Fără stare

Interfața uniformă

Siguranța și idempotența

Avantajele utilizării R.E.S.T. în proiectarea aplicației server

Arhitectura MVC utilizata în dezvoltarea aplicației server

Utilizarea limbajului PHP în dezvoltarea aplicației server

Forma generala a unui controller în PHP

Forma generala a unui model în PHP

Adresele URL ale acțiunilor

Capitolul 3 Prezentarea și arhitectura aplicației

Descrierea generala a aplicației

Partea de administrare

Partea de client

Capitolul 4 Zona de administrare (server)

Autentificarea

Pagina principala

Sursele de știri

Adăugarea unei surse de știri

Administrarea categoriilor

Conturile de administrare

Serviciile web REST

Capitolul 5 Aplicația de Android – clientul

Ecranul de start. Încărcarea datelor

Ecranul de știri

Bibliografie

Introducere

Tema lucrării prezentate a fost aleasa pentru a ilustra pe cât posibil o parte importantă din tehnologia actuală referitoare la comunicarea client-server printr-o arhitectură fără stare, ce permite dezvoltatorilor de aplicații, arhitecturizarea unor sisteme eficiente, atât din punct de vedere al costurilor fizice cât și din punctul de vedere al resurselor ocupate, sisteme ce au că scop servirea unui număr mare de clienți, în cazul de față, aplicații de mobil, pentru dispozitivele cu sistem de operare Android.

Ținând cont de creșterea accelerată a domeniului mobil și a aplicațiilor mobile, și de faptul că PC-ul, în forma sa clasica, nu mai reprezintă unealta de informare principală, așa cum se întâmpla în urma cu mai puțin de un deceniu, am ales că temă realizarea unei aplicații de mobil cu arhitectura client-server ce are că scop livrarea de știri noi către utilizatorii acestor dispozitive.

In realizarea acestui deziderat, paleta de tehnologii folosita este vasta, programatorul modern fiind nevoit sa aibă cunoștințe avansate atât pe partea de server, cât și pe partea de client, pentru a putea concepe și realiza o aplicație cât mai robusta, atât că performanta, cât și că uzabilitate.

In cele cinci capitole ale lucrării se va încerca abordarea acestei teme în cel mai fin detaliu, rezultatul fiind realizarea unei aplicații moderne, care să demonstreze posibilitățile expuse de cele mai noi dezvoltării în domeniul informaticii.

Capitolul 1
Analiza tehnologiilor utilizate

Protocolul de comunicare HTTP

Hypertext Transfer Protocol (HTTP) reprezintă o modalitate de comunicare, cel mai des întâlnita de altfel, și permite accesarea informațiilor din mediul de Internet, informații ce sunt păstrate pe servere.

Acest protocol este de tip text, HTTP fiind metoda de transport al WWW. Cu alte cuvinte, o adresa web care nu conține particula de protocol, se consideră a fi HTTP în mod implicit. Protocolul implica faptul că pe calculatorul destinație (serverul) există instalat un program care permite înțelegerea acestuia.

Este foarte importat de menționat faptul că HTTP reprezintă un protocol la nivel de aplicație.

Importanta HTTP-ului este data de faptul că pune la dispoziție o tehnica prin care seturi de date (ce pot reprezenta, spre exemplu, pagini web) se pot transmite de la un calculator la altul (printr-o legătura de tip client-server).

Daca se accesează o adresa web, de exemplu http://www.exemplu.ro, atunci, prin intermediul aplicației de tip „server-web” instalată pe calculatorul gazda, se afișează pagina web dorita.

In diagrama de mai jos este prezentată modalitatea de realizare a acestui tip de transport.

Astfel, un browser face o cerere, prin intermediul unei adrese URL, cererea ajunge la serverul web unde este interpretată, iar răspunsul este trimis către browser.

Protocolul HTTP permite trimiterea diferitelor tipuri de fișiere, iar din punctul de vedere al unui server web acestea pot fi:

Fișiere statice HTML

Rezultatul procesării unei pagini dintr-un limbaj dinamic

Fișiere de stil (CSS)

Fișiere ce conțin cod JavaScript

Pentru a acomoda mai multe situații în care protocolul HTTP poate fi folosit, acesta pune la dispoziție o serie de metode de transport:

GET

POST

HEAD

PUT

DELETE

OPTIONS

TRACE, CONNECT, PATCH

Cele mai utilizate metode de transport sunt reprezentate de metoda GET și metoda POST sau PUT. Acestea permit trimiterea, respectiv, primirea de informații de la server-ul web.

Cu precădere, atunci când se dorește accesarea unei pagini, metoda folosita este GET, iar când este vorba despre o cerere ce conține date (altele decât adresa paginii) care se doresc a fi trimise la server, se folosește metoda POST sau PUT.

PHP și mySQL în arhitectura aplicației server

Limbajul PHP, apărut în anul 1994, a prins forma datorită unei nevoi naturale, odată cu implementarea cât mai accelerata a WWW-ului. Astfel, s-a dorit că o pagina HTML să poată fi compusa că urmare a unor acțiuni făcute de utilizator, cu alte cuvinte, o maniera de a realiza conținut dinamic.

PHP sau Hypertext Preprocesor, reprezintă un limbaj ce interpretează codul scris în fișiere PHP specifice, iar rezultatul este un fișier HTML, ce este trimis către client.

Alegerea pentru dezvoltarea aplicației server a limbajului PHP a fost făcuta datorită multiplelor avantaje pe care acest sistem pe deține:

Ușurința în dezvoltare.

Limbaj de programare matur

Costuri reduse

Scalabilitate crescuta

Pentru a înțelege mai bine felul în care PHP operează, se poate observa fig. (1).

Astfel, pot fi observate 4 momente principale în execuția unei cereri:

Momentul în care de la browser WEB este transmisa o cerere HTTP de preluare a unei adrese web (URL);

Din momentul în care cererea a ajuns la serverul WEB, este în datoria acestuia de a trimite fișierul PHP corespunzător către interpretorul de PHP, care este cel responsabil cu interpretarea instrucțiunilor scrise în fișier.

In timpul execuției instrucțiunilor scrise în fișierul PHP, pot exista interacțiuni cu o baza de date (de exemplu: mySQL) pentru a prelua și manipula un set de date.

La final, după ce datele au fost manipulate și așezate în cod HTML, pagina este transmisa către browser pentru a fi afișata utilizatorului.

De asemenea, pentru stocarea informațiilor obținute, a fost folosit sistemul de baze de date mySQL, alegerea fiind făcuta în primul rând datorită tendințelor tehnologice în ceea ce privește dezvoltarea unei aplicații PHP, și anume, ușurința cu care aceste doua sisteme, PHP și mySQL, colaborează pentru a ușura pe cât posibil configurările necesare pentru punerea în funcțiune a sistemului.

Factorii care au stat la baza alegerii mySQL au fost: nivelul ridicat de performanță, caracteristici conforme cu SQL, condiții și restricții de licențiere, preț.

Printre avantajele sistemului de baze de date mySQL regăsim amprenta mică de memorie pe care aplicația îl ocupa. Acest lucru are ca o consecința directă, posibilitatea că un server WEB cu PHP și mySQL sa fie instalat cu ușurința pe un sistem, fără pretenții foarte mari în ceea ce privește hardware-ul existent.

Sistemul de operare Android

Android este o un sistem de operare pentru dispozitive mobile bazat pe Linux, și este dezvoltat de compania Google. Acesta le permite dezvoltatorilor să scrie cod în limbajul Java, punând la dispoziția dezvoltatorului o serie de biblioteci prin care aceștia pot controla dispozitivul mobil.

Un aspect important care a dus la creșterea în popularitate a sistemului de operare Android îl reprezintă faptul că pachetul de dezvoltare pus la dispoziție are la baza limbajul Java. Astfel, orice dezvoltator ce deține cunoștințe de programare în Java poate începe dezvoltarea unei aplicației pentru Android, fora a fi nevoie de învățarea unui limbaj de programare specific pentru aceasta platforma.

Totuși, trebuie menționat faptul că sistemul de operare în sine, este scris în limbajul C++, și asta datorită faptului că s-a dorit de la bun început optimizarea fiecărei acțiuni ce este pusa la dispoziția dezvoltatorului.

Totodată, a fost rescrisa și mașina virtuala în care rulează fiecare aplicație, pentru a fi cât mai eficienta din punct de vedere al consumului de memorie și al puterii de calcul.

Puntea de legătura dintre sistemul de operare și aplicațiile acestuia este realizate printr-o colecție de biblioteci ce sunt puse la dispoziția dezvoltatorului, biblioteci ce asigura interacțiunea cu diferitele funcții ale sistemului de operare:

Biblioteci ce asigura interacțiunea cu ecranul dispozitivului

Alte biblioteci ce asigura interacțiunea cu pârtile hardware adiacente dispozitivului:

GPS

Modul de WiFi

Giroscop

Biblioteci ce asigura suport nativ pentru structuri de date optimizate atent pentru a fi eficiente pe o platforma mobila:

Algoritmi de sortare eficienți

Structuri de date eficiente, diferite de cele clasice prin faptul că în permanenta acestea eliberează zona de memorie în momentul în care nu mai exista nicio referința către obiect.

O aplicație realizata pentru sistemul de operare Android este formata dintr-o serie de ecrane (Activitati) care sunt conectate între ele prin intermediul Intent-urilor.

De asemenea, sistemul de operare Android mai pune la dispoziția dezvoltatorului o serie de alte mecanisme, pentru că acesta sa poată deține un control sporit în ceea ce privește performantele aplicației și felul în care aceasta este prezentată utilizatorului final. Pe lângă cele doua menționate anterior, se mai pot adăuga:

Clasa Service

Clasa BroadcastReceiver

Clasa IntentFilter

Clasa Activity

Este o parte importantă a ecosistemului Android, pentru că aceasta reprezintă mecanismul prin care utilizatorul interacționează cu aplicația. O activitate este clasa care determina afișarea unui nou ecran în Android, fiind zona în care sunt trasate elementele de interacțiune cu utilizatorul (elementele vizuale).

In Android, clasa Activity reprezintă una din componentele primare ale unei aplicații pentru că acestea conduc experiența de utilizare a aplicației spre un tot unitar, ușor de interes din punctul de vedere al utilizatorului final.

Pentru a crea un nou ecran se extindă clasa Activity.

Un alt aspect definitoriu pentru acest mecanism, îl reprezintă durata de viața a unei Activitati. In cazuri concrete, un utilizator al aplicației vede la un moment dat, o singura activitate afișata pe ecranul dispozitivului Android.

Astfel, o activitate are mai multe stări în care se poate afla:

Starea de rulare: reprezintă starea în care se afla o activitate atunci când aceasta este afișata utilizatorului.

Starea de pauza: reprezintă momentul în care o activitate pierde focusul, însă este în continuare vizibilă utilizatorului. Un exemplu în care o activitate se afla în starea de pauza îl reprezintă momentul în care pe ecranul dispozitivului este afișata o caseta de alerta, că urmare a unei acțiuni efectuate de utilizator. Astfel, activitatea este vizibilă, însa utilizatorul nu poate interacționa direct cu aceasta, decât în urma alegeri unei acțiuni din caseta de alertare.

Starea de oprire (stop): reprezintă starea când o activitate este înlăturata de pe ecranul dispozitivului că urmare a trecerii către alte Activitati. In acest moment, activitatea exista încă în memoria dispozitivului, însa aceasta nu mai este vizibilă, și, drept urmare, utilizatorul nu mai poate interacționa cu aceasta.

Starea de finalizare: reprezintă starea când sunt eliberate toate resursele consumate de activitate, pentru o activitate care este det aspect definitoriu pentru acest mecanism, îl reprezintă durata de viața a unei Activitati. In cazuri concrete, un utilizator al aplicației vede la un moment dat, o singura activitate afișata pe ecranul dispozitivului Android.

Astfel, o activitate are mai multe stări în care se poate afla:

Starea de rulare: reprezintă starea în care se afla o activitate atunci când aceasta este afișata utilizatorului.

Starea de pauza: reprezintă momentul în care o activitate pierde focusul, însă este în continuare vizibilă utilizatorului. Un exemplu în care o activitate se afla în starea de pauza îl reprezintă momentul în care pe ecranul dispozitivului este afișata o caseta de alerta, că urmare a unei acțiuni efectuate de utilizator. Astfel, activitatea este vizibilă, însa utilizatorul nu poate interacționa direct cu aceasta, decât în urma alegeri unei acțiuni din caseta de alertare.

Starea de oprire (stop): reprezintă starea când o activitate este înlăturata de pe ecranul dispozitivului că urmare a trecerii către alte Activitati. In acest moment, activitatea exista încă în memoria dispozitivului, însa aceasta nu mai este vizibilă, și, drept urmare, utilizatorul nu mai poate interacționa cu aceasta.

Starea de finalizare: reprezintă starea când sunt eliberate toate resursele consumate de activitate, pentru o activitate care este deja în starea de oprire.

Interacțiunea cu stările unei Activitati se face suprascriind metodele aferente din clasa de baza Activity, iar metodele sunt apelate direct de către sistemul de operare Android, pentru fiecare moment în parte.

Diagrama de mai jos explica concret stările prin care o activitate trece, de la instanțierea acesteia și afișarea ei pe ecran, pana la momentul când aceasta este scoasă de pe ecran și ulterior, eliberata din memoria dispozitivului.

Clasa Intent

Un Intent reprezintă o descriere abstracta a unei anumite acțiuni ce se dorește a fi executata de aplicație.

Aceasta clasă pune la dispoziție facilitatea de a lega diferitele mecanisme de afișare prezente într-o aplicație Android. Cel mai important uz pentru această clasă îl reprezintă navigarea printre Activitati.

Deși Intent-urile reprezintă modalitatea de transport a datelor între diferitele părți ale aplicației, acestea sunt prezente în diferite cazuri de utilizare, dintre care trei sunt fundamentale:

Pornirea unei Activitati se realizează cu ajutorul unui obiect de tip Intent care deține în structura sa o acțiune (informații despre activitatea care se dorește a fi deschisă) și date (informații referitoare la obiectele și datele ce vor fi afișate)

Pornirea unei activități prin intermediul unui Intent se realizează apelând metoda startActivity() ce primește ca parametru un obiect de tip Intent.

Pornirea unui serviciu. Un serviciu în Android reprezintă o componenta care permite realizarea de operații costisitoare că timp pe un alt fir de execuție, neinterferând cu firul de execuție principal, cel în care este afișata interfața grafică.

Pentru a porni un serviciu, se apelează metoda startService() ce primește că parametru un obiect de tip Intent.

Trimiterea unei notificări (Broadcast). O notificare (broadcast) reprezintă un mesaj pe care aplicația îl poate transmite într-un loc al acesteia, pentru ca aceasta să fie preluată de o altă clasa, în vederea realizării anumitor operații.

Pentru a trimite o notificare (broadcast), se apelează metoda sendBroadcast() care primește că parametru un obiect de tip Intent.

Clasa Service

Un serviciu reprezintă o componenta a unei aplicații android reprezentata de dorința aplicației de a realiza o operație costisitoare că timp (cum ar fi descărcarea unui fișier) și de a păstra aceasta operație în fundalul aplicației, fora a fi nevoie de o interacțiune directa din partea utilizatorului, acesta având posibilitatea de a naviga în continuare în aplicație.

Un serviciu prezintă, în general, aceleași caracteristici că o Activitate, fora însa a avea o interfața grafică.

Pentru a crea un nou serviciu este nevoie de instanțierea unui obiect al unei clasei din cadrul aplicației, ce extinde clasa de sistem Service.

Uneltele disponibile pentru dezvoltarea unei aplicații mobile

Pachetul software de dezvoltare Android include un set complet de instrumente de dezvoltare.

Platformele de dezvoltare sprijinite în prezent includ calculatoare bazate pe arhitectura x86 care rulează orice sistem de operare modern, Android fiind disponibil (datorită faptului că are la baza Java), pe toate platformele.

Cerințele includ, de asemenea, Java Development Kit cel puțin versiunea șase.

Pentru a prezenta cât mai detaliu uneltele de dezvoltare, vom trece în cele ce urmează la o enumerare a acestora, împreuna cu o scurta descriere pentru fiecare:

Utilitarul adb.exe: Android Debug Bridge (adb) este o unealta versatila, prezenta sub forma unui executabil în linie de comanda, ce permite comunicarea dezvoltatorului cu dispozitivele emulate sau fizice. De asemenea, oferă acces avansat pentru a putea rula diverse comenzi pe dispozitive.

Utilitarul hierarchyviewer.exe: Pune la dispoziția dezvoltatorului o modalitate simpla pentru a analiza performatele elementelor de design

Log.d: permite înregistrarea de jurnale pe toata durata execuției aplicației, în scopul trimiterii acestora către dezvoltator, pentru a îmbunătăți cât mai mult aplicația.

Capitolul 2
Proiectarea unei aplicații mobile cu arhitectura client – server

Descrierea serverului web APACHE

Apache Server reprezintă un server web ce permite comunicare prin protocolul HTTP. Apache este cel mai popular server datorită faptului că se poate instala pe toate sistemele de operare moderne.

In arhitectura unei aplicații server, Apache joaca rolul de punte între partea de client (browser) și partea de cod pe partea de server (de exemplu: PHP) (fig. 2)

Serverul WEB este cel responsabil cu direcționarea cererilor HTTP venite dinspre client către fișierele PHP corespunzătoare.

Realizarea conexiunii client – server. Servicii de comunicare WEB

Modelul arhitectural de tip client-server este o structură de aplicație care permite procesarea de mesaje între furnizorii de servicii (servere) și elementele care solicită servicii (clienți).

Comunicarea între clienți și servere este realizata printr-o rețea de calculatoare, locala sau internet. Serverul și clientul au, de obicei, suporturi hardware diferite, dar pot rula și pe același sistem fizic sau chiar prin intermediul unor mașini virtuale.

Rolul clientului este de a apela resursele ce se afla pe server, prin intermediul unor metode puse la dispoziție de server. Clienții sunt cei care inițializează conexiunea cu serverul.

Intr-o abordare clasica a arhitecturii client-server, pentru menținerea legăturii între cei doi, indiferent de pauzele care intervin, se folosește conceptul de sesiune, care de obicei este limitată în timp. Pentru a optimiza acest aspect, în realizarea aplicației a fost folosita arhitectura de tip R.E.S.T., detaliata pe larg în cele ce urmează.

Arhitectura de tip R.E.S.T.

REST, sau Representation State Transfer, implica un stil arhitectural de dezvoltare software, folosit cu precădere pentru comunicarea în zona WWW.

Aceasta arhitectura a luat naștere de la unul dintre autorii protocolului HTTP, Roy Fielding, din dorința de a simplifica o arhitectura de tip client-server, făcând uz de ceea ce pune deja la dispoziție HTTP.

R.E.S.T. implica o colecție de standarde de arhitectura ce presupune definirea resurselor și felul în care acestea sunt adresate.

Folosirea REST nu este strâns legata de folosirea WWW sau HTTP. De asemenea se permite dezvoltarea unei arhitecturi software care sa folosească XML și HTTP pentru transport, și care sa nu respecte principiile unei arhitecturi REST, dar, în schimb, respectând paradigma dezvoltării de servicii web de tip RPC.

Metodele puse la dispoziție de protocolul HTTP sunt folosite pentru a da informații despre metoda apelată, iar prin URL se determina argumentele cu care metoda este apelată. Un exemplu de astfel de cerere este "GET /rest/news", de unde se poate înțelege tipul metodei HTTP (GET) și argumentele. Aceasta metoda ajunge în controller, unde se modelează răspunsul ce va fi trimis.

Este important de menționat faptul că, folosirea REST implica respectarea metodele de transport HTTP, altfel serviciul REST nu este standard.

Principalele caracteristici ale unui sistem REST sunt:

Adresabilitate

Fără stare (stateless)

Interfața uniformă

Siguranța și idempotența

Adresabilitate

O caracteristica a unei aplicații este adresabilitate, aceasta fiind definita prin faptul că permite aplicației sa expună un set de date și resurse. Acestea sunt expuse prin URL-uri, orice informații putând fi accesata prin intermediul acestor adrese.

De regula, adresabilitatea presupune compunerea unui rezultat final din mai multe apeluri către subseturi ce alcătuiesc în final rezultatul.

Adresabilitatea este motivul pentru care serviciile REST sunt atât de des întâlnite.

Fără stare

Intr-o arhitectura clasica a unei aplicații server, este nevoie de o serie de parametri care să permită sistemului să funcționeze la parametri normali. Acestea sunt, de regula, ținute în memoria serverului prin intermediul sesiunilor sau a cookies-urilor, problema fiind însa volatilitatea acestor date și cuplarea lor de întreg sistemul.

Prin caracteristica "fără stare" se definește felul în care aplicația web poate funcționa în parametri normali, fără a avea nevoie de variabile volatile, fiecare cerere HTTP fiind izolată complet, serverul reușind sa proceseze cererea având toate informațiile necesare furnizate la momentul realizării cererii.

Tocmai prin aceasta izolare a cererilor HTTP, aceasta caracteristică aduce un beneficiu major într-o lume moderna, în care accentul cade în egala măsura atât pe calitatea arhitecturii software, cât și pe capacitatea aplicației de a putea fi distribuită cu ușurință pe mai multe servere, pentru a putea răspunde la un număr foarte mare de cereri.

Interfața uniformă

Caracteristica de uniformitate, pe care serviciile REST o pun la dispoziție face uz de metodele de transport HTTP pentru a oferi un set de operații de baza, cum ar fi:

obținerea despre informații despre o resursa folosind HTTP GET

adăugarea unei noi resurse folosind HTTP PUT

modificarea unei resurse existente folosind HTTP POST

ștergerea unei resurse folosind HTTP DELETE

Pentru exemplificare, sa considerăm un serviciu web REST ce presupune afișarea știrilor dintr-o baza de date, permite operații de modificare și adăugare, precum și ștergerea acestora.

Astfel, o prima operație pe care un client ar putea sa o realizeze ar fi afișarea acestora, făcând o cerere HTTP GET către URL-ul specificat:

GET /rest/news/List_All

Apelarea pentru obținerea de informații se face fora parametrii în cazul de față, dar poate conține informații despre o eventuala paginare pe care aplicația o permite. De exemplu, apelul HTTP REST pentru pagina a doua, având 20 de rezultate pe pagina ar arata în felul următor:

GET /rest/news/List_All/20/2

Ordinea parametrilor pe care o metoda îi poate primi este stabilita de către dezvoltator, și este specificata printr-o documentație specifica.

In mod similar, apelurile HTTP PUT, HTTP POST sau HTTP DELETE pot efectua operații asupra aplicației, operații ce sunt fără stare.

Siguranța și idempotența

Un serviciu web de tip REST este sigur datorită utilizatorii metodelor de transport HTTP GET și HEAD. O cerere HTTP GET este sigură, deoarece un client poate executa o cerere de multe ori, răspunsul fiind mereu același.

Caracteristica de idempotența este dată de faptul că ori de câte ori se realizează o acțiune de HTTP PUT sau HTTP DELETE, resursa va rămâne creată sau ștearsa. Să considerăm spre exemplu nevoie de modificarea a titlului unui articol de știri. Aplicația client realizează un apel de tip HTTP PUT împreuna cu parametri prin care serverul poate identifica resursa și noul titlu.

PUT /rest/news/cange

{newsID: 4; titluNou: "Titlu nou de ex."}

Indiferent de câte ori se va face acest apel, resursa se va regăsi în aceeași stare.

Avantajele utilizării R.E.S.T. în proiectarea aplicației server

Principalele doua beneficii pe care o arhitectura de comunicație prin servicii web de tip REST le introduce sunt:

posibilitatea stocării rezultatului

scalabilitatea serverului

Din caracteristicile de idempotența se poate realiza o structura de date ce permite stocarea răspunsurilor gata procesate pentru a putea fi servite imediat pentru cereri ulterioare (mecanism de cache-ing). Astfel, timpul de răspuns pentru cereri multiple poate scădea, crescând fiabilitatea serverului în condiții în care acesta servește mai mulți clienți.

Datorită faptului că un serviciu web de tip REST este „fără stare” este permisa cu ușurința scalarea aplicației pe mai multe servere, fără a fi nevoie de mecanisme complexe de replicare a sesiunilor. Acest lucru este foarte important din punct de vedere al infrastructurii.

Arhitectura MVC utilizata în dezvoltarea aplicației server

MVC, sau Model-View-Controller reprezintă un model arhitectura software.

Avantajul major al acestui arhitecturi este izolarea părții logice ale aplicației de partea grafica, avantaj ce se concretizează printr-o aplicație ușor de modificat si menținut.

Datele de care are nevoie aplicația sunt reprezentate de către model, View-ul este cel responsabil cu afișarea datelor iar controller-ul leagă aceste doua entități si are rol decizional in procesarea datelor.

Modelul reprezintă partea logica, de date, a aplicației. Are responsabilitatea extragerii datelor din baza de date, modelarea acestora in structuri clar definite, precum si operații persistente asupra seturilor de date ale aplicației.

View-ul are rol in afișarea datelor, fiind partea cu care utilizatorul interacționează direct. In aceasta secțiune se pot regăsi si diferitele funcții de interacțiune (JavaScript). Datele afișate de View sunt cele care sunt aduse de Model si procesate de Controller. In esență, putem spune ca un View reprezintă șabloane de cod HTML ce împreuna compun pagina web finala.

Controller-ul este cel responsabil cu manipularea datelor venite din model si afișarea lor in View. Un controller de regula conțină regulile de bussines ale aplicației, ce sa fie afișat in funcție de anumiți parametri. Controller-ul este considerat a fi creierul intr-o arhitectura MVC. Tot in controller sunt efectuate si eventualele verificări in vederea validării datelor de intrare, date ce sunt trimise ulterior către Model pentru a fi persistate in baza de date.

Aceasta figura descrie modelul de arhitectura MVC.

Utilizarea limbajului PHP în dezvoltarea aplicației server

După cum a fost tratat și în Capitolul 1, limbajul PHP prezintă o serie de avantaje, ce îl fac ideal în dezvoltarea aplicației de server.

Limbajul PHP pune la dispoziția programatorului o serie de mecanisme și funcții pentru:

Acces la baza de date

Preluarea datelor transmise în urma unor cereri HTTP

Manipularea obiectelor și corelarea lor cu o baza de date

Mecanisme de securizare a datelor

Pentru dezvoltarea aplicației de server a fost folosita paradigma de programare orientata pe obiecte, introdusa în PHP începând cu versiunea a 5-a.

Aceasta paradigma, împreuna cu modelul de arhitectura MVC, permite o structurare cât mai clara a aplicației, având drept consecința o mai buna administrare a acesteia din punct de vedere al codului.

Astfel, structura directoarelor și fișierelor proiectului este următoarea:

Forma generala a unui controller în PHP este următoarea:

<?php
class Controller_General extends Controller {

Public function actiune_generala($params) {
//codul de executie
}

}
?>

Fiecare Controller este reprezentat de o clasa ai cărei membri reprezintă acțiunile care se pot realiza prin intermediul acestuia.

Astfel, fiecare controller din cadrul aplicației server, are în componenta sa o metoda de adăugare, editare și ștergere a unei înregistrări din modelul aferent și o metoda de afișare a tuturor înregistrărilor, toate aceste informații fiind afișate cu ajutorul VIEW-ului.

Forma generala a unui model în PHP este următoarea:

<?php
class Model_General extends Model {
var $camp_tabela1;
var $camp_tabela2;
var $camp_tabela3;
}
?>

Astfel, fiecare model este de fapt o reprezentare a unei tabele din baza de date a aplicației server.

Tot în cadrul modelul pot fi regăsite metodele de adăugare, editare și ștergere a unei înregistrare, precum și cele de întoarcerii tuturor înregistrărilor din tabela, metode ce sunt responsabile numai cu realizarea acțiunilor la nivelul bazei de date, fără a fi nevoie de o manipulare a entităților de View, acest sarcina revenind Controller-ului.

Adresele URL ale acțiunilor

Un aspect important al aplicației server este felul în care adresele web (numite în continuare URL) sunt compuse.

Pentru a fi ușor de identificat controller-ul și acțiunea aferenta și pentru a respecta principiile de funcționare ale serviciilor REST, aplicația server a fost configurata în așa fel încât URL-urile sa fie citite ușor.

Acestea sunt de forma:

http://adresa/Controller_Principal/Actiune_Test/parametri

Acest URL va fi direcționat către controller-ul Controller_Principal, metoda Actiune_test cu parametri de intrare reprezentați de ultima particula a URL-ului.

Acest lucru este obținut prin modulul mod_rewrite din cadrul serverului web Apache.

Capitolul 3
Prezentarea și arhitectura aplicației

Descrierea generala a aplicației

Aplicația prezentată, denumita „Știrile mele” reprezintă o aplicație de știri, cu arhitectura client-server, ce permite utilizatorilor citirea știrilor de pe dispozitivele mobile.

Scopul aplicației Știrile mele este de a facilita accesul la știri, din diverse surse, pentru a putea fi ușor citite de către utilizator, fără a fi nevoie că acesta sa navigheze timp îndelungat pentru a găsi informația pe care acesta o căuta.

Un avantaj pe care aplicația îl introduce, este economia de timp făcuta, prin prisma faptului că utilizatorului îi este pus la dispoziție o varietate mare de știri, din diverse domenii, organizate în categorii și din mai multe surse, pentru a putea fi cât mai ușor găsite.

Alt aspect important îl reprezintă mobilitatea pe care aplicația Știrile mele îl adăuga experienței de menținere la curent cu ultimele noutatea. Fiind o aplicație mobila, practic se pot accesa știrile curente în orice moment, fără a fi necesara deschiderea laptopului sau a PC-ului.

Aplicația „Știrile mele” este compusa din parte de administrare realizata folosind tehnologii web și o parte de client, realizata folosind tehnologii mobile – Android.

Partea de administrare

In aceasta secțiune se pot administra fluxurile de știri RSS de pe site-urile web de știri populare din Romania. Fluxurile de știri se pot adăuga în zona de Surse, iar acestea sunt organizate pe Categorii pentru a putea fi cu ușurința găsite de către utilizator pe aplicația de client.

Fiecare sursa de știri este apoi procesata, iar în urma acesteia rezulta o colecție de știri care este stocata pe server, într-o baza de date, pentru a fi servita ulterior către aplicația de client, folosind servicii web REST.

Partea de client

Aplicația de client este realizata pentru sistemul de operare Android și permite vizualizarea știrilor preluate de către aplicația server.

Aplicația permite navigarea știrilor pe categorii, iar acestea sunt de asemenea preluate cu ajutorul serviciilor web REST, de pe server.

Capitolul 4
Zona de administrare (server)

Autentificarea

Având în vedere faptul că zona de administrare reprezintă modulul central al aplicației, aceasta este protejata împotriva accesului anonim, astfel eliminându-se riscul că un utilizator rău-intenționat sa altereze sistemul, rezultând într-o experiența de utilizare deficitara pentru utilizatorul final.

Un cont de administrare este caracterizat de o pereche nume de utilizator și parola.

După completarea numelui de utilizator și a parolei, utilizatorul este direcționat către pagina de start a zonei de administrare, unde îi sunt prezentate opțiunile pe care acesta la are la dispoziție pentru a realiza acțiune de administrare.

Odată cu apăsarea butonului Login aplicația trimite la server datele de autentificare, care sunt procesate în sensul validării acestora cu înregistrările existente în baza de date, în tabela Accounts.

Funcția care are responsabilitatea de a determina daca o pereche de nume de utilizator și parola este valida, se numește checkLogin() din cadrul controller-ului UserLogin.php

public function checkLogin() {

//This method will have the credentials validation

$this->load->library('form_validation');

$this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean');

$this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean|callback_check_credentials');

if ($this->form_validation->run() == FALSE) {

$this->error = "Datele de autentificare nu sunt valide.";

$this->login();

return;

} else {

redirect('main', 'index');

}

}

De asemenea, pentru validarea autentificării se executa și funcția check_credentials, pentru a verifica în baza de date existenta contului de administrare.

function check_credentials($password) {

$username = $this->input->post('username');

$result = $this->User->login($username, $password);

if ($result) {

$sess_array = array();

foreach ($result as $row) {

$sess_array = array(

'id' => $row->id,

'username' => $row->username,

'full_name' => $row->full_name

);

$this->session->set_userdata('autentificat', $sess_array);

}

return true;

} else {

return false;

}

}

In cazul în care datele introduse au fost validate, utilizatorului îi este creată o nouă sesiune (pentru a putea fi ulterior identificat în restul paginilor din zona de administrare) și este redirecționat către pagina principala.

Ecranul de autentificare este afișat la accesare oricărei pagini din cadrul zonei de administrare, aceasta verificare făcându-se înainte de a se executa orice fel de operație de afișare a datelor.

De asemenea, în controllerul UserLogin.php este verificat și cazul în care utilizatorul are încă sesiunea activa, moment în care acesta este redirecționat către prima pagina.

public function index() {

if ($this->session->userdata('autentificat')) {

redirect('main', 'index');

}

$this->load->view('login', $data);

}

Pagina principala

Reprezintă pagina afișata utilizatorului după ce acesta a fost autentificat în zona de administrare și conține o scurta prezentare a acțiunilor pe care le poate face administratorul.

In partea stângă a ecranului, administratorul are în permanenta acces la meniul aplicației, pentru a naviga cât mai ușor.

Sursele de știri

In aceasta secțiune sunt afișate toate sursele de știri din cadrul aplicației. Fiecare sursa de știri poate fi modificata sau poate fi ștearsa.

Sursele de știri sunt afișate că urmare a acțiunii din controller-ul Sources.php metoda listall()

public function listall() {

$data['sources'] = $this->Source->getAll();

$data['template'] = 'sources/list';

$data['title'] = 'Toate sursele';

$this->load->view('master_view', $data);

}

Așadar, este incarnata lista de surse din modelul Source prin apelarea metodei getAll() și apoi aceste date sunt transmise către View, respectând astfel modelul de arhitectura MVC.

class Source extends CI_Model {

var $name;

var $feed_url;

var $category_id;

var $description;

var $lastupdate;

var $updating;

function getAll() {

$this->db->select('source.*, category.name as

category_name');

$this->db->join('category', 'category.id =

source.category_id');

$this->db->order_by('source.name', 'ASC');

$entries = $this->db->get('source');

return $entries->result();

}

}

Pe lângă metoda getAll() în model mai pot fi observate variabile care leagă practic acest model de tabela source din baza de date.

Tabelul din baza de date are forma:

Câmpurile last_update și updating indică faptul că o tabela a fost actualizată la o dată anume sau că este în curs de actualizare.

Fiecare sursă este procesată independent, la un interval de 30 de minute, interval ce poate fi modificat programatic. Acest interval de timp a fost ales astfel încât încărcarea site-ului sa nu fie foarte mare, procesarea unui flux de știri RSS (ce este în format XML) sa nu fie de durata, împiedicând astfel chiar și aplicația client atunci când se face o cerere pentru afișarea știrilor.

Însa, actualizarea știrilor disponibile la o sursa se poate declanșa și explicit prin acționarea legăturii actualizează ce reprezintă o cerere asincrona către server. Cererea asincrona este realizata folosind tehnologia AJAX prin intermediul unei funcții Javascript implementata cu ajutorul librarii jQuery și a mecanismului XML-HTTP-Request existent că implementare în toate browserele moderne.

Funcția de Javascript este următoarea:

function triggerFeedParse(url, fid, that) {

var loaderDiv = '#loader_' + fid;

$.ajax({

url: url,

beforeSend: function () {

$(loaderDiv).show();

$(that).hide();

},

success: function (data) {

$(updatedDiv).html(data);

},

complete: function () {

$(loaderDiv).hide();

$(that).show();

}

})

}

Aceasta primește că parametru URL-ul de apelat, identificatorul sursei de știri și obiectul pe care s-a acționat click-ul, în vederea realizării unei animații de incarnare pentru a semnala administratorului faptul că sursa este în curs de procesare.

In continuare este descrisa metoda de procesare a unei surse de știri din controller-ul Feed.php

public function parse($feedId) {

$feed = $this->Source->byId($feedId);

$newest = $this->News->getNewestRecordForFeedId($feedId);

$this->Source->setUpdating(1, $feedId);

$rss = new DOMDocument();

$rss->load($feed->feed_url);

$items = array();

foreach ($rss->getElementsByTagName('item') as $node) {

$pubDate = strtotime($node->getElementsByTagName('pubDate')->item(0)->nodeValue);

$image = '';

if($node->getElementsByTagName('enclosure')->item(0)) {

$image = $node->getElementsByTagName('enclosure')->item(0)->getAttribute('url');

}

if($pubDate > $newest) {

$item = array (

'title' => strip_tags($node->getElementsByTagName('title')->item(0)->nodeValue),

'description' => strip_tags($node->getElementsByTagName('description')->item(0)->nodeValue),

'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,

'image' => $image,

'published_date' => $pubDate,

'feed_id' => $feedId,

);

array_push($items, $item);

}

}

if(count($items) > 0)

$this->db->insert_batch('news', $items);

$this->Source->setUpdating(0, $feedId);

$this->Source->updateLastUpdate($feedId);

echo date('d.m.Y, H:m:s', time());

}

După cum se poate observa se face uz de clasa DomDocument() disponibila în PHP pentru a încărca un document XML, care apoi este parcurs nod cu nod în vederea extragerii informației relevante.

Mai apoi, este folosita adăugarea în calup a datelor extrase din sursa de știri în tabela News. Structura tabelei News este data de diagrama de mai jos:

Pentru eficienta, pentru fiecare sursa de știri, sunt preluate doar știrile noi apărute, verificarea făcându-se utilizând câmpul published_date ce este adăugat fiecărei știri.

Astfel, daca spre exemplu o sursa conține la un moment dat 30 de știri iar toate acestea sunt adăugate în tabela de News că urmare a acțiunii de actualizare, daca se alege imediat după din nou actualizare sursei de știri, atunci vor fi adăugate strict știrile care sunt mai noi de cea mai recenta înregistrare din baza de date.

Adăugarea unei surse de știri

In secțiunea Adăuga din cadrul sub-meniului Surse de știri se poate face adăugarea unei noi surse de știri.

In urma șalvarii formularului este apelată metoda save() din controller-ul Sources.php ce utilizează mai departe modelul Source pentru a salva datele în baza de date.

//Sources controller

public function save() {

$result = $this->Source->save();

if($result) {

$this->message = "Sursa de stiri a fost salvata!";

$this->listall();

} else {

$this->error = "O sursa de stiri cu acelasi nume exista deja. Alegeti alt nume pentru a putea adauga sursa de stiri.";

$this->add();

}

}

In urma apelul de salvare a modelului, metoda returnează TRUE sau FALSE în funcție de rezultatul adăugării în baza de date.

//model Source

function save() {

$this->name = $this->input->post('name');

$this->feed_url = $this->input->post('feed_url');

$this->category_id = $this->input->post('category_id');

$this->description = $this->input->post('description');

$source_id = $this->input->post('source_id');

if(isset($source_id) && is_numeric($source_id)) {

$this->db->update('source', $this, array('id' => $source_id));

} else {

if($this->nameExists($this->name)) {

return false;

}

$this->db->insert('source', $this);

}

return true;

}

Administrarea categoriilor

Păstrând același model că și în cazul Surselor de știri, administrarea categoriilor se realizează în mod similar.

Controller-ul Categories.php având metodele necesare rulării acțiunilor utilizatorului, iar modelul Category.php asigura conectivitatea și persistenta datelor în baza de date.

Ecranul de afișare a tuturor categoriilor este construit păstrând aceeași forma că în cazul ecranului de afișare a surselor de știri.

Iar adăugarea unei noi categorii se realizează utilizând formularul de adăugare ce are că acțiune metoda save din controller-ul de categorii.

Mai jos, se poate observa modelul detaliat al controller-ului Categories.php, împreuna cu toate metodele necesare rulării unei acțiuni.

class Categories extends CI_Controller {

var $message = '';

var $error = '';

public function __construct() {

parent::__construct();

if(!$this->session->userdata('autentificat')) {

redirect('userlogin', 'index');

}

$this->load->model('Category', '', TRUE);

}

public function listall() {

$data['categories'] = $this->Category->getAll();

$data['template'] = 'categories/list';

$data['title'] = 'Toate categoriile';

$data['error'] = $this->error;

$data['message'] = $this->message;

$this->load->view('master_view', $data);

}

public function delete($id) {

$this->Category->delete($id);

$this->message = "Categoria a fost stearsa";

$this->listall();

}

public function save() {

$result = $this->Category->save();

if($result) {

$this->message = "Categoria a fost salvata!";

$this->listall();

} else {

$this->error = "O categorie cu acelasi nume exista deja. Alegeti alt nume pentru a putea adauga categoria.";

$this->add();

}

}

public function add() {

$data["title"] = "Adauga categorie";

$this->genericCrud($data);

}

public function edit($id) {

$model = null;

if(is_numeric($id)) {

$model = $this->Category->byId($id);

}

if(!is_object($model)) {

$this->error = "Nu exista categoria pe care doriti sa o editati!";

$this->listall();

return;

}

$data["title"] = "Editeaza categoria";

$data["model"] = $model;

$this->genericCrud($data);

}

private function genericCrud($data) {

$data['error'] = $this->error;

$data['message'] = $this->message;

$data['template'] = 'categories/form';

$this->load->view('master_view', $data);

}

}

Păstrând principiile MVC, modelul asociat unei categorii este descris astfel:

class Category extends CI_Model {

var $name;

function __construct() {

parent::__construct();

}

function getAll() {

$this->db->order_by('name', 'ASC');

$entries = $this->db->get('category');

return $entries->result();

}

function getDropdownList() {

$entries = $this->getAll();

$return = array();

$return[''] = '';

foreach ($entries as $row) {

$return[$row->id] = $row->name;

}

return $return;

}

function delete($id) {

$this->db->delete('category', array('id' => $id));

}

function byId($id) {

$entry = $this->db->get_where('category', array('id' => $id));

return $entry->row();

}

function nameExists($name) {

$entry = $this->db->get_where('category', array('name' => $name));

return ($entry->num_rows() > 0);

}

function save() {

$this->name = $this->input->post('name');

$category_id = $this->input->post('category_id');

if(isset($category_id) && is_numeric($category_id)) {

$this->db->update('category', $this, array('id' => $category_id));

} else {

if($this->nameExists($this->name)) {

return false;

}

$this->db->insert('category', $this);

}

return true;

}

}

Schema tabelei category conține cheia primara ID și numele categoriei, reprezentat prin coloana name.

Având descrise entitățile principale, categorie, sursa și știre, putem compune modelul relațional final, al aplicației.

Conturile de administrare

In aceasta secțiune, administratorului îi este permis adăugarea, editarea și ștergerea conturilor de administrare.

Ca măsura de siguranța, contul de administrare curent nu poate fi șters, aceasta acțiune având că și consecința nefuncționarea la parametri normali ai aplicației. In aceeași idee, în cadrul aplicației trebuie sa exista în permanenta doua conturi de administrare, neexistând posibilitatea ștergerii tuturor conturilor, mai putem cel curent.

Ecranul care permite afișarea tuturor conturilor de administrare este următorul:

Se poate observa faptul că, încă din aceasta pagina, administratorul este informat asupra faptului că nu poate șterge contul de administrare curent.

Adăugarea unui cont de administrare se face din ramura Adăuga a sub-meniului Conturi de administrare, completând formularul afișat cu informațiile noului cont.

Pentru a avea siguranța faptului că parola aleasa este cea corecta, administratorul trebuie sa introducă din nou parola aleasa pentru cont. In cazul în care aceasta parola nu este corecta, acestuia îi este prezentat un mesaj de eroare prin care este informat asupra acestui aspect.

Controller-ul complet al secțiunii Conturi de administrare este prezentat mai jos:

class Accounts extends CI_Controller {

var $message = '';

var $error = '';

public function __construct() {

parent::__construct();

$this->load->model('Account', '', TRUE);

}

public function listall() {

$data['accounts'] = $this->Account->getAll();

$data['template'] = 'accounts/list';

$data['title'] = 'Toate conturile de administrare';

$data['error'] = $this->error;

$data['message'] = $this->message;

$this->load->view('master_view', $data);

}

public function delete($id) {

$this->Account->delete($id);

$this->message = "Contul de administrare a fost sters";

$this->listall();

}

public function save() {

//verificarea parolei

if($this->input->post('password') != $this->input->post('password2')) {

$this->error = "Parolele nu coincid!";

$is_edit = $this->input->post('account_id');

if($is_edit) {

$this->edit($is_edit);

} else {

$this->add();

}

return;

}

$result = $this->Account->save();

if($result) {

$this->message = "Contul de administrare a fost salvat";

$this->listall();

} else {

$this->error = "Numele de utilizator exista deja, va rugam alegeti alt nume de utilizator.";

$this->add();

}

}

public function add() {

$data["title"] = "Adauga un cont de administrare";

$this->genericCrud($data);

}

public function edit($id) {

$model = null;

if(is_numeric($id)) {

$model = $this->Account->byId($id);

}

if(!is_object($model)) {

$this->error = "Nu exista contul de administrare pe care doriti sa il editati!";

$this->listall();

return;

}

$data["title"] = "Editeaza contul de administrare";

$data["model"] = $model;

$this->genericCrud($data);

}

Modelul de date asociat conturilor de administrare este prezentat mai jos:

class Account extends CI_Model {

var $full_name;

var $username;

var $password;

function __construct() {

parent::__construct();

}

function getAll() {

$this->db->order_by('username', 'ASC');

$entries = $this->db->get('accounts');

return $entries->result();

}

function delete($id) {

$this->db->delete('accounts', array('id' => $id));

}

function byId($id) {

$entry = $this->db->get_where('accounts', array('id' => $id));

return $entry->row();

}

function nameExists($name) {

$entry = $this->db->get_where('accounts', array('username' => $name));

return ($entry->num_rows() > 0);

}

function save() {

$this->full_name = $this->input->post('full_name');

$this->username = $this->input->post('username');

$this->password = md5($this->input->post('password'));

$account_id = $this->input->post('account_id');

if(isset($account_id) && is_numeric($account_id)) {

$this->db->update('accounts', $this, array('id' => $account_id));

} else {

if($this->nameExists($this->username)) {

return false;

}

$this->db->insert('accounts', $this);

}

return true;

}

}

Schema tabelului mySQL al conturilor de administrare este prezentat mai jos:

Serviciile web REST

Pentru a permite comunicarea cu aplicația client, aplicația web de server are implementat un controller care primește că date de intrare ID-ul unei categorii de știri, și întoarce că valoare, un răspuns în format JSON ce conține știrile preluate din sursa de știri specificata.

JSON (JavaScript Object Notation) este un format de date generice textuale, ce este derivat din notația folosita pentru reprezentarea obiectelor în JavaScript (ECMAScript).

Exemplu de cod JSON:

{

"stiri": [

{ "titlu":"Titlu stire" , "descriere":"Stire despre…" },

{ "titlu":"Titlu stire" , "descriere":" Stire despre…" },

{ "titlu”:"Titlu stire" , "descriere":" Stire despre…" }

]

}

JSON, că și XML, reprezintă un standard în ceea ce privește comunicarea bazata pe serviciile REST, și nu numai.

Pentru a obține lista de știri pentru o anumita categorie, aplicația client trebuie sa realizează o cerere de tip HTTP GET către adresa de URL următoare:

http://adresa_aplicatie_server/index.php/rest/news/Category_Id

In aceasta maniera sunt preluate, cu ajutorul controller-ului Rest.php, știrile ce au categoria data de id-ul Category_Id.

Descrierea controller-ului este după cum urmează:

class Rest extends CI_Controller {

public function __construct() {

parent::__construct();

$this->load->model('Source', '', TRUE);

$this->load->model('Category', '', TRUE);

$this->load->model('News', '', TRUE);

}

public function categories() {

$response = $this->Category->getAll();

echo json_encode($response);

}

public function news($id = null) {

if(isset($id)) {

$response = $this->News->getByCategory($id);

} else {

$response = $this->News->getAll();

}

echo json_encode($response);

}

}

Sunt descrise doua metode categories() și news() prin intermediul cărora aplicația de client poate compune lista de categorii, precum și lista de știri pentru fiecare categorie.

Acest controller este de sine stătător, fără a avea nevoie de un model specific, Rest.php făcând uz de modele deja create în aplicație pentru diferitele operații din zona de administrare.

Pentru a trimite către client răspunsul codificat în format JSON, se folosește funcția de PHP json_encode() ce primește că parametru de intrare un tablou de date asociative, de pe urma căruia realizează conversia.

Capitolul 5
Aplicația de Android – clientul

Ecranul de start. Încărcarea datelor

In momentul în care este rulata aplicația Știrile mele de către utilizator, acestuia îi este prezentat un ecran de start, timp în care aplicația incarna datele necesare deschiderii.

Datele sunt preluate în urma unor apeluri HTTP GET către serviciul web REST expus de aplicația server.

In prima faza, sunt preluate categoriile de știri. Pentru a nu bloca firul de execuție principal, secțiunea de preluare a categoriilor se realizează pe un fir de execuție separat, notificând la finalul execuției, interfața grafică, în sensul deschiderii activității de vizualizare a listei de știri.

private void refreshCategories() {
JsonRequest<CategoriesCollection> request = new JsonRequest<CategoriesCollection>(Request.Method.GET, Constants.CATEGORIES_URL, null,
new Response.Listener<CategoriesCollection>() {
@Override
public void onResponse(CategoriesCollection response) {
Log.d(TAG, "Response came…");
if(response != null) {
AssetsManager.getInstance().setCategoriesCollection(response);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
proceed();
}
}, SPLASH_TIME_OUT);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage(), error.getCause());
}
}) {
@Override
protected Response<CategoriesCollection> parseNetworkResponse(NetworkResponse response) {
String jsonString = null;
try {
jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
JSONArray ja = new JSONArray(jsonString);

CategoriesCollection r = new CategoriesCollection();
int length = ja.length();
for (int i = 0; i < length; i++) {
JSONObject o = (JSONObject) ja.get(i);

r.addCategory(new Category(
o.getInt("id"),
o.getString("name")
));
}

return Response.success(r, null);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, e.getMessage(), e.getCause());
} catch (JSONException e2) {
Log.e(TAG, e2.getMessage(), e2.getCause());
}

return null;
}
};

Așadar, se poate observa în metoda anonima onResponse, că se face apel la funcția proceed(), cea care este responsabila cu trimiterea utilizatorului către următorul ecran.

private void proceed() {
startActivity(new Intent(this, MainActivity.class));
overridePendingTransition(0, 0);
finish();
}

Ecranul de știri

Astfel, folosind metoda startActivity() se instanțiază activitatea MainActivity în mod explicit, iar următorul ecran este cel în care sunt prezentate toate știrile.

In acest ecran, utilizatorul poate vedea lista de știri din categoria selectata. In cazul în care nu este selectata nicio categorie, apelul către serviciul web REST se realizează fără parametru de categorie, iar rezultatul va fi listarea tuturor știrilor existente din ultima perioada.

In cazul în care utilizatorul dorește afișarea știrilor după o anumita categorie, acesta are la dispoziție un meniu afișat în partea stânga a ecranului, pentru deschiderea căruia nu este necesara paradirea activității principale.

Odată selectata o noua categorie, lista de știri se actualizează folosind de acest data apelul REST cu parametru de categorie.

Afișarea știrilor sub forma de lista este realizează folosind clasa de sistem ListView împreuna cu un Adaptor necesar pentru popularea listei.

Modalitatea prin care sistemul de operare Android afișează date intr-un control de tip ListView, este data de către Adaptor, ce reprezintă o instanța a unei clasei ce extinde clasa de sistem BaseAdapter.

Un alt aspect important al acestui ecran este modalitatea de încărcarea a imaginilor. Fiind vorba de imagini ce nu se regăsesc local (pe dispozitivul pe care este instalata aplicația) acestea trebuie descărcate în prealabil afișării, însa acest lucru trebuie realizat pe un fir de execuție diferit de cel principal, pentru a nu bloca interfața grafică.

Bibliografie

Curs „Tehnici de dezvoltare web”, Lect. Dr. Mihail Cherciu

Leonard Richardson, RESTful Web Services, O'Reilly, 2007

Architecture for Developers, James Governor, Duane Nickull, Dion Hinchcliffe

PHP and MySQL Web Development, Luke Welling și Laura Thomson

Ghid de dezvoltare a aplicațiilor
http://developer.android.com

Android Programming, Bill Phillips

Bibliografie

Curs „Tehnici de dezvoltare web”, Lect. Dr. Mihail Cherciu

Leonard Richardson, RESTful Web Services, O'Reilly, 2007

Architecture for Developers, James Governor, Duane Nickull, Dion Hinchcliffe

PHP and MySQL Web Development, Luke Welling și Laura Thomson

Ghid de dezvoltare a aplicațiilor
http://developer.android.com

Android Programming, Bill Phillips

Similar Posts