Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:laborator04 [2015/03/16 05:24]
Andrei Roșu-Cojocaru
laboratoare:laborator04 [2016/03/19 12:36] (current)
Andrei Roșu-Cojocaru
Line 75: Line 75:
 <code xml> <code xml>
 <​activity <​activity
-  android:​name="​ro.pub.cs.systems.pdsd.lab04.MainActivity"​+  android:​name="​ro.pub.cs.systems.eim.lab04.MainActivity"​
   android:​label="​@string/​app_name"​ >   android:​label="​@string/​app_name"​ >
   <​intent-filter>​   <​intent-filter>​
-    <action android:​name="​ro.pub.cs.systems.pdsd.lab04.intent.action.MainActivity"​ />+    <action android:​name="​ro.pub.cs.systems.eim.lab04.intent.action.MainActivity"​ />
     <​category android:​name="​android.intent.category.LAUNCHER"​ />     <​category android:​name="​android.intent.category.LAUNCHER"​ />
   </​intent-filter>​   </​intent-filter>​
Line 99: Line 99:
 </​code>​ </​code>​
   * dacă se dorește rularea unei activități existente în cadrul altei aplicații, aceasta va trebui referită prin numele său complet, inclusiv denumirea pachetului care o identifică ​ <code java>   * dacă se dorește rularea unei activități existente în cadrul altei aplicații, aceasta va trebui referită prin numele său complet, inclusiv denumirea pachetului care o identifică ​ <code java>
-startActivity(new Intent("​ro.pub.cs.systems.pdsd.lab04.AnotherActivity"​));​+startActivity(new Intent("​ro.pub.cs.systems.eim.lab04.AnotherActivity"​));​
 </​code>​ </​code>​
  
Line 117: Line 117:
   * vizualizarea conținutului specificat în secțiunea ''​data''​ asociată intenției, sub forma unui URI, de către aplicații Android diferite, în funcție de schema (protocolul) utilizat (''​http''​ - navigator, ''​tel''​ - aplicația pentru formarea unui număr de telefon, ''​geo''​ - Google Maps, ''​content''​ - aplicația pentru gestiunea contactelor din agenda telefonică):​ <code java>   * vizualizarea conținutului specificat în secțiunea ''​data''​ asociată intenției, sub forma unui URI, de către aplicații Android diferite, în funcție de schema (protocolul) utilizat (''​http''​ - navigator, ''​tel''​ - aplicația pentru formarea unui număr de telefon, ''​geo''​ - Google Maps, ''​content''​ - aplicația pentru gestiunea contactelor din agenda telefonică):​ <code java>
 Intent intent = new Intent(Intent.ACTION_VIEW);​ Intent intent = new Intent(Intent.ACTION_VIEW);​
-intent.setData(Uri.parse("​http://​ocw.cs.pub.ro/​pdsd"));+intent.setData(Uri.parse("​http://​ocw.cs.pub.ro/​eim"));
 </​code>​ </​code>​
   * căutarea unor informații pe Internet folosind un motor de căutare, termenul căutat fiind indicat în secțiunea ''​extra''​ asociată intenției, fiind identificată prin cheia ''​SearchManager.QUERY'':​ <code java>   * căutarea unor informații pe Internet folosind un motor de căutare, termenul căutat fiind indicat în secțiunea ''​extra''​ asociată intenției, fiind identificată prin cheia ''​SearchManager.QUERY'':​ <code java>
Line 252: Line 252:
 <code xml> <code xml>
 <​activity <​activity
-  android:​name="​ro.pub.cs.systems.pdsd.lab04.AnotherActivity"​+  android:​name="​ro.pub.cs.systems.eim.lab04.AnotherActivity"​
   android:​label="​@string/​app_name"​ >   android:​label="​@string/​app_name"​ >
   <​intent-filter>​   <​intent-filter>​
-    <action android:​name="​ro.pub.cs.systems.pdsd.lab04.intent.action.AnotherActivity"​ />+    <action android:​name="​ro.pub.cs.systems.eim.lab04.intent.action.AnotherActivity"​ />
     <​category android:​name="​android.intent.category.DEFAULT"​ />     <​category android:​name="​android.intent.category.DEFAULT"​ />
     <data     <data
Line 292: Line 292:
   super.onCreate(state);​   super.onCreate(state);​
   setContentView(R.layout.activity_main);​   setContentView(R.layout.activity_main);​
-  Intent intent = new Intent("​ro.pub.cs.systems.pdsd.lab04.AnotherActivity"​);​ +  Intent intent = new Intent("​ro.pub.cs.systems.eim.lab04.AnotherActivity"​);​ 
-  intent.putExtra("​ro.pub.cs.systems.pdsd.lab04.someKey",​ someValue);+  intent.putExtra("​ro.pub.cs.systems.pdsd.eim.someKey",​ someValue);
   startActivityForResult(intent,​ ANOTHER_ACTIVITY_REQUEST_CODE);​   startActivityForResult(intent,​ ANOTHER_ACTIVITY_REQUEST_CODE);​
   // start another activities with their own request codes   // start another activities with their own request codes
Line 327: Line 327:
   // intent to parent   // intent to parent
   Intent intentToParent = new Intent();   Intent intentToParent = new Intent();
-  intent.putExtra("​ro.pub.cs.systems.pdsd.lab04.anotherKey",​ anotherValue);​+  intent.putExtra("​ro.pub.cs.systems.eim.lab04.anotherKey",​ anotherValue);​
   setResult(RESULT_OK,​ intentToParent);​   setResult(RESULT_OK,​ intentToParent);​
   finish();   finish();
Line 375: Line 375:
  
 <code java> <code java>
-final public static String SOME_ACTION = "​ro.pub.cs.systems.pdsd.lab04.SomeAction.SOME_ACTION";​+final public static String SOME_ACTION = "​ro.pub.cs.systems.eim.lab04.SomeAction.SOME_ACTION";​
  
 Intent intent = new Intent(SOME_ACTION);​ Intent intent = new Intent(SOME_ACTION);​
-intent.putExtra("​ro.pub.cs.systems.pdsd.lab04.someKey",​ someValue);+intent.putExtra("​ro.pub.cs.systems.eim.lab04.someKey",​ someValue);
 sendBroadcast(intent);​ sendBroadcast(intent);​
 </​code>​ </​code>​
Line 393: Line 393:
       android:​name="​.SomeEventBroadcastReceiver">​       android:​name="​.SomeEventBroadcastReceiver">​
       <​intent-filter>​       <​intent-filter>​
-        <action android:​name="​ro.pub.cs.systems.pdsd.lab04.SomeAction.SOME_ACTION"​ />+        <action android:​name="​ro.pub.cs.systems.eim.lab04.SomeAction.SOME_ACTION"​ />
       </​intent-filter> ​       </​intent-filter> ​
     </​receiver>​     </​receiver>​
Line 450: Line 450:
  
 <code java> <code java>
-final public static String SOME_ORDERED_ACTION = "​ro.pub.cs.systems.pdsd.lab04.SomeOrderedAction.SOME_ORDERED_ACTION";​+final public static String SOME_ORDERED_ACTION = "​ro.pub.cs.systems.eim.lab04.SomeOrderedAction.SOME_ORDERED_ACTION";​
  
 Intent intent = new Intent(SOME_ORDERED_ACTION);​ Intent intent = new Intent(SOME_ORDERED_ACTION);​
-intent.putExtra("​ro.pub.cs.systems.pdsd.lab04.someKey",​ someValue);​ +intent.putExtra("​ro.pub.cs.systems.pdsd.eim.someKey",​ someValue);​ 
-sendOrderedBroadcast(intent,​ "​ro.pub.cs.systems.pdsd.lab04.SOME_PERMISSION"​);​+sendOrderedBroadcast(intent,​ "​ro.pub.cs.systems.pdsd.eim.SOME_PERMISSION"​);​
 </​code>​ </​code>​
  
Line 462: Line 462:
     <​receiver     <​receiver
       android:​name="​.SomeEventOrderedBroadcastReceiver"​       android:​name="​.SomeEventOrderedBroadcastReceiver"​
-      android:​permission="​ro.pub.cs.systems.pdsd.lab04.SOME_PERMISSION">​+      android:​permission="​ro.pub.cs.systems.eim.lab04.SOME_PERMISSION">​
       <​intent-filter       <​intent-filter
         android:​permission="​100">​         android:​permission="​100">​
-        <action android:​name="​ro.pub.cs.systems.pdsd.lab04.SomeOrderedAction.SOME_ORDERED_ACTION"​ />+        <action android:​name="​ro.pub.cs.systems.eim.lab04.SomeOrderedAction.SOME_ORDERED_ACTION"​ />
       </​intent-filter> ​       </​intent-filter> ​
     </​receiver>​     </​receiver>​
Line 479: Line 479:
  
 <code java> <code java>
-final public static String SOME_STICKY_ACTION = "​ro.pub.cs.systems.pdsd.lab04.SomeStickyAction.SOME_STICKY_ACTION";​+final public static String SOME_STICKY_ACTION = "​ro.pub.cs.systems.eim.lab04.SomeStickyAction.SOME_STICKY_ACTION";​
  
 Intent intent = new Intent(SOME_STICKY_ACTION);​ Intent intent = new Intent(SOME_STICKY_ACTION);​
-intent.putExtra("​ro.pub.cs.systems.pdsd.lab04.someKey",​ someValue);+intent.putExtra("​ro.pub.cs.systems.eim.lab04.someKey",​ someValue);
 sendStickyBroadcast(intent);​ sendStickyBroadcast(intent);​
 </​code>​ </​code>​
Line 557: Line 557:
  
 <file java SomeFragment.java>​ <file java SomeFragment.java>​
-package ro.pub.cs.systems.pdsd.lab04;+package ro.pub.cs.systems.eim.lab04;
  
 import android.app.Fragment;​ import android.app.Fragment;​
Line 651: Line 651:
  
 <file java SomeFragment.java>​ <file java SomeFragment.java>​
-package ro.pub.cs.systems.pdsd.lab04;+package ro.pub.cs.systems.eim.lab04;
  
 import android.app.Activity;​ import android.app.Activity;​
Line 758: Line 758:
   tools:​context="​.MainActivity"​ >   tools:​context="​.MainActivity"​ >
   <​fragment   <​fragment
-    android:​name="​ro.pub.cs.systems.pdsd.labo04.Fragment1"​+    android:​name="​ro.pub.cs.systems.eim.labo04.Fragment1"​
     android:​id="​@+id/​fragment1"​     android:​id="​@+id/​fragment1"​
     android:​layout_weight="​1"​     android:​layout_weight="​1"​
Line 764: Line 764:
     android:​layout_height="​wrap_content"​ />     android:​layout_height="​wrap_content"​ />
   <​fragment   <​fragment
-    android:​name="​ro.pub.cs.systems.pdsd.labo04.Fragment2"​+    android:​name="​ro.pub.cs.systems.eim.labo04.Fragment2"​
     android:​id="​@+id/​fragment2"​     android:​id="​@+id/​fragment2"​
     android:​layout_weight="​1"​     android:​layout_weight="​1"​
Line 940: Line 940:
 </​code>​ </​code>​
  
-===== Servicii ​=====+===== Activitate de Laborator ​=====
  
-În Android, ​clasa ''​Service''​ este utilizată pentru componente a căror funcționalitate implică procesări complexede lungă durată, necesitând anumite resurse, fără a fi necesar ​să pună la dispoziție o interfață grafică sau un mecanism ​de interacțiune cu utilizatorul. Prin intermediul unui serviciu, se asigură faptul că aplicația Android continuă să se găsească ​în execuțiechiar și atunci când interfața grafică a acesteia nu este vizibilă.+Se dorește implementarea unei aplicații ​Android, ​conținând o activitate conținând două fragmentecare să ofere utilizatorilor funcționalitatea necesară pentru a stoca un număde telefon ​în agenda de contactespecificând pentru acesta mai multe informații.
  
-<note tip>​Întrucât prioritatea unui serviciu este mai mare decât a unei activități inactive, este mai puțin probabil ca acestea să fie distruse atunci când trebuie eliberate resursele sistemului de operareDe altfel, un serviciu poate fi configurat să fie repornit imediat ce este posibil sau chiar pentru a i se asocia o prioritate echivalentă cu a unei activități active (dacă distrugerea serviciului are un impact la nivelul interfeței grafice).</​note>​+{{ :​laboratoare:​laborator04:​activitate_de_laborator01.png?​nolink&​300 }}
  
-Astfel, un serviciu nu trece prin evenimentele ce fac parte din ciclul de viață al unei activități. Totuși, un serviciu poate fi controlat (pornit, oprit) din contextul altor componente ale unei aplicații Android (activități,​ ascultători de intenții cu difuzare, alte servicii).+{{ :​laboratoare:​laborator04:​activitate_de_laborator02.png?​nolink&​300 }}
  
-Un serviciu este de regulă rulat pe firul de execuție principal al aplicației AndroidDe aceeaîn cazul în care operațiile pe care le realizează influențează experiența utilizatoruluiacestea trebuie transferate pe alte fire de execuție din fundal (folosind clasele ​''​Thread''​ și ''​AsyncTask''​).+**1.** În contul Github personalsă se creeze un depozit denumit '​Laborator04'​. Acesta trebuie să conțină unui fișier ''​README.md''​un fișier ​''​.gitignore'' ​specific unei aplicații Android ​și un fișier ​''​LICENSE'' ​care să descrie condițiile pentru utilizarea aplicației.
  
-==== Gestiunea unui Serviciu ====+**2.** Să se cloneze într-un director de pe discul local conținutul depozitului la distanță astfel creat. În urma acestei operații, directorul Laborator04 va trebui să se conțină fișierele ''​README.md'',​ ''​.gitignore''​ care indică tipurile de fișiere (extensiile) ignorate și ''​LICENSE''​. <​code>​ 
 +student@eim2016:​~$ git clone https://​www.github.com/​perfectstudent/​Laborator04 
 +</​code>​
  
-Un serviciu este o clasă derivată din ''​android.app.Service'',​ implementând metodele: +**3.** În directorul Laborator04 ​de pe discul localsă se creeze un proiect Eclipse denumit //​ContactsManager//​.
-  ​''​onCreate()''​ - realizând operațiile asociate construirii serviciului respectiv;​ +
-  ​''​onBind()''​ - asigurând asocierea serviciului la o altă componentă a aplicației Android; metoda primește un parametru ​de tip ''​Intent''​reprezentând intenția prin intermediul căruia a fost lansat în execuție.+
  
-<file java SomeService.java>​ +Se utilizează următoarele detalii ale proiectului:​ 
-import android.app.Service; +  * **Application Name** - //Contacts Manager// 
-import android.content.Intent; +  * **Project Name** - //​ContactsManager//​ 
-import android.os.IBinder;+  * **Package Name** - ''​ro.pub.cs.systems.eim.lab04.contactsmanager''​ 
 +  * **Minimum Required SDK** - API 16: Android 4.1 (Jelly Bean) 
 +  * **Target SDK** - API 16: Android 4.1 (Jelly Bean) 
 +  * **Compile With** - API 16: Android 4.1 (Jelly Bean) 
 +  * **Theme** - Holo Light with Dark Action Bar
  
-public class SomeService extends Service { +Ceilalți parametrii de configurare sunt impliciți: 
-  ​@Override +  ​* denumirea activității - ''​ContactsManagerActivity'';​ 
-  ​public void onCreate() { +  ​* denumirea fișierului XML din ''​res/layout''​ în care va fi construită interfața grafică - ''​activity_contacts_manager''​.
-    super.onCreate();​ +
-    // ... +
-  }+
  
-  @Override +**4.** În fișierul ''​activity_contacts_manager''​ din directorul ''​res/​layout''​ să se construiască interfața grafică folosind: 
-  ​public IBinder onBind(Intent intent) { +  ​* editorul vizual ​(//Graphical Layout//) 
-    ​// ... +  ​* editorul XML (manual)
-    return null; +
-  ​+
-+
-</​file>​+
  
-Orice serviciu trebuie să fie înregistrat în cadrul fișierului ​''​AndroidManifest.xml'',​ prin intermediul etichetei ''<​service>​''​ în cadrul elementului ''<​application>''​. Eventualse poate indica o permisiune necesară pentru pornirea și oprirea serviciului,​ astfel încât aceste operații să poată fi realizate numai de anumite aplicații Android.+Acesta va fi format din două containere de tip ''​FrameLayout''​ în care vor fi plasate fragmenteledispuse vertical.
  
-<file xml AndroidManifest.xml> +**5.** Să se definească două fragmente: 
-<​manifest ​...> +  * ''​BasicDetailsFragment''​ cu interfața grafică în fișierul ''​fragment_basic_details.xml''​ din directorul ''​res/​layout'';​ acesta va fi afișat în permanență în cadrul activității (pe metoda ''​onCreate()''​ a acesteia se adaugă o instanță a fragmentului la containerul ​ <code java
-  <application ...+FragmentManager fragmentManager = getFragmentManager();​ 
-    <​service +FragmentTransaction fragmentTransaction ​fragmentManager.beginTransaction();​ 
-      ​android:​name="ro.pub.cs.systems.pdsd.lab04.SomeService"​ +fragmentTransaction.add(R.id.containerTop,​ new BasicDetailsFragment());​ 
-      ​android:​enabled="​true"​ +fragmentTransaction.commit(); 
-      android:​permission="​ro.pub.cs.systems.pdsd.lab04.SOME_SERVICE_PERMISSION"​ /> +</code
-  </application+  * ''​AdditionalDetailsFragment''​ cu interfața grafică în fișierul ''​fragment_additional_details.xml''​ din directorul ''​res/​layout'';​ acesta va fi atașat / detașat la activitate la accesarea butonului //Show Additional Fields//, respectiv //Hide Additional Fields//.
-</manifest>​ +
-</file>+
  
-În momentul în care este pornit (printr-un apel al metodei ​''​startService()'' ​din cadrul altei componente),​ un serviciu apelează în mod automat ​metoda ''​onStartCommand()''​. În cadrul acestei metode trebuie realizată procesarea ​pe care o presupune serviciul respectiv. Având în vedere faptul că această metodă poate fi apelată de mai multe ori pe parcursul ciclului de viață al unui serviciu, tot aici trebuie implementa și comportamentul în cazul în care acesta este repornit. Metoda primește ca parametrii:​ +O clasă asociată unui fragment ​este derivată din ''​android.app.Fragment'' ​și implementează metoda ''​onCreateView()''​ pe care se încarcă interfața grafică corespunzătoare:
-  * intenția care invocat serviciul;​ +
-  * anumite valori prin care poate fi semnalat modul în care a fost pornit: +
-    * ''​START_FLAG_REDELIVERY''​ - serviciul a fost repornit ca urmare a distrugerii sale de către sistemul de operare înainte de se fi terminat ​corespunzător; +
-    * ''​START_FLAG_RETRY''​ - serviciul a fost repornit după o execuție anormală;​ +
-  * un identificator unic prin care se poate face distincția între apeluri diferite ale aceluiași serviciu.+
  
 <code java> <code java>
-@Override +public class SomeFragment extends Fragment { 
-public ​int onStartCommand(Intent intentint flagsint startId) { +  ​@Override 
-  ​processInBackground(intentstartId); +  public ​View onCreateView(LayoutInflater layoutInflaterViewGroup containerBundle state) { 
-  ​return Service.START_STICKY;​+    ​return layoutInflater.inflate(R.layout.fragment_somecontainer, false); 
 +  ​}
 } }
 </​code>​ </​code>​
  
-Comportamentul serviciului în situația în care este repornit poate fi controlată prin intermediul valorii întregi care este furnizată ca rezultat al metodei ''​onStartCommand()''​+**6**. Să se implementeaze intefețele grafice ale fragmentelor,​ conținând următoarele controale
-  * ''​Service.START_STICKY'' ​- mecanism standard, folosit de serviciile care își gestionează propriile stări și care sunt pornite și oprite în funcție de necesități ​(prin intermediul metodelor ​''​startService()'' ​și ''​stopService()''​);​ prin aceasta, se indică faptul că metoda ''​onStartCommand()''​ va fi invocată de fiecare dată când serviciul ​este (re)pornit după ce a fost distrus de sistemul de operare Android (situație ​în care parametrul ​de tip ''​Intent''​ va avea valoarea ''​null''​);​ +  * ''​fragment_basic_details.xml'' ​conține mai multe elemente dispuse vertical ​și ocupând pe lățime întregul spațiu avut la dispoziție
-  ''​Service.START_NOT_STICKY'' ​mecanism utilizat de serviciile utilizate pentru a procesa anumite comenzi, care se opresc singure ​(printr-un apel al metodei ​''​stopSelf()''​) ​atunci când operațiile pe care trebuiau ​să le realizeze s-au terminat; serviciul este (re)pornit după ce a fost distrus de sistemul de operare Android numai în situația în care între timp au mai fost realizate apeluri ale metodei ​''​startService()''; ​un astfel de comportament este adecvat pentru procese care sunt realizate periodic+    * un buton (''​Button''​) ​având mesajul //Show Additional Fields// în cazul în care celălalt fragment nu este afișat, respectiv mesajul //Hide Additional Fields// în cazul în care celălalt fragment este afișat, determinând atașarea / detașarea acestuia la activitate;​ 
-  * ''​Service.START_REDELIVER_INTENT'' ​- mecanism utilizat atunci când se dorește să se asigure faptul că procesările asociate serviciului au fost terminate; în situația în care serviciul a fost distrus de sistemul de operare Android, este (re)pornit numai în situația în care între timp au fost realizate apeluri ale metodei ''​startService()''​ sau procesul a fost oprit ca acesta să invoce metoda ''​stopSelf()'' ​metoda ''​onStartCommand()''​ va fi apelată folosind ca parametru intenția originală, a cărei procesări nu a fost terminată corespunzător.+    * patru controale ​de tip câmpuri text (''​EditText''​) ​prin care se introduc: 
 +      * numele
 +      numărul de telefon ​acest câmp este dezactivat ​(are proprietatea ​''​android:​enabled="​false"​''​), urmând ca valoarea sa să fie preluată din câmpul ​''​extra'' ​al unei intenții; 
 +      * adresa electronică; 
 +      * adresa poștală. 
 +  * ''​fragment_additional_details.xml'' ​conține patru controale de tip câmpuri text dispuse vertical ​și ocupând pe lățime întregul spațiu avut la dispoziție,​ prin care se introduc: 
 +    * poziția ocupată
 +    * denumirea companiei;​ 
 +    * site-ul web; 
 +    * identificatorul pentru mesagerie instantanee.
  
-În toate aceste cazuri, oprirea serviciului trebuie realizată explicit, prin apelul metodelor: +**7.** Să se implementeaze interacțiunea cu utilizatorul a aplicației. ​ 
-  * ''​stopService()'' ​din contextul componentei care l-pornit; +  * în metoda ​''​onActivityCreated()''​ a fragmentului ​''​BasicDetailsFragment'' ​se obțin referințe către butoanele //Show Additional Details// / //Hide Additional Details//, respectiv //Save// și //Cancel// prin intermediul ​metodei ''​getActivity().findViewById(R.id....)''​
-  * ''​stopSelf()'' ​din contextul serviciului. +  * se implementează o clasă ascultător pentru butoane, care implementează ''​View.OnClickListener''​ și (re)definește metoda ​''​onClick(View v)''​; în funcție de identificatorul butonului ​care este transmis ca parametru al metodei, sunt realizate următoarele acțiuni
- +    butonul //Show Additional Details// / //Hide Additional Details// - atașează / detașează fragmentul ''​AdditionalDetailsFragment''​ la activitate în funcție de existența / inexistența acestuiamodificând corespunzător textul afișat pe buton: ​<​code>​ 
-=== Pornirea unui Serviciu === +FragmentManager fragmentManager ​getActivity().getFragmentManager();​ 
- +FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();​ 
-Un serviciu este pornit printr-un apel al metodei ''​startService()''​. ​Aceasta primește ca parametru un obiect de tip ''​Intent''​ care poate fi creat+AdditionalDetailsFragment additionalDetailsFragment = (AdditionalDetailsFragment)fragmentManager.findFragmentById(R.id.containerBottom);​ 
-  explicitpe baza denumirii clasei care implementează serviciul respectiv; ​<​code ​java+if (additionalDetailsFragment == null) { 
-Intent intent ​new Intent(thisSomeService.class); +  fragmentTransaction.add(R.id.containerBottomnew AdditionalDetailsFragment());​ 
-startService(intent);+  ((Button)v).setText(getActivity().getResources().getString(R.string.hide_additional_fields)); 
 +  ​fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);​ 
 +} else { 
 +  fragmentTransaction.remove(additionalDetailsFragment);​ 
 +  ((Button)v).setText(getActivity().getResources().getString(R.string.show_additional_fields));​ 
 +  fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_EXIT_MASK);​ 
 +
 +fragmentTransaction.commit();
 </​code>​ </​code>​
-  ​implicit, indicând o acțiune înregistrată ca fiind tratată de serviciul respectiv. ​<code java> +    ​butonul //Save// - lansează în execuție aplicația Android nativă pentru stocarea unui contact în agenda telefonică, după ce în prealabil au fost preluate informațiile din controalele grafice: ​<code java> 
-Intent intent = new Intent(SomeService.SOME_SERVICE); +Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION); 
-startService(intent);+intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);​ 
 +if (name != null) { 
 +  ​intent.putExtra(ContactsContract.Intents.Insert.NAME,​ name); 
 +
 +if (phone != null) { 
 +  intent.putExtra(ContactsContract.Intents.Insert.PHONE,​ phone); 
 +
 +if (email != null) { 
 +  intent.putExtra(ContactsContract.Intents.Insert.EMAIL,​ email); 
 +
 +if (address != null) { 
 +  intent.putExtra(ContactsContract.Intents.Insert.POSTAL,​ address); 
 +
 +if (jobTitle != null) { 
 +  intent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE,​ jobTitle);​ 
 +
 +if (company != null) { 
 +  intent.putExtra(ContactsContract.Intents.Insert.COMPANY,​ company); 
 +
 +ArrayList<​ContentValues>​ contactData = new ArrayList<​ContentValues>​();​ 
 +if (website != null) { 
 +  ContentValues websiteRow = new ContentValues();​ 
 +  websiteRow.put(ContactsContract.Data.MIMETYPE,​ ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);​ 
 +  websiteRow.put(ContactsContract.CommonDataKinds.Website.URL,​ website); 
 +  contactData.add(websiteRow);​ 
 +
 +if (im != null) { 
 +  ContentValues imRow = new ContentValues();​ 
 +  imRow.put(ContactsContract.Data.MIMETYPE,​ ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);​ 
 +  imRow.put(ContactsContract.CommonDataKinds.Im.DATA,​ im); 
 +  contactData.add(imRow);​ 
 +
 +intent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA,​ contactData);​ 
 +getActivity().startActivity(intent);​ 
 +</​code>​ Intenția pentru realizarea acestei operații are asociată acțiunea ''​ContactsContract.Intents.Insert.ACTION''​ și tipul ''​ContactsContract.RawContacts.CONTENT_TYPE''​. Informațiile care se doresc a fi completate sunt atașate în câmpul ''​extra''​ al acesteia, având cheile:\\ ✔ ''​ContactsContract.Intents.Insert.NAME'';​\\ ✔ ''​ContactsContract.Intents.Insert.PHONE'';​\\ ✔ ''​ContactsContract.Intents.Insert.EMAIL'';​\\ ✔ ''​ContactsContract.Intents.Insert.POSTAL'';​\\ ✔ ''​ContactsContract.Intents.Insert.JOB_TITLE'';​\\ ✔ ''​ContactsContract.Intents.Insert.COMPANY'';​\\ Pentru site-ul web și identificatorul de mesagerie instantanee,​ se folosește un tablou de elemente ''​ContentValues''​ în care se specifică înregistrări de tipul ''​CommonDataKinds.Website.URL'',​ respectiv ''​CommonDataKinds.Im.DATA'';​\\ Pentru a putea gestiona agenda telefonică,​ este necesar ca în fișierul ''​AndroidManifest.xml''​ să fie specificate următoarele permisiuni: <code xml> 
 +<​uses-permission 
 +  android:​name="​android.permission.READ_CONTACTS"​ /> 
 +<​uses-permission 
 +  android:​name="​android.permission.WRITE_CONTACTS"​ /> 
 +</​code>​ 
 +    * butonul //Cancel// - termină aplicația Android: <code java> 
 +getActivity().finish();
 </​code>​ </​code>​
 +  * se înregistrează o instanță a clasei ascultător ca mecanism de tratare a evenimentelor de tip accesare a butoanelor din cadrul interfeței grafice, prin apelul metodei ''​setOnClickListener()''​.
  
-Transmiterea de informații suplimentare către serviciu poate fi realizată prin intermediul metodelor ''​putExtras(Bundle)'',​ ''​putExtra(String,​ Parcelable)''​ sau ''​put<​type>​Extra(String,​ <​type>​)''​.+**8.** Să se modifice aplicația Android [[https://​github.com/​eim2016/​Laborator03.git|Phone Dialer]] astfel încât să conțină un buton suplimentar ​prin care este invocată aplicația //Contacts Manager// căreia îi transmite numărul de telefon format și așteptând un rezultat cu privire la stocarea contactului în agenda telefonică.
  
-=== Oprirea unui Serviciu ===+{{ :​laboratoare:​laborator04:​activitate_de_laborator03.png?​nolink&​300 }}
  
-Un serviciu poate fi oprit: +{{ :laboratoare:​laborator04:​activitate_de_laborator04.png?​nolink&​500 }}
-  * de componenta care l-a pornit, printr-un apel al metodei ''​stopService()'',​ ce primește ca parametru un obiect de tip ''​Intent''​ care poate fi creat explicit sau implicit;+
  
-<note important>​Întrucât apelurile metodei ''​startService()''​ nu sunt imbricate, invocarea metodei ''​stopService()''​ oprește numai serviciul corespunzător (dacă se află în execuție).</​note>​ +Metoda ​de tratare ​evenimentului ​de tip accesare ​butonului de stocare ​numărului de telefon în agenda telefonică invocă o intenție asociată aplicației //Contacts Manager//, transmițând și numărul de telefon în câmpul ​''​extra'' ​asociat acesteia, identificabil prin intermediul unei chei. <code java
- +if (phoneNumber.length() ​0) { 
-  * chiar de el însuși, în momentul în care procesările pe care trebuie să le realizeze s-au terminat, printr-un apel al metodei ''​stopSelf()'',​ eliberând resursele pe care sistemul ​de operare le-ar fi folosit pentru ​a-l menține în execuție; metoda poate fi apelată: +  ​intent = new Intent("​ro.pub.cs.systems.eim.lab04.contactsmanager.intent.action.ContactsManagerActivity"​)
-    * fără parametri, pentru a forța oprirea imediată;​ +  ​intent.putExtra("​ro.pub.cs.systems.eim.lab04.contactsmanager.PHONE_NUMBER_KEY",​ phoneNumber); 
-    * transmițând un parametru ​de tip întreg, reprezentând identificatorul instanței care rulează, pentru ​se asigura faptul că procesarea ​fost realizată pentru fiecare apel care a fost realizat. +  ​startActivityForResult(intent, Constants.CONTACTS_MANAGER_REQUEST_CODE); 
- +else { 
-==== Asocierea unui Serviciu la o Activitate ==== +  ​Toast.makeText(getApplication(),​ getResources().getString(R.string.phone_error), Toast.LENGTH_LONG).show();
- +
-Un serviciu poate fi atașat la o activitate, astfel încât activitatea menține o referință către serviciu, prin intermediul căreia poate invoca metode așa cum ar face cu orice alt obiect. Un astfel ​de comportament este util pentru activitățile care necesită interfațarea cu un serviciu. +
- +
-Acestă funcționalitate este realizată prin intermediul metodei ''​onBind()''​ care furnizează o referință către serviciu sub forma unui obiect ​de tipul ''​IBinder''​. +
- +
-<file java SomeService.java+
-import android.app.Service; +
-import android.content.Intent; +
-import android.os.IBinder; +
- +
-public class SomeService extends Service { +
- +
-  ​final private IBinder binder = new SomeBinder(); +
- +
-  ​public class SomeBinder extends Binder { +
-    SomeService getService() +
-      return SomeService.this+
-    +
-  ​+
- +
-  @Override +
-  public void onCreate() +
-    super.onCreate()+
-    // ..+
-  } +
- +
-  @Override +
-  public IBinder onBind(Intent intent+
-    return binder; +
-  }+
 } }
-</​file>​ 
- 
-Legătura dintre serviciu și activitate este reprezentată sub forma unui obiect de tipul ''​ServiceConnection'',​ a cărui implementare presupune definirea metodelor ''​onServiceConnected()'',​ respectiv ''​onServiceDisconnected()''​. Asocierea propriu-zisă dintre serviciu și activitate este realizată de metoda ''​bindService()''​ care primește ca parametri: 
-  * intenția (creată explicit sau implicit) reprezentând serviciul care se asociază activității;​ 
-  * un obiect de tip ''​ServiceConnection'';​ 
-  * anumite valori prin care se controlează modul în care este făcută asocierea între cele două componente ale aplicației Android: 
-    * ''​Context.BIND_AUTO_CREATE''​ - serviciul trebuie creat în momentul în care se realizează asocierea; 
-    * ''​Context.BIND_ADJUST_WITH_ACTIVITY''​ - modifică prioritatea serviciului în funcție de importanța activității de care este legat (mai mare atunci când este activă, mai mică atunci când este inactivă); 
-    * ''​Context.BIND_ABOVE_CLIENT''​ / ''​Context.BIND_IMPORTANT''​ - specifică faptul că prioritatea serviciului este mai mare decât a activității asociate; 
-    * ''​Context.BIND_NOT_FOREGROUND''​ - asigură faptul că serviciul atașat activității nu va avea niciodată prioritatea necesară pentru a rula pe firul de execuție principal; 
-    * ''​Context.BIND_WAIVE_PRIORITY''​ - face ca prioritatea serviciului asociat să nu fie modificată (implicit, prioritatea relativă a serviciului este mărită). 
- 
-<code java> 
-private SomeService someServiceReferrence;​ 
- 
-private ServiceConnection serviceConnection = new ServiceConnection() { 
-  @Override 
-  public void onServiceConnected(ComponentName className, IBinder service) { 
-    serviceConnection = ((SomeService.SomeBinder)service).getService();​ 
-  } 
-  ​ 
-  @Override 
-  public void onServiceDisconnected(ComponentName className) { 
-    serviceConnection = null; 
-  } 
-}; 
- 
-Intent intent = new Intent(this,​ SomeService.class);​ 
-bindService(intent,​ serviceConnection,​ Context.BIND_AUTO_CREATE);​ 
 </​code>​ </​code>​
  
-După ce serviciul a fost atașat ​activității, toate metodele șatributele sale publice sunt disponibile ​prin intermediul ​parametrului de tip ''​IBinder'' ​din cadrul metodei ​''​onServiceConnected()''​.+**9.** Să se modifice aplicația Android //Contacts Manager// astfel încât să poată fi lansată în execuție doar din contextul altei activitățiprin intermediul ​unei intenții care conține în câmpul ​''​extra'' ​un număr de telefon, identificabil prin cheia ''​ro.pub.cs.systems.eim.lab04.contactsmanager.PHONE_NUMBER_KEY'',​ acesta fiind plasat în câmpul text needitabil corespunzător. Totodată, va transmite înapoi rezultatul operației de stocare ​(''​Activity.RESULT_OK''​ sau ''​Activity.RESULT_CANCELED''​).
  
-==== Categorii de Procesări ==== +  ​* în fișierul ''​AndroidManifest.xml''​ se modifică filtrul ​de intenții (acțiunea șcategoria), astfel încât ​activitatea să poată fi rulată doar prin intermediul ​unei intenții ​<file xml AndroidManifest.xml> 
- +<manifest ...
-În funcție de firul de execuție pe care rulează precum și de prioritatea care le este atribuită (în funcție de care sistemul de operare Android poate reclama resursele pe care acestea le utilizează),​ operațiile complexe pot fi realizate prin intermediul unor: +  <​application ​...> 
-  ​servicii care rulează ​în prim-plan;​ +    <​activity 
-  * procesări realizate în fundal. +      ​android:name="​.graphicuserinterface.ContactsManagerActivity"​ 
- +      ​android:​label="​@string/​app_name"​ > 
-=== Servicii ce Rulează în Prim-Plan === +      <​intent-filter> 
- +        <​action android:​name="​ro.pub.cs.systems.eim.lab04.contactsmanager.intent.action.ContactsManagerActivity"​ /> 
-În situația în care un serviciu interacționează cu utilizatorul,​ prioritatea acestuia trebuie mărită, astfel încât sistemul de operare Android să nu poată reclama resursele pe care le utilizează.  +        <​category android:​name="​android.intent.category.DEFAULT"​ /> 
- +      </​intent-filter>​ 
-Un astfel de comportament poate fi obținut prin marcarea serviciului ca rulând în prim-plan, prin invocarea metodei ''​startForeground()''​ care primește ca parametri:​ +    </activity> 
-  * identificatorul unei notificări;​ +  ​</application
-  * un obiect de tip ''​Notification'',​ care va fi afișată cât timp serviciul se află în prim-plan, întrucât se presupune că serviciul trebuie să aibă o reprezentare vizuală cu care utilizatorul să poată interacționa. +</manifest> 
- +</file
-Este recomandat ca utilizatorii să poată dezactiva ei înșiși rularea serviciului în prim-plan, de regulă prin intermediul obiectului de tip ''​Notification''​. Același lucru trebuie realizat și în momentul în care rularea serviciului în prim-plan nu mai este necesară. În acest sens, trebuie apelată metoda ''​stopForeground(true)'',​ aceasta anulând în mod automat notificarea asociată. +  * în metoda ​''​onActivityCreated()'' ​asociată fragmentului ''​BasicDetailsFragment''​ este verificată intenția cu care este pornită activitatea părinteși în cazul în care aceasta nu este nulă, este preluată informația din secțiunea ''​extra''​, identificată prin cheia ''​ro.pub.cs.systems.eim.lab04.contactsmanager.PHONE_NUMBER_KEY''​, conținutul său fiind plasat în cadrul câmpului text corespunzător: <code java> 
- +if (intent != null) 
-<note tip>Nu este recomandat să existe mai multe servicii care rulează în prim-plan simultan întrucât acestea nu pot fi distruse de sistemul de operare Android și în situația în care necesarul de memorie devine o problemă critică, performanțele dispozitivului mobil se vor deprecia considerabil.</​note>​ +  String ​phone = intent.getStringExtra("ro.pub.cs.systems.eim.lab04.contactsmanager.PHONE_NUMBER_KEY"​); 
- +  ​if ​(phone !null) { 
-=== Procesări Realizate în Fundal === +    ​phoneEditText.setText(phone); 
- +  } else 
-Întrucât responsivitatea aplicației Android reprezintă un criteriu foarte important, asigurarea unei experiențe corespunzătoare a utilizatorului poate fi obținută prin transferul operațiilor complexe ​de procesare și a operațiilor de intrare/​ieșire în fundal, pe un alt fir de execuție. Acest lucru este necesar datorită faptului că pe firul de execuție principal sunt rulate mai multe componente ale aplicației Android ​(activități, servicii, ascultători ai intențiilor cu difuzare), astfel încât ​interacțiunea cu utilizatorul poate fi blocată în situația în care procesarea realizată de servicii nu este transferată în fundal. +    ​Activity activity = getActivity(); 
- +    ​Toast.makeText(activity,​ activity.getResources().getString(R.string.phone_error)Toast.LENGTH_LONG).show();
-<​note>​În Android, o activitate care nu răsunde la un eveniment în decurs de 5 secunde sau un ascultător al unei intenții ​cu difuzare a cărei metodă ''​onReceive()''​ nu se termină în 5 secunde sunt considerate blocate.</note+
- +
-De regulă, sunt plasate pe fire de execuție dedicate operații cu fișiere (scrieri, citiri), căutări în rețea, tranzacții cu baza de date, calcule complexe+
- +
-Android oferă mai multe mecanisme pentru gestiunea serviciilor care rulează în fundal+
-  - utilizarea clasei ''​AsyncTask''​ permite definirea unei operații care va fi realizată pe un fir de execuție separat, oferind metode care oferă informații cu privire la progres, ce pot fi consultate de alte fire de execuție; +
-  folosirea clasei ''​IntentService'';​ +
-  - definirea unei clase derivate din ''​Loader'';​ +
-  - implementarea unui fir de execuție definit de utilizator, transmiterea valorilor către interfața grafică fiind realizat prin intermediul clasei ''​Handler''​+
- +
-== Clasa AsyncTask == +
- +
-Prin intermediul clasei ''​AsyncTask''​ se permite mutarea operațiilor costisitoare din punct de vedere al utilizării procesorului și al memoriei pe fire de execuție rulate în fundal, oferind sincronizarea cu firul de execuție ce randează interfața grafică, acesta fiind notificat cu privire la progresul realizat cât și cu privire la momentul în care procesarea a fost terminată+
- +
-<note tip>Întrucât clasa ''​AsyncTask''​ nu este persistentă în cazul (re)pornirii unei activități (situație în care firul de execuție asociat este distrus), se recomandă utilizarea sa pentru procese de fundal care nu durează o perioadă de timp prea mare.</note> +
- +
-O implementare a clasei ''​AsyncTask''​ poate fi parametrizată cu tipurile de date care sunt folosite pentru intrare, pentru raportarea progresului și pentru ieșire (rezultate). +
- +
-<note tip>În situația în care nu se dorește transmiterea unor parametrii de intrare / ieșire sau nu este necesară raportarea progresului,​ se poate utiliza valoarea ''​Void''​ pentru toate aceste tipuri.</note> +
- +
-Este necesară suprascrierea următoarelor metode: +
-  * ''​doInBackground()'' ​- metoda care va fi executată pe firul de execuție dedicat, care primește parametrii de intrare de tipul specificat; acesta trebuie să conțină procesările complexe ​care se doresc a fi realizate fără a interacționa însă cu firul de execuție principal; notificările sunt realizate:​ +
-    * prin intermediul metodei ''​publishProgress()''​, care primește ca parametru progresul realizat, valorile fiind transmise metodei ''​onProgressUpdate()'';​ +
-    * prin întoarcerea unui rezultat, atunci când procesarea ​este terminată, valoarea fiind transmisă metodei ''​onPostExecute()'';​ +
-  * ''​onProgressUpdate()''​ - folosită pentru actualizarea interfeței grafice, cu valorile primite de la metoda ''​publishProgress()'';​ metoda ​este sincronizată cu firul de execuție principal (care randează interfața grafică), astfel încât diferitele controale pot fi accesate de aici; +
-  * ''​onPostExecute()'' ​- apelată în momentul în care procesarea este terminată, primind ca parametru rezultatul întors de metoda ​''​doInBackground()''​; metoda este sincronizată cu firul de execuție principal (care randează interfața grafică), astfel încât diferitele controale pot fi accesate de aici. +
- +
-<code java> +
-private class SomeAsyncTask extends AsyncTask<​String,​ Integer, String> ​+
-  ​@Override +
-  protected ​String ​doInBackground(String... parameter) { +
-    String result = new String(); +
-    int progress = 0; +
-    for (int k 1; k <= parameter[0].length();​ k++) { +
-      ​progress = k; +
-      result += parameter[0].charAt(parameter[0].length() - k); +
-      ​try ​+
-        ​Thread.sleep(100); +
-      } catch (InterruptedException interruptedException+
-        Log.e(Constants.TAG"An exception has occurred: "​+interruptedException.getMessage()); +
-      } +
-      publishProgress(myProgress)+
-    } +
-    return result;+
   }   }
- +}  
-  ​@Override +</​code>​ 
-  ​protected void onProgressUpdate(Integer... progress+  ​* pe metodele de tratare a evenimentelor de accesare a butoanelor: 
-    asyncTextView.setText(progress[0].toString()); +    * //Save// - este lansată în execuție aplicația nativă pentru gestiunea agendei telefonice, folosind un cod de cerere prin intermediul căruia se va verifica rezultatul furnizat: <code java> 
-  } +getActivity().startActivityForResult(intent, Constants.CONTACTS_MANAGER_REQUEST_CODE); 
- +</​code>​ 
-  ​@Override +    * //Cancel// - se transmite înapoi rezultatul <code java> 
-  protected void onPostExecute(String result+getActivity().setResult(Activity.RESULT_CANCELED,​ new Intent());
-    asyncTextView.setText(result); +
-  } +
-}+
 </​code>​ </​code>​
  
-Rularea unui obiect de tip ''​AsyncTask''​ se face prin invocarea metodei ''​execute()'' ​care primește ca parametru informațiile care se doresc a fi procesate. +  * în metoda ​''​onActivityResult()'' ​asociată activității ''​ContactsManagerActivity''​în momentul ​în care s-a părăsit aplicația nativă ​pentru ​gestiunea agendei telefonice, se verifică codul de cerere ​șse transmite înapoi ​un rezultat: ​<code java> 
- +public ​void onActivityResult(int requestCode,​ int resultCode, Intent intent) { 
-<note important>​Fiecare obiect de tip ''​AsyncTask''​ poate fi rulat o singură dată. Apelurile ulterioare ale metodei ''​execute()''​ vor genera excepții. </​note>​ +switch(requestCode{ 
- +  case Constants.CONTACTS_MANAGER_REQUEST_CODE:​ 
-== Clasa IntentService == +    ​setResult(resultCode,​ new Intent()); 
- +    ​finish(); 
-Recursul la clasa ''​IntentService'' ​este adecvată ​în situația ​în care se dorește implementarea unor servicii care rulează în fundal, realizând un set de operații la un moment dat de timp, atunci când sunt solicitate. +    ​break;
- +
-Un obiect de acest tip este lansat în execuție prin pornirea unui serviciu și transmiterea unui obiect de tip ''​Intent''​ care conține toți parametrii necesari ​pentru ​realizarea sarcinii respective. Toate operațiile solicitate sunt înregistrate și executate succesiv. După ce procesarea a fost finalizatăprocesul ​se oprește singur. +
- +
-O implementare este o clasă derivată din ''​IntentService'',​ definind metoda ''​onHandleIntent()''​ ce primește ca parametru intenția conținând parametrii ce se doresc a fi procesați, execuția sa fiind realizată pe un fir de execuție ce rulează în fundal (câte unul pentru fiecare invocare). +
- +
-<code java> +
-import android.app.IntentService;​ +
-import android.content.Intent;​ +
- +
-public ​class SomeIntentService extends IntentService { +
-  public SomeIntentService(String name) { +
-    super(name); +
-    // ..+
-  } +
-   +
-  @Override +
-  public void onCreate() +
-    super.onCreate(); +
-    ​// ... +
-  } +
- +
-  @Override +
-  protected void onHandleIntent(Intent intent{ +
-    ​// ...+
   }   }
 } }
 </​code>​ </​code>​
  
-== Clasa Abstractă Loader == +**10.* Să se încarce modificările realizate ​în cadrul depozitului ​'Laborator04' ​de pe contul Github personalfolosind ​un mesaj sugestiv. <​code>​ 
- +student@eim2016:​~/​Laborator04$ git add * 
-Clasa abstractă ''​Loader''​ implementează practicile recomandate pentru încărcarea asincronă a informațiilor în cadrul unor controale grafice din interfața cu utilizatorul (afișate în activități sau fragmente). +student@eim2016:​~/​Laborator04$ git commit -m "​implemented taks for laboratory 04" 
- +student@eim2016:~/Laborator04$ git push origin master
-O astfel de abordare este utilizată pentru: +
-  ​a încărca date asincron; +
-  * a monitoriza sursele din care sunt încărcate datele, oferind informații cu privire la rezultatele obținute. +
- +
-De regulă, ​se folosește o implementare a clasei ''​AsyncTaskLoader''​. +
- +
-== Utilizarea firelor de execuție definite de utilizator == +
- +
-Folosirea unor fire de execuție definite de utilizator și sincronizarea manuală cu interfața grafică poate fi necesară în situația în care trebuie realizată o gestiune mai complexă decât cea oferită de clasele ''​AsyncTask'', ​''​IntentService''​ sau ''​Loader''​. +
- +
-În acest sens, este folosită o implementare a clasei ''​Thread'',​ procesarea pe un fir de execuție separat fiind realizată în cadrul metodei ''​run()''​. +
- +
-<​code ​java+
-private void executeOnSeparateThread() { +
-  ​Thread separateThread = new Thread(new Runnable() { +
-    @Override +
-    public void run() { +
-      ​// ... +
-    } +
-  }); +
-  separateThread.start();​ +
-}+
 </​code>​ </​code>​
- 
-Dacă se dorește actualizarea controalelor din cadrul interfeței grafice, este necesar ca firele de execuție care rulează în fundal să fie sincronizate cu firul de execuție principal anterior acestei operații. Acest lucru poate fi realizat: 
-  - folosind metoda ''​runOnUiThread()''​ care forțează codul transmis să fie executat pe același fir de execuție care redă interfața grafică: <code java> 
-runOnUiThread(new Runnable() { 
-  @Override 
-  public void run() { 
-    // ... 
-  } 
-}); 
-</​code>​ 
-  - utilizând un obiect de tip ''​Handler''​ pentru a realiza actualizări în contextul firului de execuție în care acesta a fost creat <code java> 
-private Handler handler = new Handler(); // created on the main thread 
- 
-private void executeOnSeparateThread() { 
-  Thread separateThread = new Thread(new Runnable() { 
-    @Override 
-    public void run() { 
-      // do some background processing here 
-      handler.post(new Runnable() { 
-        @Override 
-        public void run() { 
-          // access the graphical user interface here 
-        } 
-      }); 
-    } 
-  }); 
-  separateThread.start();​ 
-} 
-</​code>​ Clasa ''​Handler''​ pune la dispoziție și metode pentru a executa anumite metode la un moment dat de timp: 
-  * ''​postDelayed()''​ - realizează o modificare la nivelul interfeței grafice cu o întârziere specificată ca parametru (exprimat în milisecunde);​ 
-  * ''​postAtTime()''​ - realizează o modificare la nivelul interfeței grafice la un moment de timp specificat ca parametru (exprimat ca număr de milisecunde ce au trecut de la 1 ianuarie 1970. 
- 
-===== Activitate de Laborator ===== 
- 
-==== Intenții ==== 
-  - Să se creeze încă o fereastră (activitate) pe care să se afișeze o imagine. Aceasta trebuie să apară pe ecran în momentul în care se apasă butonul //​Fereastră Nouă//. 
-  - Să se adauge la fereastra creată anterior un buton de revenire. 
-  - Să se afișeze fereastra creată anterior și atunci când se apasă butonul //Inserați Fereastra//​. Să se afișeze sub imagine, într-un câmp text, care a fost butonul ce a determinat invocarea ferestrei. 
-  - Să se adauge la fereastra creată anterior un buton prin intermediul căruia să se schimbe imaginea existentă cu o alta. 
- 
-==== Fragmente ==== 
-  - Să se plaseze conținutul celor două ferestre create anterior în două fragmente aparținând aceleiași activități,​ afișându-se simultan pe ecran. 
-  - Să se adauge un două butoane în cadrul primului fragment pentru atașarea, respectiv detașarea celui de-al doilea fragment de la activitate. 
  
 ===== Resurse Utile ===== ===== Resurse Utile =====
laboratoare/laborator04.1426476244.txt.gz · Last modified: 2016/02/09 11:19 (external edit)
CC Attribution-Share Alike 3.0 Unported
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0