50% au considerat acest document util (2 voturi)
448 vizualizări43 pagini

Android Studio

Documentul prezintă noțiuni de bază despre activități în Android Studio. Sunt explicate rolul și ciclul de viață al unei activități, evenimentele onCreate și onPause, precum și gestiunea stării unei activități.

Încărcat de

PeloiuCatalin
Drepturi de autor
© © All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca DOCX, PDF, TXT sau citiți online pe Scribd
50% au considerat acest document util (2 voturi)
448 vizualizări43 pagini

Android Studio

Documentul prezintă noțiuni de bază despre activități în Android Studio. Sunt explicate rolul și ciclul de viață al unei activități, evenimentele onCreate și onPause, precum și gestiunea stării unei activități.

Încărcat de

PeloiuCatalin
Drepturi de autor
© © All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca DOCX, PDF, TXT sau citiți online pe Scribd
Sunteți pe pagina 1/ 43

1

Laborator 01 - Introducere (Git + Android Studio)


Intro Android Studio
Android Studio
Pn n luna mai a anului 2013, aplicaiile Android se puteau realiza prin intermediul mediului de dezvoltare Eclipse, mpreun cu plugin-
ul ADT (Android Development Tools) - dezvoltat de Google.

Mai apoi, Google a propus un nou IDE - Android Studio, care are acela i scop(de a permite dezvoltarea de aplica ii mobile), dar ofer mai
multe faciliti n ceea ce privete instalarea mediului de lucru, performana, code completion and refactoring la nivel avansat, etc.

Dac dorii s instalai Android Studio pe laptop-urile personale, este suficient s ave i Java Development Kit (jdk) instalat, iar apoi pute i
descrca Android Studio de pe pagina oficial .

Structura unui proiect

nainte de a testa primul program Hello World, ne vom concentra pe structura unui proiect Android. Aceast etap ne va ajuta s
nelegem rolul fiecrui director i fiier, fr de care nu am putea s dezvoltm o aplicaie Android.

Aadar, n mod implicit(modul Project), n partea din stanga a IDE-ului exist o vedere de ansamblu a ntregului proiect:
2
3

n Android Studio exist mai multe moduri de vizualizare a unui proiect, printre care i modul Android. Odat selectat aceast op iune,
Android Studio organizeaz fiierele n funcie de cele mai importante pr i ale unei aplica ii Android (fi iere java, ressources, scripturi
gradle). n funcie de nevoile i preferinele vostre, acest mod de afiare poate fi destul de practic:

Aadar:

fiierele java - sunt fiierele pe care le vei foloi probabil cel mai des, deoarece fiecare func ionalitate va fi
implementat n clasa corespunztoare
directorul res - unde sunt organizate toate resursele unei aplicaii. Aici putem gsi mai multe directoare, fiecare
coninnd n general fiere de tip .xml i imagini, precum:
4

n directorul drawable: se gsesc imagini(de tip .png, .jpg sau .gif) i/sau fiiere de tip .xml n care poate fi
definit o anumit form/culoare
n directorul layout: se gsesc fiiere .xml care definesc afiajul(interfaa grafic) i poziionarea diferitelor
elemente pe ecran.
n directorul menu: se gsesc fiiere .xml n care putem customiza meniul unei aplicaii
directorul mimap : este rezervat diferitelor iconie folosite ntr-o aplicaie. Dat fiind faptul c dispozitivele Android
sunt de diferite tipuri i mrimi, o imagine nu se poate adapta tuturor ecranelor existente, de aceea dimensiunile
acesteia trebuie s varieze.
values: n fiierele .xml din acest director se pot gsi/personaliza diferite elemente ale aplica iei. De exemplu,
putei defini un text(strings.xml), o anumit culoare(colors.xml), care s fie mai apoi folosite oriunde n cod. n
acest fel, dac avei nevoie s facei o modificare al unuia dintre aceste elemente, o vei face o singur dat.
gradle scripts: verific faptul c toate elementele necesare proiectului sunt disponibile; asigur asamblarea tuturor
dependenelor necesare.
Android Manifest

Pe lnge aceste fiiere i directoare (prezentate mai sus), la rdcina fiecrui proiect exist un fi ier numit AndroidManifest.xml. Acest
fiier conine detalii eseniale despre aplicaie, cum ar fi permisiunile i versiunea acesteia.

Mai multe informaii despre AndroidManifest.xml gsii aici.

Prima aplicaie - Hello, World!


Deschidei Android Studio. Din meniul de sus, alegei opiunea de creare a unui nou proiect android: File > New > New
Project

n mod normal ar trebui s se afieze urmtoarea ferestr:


5

n etapa urmtoare vom face cteva setri simple. n fereastra de mai sus, introducei numele aplicaiei, HelloWorld.
Cmpul Company Domain identific n mod unic aplicaia. Astfel, dou aplicaii pot avea acela i nume, dar se vor diferen ia prin
domeniul companiei(dac exist), scris invers. n mod implicit, acest cmp este completat automat cu un domeniu fictiv.
6

Next!

Fereastra de mai sus simplific alegerea versiunii de Android - aceasta poate fi schimbat mai apoi n fi ierul build.gradle. Pentru
moment, nu vom modifica nimic aici. Next!
7

Pentru a ne uura munca, Android Studio propune diferite schelete de aplica ie. Pentru aplica ia noastr, HelloWorld, vom
alege BlankActivity.
8

Vom afla mai multe despre ce este o activitate( Activity) n cursul/laboratorul urmtor. Pentru moment, putem considera c o activitate
este asociat ecranului aplicaiei.

n fereastra urmtoare, putem s customizm felul n care vom numi fiierele .xml asocitae activitii noastre:

Activity name - clasa java corespunztoare activitii


Layout name - fiierul .xml ce corsepunde layout-ului activitii(interfaa grafic)
Title - textul afiat n bara de sus a plicaiei(ActionBar)
Menu Ressource name - fiierul .xml corespunztor meniului aplicaiei

Finish!
9

1. nainte de a testa aplicaia pe dispozitivul mobil(sau pe simulator), explorai proiectul(n special fi ierele din
directorul res)
2. Schimbai modul de afiare al proiectului(Project, Android, etc.) i observai diferitele tipuri de afiaj.

Lansarea pe dispozitivul mobil


nainte de a testa aplicaa, asigurai-v c dispozitivul Android este conectat i c a i activat modul Developper, din setrile
dispozitivului.

Pentru a lansa aplicaia pe dispozitivul Android, tastai Shift+ f10 (sau click pe butonul Run). Ar trebui s se afieze urmtoarea
fereastr:
10

Observai c Android Studio detecteaz automat dispozitivul mobil. Dac nu dispune i de unul, pute i alege varianta
simulatorului(Launch Emulator).

Rezultat:
11

For fun

1. Testai simulatorul Android


12

2. n res/values/colors.xml, definii o nou culoare, #c116ff, i folosii-o pentru a schimba culoarea


fiierul
textului Hello, world!, afiat pe ecran.
Hints:
TextView, ntr-unul din fiierele .xml aflate n res/layout)
Textul este definit ntr-o etichet de tip
Pentru a accesa noua culoare definit n colors.xml, folosii sintaxa:

android:textColor="@color/$numeCuloare"

Laborator 02 - Activiti
Activiti
In sistemul Android ferestrele se numesc activitati. Din punct de vedere al programarii, acestea sunt clase care extind clasa Activity. Spre
deosebire de alte sisteme in care un program contine mai multe ferestre afisate simultan, in Android, ecranul este mereu ocupat de o
singura fereastra. Mai mult, ferestrele sunt conectate prin simplul fapt ca o fereastra da nastere mai multor ferestre. Fereastra care apare
pe ecran in momentul in care aplicatia este pornita este considerata fereastra principala, din ea pornind toate celelalte. Pentru a crea o
activitate, vom crea o clasa ce extinde clasa Activity. La pornire, programul o va genera, iar noi putem interactiona cu fereastra prin
evenimente. Unele dintre cele mai importante evenimente sunt: onCreate si onPause.
public class MainActivity extends Activity
{

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onPause()
{
// TODO Auto-generated method stub
super.onPause();
}
13

Nu uitati sa apelati functia parintelui (in exemplul nostru Activity) in interiorul evenimentelor!

onCreate
Evenimentul este apelat in momentul in care se creaza activitate. Aici vom initializa compentele ferestrei. Pentru a face elementele de pe
fereastra vizibile, este necesar sa apelam functia setContentView. Exista cazuri in care la pornirea eplicatiei, aceasta trebuie sa revina la
o stare anterioara (ex: dupa o oprire fortata). Astfel, este recomandat ca in acest aveniment sa se verifice daca fereastra este una noua
sau nu, adica daca variabila de tip Bundle pasata ca parametru este nula sau nu.
if (savedInstanceState!=null)
{
//fereastra nu e noua si trebuie incarcate anumite date ramase
}
else
{
//fereastra e noua
}

onPause
Cand acest eveniment este apelat, fereastra se pregateste pentru oprire. De aceea este important sa salvam toate schimbarile de care
avem nevoie. Aici vom opri procesele care nu mai sunt necesare cand aplicatia nu ruleaza, cum ar fi elementele video sau audio.

Gestiunea Starii unei Activitati


Unele dintre metodele care gestioneaz ciclul de via al unei activit i primesc ca parametru un obiect de tip Bundle, utilizat pentru
gestiunea strii 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 gsete starea anterioar (aa cum a fost reinut de metoda onSaveInstanceState());
onSaveInstanceState() - este apelat cnd activitatea urmeaz s fie ascuns i exist posibilitatea ca procesul acesteia s
fie terminat din lips de memorie, pentru a salva starea activitii;
14

onRestoreInstanceState() - este apelat doar dac exist o stare a activit ii care ar trebui s fie restaurat.

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
(asemntor cu Serializable din Java, dei acesta nu este un mecanism de serializare n sine).

Starea unei activiti este meninut atta vreme ct ea este activ (deci inclusiv cnd au fost apelate metodele onPause() i onStop()),
aceasta putnd fi restaurat corespunztor. Necesitatea asigurrii consistenei activit ii de ctre 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
configuraie (se modific orientarea dispozitivului de afiare - portrait vs. landscape, limba, disponibilitatea tastaturii), ntruct de fiecare
dat este necesar s se (re)ncarce resursele specifice pentru valorile respective.

inndu-se cont de faptul c activitatea poate fi terminat/distrus n orice moment dup ce nu se mai gse te n prim-plan / este
ascuns, asigurarea consistenei trebuie realizat de fiecare dat.
15

Salvarea Strii
Metoda onSaveInstanceState() este nainte de metoda onStop() i posibil nainte de metoda onPause(), de i acest lucru nu este garantat.
Ea primete ca parametru un obiect de tip Bundle n care vor fi plasate datele din cadrul activit ii care se doresc a fi salvate, acestea
putnd fi identificate prin intermediul unei chei (de tip String).

Apelul metodei onSaveInstanceState() nu este garantat s fie realizat de fiecare dat ntruct pot fi situa ii n care nu este necesar ca
starea activitii s fie restaurat (utilizatorul a terminat activitatea prin apsarea butonului Back).

n cazul n care se dorete salvarea explicit a coninutului unui obiect EditText, se poate proceda astfel:
@Override

protected void onSaveInstanceState(Bundle savedInstanceState) {


super.onSaveInstanceState(savedInstanceState);
EditText myEditText = (EditText)findViewById(R.id.my_edit_text);
savedInstanceState.putString("myEditText", myEditText.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 instane ale acestei activiti.

Apelarea metodei printe este necesar ntruct API-ul Android furnizeaz o implementare implicit pentru salvarea strii unei activit i,
parcurgnd 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 condiiei menionate. De aceea, n metoda onSaveInstanceState, va fi realizat salvarea unor informa ii
(obiecte ale clasei) pentru care procesul de salvare a strii nu este apelat. Totu i, asigurarea persisten ei datelor nu se va realiza
niciodat aici (ntruct 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 activitii (care sunt identificate prin intermediul unui cmp android:id). n cadrul acestuia, prin cheia
android:views se reine un obiect de tip SparseArray (un tip de dat specific Android care realizeaz mapri ntre ntregi i obiecte, mai
eficient dect un hashmap) care conine starea fiecrui obiect de tip View prin intermediul identificatorului su.

Bundle viewHierarchy = savedInstanceState.getBundle("android:viewHierarchyState");


if (viewHierarchy != null) {
SparseArray<? extends Parcelable> views = viewHierarchy.getSparseParcelableArray("android:views");
for (int k=0; k < views.size(); k++) {
Log.d("BundleTAG", views.get(k) + "->" + views.valueAt(k));
}
16

}
else {
Log.d("BundleTAG", "No view information was saved!");
}

Prin urmare, dac aplicaia este oprit i apoi pornit din nou, obiectele de tip View vor avea con inutul existent n prealabil. Pentru a
dezactiva aceast opiune, trebuie specificat n fiierul .xml care descrie interfa a grafic a activit ii, n elementul corespunztor
obiectului de tip View proprietatea android:saveEnabled=false.

Dezactivarea se poate realiza i programatic, folosind metoda setSaveEnabled(boolean).

Restaurarea Strii
ncrcarea coninutului din obiectul de tip Bundle (n vederea restaurrii strii) poate fi realizat:

1. n metoda onCreate()

2. @Override

3. protected void onCreate(Bundle savedInstanceState) {

4. super.onCreate(savedInstanceState);

5. setContentView(R.layout.activity_lifecycle_monitor);

6. EditText usernameEditText = (EditText)findViewById(R.id.my_edit_text);

7. if ((savedInstanceState != null) && (savedInstanceState.getString("myEditText") != null)) {

8. usernameEditText.setText(savedInstanceState.getString("myEditText"));

9. }

10. 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 strii unei
ferestre
17

11. @Override

12. protected void onRestoreInstanceState(Bundle savedInstanceState) {

13. super.onRestoreInstanceState(savedInstanceState);

14. EditText usernameEditText= (EditText)findViewById(R.id.my_edit_text);

15. if (savedInstanceState.getString("myEditText") != null) {

16. usernameEditText.setText(savedInstanceState.getString(Constants.MY_EDIT_TEXT));

17. }

Transmisia datelor intre activitati


De cele mai multe ori, la trecerea intre activitati vom vrea sa si pasam informatie. Desi metodele sunt numeroase, pentru moment va
vom arata pasarea de variabile prin Intentii
In activitatea din care se initiaza transferul trebuie definit un intent. In cadrul acestuia putem adauga variabila dorita prin metoda
putExtra. Aceasta poate aproape toate tipurile de baza, dar si obiecte custom, atata timp cat acestea extind Parcelable sau Serializable.

public class MainActivity extends AppCompatActivity {


@Override
protected void onCreate(Bundle savedInstanceState) { ... }

@Override
public boolean onCreateOptionsMenu(Menu menu) { ... }

@Override
public boolean onOptionsItemSelected(MenuItem item) { ... }

public void onCenterButtonClick(View view) {


EditText inputName = (EditText) findViewById(R.id.editText);
Intent intent = new Intent(getApplicationContext(), HelloActivity.class);
intent.putExtra("Nume", inputName.getText().toString());
startActivity(intent);
}
}
18

In noua activitate, extragem datele trimise prin intent astfel:

public class HelloActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello);
TextView helloText = (TextView) findViewById(R.id.textView);

Bundle extras = getIntent().getExtras();


if (extras != null) {
String nume = extras.getString("Nume");

if (nume != null && nume.length() > 0) {


helloText.setText("Hello, " + nume);
} else {
helloText.setText("Hello there!");
}
} else {
helloText.setText("Hello there!");
}
}
}

Depanare
Depanarea este foarte importanta in procesul de realizare a aplicatiilor pentru dispozitive mobile. Acest proces este insa putin diferit fata
de depanarea programelor clasice pentru calculator, in primul rand pentru ca ruleaza pe alt dispozitiv. Tocmai din acest motiv, avem
nevoie de programe spcializate pentru a realiza depanarea. De asemenea, fiind vorba de dispozitive mobile, apar si anumite evenimente
specifice, cum ar fi apeluri telefonice, descarcarea bateriei etc., evenimente ce trebuie tratate intr-un fel sau altul. In laboratorul de astazi
vom prezenta programele de depanare existente si modul lor de functionare. De asemenea, ne vom ocupa putin de studierea
evenimentelor ferestrelor.

Logcat - debugging monitor pentru Android. Apeland Log.d(TAG, Text) putem afisa orice informatie ne putem dori. De
asemenea, Log poate avea mai multe prioritati, acestea determinand nivelul de importanta al mesajului si ajutand la
filtrarea mai usoara (In mesajele din logcat apar atat cele de la aplicatia in curs de rulare cat si alte mesaje de log ale
sistemului de operare si ale altor aplicatii care ruleaza in background).
19

exemplu de utilizare a unui Log:


rezultat (ultima linie):
2. DDMS - utilitarul pentru depanarea aplicatiilor pentru Android se numeste DDMS (Dalvik Debug Monitor System). Acesta
foloseste de fapt un alt utilitar, numit ADB (Android Debug Bridge), pentru a se conecta la simulatoare sau dispozitive fizice.
Cu ajutorul DDMS putem vizualiza parametrii dispozitivului si a programelor ce ruleaza pe acesta.
pentru a rula pana la linia cu pricina, mai intai setam un breakpoint (click in stanga liniei):
20

apoi putem rula in debug mode: }


dupa care putem observa valoarea din variabila noastra: Laborator 02 - Activiti
Activiti
In sistemul Android ferestrele se numesc activitati. Din punct de vedere al programarii, acestea sunt clase care extind clasa
Activity. Spre deosebire de alte sisteme in care un program contine mai multe ferestre afisate simultan, in Android,
ecranul este mereu ocupat de o singura fereastra. Mai mult, ferestrele sunt conectate prin simplul fapt ca o fereastra da
nastere mai multor ferestre. Fereastra care apare pe ecran in momentul in care aplicatia este pornita este considerata
fereastra principala, din ea pornind toate celelalte. Pentru a crea o activitate, vom crea o clasa ce extinde clasa Activity. La
pornire, programul o va genera, iar noi putem interactiona cu fereastra prin evenimente. Unele dintre cele mai importante
evenimente sunt: onCreate si onPause.
public class MainActivity extends Activity
{

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onPause()
{
// TODO Auto-generated method stub
21

super.onPause();
}
}
Nu uitati sa apelati functia parintelui (in exemplul nostru Activity) in interiorul evenimentelor!
onCreate
Evenimentul este apelat in momentul in care se creaza activitate. Aici vom initializa compentele ferestrei. Pentru a face
elementele de pe fereastra vizibile, este necesar sa apelam functia setContentView. Exista cazuri in care la pornirea
eplicatiei, aceasta trebuie sa revina la o stare anterioara (ex: dupa o oprire fortata). Astfel, este recomandat ca in acest
aveniment sa se verifice daca fereastra este una noua sau nu, adica daca variabila de tip Bundle pasata ca parametru este
nula sau nu.
if (savedInstanceState!=null)
{
//fereastra nu e noua si trebuie incarcate anumite date ramase
}
else
{
//fereastra e noua
}
onPause
Cand acest eveniment este apelat, fereastra se pregateste pentru oprire. De aceea este important sa salvam toate
schimbarile de care avem nevoie. Aici vom opri procesele care nu mai sunt necesare cand aplicatia nu ruleaza, cum ar fi
elementele video sau audio.
Gestiunea Starii unei Activitati
Unele dintre metodele care gestioneaz ciclul de via al unei activit i primesc ca parametru un obiect de tip Bundle,
utilizat pentru gestiunea strii n cazul n care activitatea este distrus din lips de memorie:
22

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 gsete starea anterioar (aa cum a fost reinut de metoda onSaveInstanceState());
onSaveInstanceState() - este apelat cnd activitatea urmeaz s fie ascuns i exist posibilitatea ca procesul acesteia s
fie terminat din lips de memorie, pentru a salva starea activitii;
onRestoreInstanceState() - este apelat doar dac exist o stare a activit ii care ar trebui s fie restaurat.

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 (asemntor cu Serializable din Java, dei acesta nu este un mecanism de serializare n sine).
Starea unei activiti este meninut atta vreme ct ea este activ (deci inclusiv cnd au fost apelate metodele onPause()
i onStop()), aceasta putnd fi restaurat corespunztor. Necesitatea asigurrii consisten ei activit ii de ctre
programator apare n momentul n care activitatea este terminat/distrus i apoi (re)pornit. O astfel de situa ie este
23

frecvent n cazul n care se produce o schimbare de configuraie (se modific orientarea dispozitivului de afi are - portrait
vs. landscape, limba, disponibilitatea tastaturii), ntruct de fiecare dat este necesar s se (re)ncarce resursele specifice
pentru valorile respective.
inndu-se cont de faptul c activitatea poate fi terminat/distrus n orice moment dup ce nu se mai gse te n prim-
plan / este ascuns, asigurarea consistenei trebuie realizat de fiecare dat.
Salvarea Strii
Metoda onSaveInstanceState() este nainte de metoda onStop() i posibil nainte de metoda onPause(), de i acest lucru nu
este garantat. Ea primete ca parametru un obiect de tip Bundle n care vor fi plasate datele din cadrul activit ii care se
doresc a fi salvate, acestea putnd fi identificate prin intermediul unei chei (de tip String).
Apelul metodei onSaveInstanceState() nu este garantat s fie realizat de fiecare dat ntruct pot fi situa ii n care nu este
necesar ca starea activitii s fie restaurat (utilizatorul a terminat activitatea prin apsarea butonului Back).
n cazul n care se dorete salvarea explicit a coninutului unui obiect EditText, se poate proceda astfel:
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
EditText myEditText = (EditText)findViewById(R.id.my_edit_text);
savedInstanceState.putString("myEditText", myEditText.getText());
}
Valoarea introdus de utilizator va fi salvat n obiectul de tip Bundle sub denumirea userNameEditText, acesta fiind
meninut i prin urmare utilizat ntre mai multe instane ale acestei activiti.
Apelarea metodei printe este necesar ntruct API-ul Android furnizeaz o implementare implicit pentru salvarea strii
unei activiti, parcurgnd 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 menin starea, acest lucru fiind realizat n mod automat, cu respectarea condi iei men ionate. De aceea, n metoda
onSaveInstanceState, va fi realizat salvarea unor informaii (obiecte ale clasei) pentru care procesul de salvare a strii nu
24

este apelat. Totui, asigurarea persistenei datelor nu se va realiza niciodat aici (ntruct 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 activitii (care sunt identificate prin intermediul unui cmp android:id). n cadrul
acestuia, prin cheia android:views se reine un obiect de tip SparseArray (un tip de dat specific Android care realizeaz
mapri ntre ntregi i obiecte, mai eficient dect un hashmap) care con ine starea fiecrui obiect de tip View prin
intermediul identificatorului su.
Bundle viewHierarchy = savedInstanceState.getBundle("android:viewHierarchyState");
if (viewHierarchy != null) {
SparseArray<? extends Parcelable> views = viewHierarchy.getSparseParcelableArray("android:views");
for (int k=0; k < views.size(); k++) {
Log.d("BundleTAG", views.get(k) + "->" + views.valueAt(k));
}
}
else {
Log.d("BundleTAG", "No view information was saved!");
}
Prin urmare, dac aplicaia este oprit i apoi pornit din nou, obiectele de tip View vor avea con inutul existent n
prealabil. Pentru a dezactiva aceast opiune, trebuie specificat n fiierul .xml care descrie interfa a grafic a activit ii,
n elementul corespunztor obiectului de tip View proprietatea android:saveEnabled=false.
Dezactivarea se poate realiza i programatic, folosind metoda setSaveEnabled(boolean).
Restaurarea Strii
ncrcarea coninutului din obiectul de tip Bundle (n vederea restaurrii strii) poate fi realizat:
n metoda onCreate()
@Override
25

protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_monitor);
EditText usernameEditText = (EditText)findViewById(R.id.my_edit_text);
if ((savedInstanceState != null) && (savedInstanceState.getString("myEditText") != null)) {
usernameEditText.setText(savedInstanceState.getString("myEditText"));
}
}
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 strii unei
ferestre
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
EditText usernameEditText= (EditText)findViewById(R.id.my_edit_text);
if (savedInstanceState.getString("myEditText") != null) {
usernameEditText.setText(savedInstanceState.getString(Constants.MY_EDIT_TEXT));
}
}
Transmisia datelor intre activitati
De cele mai multe ori, la trecerea intre activitati vom vrea sa si pasam informatie. Desi metodele sunt numeroase, pentru
moment va vom arata pasarea de variabile prin Intentii
In activitatea din care se initiaza transferul trebuie definit un intent. In cadrul acestuia putem adauga variabila dorita prin
metoda putExtra. Aceasta poate aproape toate tipurile de baza, dar si obiecte custom, atata timp cat acestea extind
Parcelable sau Serializable.
26

public class MainActivity extends AppCompatActivity {


@Override
protected void onCreate(Bundle savedInstanceState) { ... }

@Override
public boolean onCreateOptionsMenu(Menu menu) { ... }

@Override
public boolean onOptionsItemSelected(MenuItem item) { ... }

public void onCenterButtonClick(View view) {


EditText inputName = (EditText) findViewById(R.id.editText);
Intent intent = new Intent(getApplicationContext(), HelloActivity.class);
intent.putExtra("Nume", inputName.getText().toString());
startActivity(intent);
}
}
In noua activitate, extragem datele trimise prin intent astfel:
public class HelloActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello);
TextView helloText = (TextView) findViewById(R.id.textView);
27

Bundle extras = getIntent().getExtras();


if (extras != null) {
String nume = extras.getString("Nume");

if (nume != null && nume.length() > 0) {


helloText.setText("Hello, " + nume);
} else {
helloText.setText("Hello there!");
}
} else {
helloText.setText("Hello there!");
}
}
}
Depanare
Depanarea este foarte importanta in procesul de realizare a aplicatiilor pentru dispozitive mobile. Acest proces este insa
putin diferit fata de depanarea programelor clasice pentru calculator, in primul rand pentru ca ruleaza pe alt dispozitiv.
Tocmai din acest motiv, avem nevoie de programe spcializate pentru a realiza depanarea. De asemenea, fiind vorba de
dispozitive mobile, apar si anumite evenimente specifice, cum ar fi apeluri telefonice, descarcarea bateriei etc.,
evenimente ce trebuie tratate intr-un fel sau altul. In laboratorul de astazi vom prezenta programele de depanare
existente si modul lor de functionare. De asemenea, ne vom ocupa putin de studierea evenimentelor ferestrelor.
Logcat - debugging monitor pentru Android. Apeland Log.d(TAG, Text) putem afisa orice informatie ne putem dori. De
asemenea, Log poate avea mai multe prioritati, acestea determinand nivelul de importanta al mesajului si ajutand la
28

filtrarea mai usoara (In mesajele din logcat apar atat cele de la aplicatia in curs de rulare cat si alte mesaje de log ale
sistemului de operare si ale altor aplicatii care ruleaza in background).

exemplu de utilizare a unui Log:


rezultat (ultima linie):
DDMS - utilitarul pentru depanarea aplicatiilor pentru Android se numeste DDMS (Dalvik Debug Monitor System). Acesta
foloseste de fapt un alt utilitar, numit ADB (Android Debug Bridge), pentru a se conecta la simulatoare sau dispozitive

fizice. Cu ajutorul DDMS putem vizualiza parametrii dispozitivului si a programelor ce ruleaza pe acesta.
pentru a rula pana la linia cu pricina, mai intai setam un breakpoint (click in stanga liniei):
29

apoi putem rula in debug mode: }


dupa care putem observa valoarea din variabila noastra:
de asemenea putem adauga si in watch expresii mai complicate (try it out)
Exercitii

Realizati o activitate careia ii suprascrieti urmatoarele functii de eveniment. Afisati cate un mesaj de log in fiecare dintre
aceste functii. Pentru a putea citi mai usor mesajele de log afisate de catre programul vostru, o sa creati un filtru de log
dupa tag-ul eveniment.
Log.d("AWESOME_TAG", "??? method was invoked");
onCreate
onRestart
onStart
onResume
30

onPause
onStop
onDestroy
Sa se modifice mesajul din metoda onCreate(), astfel incat sa se indice daca activitatea a mai fost lansata in executie
anterior sau nu (daca exista o stare a activitatii care trebuie restaurata).
Observati ce se intampla cu evenimentele ferestrelor cand:
Primiti un apel telefonic (Hint: utilizati Emulator Control din DDMS)
Se apasa butonul Home
Se tine mult apasat butonul Home
Se apasa butonul de raspundere la convorbire
Se apasa butonul de inchidere al ecranului (este butonul de inchidere a convorbrii)
Adaugati pe fereastra un EditText si un CheckBox. Observati ce se intampla in cazurile de mai sus.
Dezactivati optiunea de salvare a starii, dupa care repetati pasii din exercitiul anterior.
Salvati starea EditBox-ului si a CheckBox-ului in functia de salvare a starii (hint: utilizati putString si putBoolean), fara a
modifica functia onCreate si/sau onRestoreInstanceState, observati ce se intampla in cazurile de mai sus.
BONUS (pentru 10000p) Creati un Empty activity. In MainActivity (in content_main.xml mai exact) creati un EditText in
care sa faceti input pentru nume, urmat de un Buton. Nu va chinuiti sa-l faceti sa arate bine sau ceva, importanta e
functionalitatea. Adaugati logica butonului astfel incat sa permita navigarea la activitatea noua, transmitand numele din
EditText si afisand textul Hello, + numele transmis. (exemplu de sursa puteti gasi aici: myapplication.zip)
31


de asemenea putem adauga si in watch expresii mai complicate (try it out)
Exercitii

1. Realizati o activitate careia ii suprascrieti urmatoarele functii de eveniment. Afisati cate un mesaj de log in fiecare dintre
aceste functii. Pentru a putea citi mai usor mesajele de log afisate de catre programul vostru, o sa creati un filtru de log dupa
tag-ul eveniment.

Log.d("AWESOME_TAG", "??? method was invoked");

onCreate
32

onRestart
onStart
onResume
onPause
onStop
onDestroy
2. Sa se modifice mesajul din metoda onCreate(), astfel incat sa se indice daca activitatea a mai fost lansata in executie anterior
sau nu (daca exista o stare a activitatii care trebuie restaurata).
3. Observati ce se intampla cu evenimentele ferestrelor cand:
Primiti un apel telefonic (Hint: utilizati Emulator Control din DDMS)
Se apasa butonul Home
Se tine mult apasat butonul Home
Se apasa butonul de raspundere la convorbire
Se apasa butonul de inchidere al ecranului (este butonul de inchidere a convorbrii)
4. Adaugati pe fereastra un EditText si un CheckBox. Observati ce se intampla in cazurile de mai sus.
5. Dezactivati optiunea de salvare a starii, dupa care repetati pasii din exercitiul anterior.
6. Salvati starea EditBox-ului si a CheckBox-ului in functia de salvare a starii (hint: utilizati putString si putBoolean), fara a
modifica functia onCreate si/sau onRestoreInstanceState, observati ce se intampla in cazurile de mai sus.
7. BONUS (pentru 10000p) Creati un Empty activity. In MainActivity (in content_main.xml mai exact) creati un EditText in care
sa faceti input pentru nume, urmat de un Buton. Nu va chinuiti sa-l faceti sa arate bine sau ceva, importanta e
functionalitatea. Adaugati logica butonului astfel incat sa permita navigarea la activitatea noua, transmitand numele din
EditText si afisand textul Hello, + numele transmis. (exemplu de sursa puteti gasi aici: myapplication.zip)
33

Laborator 03 - Interfee grafice


Interfata grafica -XML
Unul dintre cele mai importante elemente ale unei aplicatii il reprezinta interfata grafica. Pentru a putea diferentia interfata grafica de
scrierea codului aplicatiei, cele doua se afla in fisiere diferite. De asemenea, design-ul interfetei este facut intr-un alt limbaj, unul
descriptiv. Acesta seamana cu limbajul HTML, fiind alcatuit din marcaje.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world"
tools:context=".MainActivity" />

</RelativeLayout>

Pentru fiecare element de pe fereastra exista un marcaj. Numele marcajului este acelasi cu numele clasei din partea de cod. Elementele
au anumite caracteristici: pozitionarea, dimensiunile, culoarea, textul de pe ele. Pentru setarea fiecarei proprietati se scrie un parametru
in acest mod:

android:proprietate="valoare"

Un buton rosu cu textul Buton nou pe el, va fi declarat astfel:

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="Buton nou"
/>
34

Observam ca proprietatile layout_width si layout_height au valoarea wrap_content. Luand aceasta valoarea, butonul va avea cele mai
mici dimensiuni posibile. Putem inlocui wrap_content cu fill_parent si vom observa ca butonul va acoperi toata fereastra. Dimensiunile
pot, de asemenea, sa fie absolute, in pixeli. Culoarea butonului poate fi scrisa in format RGB sau aRGB (a reprezinta transparenta).

Layout
Pentru ca pe o fereastra putem avea un singur view, exista view-uri speciale care au rolul de a aranja continutul. Aceste view-uri se
numesc layout-uri si se comporta ca niste containere care aranjeaza elementele din interiorul lor dupa o anumita regula. Exista mai multe
tipuri de layout-uri:

LinearLayout
RelativeLayout
GridLayout
LinearLayout
LinearLayout este un container care aliniaza toate elementele pe care le contine fie vertical, fie orizontal. Selectarea orientarii se face prin
atributul android:orientation. Pentru a face ca cele doua butoane create anterior sa nu se suprapuna putem folosi un layout linear.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="Buton nou"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="Buton "
/>

</LinearLayout>
35

Setarea evenimentelor pe elementele grafice


Pana acum am editat fereastra aplicatiei, dar aceasta nu este functionala. Pentru a putea utiliza butoanele create, trebuie sa le legam de
actiunea pe care dorim sa o execute. Acest lucru se realizeaza prin intermediul unei alte proprietati:

android:onClick="metodaExecutata"

Daca dorim sa executam o actiune la un alt eveniment si nu la apasarea butonului, vom selecta o alta variabila in loc de onClick.

Accesarea elementelor grafice din Java


Widget-urile pot fi modificate si din codul Java, nu doar fisierul XML, deoarece apropate toate proprietatile din XML au o functie
echivalenta in JAVA. Apelam la aceasta optiune cand dorim ca la apelarea unui anumit eveniment, un element al ferestrei sa se modifice.
Pentru a realiza acest lucru, trebuie sa cream o legatura intre elementul din XML si partea de cod. In primul rand, pe langa propietatile
deja setate, ale elementului, vom mai adauga una:id.

android:id="@+id/idElement"

Dupa ce elementul poate fi identificat prin id, il putem lega de codul Java.

Button buton=findViewById(R.id.buton1);

Exercitii
1. Pentru urmatoarele exercitii vom avea nevoie de acest proiect. Descarcati-l si asigurati-va ca aveti toate dependintele
necesare pentru a-l rula.
2. In cadrul acestui laborator vom incerca sa dezvoltam o aplicatie care sa aiba cateva din feature-urile unui Dialer. Vom folosi
drept model urmatorul mockup. Pentru acest task, elaborati o structura de views layouturi / ( LinearLayout sau RelativeLayout
) care sa respecte modelul propus. Activitatea prezentata contine:
Un grup de View-uri care simuleaza o tastatura numerica [ 50% din inaltimea totala]
36

Un TextView care sa primeasca input din partea tastaturii [ 10% din inaltimea totala]
O lista de numere care au fost apelate. Lista poate fi scrollata [ 40% din inaltimea totala]
3. Implementati tastatura in fisierul xml dedicat MainActivity. Pentru moment, tastele nu vor prezenta nici o functionalitate.
Hint:
Pentru a implementa delimitatorul dintre coloane am folosit un astfel de view:

<View

android:layout_width="1dp"

android:layout_height="match_parent"

android:background="#ff050505"/>

1. Adaugati TextView-ul care va contine numarul format de utilizator.


2. Implementati functionalitea tastelor de a adauga / sterge din viewul de la taskul anterior.
3. La apasarea buttonului Call se va face o noua inregistrare in lista de apeluri. Inregistrarea va contine numarul apelat.
4. BONUS Un apel va fi inregistrat numai daca numarul continut de TextView este valid (numar cifre > 0), altfel se va afisa un
Toast cu un mesaj de eroare. Pe langa numar, inregistrarea va mai contine si ora exact a apelului.

Laborator 04 - Fragmente
n laboratoarele precedente ai nvat despre activiti, cum funcioneaz acestea, i cum le putem conecta ntre ele. Astzi vom lucra cu
Fragmente. n Android, un Fragment este o clas ce reprezint o component independent ce se execut n contextul unei activit i.

De ce folosim fragmente? Fragmentele au fost introduse ncepnd cu Android 3.0 (API level 11), iar scopul lor este de a facilita crearea
de interefee ce se pot adapta diferitelor tipuri de ecrane.
37

Mai pe scurt, un fragment poate fi vzut ca o poriune de interfa ce poate fi refolosit n cadrul mai multor activit i sau pentru o
poziionare diferit a aceleiai interfee - dac folosim alte tipuri de ecrane (exemplu n figura de mai jos).

Ciclul de via al unui fragment


Dei se execut n cadrul contextului unei activiti, fragmentele au propriul lor ciclu de via , propriile evenimente i pot fi adugate sau
terse, chiar dac activitatea de care aparine este n curs de execu ie. Ciclul de via al fragmentului este dependent de cel al activit ii
sale. De aceea, dac o activitate apeleaz onPause(), atunci toate fragmentele sale vor avea aceast stare.
38
39

Metoda onCreate() este apelat dup apelul onCreate() al activitii.


Metoda onCreateView() este apelat atunci cnd fragmentul trebuie s creeze interfaa grafic.
Metoda onActivityCreated() este apelat dup metoda onCreateView(), atunci cnd activitatea a fost creat.
Metoda onStart() este apelat odat ce fragmentul devine vizibil.
Atenie: Fragmentele nu motenesc clasa Context. Pentru a avea acces la activitatea gazd, trebuie s folosii metoda getActivity()

Crearea unui fragment


Pentru a scrie un fragment, trebuie s creai o clas care s mo teneasc clasa Fragment. A a cum a i vzut n laboratorul despre
activiti, putei suprascrie diverse metode (descrise mai sus) care pot modifica un fragment de-a lungul ciclului su de via.

public class MyFirstFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.my_first_fragment, container, false);
}
}

n exemplul de mai sus am creat o clas de tip Fragment, n care putem observa c am suprascris metoda onCreateView(). A a cum am
spus mai sus, aceast metod este folosit pentru a crea componentele interfeei(din fiierul .xml) corespunztoare fragmentului.

Parametrii acestei metode sunt urmtorii:

inflater : ncrcarea layout-ului (fiierul .xml) ;


container : dac este non null, corespunde unui view printe unde ar trebui integrat interfaa fragmentului
savedInstanceState : dac este non-null, fragmentul este reconstruit pe baza unei stri salvate anterior, transmis prin
acest parametru.
Fragmentele sunt de dou tipuri: statice(definite o singur dat n fiierul layout - nu pot fi suprimate sau inlocuite) i dinamice. n acest
laborator nu vom intra n detalii n ceea ce privete fragmentele statice, ns este important s ti i de existena lor.

Exerciii(simple)
40

n urmtorul exerciiu vom nva cum putem manipula fragmentele ntr-o activitate. Pentru aceasta vom lucra cu tab-uri. Scopul acestui
exerciiu este s putem naviga de la un tab la altul, utiliznd fragmente.

Pentru nceput, descrcai scheletul de cod urmtor: labFragmente.zip


E1. Importai acest proiect n AndroidStudio.
E2. n proiectul creat, exist 2 clase (de tip Fragment) : Fragment1.java i Fragment2.java
E3. Customizai cele 2 fiiere .xml (corespunztoare interfeei fiecrui fragment), ca n exemplul de mai jos :
fragment1.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="#FFFF66"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/textFragment1"
android:textSize="40dp" />
</RelativeLayout>

fragment2.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="#FF4081"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/textFragment2"
android:textSize="40dp"
/>

</RelativeLayout>

E4. Adugai apoi componentele corespunzatoare fiierului asociat interfeei activitatii principale:
41

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

<android.support.design.widget.TabLayout
android:id="@+id/layout_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@id/layout_tab"/>

</android.support.design.widget.CoordinatorLayout>

Acest layout conine urmtoarele elemente:

Android toolbar widget: inlocuieste fostul actionbar


TabLayout widget: folosit pentru redarea diferitelor opiuni(tab-uri)
42

ViewPager: folosit pentru a face swipe ntre tab-uri


E5. n fiecare fragment: suprascriei metoda onCreateView(). ncrcai fiierele .xml corespunztoare.
E6. Este timpul s adugm cele dou tab-uri n activitatea principal a aplicaiei:
a) n metoda onCreate() adugai un obiect de tip TabLayout. n acest fel pute i accesa la TabLayout widget descris (mai
sus) n layout-ul activitii:

TabLayout tabLayout = (TabLayout) findViewById(R.id.layout_tab);

b) Adugarea tab-urilor corespunztoare se face n felul urmtor (bineneles, n metoda onCreate()):

tabLayout.addTab(tabLayout.newTab().setText(SnumeOptiune1))

tabLayout.addTab(tabLayout.newTab().setText(SnumeOptiune2))

Adugai cele dou opiuni, dup care setai poziionarea acestora n actionbar:

tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

E7. Pentru a face posibil interschimbarea ntre cele dou fragmente, descrca i fi ierul FragmentAdapter.java i aduga i-l n proiect, n
acelai director cu MainActivity i cu cele dou fragmente. Acest fiier face posibil manipularea celor dou fragmente, i este destul de
simplu de folosit. Vom folosi acest adapter n activitatea principal, pentru a ne uura accesul la cele dou fragmente.
n acest exerciiu, adapter-ul pentru fragmente este deja instaniat n activitatea principal. Cel mai important este s n elege i modul de
funcionare al acestuia, cu siguran v va fi util pe mai departe.

E8.n metoda onCreate() din activitatea principal, apelai


tabLayout.setOnTabSelectedListener(..)

Acest apel va suprascrie automat metodele onTabSelected(), onTabUnselected() i onTabReleased().


43

E9. n onTabSelected(), adugai opiunea corespunztoare n momentul selecionrii unui tab:


viewPager.setCurrentItem(tab.getPosition());

Testai!

S-ar putea să vă placă și