====== Laborator 02. Structura unei Aplicații (I) ====== O aplicație Android poate conține mai multe componente: - [[http://developer.android.com/reference/android/content/Context.html|contextul]] reprezintă punctul central al unei aplicații Android, oferind acces către mai multe funcționalități ale acesteia (inclusiv la resursele dizpozitivului mobil, serviciile sistemului de operare, diferite fișiere de configurare); este instanțiat sub forma unui obiect de tip ''android.app.Application''; - [[http://developer.android.com/reference/android/app/Activity.html|activitatea]] realizează sarcini a căror execuție nu influențează timpul de răspuns al aplicației Android, astfel încât să nu aibă un impact asupra experienței utilizatorului; de aceea, este asociată unei ferestre (interfețe grafice), o aplicație Android fiind formată din una sau mai multe activități; - [[http://developer.android.com/reference/android/app/Fragment.html|fragmentul]] conține interfața grafică și logica aplicației corespunzătoare unei părți din cadrul unei activități; motivul pentru care se recurge la modularizarea unei activități prin intermediul a mai multor fragmente este asigurarea consistenței și flexibilității aplicației Android pe mai multe echipamente mobile, cu dispozitive de afișare de dimensiuni și rezoluții diferite; - [[http://developer.android.com/reference/android/app/Service.html|serviciul]] încapsulează procese mai complexe, executate în fundal (și posibil la intervale de timp regulate) a căror rulare durează o perioadă de timp semnificativă, astfel încât să nu poată fi plasate în cadrul aceluiași fir de execuție ca și interfața grafică prin care se asigură interacțiunea cu utilizatorul; - [[http://developer.android.com/reference/android/content/Intent.html|intenția]] este mecanismul de comunicare între elementele unei aplicații Android (activități și servicii); prin intermediul unui sistem de mesagerie (asincronă), sistemul de operare Android mapează o solicitare (împachetată sub forma unei intenții) către componenta adecvată. {{ :laboratoare:laborator02:structura_unei_aplicatii_Android.png?nolink&500 }} ===== Contextul ===== Contexul este utilizat pentru a implementa diferite funcționalități la nivelul întregii aplicații: * obținerea de referințe la resursele aplicației (șiruri de caractere, elemente grafice, fișiere XML); * accesarea preferințelor aplicației; * gestiunea sistemului de fișiere corespunzător aplicației; * lucrul cu resurse necompilate ale aplicației; * utilizarea serviciilor de sistem; * folosirea unei baza de date SQLite; * administrarea permisiunilor aplicației. În clasele de tip ''Activity'' sau ''Service'', contextul aplicației poate fi obținut printr-un apel de forma: Context context = getApplicationContext(); // definita in clasa Context Context context = getApplication(); // definita in clasa Activity Pentru a se evita utilizarea ineficientă a memoriei (//eng.// memory leak), în situația în care obiectele trebuie să existe pe toată durata aplicației, se recomandă ca acestea să refere contextul aplicației (nu al activității), astfel încât să nu fie condiționate de diverse evenimente din ciclul de viață al acestora. ===== Activitatea ===== Activitatea reprezintă o componenta a aplicației Android ce oferă o interfață grafică cu care utilizatorul poate să interacționeze. Cele mai multe activități ocupă întreaga suprafață de afișare, însă acest lucru nu este obligatoriu. O aplicație Android este formată din una sau mai multe activități (slab cuplate între ele). Există întotdeauna o activitate principală care este afișată atunci când aplicația Android este lansată în execuție inițial. O activitate poate invoca o altă activitate pentru a realiza diferite sarcini, prin intermediul unei intenții. În acest moment, activitatea veche este oprită și salvată pe stivă (//eng.// back stack), după care este pornită activitatea nouă. Restaurarea și (re)începerea activității vechi este realizată în momentul în care activitatea nouă (curentă) este terminată. Un comportament similar are loc în momentul în care se produce un eveniment (primirea unui apel telefonic, apăsarea tastelor //Home// sau //Back//, lansarea altei aplicații). O activitate trebuie să își gestioneze corespunzător comportamentul (inclusiv folosirea memoriei) în cazul producerii diferitelor evenimente, salvând și restaurând starea de fiecare dată când aplicația este oprită, respectiv (re)pornită. ==== Componentele unei Activități ==== O activitate poate fi utilizată numai dacă este definită în fișierul ''AndroidManifest.xml'', în cadrul elementului de tip ''''. Pentru fiecare activitate trebuie creată o intrare de tip [[http://developer.android.com/guide/topics/manifest/activity-element.html|]] pentru care se specifică diferite atribute, dintre care obligatoriu este numai denumirea activității (''android:name''). Din momentul în care aplicația Android este publicată, conținutul manifestului devine un contract față de utilizatori, iar denumirile componentelor nu mai pot fi modificate întrucât pot genera erori în cazul producerii unor actualizări. Pentru o activitate se poate specifica și un filtru de intenții, în cadrul elementului [[http://developer.android.com/guide/topics/manifest/intent-filter-element.html|]], spre a indica modul în care componentele aplicației o pot accesa. Acesta este necesar pentru ca activitatea să poată fi rulată folosind intenții implicite (furnizate de alte aplicații). Așadar, o astfel de intrare va fi necesară pentru fiecare tip de intenție, precizând elementele '''' și opțional '''' / ''''. În cazul activităților care nu vor fi accesibile din cadrul altor aplicații Android, nu este necesară definirea unui filtru de intenții. O activitate principală din cadrul unei aplicații Android este caracterizată prin următoarele proprietăți: * acțiunea are valoarea ''android.intent.action.MAIN'', întrucât reprezintă punctul de intrare al aplicației Android; * categoria are valoarea ''android.intent.category.LAUNCHER'', întrucât activitatea trebuie inclusă în meniul dispozitivului mobil pentru a putea fi lansată în execuție. Ulterior, se va implementa și clasa identificată prin denumirea activității. Aceasta trebuie să fie derivată din ''android.app.Activity'' și să implementeze cel puțin metoda ''onCreate()'' în care sunt inițializate componentele sale. public class LifecycleMonitorActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_lifecycle_monitor); // ... } // ... } 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. 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 oprită în mod explicit prin intermediul metodei ''finish()''. De regulă, folosirea unei astfel de metode este descurajată, datorită impactului pe care îl poate avea asupra experienței utilizatorului. ==== Ciclul de Viață al unei Activități ==== Din momentul în care activitatea este creată și până la momentul în care este distrusă, ea trece printr-o serie de etape, cunoscute sub denumirea de **ciclul de viață al activității**: * **în execuție** (//eng.// running) - activitatea se află în prim plan și este vizibilă, astfel încât utilizatorul poate interacționa cu aceasta prin intermediul interfeței grafice pe care o oferă; * **întreruptă temporar** (//eng.// paused) - activitatea se află în fundal și este (parțial) vizibilă; o astfel de situație este întâlnită în momentul în care o altă activitate a fost pornită, însă interfața sa grafică este transparentă sau nu ocupă întreaga suprafață a dispozitivului de afișare; în acest caz, activitatea este încă activă în sensul că obiectul de tip ''Activity'' este stocat în memorie, fiind atașată în continuare procesului responsabil cu gestiunea ferestrelor și menținându-se starea tuturor componentelor sale; totuși, ea poate fi distrusă de sistemul de operare dacă necesarul de memorie disponibilă nu poate fi întrunit din cauza sa; * **oprită** (//eng.// stopped) - activitatea se află în fundal și este complet ascunsă; o astfel de situație este întâlnită în momentul în care o altă activitate a fost pornită, iar interfața sa grafică ocupă întreaga suprafață a dispozitivului de afișare; și în acest caz, activitatea este activă în sensul că obiectul de tip ''Activity'' fiind stocat în memorie, menținându-se starea tuturor componentelor sale, dar detașându-se de procesul responsabil cu gestiunea ferestrelor; ea poate fi distrusă de sistemul de operare dacă necesarul de memorie disponibilă nu poate fi întrunit din cauza sa; * **inexistentă** - activitatea a fost terminată sau distrusă de sistemul de operare, rularea sa impunând crearea tuturor componentelor sale ca și când ar fi accesată inițial. {{ :laboratoare:laborator02:ciclul_de_viata_al_unei_activitati_1.png?nolink&300 }} Tranziția unei activități dintr-o stare în alta este notificată prin intermediul unor metode (//eng.// callbacks), care pot fi suprascrise pentru a realiza diferite operații necesare pentru gestiunea memoriei, asigurarea persistenței informațiilor și a consistenței aplicației Android în situația producerii de diferite evenimente: * ''onCreate(Bundle)'' - apelată în momentul în care activitatea este creată; această metodă va fi folosită pentru inițializări statice: * încărcarea interfeței grafice printr-un apel al metodei ''setContentView(int)'' (al cărei parametru reprezintă referința către resursa de tip ''.xml'' care descrie interfața grafică); * obținerea de referințe către componentele interfeței grafice printr-un apel al metodei ''findViewById(int)'' (al cărei parametru reprezintă referința către componenta respectivă - //eng.// widget - așa cum apare în resurse); * indicarea unor obiecte de tip ascultător care să gestioneze evenimentele legate de interacțiunea cu utilizatorul; * realizarea unor conexiuni către alte modele de date. Crearea activității este diferită de apariția acesteia pe ecran. Metoda ''onCreate()'' este întotdeauna urmată de metoda ''onStart()''. * ''onRestart()'' - apelată atunci când activitatea a fost oprită și ulterior repornită; este urmată întotdeauna de metoda ''onStart()''; * ''onStart()'' - apelată înainte ca activitatea să apară pe ecran; poate fi urmată de metoda ''onResume()'' dacă activitatea trece în prim-plan sau de metoda ''onPause()'' dacă activitatea trece în fundal; * ''onResume()'' - apelată înainte ca activitatea să interacționeze cu utilizatorul; această metodă va fi folosită pentru a porni servicii sau cod care trebuie să ruleze atâta timp cât aplicația este afișată pe ecran; este urmată întotdeauna de metoda ''onPause()''; * ''onPause()'' - apelată înainte ca activitatea să fie întreruptă temporar, iar o altă activitate să fie reluată; această metodă va fi utilizată pentru a opri servicii sau cod care nu trebuie să ruleze atâta timp cât activitatea se află în fundal (întrucât consumă timp de procesor) și pentru a salva starea diferitelor componente în vederea asigurării persistenței și a consistenței aplicației înainte și după evenimentul care a produs suspendarea sa; poate fi urmată de metoda ''onResume()'' dacă activitatea trece în prim-plan sau de metoda ''onStop()'' dacă activitatea este ascunsă; Procesările realizate în metoda ''onPause()'' nu trebuie să ocupe un interval de timp prea mare întrucât în caz contrar ar bloca noua activitate care urmează să fie lansată în execuție. Procesul în contextul căruia rulează o activitate nu poate fi distrus de sistemul de operare până ce nu s-a terminat apelul metodei ''onPause()'', aceasta fiind singura metodă care este apelată în mod garantat **înainte** de a se solicita memoria pe care activitatea o folosește. * ''onStop()'' - apelată în momentul în care activitatea este ascunsă, fie din cauză că urmează să fie distrusă, fie din cauză că o altă activitate, a cărei interfață grafică ocupă întreaga suprafață a dispozitivului de afișare, urmează să devină vizibilă; poate fi urmată de metoda ''onRestart()'', dacă activitatea urmează să interacționeze (din nou) cu utilizatorul, sau de metoda ''onDestroy()'' dacă activitatea urmează să fie terminată sau distrusă de sistemul de operare; * ''onDestroy()'' - apelată înainte ca activitatea să se termine sau să fie distrusă de către sistemul de operare (fie manual, fie automat) din lipsă de memorie; această metodă va fi utilizată pentru a elibera resursele ocupate. Distincția între cele două situații în care o activitate este distrusă poate fi realizată prin intermediul metodei ''isFinishing()''. {{ :laboratoare:laborator02:ciclul_de_viata_al_unei_activitati_2.png?nolink&700 }} 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. În cadrul unei activități, este interzisă apelarea manuală a metodelor legate de ciclul de viață, acestea fiind invocate în mod automat de sistemul de operare Android la producerea diferitelor evenimente. public class LifecycleMonitorActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... } @Override protected void onStart() { super.onStart(); // ... } @Override protected void onResume() { super.onResume(); // ... } @Override protected void onPause() { super.onPause(); // ... } @Override protected void onStop() { super.onStop(); // ... } @Override protected void onDestroy() { super.onDestroy(); // ... } @Override protected void onRestart() { super.onRestart(); // ... } // metode folosite pentru salvarea si restaurarea starii @Override protected void onSaveInstanceState(Bundle savedInstanceState) { // apelarea metodei din activitatea parinte este recomandata, dar nu obligatorie super.onSaveInstanceState(savedInstanceState); // ... } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { // apelarea metodei din activitatea parinte este recomandata, dar nu obligatorie super.onRestoreInstanceState(savedInstanceState); // ... } } ==== Gestiunea Stării unei Activități ==== Unele dintre metodele care gestionează ciclul de viață al unei activități primesc ca parametru un obiect de tip [[http://developer.android.com/reference/android/os/Bundle.html|Bundle]], utilizat pentru gestiunea stării în cazul în care activitatea este distrusă din lipsă de memorie: * ''onCreate()'' - parametrul ''savedInstance'' poate să fie ''null'', daca activitatea nu a mai fost rulată anterior, fie este o instanță a unui obiect de tip ''Bundle'' în care se găsește starea anterioară (așa cum a fost reținută de metoda ''onSaveInstanceState()''); * ''onSaveInstanceState()'' - este apelată când activitatea urmează să fie ascunsă și există posibilitatea ca procesul acesteia să fie terminat din lipsă de memorie, pentru a salva starea activității; * ''onRestoreInstanceState()'' - este apelată doar dacă există o stare a activității care ar trebui să fie restaurată. {{ :laboratoare:laborator02:gestiune_stare_activitati.png?nolink&700 }} Obiectul de tip ''Bundle'' este o formă de hash map, în care cheia este întotdeauna de tip ''String'', iar valorile au tipul ''android.os.Parcelable'' (asemănător cu ''Serializable'' din Java, deși acesta nu este un mecanism de serializare în sine). Astfel, tipurile de date care pot fi salvate și încărcate prin intermediul unui obiect de tip ''Bundle'' sunt:
| ''boolean'' | ''boolean[]'' | | | ''Bundle'' ||| | ''byte'' | ''byte[]'' | | | ''char'' | ''char[]'' | | | ''CharSequence'' | ''CharSequence[]'' | ''ArrayList'' | | ''double'' | ''double[]'' | | | ''float'' | ''float[]'' | | | ''int'' | ''int[]'' | ''ArrayList'' | | ''long'' | ''long[]'' | | | ''Serializable'' ||| | ''short'' | ''short[]'' | | | ''SparseArray'' ||| | ''String'' | ''String[]'' | ''ArrayList'' |
Starea unei activități este menținută atâta vreme cât ea este activă (deci inclusiv când au fost apelate metodele ''onPause()'' și ''onStop()''), aceasta putând fi restaurată corespunzător. Necesitatea asigurării consistenței activității de către programator apare în momentul în care activitatea este terminată/distrusă și apoi (re)pornită. O astfel de situație este frecventă în cazul în care se produce o schimbare de configurație (se modifică orientarea dispozitivului de afișare - portrait vs. landscape, limba, disponibilitatea tastaturii), întrucât de fiecare dată este necesar să se (re)încarce resursele specifice pentru valorile respective. Ținându-se cont de faptul că activitatea poate fi terminată/distrusă în orice moment după ce nu se mai găsește în prim-plan / este ascunsă, asigurarea consistenței trebuie realizată de fiecare dată. === Salvarea Stării === Metoda ''onSaveInstanceState()'' este înainte de metoda ''onStop()'' și posibil înainte de metoda ''onPause()'', deși acest lucru nu este garantat. Ea primește ca parametru un obiect de tip ''Bundle'' în care vor fi plasate datele din cadrul activității care se doresc a fi salvate, acestea putând fi identificate prin intermediul unei chei (de tip ''String''). Apelul metodei ''onSaveInstanceState()'' nu este garantat să fie realizat de fiecare dată întrucât pot fi situații în care nu este necesar ca starea activității să fie restaurată (utilizatorul a terminat activitatea prin apăsarea butonului //Back//). În cazul în care se dorește salvarea explicită a conținutului unui obiect ''EditText'', se poate proceda astfel: @Override protected void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); EditText usernameEditText = (EditText)findViewById(R.id.username_edit_text); savedInstanceState.putString(Constants.USERNAME_EDIT_TEXT, usernameEditText.getText()); } Valoarea introdusă de utilizator va fi salvată în obiectul de tip ''Bundle'' sub denumirea ''userNameEditText'', acesta fiind menținut și prin urmare utilizat între mai multe instanțe ale acestei activități. Apelarea metodei părinte este necesară întrucât API-ul Android furnizează o implementare implicită pentru salvarea stării unei activități, parcurgând ierarhia de componente grafice (obiecte de tip ''View'') care au asociat un identificator (''android:id''), folosit drept cheie în obiectul ''Bundle''. Astfel, de regulă, pentru elementele interfeței grafice, nu este necesar să se mențină starea, acest lucru fiind realizat în mod automat, cu respectarea condiției menționate. De aceea, în metoda ''onSaveInstanceState'', va fi realizată salvarea unor informații (obiecte ale clasei) pentru care procesul de salvare a stării nu este apelat. Totuși, asigurarea persistenței datelor nu se va realiza niciodată aici (întrucât nu se garantează apelarea sa), ci în metoda ''onPause()''. În obiectul de tip ''Bundle'', prin cheia ''android:viewHierarchyState'' se va reține un alt obiect de tip ''Bundle'' care reține starea tuturor obiectelor de tip ''View'' din cadrul activității (care sunt identificate prin intermediul unui câmp ''android:id''). În cadrul acestuia, prin cheia ''android:views'' se reține un obiect de tip ''SparseArray'' (un tip de dată specific Android care realizează mapări între întregi și obiecte, mai eficient decât un hashmap) care conține starea fiecărui obiect de tip ''View'' prin intermediul identificatorului său. Bundle viewHierarchy = savedInstanceState.getBundle("android:viewHierarchyState"); if (viewHierarchy != null) { SparseArray views = viewHierarchy.getSparseParcelableArray("android:views"); for (int k=0; k < views.size(); k++) { Log.d(Constants.TAG, views.get(k) + "->" + views.valueAt(k)); } } else { Log.d(Constants.TAG, "No view information was saved!"); } Prin urmare, dacă aplicația este oprită și apoi pornită din nou, obiectele de tip ''View'' vor avea conținutul existent în prealabil. Pentru a dezactiva această opțiune, trebuie specificată în fișierul .xml care descrie interfața grafică a activității, în elementul corespunzător obiectului de tip ''View'' proprietatea ''android:saveEnabled="false"''. Dezactivarea se poate realiza și programatic, folosind metoda ''setSaveEnabled(boolean)''. === Restaurarea Stării === Încărcarea conținutului din obiectul de tip ''Bundle'' (în vederea restaurării stării) poate fi realizată: - în metoda ''onCreate()''\\ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_lifecycle_monitor); EditText usernameEditText = (EditText)findViewById(R.id.username_edit_text); if ((savedInstanceState != null) && (savedInstanceState.getString(Constants.USERNAME_EDIT_TEXT) != null)) { usernameEditText.setText(bundle.getString(Constants.USERNAME_EDIT_TEXT)); } } - prin intermediul metodei ''onRestoreInstanceState()'', apelată în mod automat între metodele ''onStart()'' și ''onResume()''; această abordare permite separarea dintre codul folosit la crearea ferestrei și codul utilizat la restaurarea stării unei ferestre\\ @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(bundle); EditText usernameEditText= (EditText)findViewById(R.id.username_edit_text); if (savedInstanceState.getString(Constants.USERNAME_EDIT_TEXT) != null) { usernameEditText.setText(savedInstanceState.getString(Constants.USERNAME_EDIT_TEXT)); } } ==== Coordonarea Activităților ==== În situația în care o activitate nouă este pornită în timp ce o activitate veche este în execuție, fiind necesară transmiterea de informații dintre acestea, este util să se cunoască ordinea în care sunt apelate metodele care gestionează ciclul de viață al celor două activități, astfel încât comunicarea dintre acestea să se realizeze în mod corect: - se apelează metoda ''onPause()'' a activității vechi - aici trebuie realizată partea de scriere a informațiilor care trebuie să fie trimise; - se apelează metodele ''onCreate()'', ''onStart()'' și ''onResume()'' ale activității noi - aici trebuie realizată partea de citire a informațiilor care trebuie să fie primite; - se apelează metoda ''onStop()'' a activității vechi; - în situația în care necesarul de memorie nu este satisfăcut, este posibil să se apeleze metoda ''onDestroy()'' a activității vechi. {{ :laboratoare:laborator02:coordonare_activitati.png?nolink&400 }} ===== 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//. {{ :laboratoare:laborator02:eclipse_package_explorer.png?nolink&300 }} * biblioteca **Android 4.1.2** (Google APIs) - conține mai multe fișiere: * ''android.jar'' - cuprinde toate clasele necesare pentru aplicația Android; * ''usb.jar'' - încapsulează clase necesare instalării aplicației Android prin USB și comunicării cu dispozitivul fizic; * ''effects.jar'' - utilizată pentru aplicarea de diferite efecte; * ''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''; * **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: * ''BuildConfig.java'' - definește unele proprietăți ale aplicației (cum ar fi activarea sau nu a modului de depanare); * ''R.java'' - include identificatori către toate resursele din cadrul proiectului, prin intermediul cărora pot fi obținute referințe către acestea; conține subclasele: * ''attr'' - diferite atribute; * ''color'' - culorile utilizate ca fundal pentru diferite componente grafice afișate în cadrul activităților din cadrul aplicației; * ''dimen'' - dimensiunile dispozitivului de afișare, pentru fiecare configurație suportată de aplicație; * ''drawable'' - resurse de tip grafic, utilizate în cadrul aplicației; * ''id'' - identificatori pentru toate resursele care pot fi referite prin intermediul unui câmp de tipul ''android:id''; * ''layout'' - mecanisme de dispunere a conținutului aferente activităților (interfețelor grafice), pentru fiecare configurație suportată de aplicație; * ''menu'' - diferitele meniuri atașate activităților (interfețelor grafice) din cadrul aplicației; * ''string'' - șirurile de caractere definite în cadrul aplicației; * ''style'' - stilurile (temele) folosite în cadrul aplicației. Este interzisă modificarea fișierelor din directorul ''gen''.\\ În cazul în care fișierul ''R.java'' este șters manual, acesta va fi imediat generat de către mediul de dezvoltare, cu condiția ca proiectul să nu conțină erori (erori de sintaxă în cazul codului sursă sau documente XML care nu sunt bine formate). * **assets** - cuprinde toate activele utilizate de aplicație (fișiere text, pagini HTML, baze de date), acestea fiind necompilate; * **bin** - include fișierele construite de ADT în timpul procesului de generare, mai ales fișierul ''.apk'' (Android Package), un binar care conține toate resursele necesare pentru a rula o aplicație Android; * **libs** - cuprinde toate bibliotecile necesare pentru compilarea și rularea proiectului; * **res** - deține toate resursele folosite în cadrul aplicației * ''drawable-'': imaginile utilizate in aplicație, în funcție de rezoluție (ldpi, mdpi, hdpi, xhdpi, xxhdpi) * ''layout'': fișierul ''activity_lifecycle_monitor.xml'' care descrie modul de dispunere a elementelor grafice în cadrul interfaței cu utilizatorul, separată de codul programului (de asemenea, sunt conținute și fișierele care descriu mecanismele de dispunere pentru ferestrele care indică rezultatul operației de autentificare: ''popup_window_authentication_success.xml'' și ''popup_window_authentication_fail.xml'');\\