Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
laboratoare:laborator02 [2015/03/02 07:08] Andrei Roșu-Cojocaru [Hierarchy View] |
laboratoare:laborator02 [2017/02/20 20:54] (current) |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Laborator 02. Structura unei Aplicații Android (I) ====== | + | ====== Laborator 02. Structura unei Aplicații (I) ====== |
| O aplicație Android poate conține mai multe componente: | O aplicație Android poate conține mai multe componente: | ||
| Line 88: | Line 88: | ||
| </file> | </file> | ||
| - | Este obligatoriu ca metoda ''onCreate()'' să apeleze metoda părinte, în caz contrar generându-se o excepție. Tot aici se realizează și încărcarea interfeței grafice (a cărei structură a fost definită într-un fișier .xml din resursele aplicației Android), prin intermediul metodei ''setContentView()''. | + | Este obligatoriu ca metoda ''onCreate()'' să apeleze metoda părinte, în caz contrar generându-se o excepție. |
| + | |||
| + | Pentru fiecare activitate, este necesar să se descrie interfața grafică în cadrul unui fișier .xml (încărcat manual, în cadrul metodei ''onCreate()'', printr-un apel al metodei ''setContentView()'') în care elementul părinte este un mecanism de dispunere a conținutului (derivat din clasa ''android.view.ViewGroup''). Acest fișier este plasat în directorul ''res/layout'' și conține referințe către toate obiectele care vor fi afișate în cadrul ferestrei. În urma compilării, vor fi generate niște referințe (adrese în cadrul pachetului de resurse) prin intermediul cărora resursele vor putea fi accesate. | ||
| + | |||
| + | <file xml activity_lifecycle_monitor.xml> | ||
| + | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| + | xmlns:tools="http://schemas.android.com/tools" | ||
| + | android:layout_width="match_parent" | ||
| + | android:layout_height="wrap_content" | ||
| + | android:paddingBottom="@dimen/activity_vertical_margin" | ||
| + | android:paddingLeft="@dimen/activity_horizontal_margin" | ||
| + | android:paddingRight="@dimen/activity_horizontal_margin" | ||
| + | android:paddingTop="@dimen/activity_vertical_margin" | ||
| + | android:orientation="vertical" | ||
| + | tools:context="ro.pub.cs.systems.pdsd.lab02.graphicuserinterface.LifecycleMonitorActivity" > | ||
| + | |||
| + | <!-- ... --> | ||
| + | |||
| + | </LinearLayout> | ||
| + | </file> | ||
| + | |||
| + | Prin urmare, componentele definitorii ale unei activități sunt clasa în care este implementat comportamentul în urma interacțiunii cu utilizatorul și fișierul .xml care descrie modelul static al interfeței grafice. | ||
| + | |||
| + | {{ :laboratoare:laborator02:activity_relationships.png?nolink&700 }} | ||
| O activitate poate fi pornită în mod explicit prin intermediul metodei ''startActivity()'' care primește ca parametru un obiect de tip intenție (căruia i se pot atașa și niște date, transferate activității). În cazul în care se așteaptă ca activitatea să producă unele rezultate, se va apela metoda ''startActivityForResult()'' - furnizându-se și un cod de cerere -, fiind necesar ca activitatea astfel invocată să implementeze metoda ''onActivityResult()''. | O activitate poate fi pornită în mod explicit prin intermediul metodei ''startActivity()'' care primește ca parametru un obiect de tip intenție (căruia i se pot atașa și niște date, transferate activității). În cazul în care se așteaptă ca activitatea să producă unele rezultate, se va apela metoda ''startActivityForResult()'' - furnizându-se și un cod de cerere -, fiind necesar ca activitatea astfel invocată să implementeze metoda ''onActivityResult()''. | ||
| Line 129: | Line 152: | ||
| <note tip>Distincția între cele două situații în care o activitate este distrusă poate fi realizată prin intermediul metodei ''isFinishing()''.</note> | <note tip>Distincția între cele două situații în care o activitate este distrusă poate fi realizată prin intermediul metodei ''isFinishing()''.</note> | ||
| - | {{ :laboratoare:laborator02:ciclul_de_viata_al_unei_activitati_2.png?nolink&500 }} | + | {{ :laboratoare:laborator02:ciclul_de_viata_al_unei_activitati_2.png?nolink&700 }} |
| <note important>Fiecare dintre metodele ce gestionează ciclul de viață al activității trebuie să apeleze metoda părintelui. În cazul metodei ''onCreate()'', este necesar ca acest lucru să fie realizat la începutul metodei.</note> | <note important>Fiecare dintre metodele ce gestionează ciclul de viață al activității trebuie să apeleze metoda părintelui. În cazul metodei ''onCreate()'', este necesar ca acest lucru să fie realizat la începutul metodei.</note> | ||
| Line 249: | Line 272: | ||
| super.onSaveInstanceState(savedInstanceState); | super.onSaveInstanceState(savedInstanceState); | ||
| EditText usernameEditText = (EditText)findViewById(R.id.username_edit_text); | EditText usernameEditText = (EditText)findViewById(R.id.username_edit_text); | ||
| - | state.putString(Constants.USERNAME_EDIT_TEXT, usernameEditText.getText()); | + | savedInstanceState.putString(Constants.USERNAME_EDIT_TEXT, usernameEditText.getText()); |
| } | } | ||
| </code> | </code> | ||
| Line 311: | Line 334: | ||
| {{ :laboratoare:laborator02:coordonare_activitati.png?nolink&400 }} | {{ :laboratoare:laborator02:coordonare_activitati.png?nolink&400 }} | ||
| - | ===== Structura unui Proiect Android în Eclipse Luna SR1a (4.4.1) ===== | + | ===== Structura unui Proiect Android în Eclipse Mars 1 (4.5.1) ===== |
| Structura unui proiect Android în mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) poate fi observată în fereastra //Package Explorer//. | Structura unui proiect Android în mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) poate fi observată în fereastra //Package Explorer//. | ||
| Line 323: | Line 346: | ||
| * ''maps.jar'' - folosită de aplicațiile Android care implementează funcționalități legate de localizare. | * ''maps.jar'' - folosită de aplicațiile Android care implementează funcționalități legate de localizare. | ||
| * **Android Private Libraries** conține un singur fișier ''android-support-v4.jar''; | * **Android Private Libraries** conține un singur fișier ''android-support-v4.jar''; | ||
| - | * **src** - conține sursele ''.java'' ale proiectului, organizate pe pachete. În exemplu, există un singur fișier, ''LifecycleMonitorActivity.java'' (în pachetul ''ro.pub.cs.systems.pdsd.lab02.graphicuserinterface'') care reprezintă codul sursă al activității principale a aplicației Android. | + | * **src** - conține sursele ''.java'' ale proiectului, organizate pe pachete. În exemplu, codul este organizat pe trei pachete, cea mai importantă clasă fiind ''LifecycleMonitorActivity.java'' (în pachetul ''ro.pub.cs.systems.pdsd.lab02.graphicuserinterface'') continand activitatea principala a aplicației Android. |
| * **gen** - cuprinde fișiere generate: | * **gen** - cuprinde fișiere generate: | ||
| * ''BuildConfig.java'' - definește unele proprietăți ale aplicației (cum ar fi activarea sau nu a modului de depanare); | * ''BuildConfig.java'' - definește unele proprietăți ale aplicației (cum ar fi activarea sau nu a modului de depanare); | ||
| Line 424: | Line 447: | ||
| * un element de tip ''CheckBox'' prin intermediul căruia utilizatorul va putea să indice dacă dorește ca informațiile sale de autentificare să fie reținute sau nu; | * un element de tip ''CheckBox'' prin intermediul căruia utilizatorul va putea să indice dacă dorește ca informațiile sale de autentificare să fie reținute sau nu; | ||
| * două butoane, dispuse folosind un mecanism de aliniere orizontală, prin intermediul cărora utilizatorul poate să transmită (către un server) informațiile sale de autentificare, pentru a fi procesate, respectiv dorește să anuleze informațiile introduse; | * două butoane, dispuse folosind un mecanism de aliniere orizontală, prin intermediul cărora utilizatorul poate să transmită (către un server) informațiile sale de autentificare, pentru a fi procesate, respectiv dorește să anuleze informațiile introduse; | ||
| - | * ''menu'': fișierul ''main.xml'' conține un meniu care se va afișa la accesarea butonului ''Options'', fiind folosit de ''metoda onCreateOptionsMenu()''; | + | * ''menu'': fișierul ''main.xml'' conține un meniu care se va afișa la accesarea butonului ''Options'', fiind folosit de metoda ''onCreateOptionsMenu()''; |
| * ''values'' | * ''values'' | ||
| * ''colors.xml'': conține definițiile pentru culorile utilizate în cadrul interfeței grafice, ca fundal; <file xml colors.xml> | * ''colors.xml'': conține definițiile pentru culorile utilizate în cadrul interfeței grafice, ca fundal; <file xml colors.xml> | ||
| Line 581: | Line 604: | ||
| ==== Depanarea unei aplicații Android ==== | ==== Depanarea unei aplicații Android ==== | ||
| + | |||
| + | Depanarea unei aplicații Android poate fi realizată în mod clasic, ca în cazul oricărui proiect (prin stabilirea unor puncte în care execuția codului sursă este întreruptă și rularea pas cu pas) sau prin intermediul unor utilitare specifice. | ||
| + | |||
| + | În cadrul mediului integrat de dezvoltare Eclipse Luna SR1a (4.4.1), depanarea unei aplicații este facilitată prin împărțirea ecranului în mai multe perspective între care programatorul are posibilitatea de a comuta: | ||
| + | * Java - pentru realizarea de modificări la nivelul codului sursă | ||
| + | * Debug - pentru monitorizarea pas cu pas a execuției programului, cu posibilitatea de consultare a valorilor pe care le au la un moment dat diferite obiecte | ||
| + | * DDMS - pentru furnizarea de informații detaliate la nivel de procese, fire de execuție, sistem de fișiere, memorie ocupată, evenimente specifice dispozitivelor mobile | ||
| + | * Hierarchy View - pentru vizualizarea ierarhiei de componente grafice din cadrul interfeței afișate utilizatorului | ||
| + | |||
| + | {{ :laboratoare:laborator02:eclipse_perspectives_for_android.png?nolink }} | ||
| === Android Debug Bridge (ADB) === | === Android Debug Bridge (ADB) === | ||
| + | |||
| Android Debug Bridge este un utilitar în linie de comandă care permite comunicarea cu cu un dispozitiv mobil fizic sau cu un emulator, prin intermediul unui program client-server ce include 3 componente: | Android Debug Bridge este un utilitar în linie de comandă care permite comunicarea cu cu un dispozitiv mobil fizic sau cu un emulator, prin intermediul unui program client-server ce include 3 componente: | ||
| * un client, apelat prin comanda ''adb'' (alți clienți sunt plugin-ul ADT, DDMS-ul, Hierarchy View); | * un client, apelat prin comanda ''adb'' (alți clienți sunt plugin-ul ADT, DDMS-ul, Hierarchy View); | ||
| Line 592: | Line 626: | ||
| * pentru a folosi ADB shell, device-ul Android trebuie să fie root-at (imaginile genymotion sunt deja). | * pentru a folosi ADB shell, device-ul Android trebuie să fie root-at (imaginile genymotion sunt deja). | ||
| * comenzile ADB pot fi rulate din linia de comandă sau din script, având următorul format:<code> | * comenzile ADB pot fi rulate din linia de comandă sau din script, având următorul format:<code> | ||
| - | student@pdsd2015:/opt/android-sdk-linux/platform-tools$ adb [-d|-e|-s <serialNumber>] <command> | + | student@eim2016:/opt/android-sdk-linux/platform-tools$ adb [-d|-e|-s <serialNumber>] <command> |
| </code> | </code> | ||
| * înainte de a utiliza comenzi ''adb'' este important să fie cunoscut identificatorul dispozitivului care este conectat la serverul adb, acesta putând fi identificat prin comanda ''adb devices'':<code> | * înainte de a utiliza comenzi ''adb'' este important să fie cunoscut identificatorul dispozitivului care este conectat la serverul adb, acesta putând fi identificat prin comanda ''adb devices'':<code> | ||
| - | student@pdsd2015:/opt/android-sdk-linux/platform-tools$ adb devices | + | student@eim2016:/opt/android-sdk-linux/platform-tools$ adb devices |
| List of devices attached | List of devices attached | ||
| emulator-5556 device | emulator-5556 device | ||
| Line 667: | Line 701: | ||
| {{ :laboratoare:laborator02:logcat_message_filter_settings.png?nolink }} | {{ :laboratoare:laborator02:logcat_message_filter_settings.png?nolink }} | ||
| + | |||
| + | Se recomandă să se configureze un număr cât mai mare de mesaje de jurnalizare care să fie stocate în memoria tampon (//Window// → //Preferences// → //Android// → //LogCat//) întrucât după depășirea valorii respective, monitorizarea nu va mai fi posibilă. | ||
| + | |||
| + | {{ :laboratoare:laborator02:logcat_configuration.png?nolink&700 }} | ||
| === DDMS === | === DDMS === | ||
| Line 700: | Line 738: | ||
| Consultarea sistemului de fișiere al dispozitivului mobil poate fi realizat prin intermediul panoului **//File Explorer//**, putând fi vizualizate datele aplicației, stocate în ''data/data/<package-name>'', unde ''<package-name>'' este denumirea pachetului corespunzător aplicației investigate. | Consultarea sistemului de fișiere al dispozitivului mobil poate fi realizat prin intermediul panoului **//File Explorer//**, putând fi vizualizate datele aplicației, stocate în ''data/data/<package-name>'', unde ''<package-name>'' este denumirea pachetului corespunzător aplicației investigate. | ||
| + | |||
| + | {{ :laboratoare:laborator02:ddms_file_explorer.png?nolink&600 }} | ||
| **Simularea unor evenimente de tip întrerupere pentru emulator** | **Simularea unor evenimente de tip întrerupere pentru emulator** | ||
| Line 745: | Line 785: | ||
| ===== Activitate de Laborator ===== | ===== Activitate de Laborator ===== | ||
| + | |||
| **1.** În contul Github personal, să se creeze un depozit denumit 'Laborator02'. Inițial, acesta trebuie să fie gol (nu trebuie să bifați nici adăugarea unui fișier ''README.md'', nici a fișierului ''.gitignore'' sau a a fișierului ''LICENSE''). | **1.** În contul Github personal, să se creeze un depozit denumit 'Laborator02'. Inițial, acesta trebuie să fie gol (nu trebuie să bifați nici adăugarea unui fișier ''README.md'', nici a fișierului ''.gitignore'' sau a a fișierului ''LICENSE''). | ||
| - | **2.** Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la [[https://www.github.com/pdsd2015/Laborator02|]]. În urma acestei operații, directorul Laborator02 va trebui să se conțină proiectul Eclipse denumit ''ActivityLifecycleMonitor'', fișierul ''README.md'' și un fișier ''.gitignore'' care indică tipurile de fișiere (extensiile) ignorate. <code> | + | **2.** Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la [[https://www.github.com/eim2016/Laborator02|]]. În urma acestei operații, directorul Laborator02 va trebui să se conțină un director ''labtasks'' ce va deține atât proiectul AndroidStudio cât și proiectul Eclipse, ambele denumite ''ActivityLifecycleMonitor'', fișierul ''README.md'' și un fișier ''.gitignore'' care indică tipurile de fișiere (extensiile) ignorate. <code> |
| - | student@pdsd2015:~$ git clone https://www.github.com/pdsd2015/Laborator02 | + | student@eim2016:~$ git clone https://www.github.com/eim2016/Laborator02.git |
| </code> | </code> | ||
| **3.** Să se încarce conținutul descărcat în cadrul depozitului 'Laborator02' de pe contul Github personal. <code> | **3.** Să se încarce conținutul descărcat în cadrul depozitului 'Laborator02' de pe contul Github personal. <code> | ||
| - | student@pdsd2015:~$ cd Laborator02 | + | student@eim2016:~$ cd Laborator02 |
| - | student@pdsd2015:~/Laborator02$ git remote add Laborator02_perfectstudent https://github.com/perfectstudent/Laborator02 | + | student@eim2016:~/Laborator02$ git remote add Laborator02_perfectstudent https://github.com/perfectstudent/Laborator02 |
| - | student@pdsd2015:~/Laborator02$ git push Laborator02_perfectstudent master | + | student@eim2016:~/Laborator02$ git push Laborator02_perfectstudent master |
| </code> | </code> | ||
| Line 763: | Line 804: | ||
| {{ :laboratoare:laborator02:eclipse_import_project02.png?nolink&500 }} | {{ :laboratoare:laborator02:eclipse_import_project02.png?nolink&500 }} | ||
| - | **5.** În clasa ''LifecycleMonitorActivity'' din pachetul ''ro.pub.cs.systems.pdsd.lab02.graphicuserinterface'', să se suprascrie metodele care monitorizează ciclul de viață al unei activități; fiecare dintre acestea va trebui **să apeleze metoda părinte** și **să notifice apelarea sa prin intermediul unui mesaj**, având prioritatea ''DEBUG'' și eticheta ''lifecycleevents'':<code java> | + | **5.** În clasa ''LifecycleMonitorActivity'' din pachetul ''ro.pub.cs.systems.eim.lab02.activitylifecyclemonitor.graphicuserinterface'', să se suprascrie metodele care monitorizează ciclul de viață al unei activități; fiecare dintre acestea va trebui **să apeleze metoda părinte** și **să notifice apelarea sa prin intermediul unui mesaj**, având prioritatea ''DEBUG'' și eticheta ''lifecycleevents'':<code java> |
| Log.d(Constants.TAG, "??? method was invoked"); | Log.d(Constants.TAG, "??? method was invoked"); | ||
| </code> | </code> | ||
| Line 773: | Line 814: | ||
| - ''onDestroy()'' | - ''onDestroy()'' | ||
| - | **6.** Să se creeze un filtru, denumit ''ActivityLifecycleMonitor'', astfel încât LogCat să afișeze doar mesajele care au eticheta ''lifecycleevents'', generate de aplicația ''ro.pub.cs.systems.pdsd.lab02'' și au cel puțin prioritatea ''debug''. | + | **6.** Să se creeze un filtru, denumit ''ActivityLifecycleMonitor'', astfel încât LogCat să afișeze doar mesajele care au eticheta ''activitylifecyclemonitor'', generate de aplicația ''ro.pub.cs.systems.eim.lab02.activitylifecyclemonitor'' și au cel puțin prioritatea ''debug''. |
| **7.** Să se modifice mesajul din metoda ''onCreate()'', astfel încât să se indice dacă activitatea a mai fost lansată în execuție anterior sau nu (dacă există o stare a activității care trebuie restaurată). | **7.** Să se modifice mesajul din metoda ''onCreate()'', astfel încât să se indice dacă activitatea a mai fost lansată în execuție anterior sau nu (dacă există o stare a activității care trebuie restaurată). | ||
| Line 782: | Line 823: | ||
| - se apasă butonul //OK// din cadrul aplicației (indiferent dacă datele de autentificare sunt corecte sau nu) | - se apasă butonul //OK// din cadrul aplicației (indiferent dacă datele de autentificare sunt corecte sau nu) | ||
| - se ține apăsat butonul //Home// o perioadă de timp mai mare | - se ține apăsat butonul //Home// o perioadă de timp mai mare | ||
| - | - se primește un apel telefonic\\ a) pentru dispozitive fizice root-ate / AVD, se poate folosi //DDMS// → //Emulator Control//\\ b) pentru Genymotion se poate simula doar formarea unui număr de telefon <code> | + | - se primește un apel telefonic\\ a) pentru AVD, se poate folosi //DDMS// → //Emulator Control//\\ b) pentru Genymotion se poate simula doar formarea unui număr de telefon <code> |
| - | student@pdsd2015:/opt/android-sdk-linux/platform-tools$ adb devices | + | student@eim2016:/opt/android-sdk-linux/platform-tools$ adb devices |
| List of devices attached | List of devices attached | ||
| 192.168.56.101:5555 device | 192.168.56.101:5555 device | ||
| - | student@pdsd2015:/opt/android-sdk-linux/platform-tools$ adb -s 192.168.56.101:5555 shell | + | student@eim2016:/opt/android-sdk-linux/platform-tools$ adb -s 192.168.56.101:5555 shell |
| - | student@pdsd2015:/opt/android-sdk-linux/platform-tools$ am start -a android.intent.action.CALL tel:1122334455 | + | root@android:/ # am start -a android.intent.action.CALL tel:1122334455 |
| + | Starting: Intent { act=android.intent.action.CALL dat=tel:xxxxxxxxxx } | ||
| </code> | </code> | ||
| - se acceptă convorbirea | - se acceptă convorbirea | ||
| Line 813: | Line 855: | ||
| **10.** Să se implementeze metoda ''onSaveInstanceState()'', astfel încât, **în condițiile în care este bifat elementul grafic de tip ''CheckBox''**, să se salveze informațiile din interfața cu utilizatorul. | **10.** Să se implementeze metoda ''onSaveInstanceState()'', astfel încât, **în condițiile în care este bifat elementul grafic de tip ''CheckBox''**, să se salveze informațiile din interfața cu utilizatorul. | ||
| - | <note tip>Se vor folosi metodele ''putString()'' și ''putBoolean()'' ale clasei ''Bundle''.\\ \\ Cheile sub care vor fi identificate valorile salvate sunt definite în interfața ''Constants'' din pachetul ''ro.pub.cs.systems.pdsd.lab02.general''.\\ \\ Verificarea faptului că un element grafic de tip ''CheckBox'' este bifat se face prin intermediul metodei ''isChecked()''.</note> | + | <note tip>Se vor folosi metodele ''putString()'' și ''putBoolean()'' ale clasei ''Bundle''.\\ \\ Cheile sub care vor fi identificate valorile salvate sunt definite în interfața ''Constants'' din pachetul ''ro.pub.cs.systems.eim.lab02.activitylifecyclemonitor.general''.\\ \\ Verificarea faptului că un element grafic de tip ''CheckBox'' este bifat se face prin intermediul metodei ''isChecked()''.</note> |
| Să se observe comportamentul aplicației în condițiile producerii evenimentului descris anterior. | Să se observe comportamentul aplicației în condițiile producerii evenimentului descris anterior. | ||
| Line 819: | Line 861: | ||
| **11.** Să se implementeze metoda ''onRestoreInstanceState()'' astfel încât să se restaureze starea elementelor grafice. Să se observe comportamentul aplicației în condițiile producerii evenimentului descris anterior. | **11.** Să se implementeze metoda ''onRestoreInstanceState()'' astfel încât să se restaureze starea elementelor grafice. Să se observe comportamentul aplicației în condițiile producerii evenimentului descris anterior. | ||
| - | Să se transfere comportamentul de restaurare a stării pe metoda ''onCreate()'' și să se identifice diferențele de implementare. | + | Să se transfere comportamentul de restaurare a stării pe metoda ''onCreate()'' și să se identifice diferențele de implementare ([[http://developer.android.com/training/basics/activity-lifecycle/recreating.html|Hint]]). |
| **12.** Să se încarce modificările realizate în cadrul depozitului 'Laborator02' de pe contul Github personal, folosind un mesaj sugestiv. <code> | **12.** Să se încarce modificările realizate în cadrul depozitului 'Laborator02' de pe contul Github personal, folosind un mesaj sugestiv. <code> | ||
| - | student@pdsd2015:~/Laborator02$ git add ActivityLifecycleMonitor/src/ro/pub/cs/systems/pdsd/lab02/* | + | student@eim2016:~/Laborator02$ git add labtasks/* |
| - | student@pdsd2015:~/Laborator02$ git commit -m "implemented taks for laboratory 02" | + | student@eim2016:~/Laborator02$ git commit -m "implemented taks for laboratory 02" |
| - | student@pdsd2015:~/Laborator02$ git push Laborator02_perfectstudent master | + | student@eim2016:~/Laborator02$ git push Laborator02_perfectstudent master |
| </code> | </code> | ||
