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:laborator05 [2016/03/25 01:23]
Andrei Roșu-Cojocaru
laboratoare:laborator05 [2017/02/20 20:54] (current)
Line 39: Line 39:
   <​application ...>   <​application ...>
     <service     <service
-      android:​name="​ro.pub.cs.systems.eim.lab04.SomeService"​+      android:​name="​ro.pub.cs.systems.eim.lab05.SomeService"​
       android:​enabled="​true"​       android:​enabled="​true"​
       android:​exported="​true"​       android:​exported="​true"​
-      android:​permission="​ro.pub.cs.systems.eim.lab04.SOME_SERVICE_PERMISSION"​ />+      android:​permission="​ro.pub.cs.systems.eim.lab05.SOME_SERVICE_PERMISSION"​ />
   </​application>​   </​application>​
 </​manifest>​ </​manifest>​
Line 154: Line 154:
 <note important>​În cazul metodelor care guvernează ciclul de viață al unui serviciu, NU este obligatoriu să se apeleze metodele din clasa părinte (nu se va genera nici o excepție în această situație).</​note>​ <note important>​În cazul metodelor care guvernează ciclul de viață al unui serviciu, NU este obligatoriu să se apeleze metodele din clasa părinte (nu se va genera nici o excepție în această situație).</​note>​
  
-{{ :​laboratoare:​laborator05:​01service_lifecycle.png?​nolink&​800 }}+{{ :eim:​laboratoare:​laborator05:​service_lifecycle.png?​nolink&​800 }}
  
 Se observă faptul că ciclul de viață al unui serviciu are loc între metodele ''​onCreate()''​ și ''​onDestroy()''​. De cele mai multe ori, este necesar ca un serviciu să folosească unul sau mai multe fire de execuție (dedicate) astfel încât să nu influențeze responsivitatea aplicației Android. Într-o astfel de situație, firul de execuție va fi pornit pe metoda ''​onCreate()''​ și va fi oprit pe metoda ''​onDestroy()''​. De asemenea, în cadrul metodei ''​onCreate()''​ au loc diferite operații de configurare (inițializări),​ în timp ce în cadrul metodei ''​onDestroy()''​ realizează eliberarea resurselor folosite. Metodele ''​onCreate()''​ și ''​onDestroy()''​ sunt invocate pentru toate tipurile de servicii, atât pentru cele de tip started, cât și pentru cele de tip bounded. Se observă faptul că ciclul de viață al unui serviciu are loc între metodele ''​onCreate()''​ și ''​onDestroy()''​. De cele mai multe ori, este necesar ca un serviciu să folosească unul sau mai multe fire de execuție (dedicate) astfel încât să nu influențeze responsivitatea aplicației Android. Într-o astfel de situație, firul de execuție va fi pornit pe metoda ''​onCreate()''​ și va fi oprit pe metoda ''​onDestroy()''​. De asemenea, în cadrul metodei ''​onCreate()''​ au loc diferite operații de configurare (inițializări),​ în timp ce în cadrul metodei ''​onDestroy()''​ realizează eliberarea resurselor folosite. Metodele ''​onCreate()''​ și ''​onDestroy()''​ sunt invocate pentru toate tipurile de servicii, atât pentru cele de tip started, cât și pentru cele de tip bounded.
Line 226: Line 226:
 Pentru oprirea unui serviciu este suficient un singur apel al uneia dintre metodele ''​stopSelf()''​ sau ''​stopService()''​. Pentru oprirea unui serviciu este suficient un singur apel al uneia dintre metodele ''​stopSelf()''​ sau ''​stopService()''​.
  
-== Utilizarea clasei ​PendingIntent ​==+== Utilizarea clasei ​IntentService ​==
  
 Recursul la clasa [[http://​developer.android.com/​reference/​android/​app/​IntentService.html|IntentService]] este adecvată în situația în care se dorește implementarea unor servicii care rulează în fundal, **pe un fir de execuție dedicat** realizând un set de operații la un moment dat de timp, atunci când sunt solicitate. În situația în care serviciul este accesat simultan de mai multe componente ale unei (unor) aplicații Android, procesarea acestora va fi realizată secvențial. Recursul la clasa [[http://​developer.android.com/​reference/​android/​app/​IntentService.html|IntentService]] este adecvată în situația în care se dorește implementarea unor servicii care rulează în fundal, **pe un fir de execuție dedicat** realizând un set de operații la un moment dat de timp, atunci când sunt solicitate. În situația în care serviciul este accesat simultan de mai multe componente ale unei (unor) aplicații Android, procesarea acestora va fi realizată secvențial.
Line 232: Line 232:
 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 într-o coadă de așteptare și executate succesiv, prin invocarea automată a metodei [[http://​developer.android.com/​reference/​android/​app/​IntentService.html#​onHandleIntent(android.content.Intent)|onHandleIntent()]]. După ce procesarea a fost finalizată,​ procesul se oprește singur (nu este necesar să se apeleze metodele ''​stopSelf()''​ sau ''​stopService()''​ explicit). 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 într-o coadă de așteptare și executate succesiv, prin invocarea automată a metodei [[http://​developer.android.com/​reference/​android/​app/​IntentService.html#​onHandleIntent(android.content.Intent)|onHandleIntent()]]. După ce procesarea a fost finalizată,​ procesul se oprește singur (nu este necesar să se apeleze metodele ''​stopSelf()''​ sau ''​stopService()''​ explicit).
  
-<note tip>​Clasa ''​PendingIntent''​ oferă o implementare implicită a metodelor ''​onStartCommand()''​ care plasează intenția către coada de așteptare și invocă metoda ''​onHandleIntent()''​ precum și a metodei ''​onBind()''​ care întoarce valoarea ''​null''​.</​note>​+<note tip>​Clasa ''​IntentService''​ oferă o implementare implicită a metodelor ''​onStartCommand()''​ care plasează intenția către coada de așteptare și invocă metoda ''​onHandleIntent()''​ precum și a metodei ''​onBind()''​ care întoarce valoarea ''​null''​.</​note>​
  
 Prin urmare, o implementare presupune definirea unei clase derivată din ''​IntentService''​ care suprascrie 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ă (în mod transparent) pe un fir de execuție ce rulează în fundal. De asemenea, trebuie furnizat și un constructor implicit. Prin urmare, o implementare presupune definirea unei clase derivată din ''​IntentService''​ care suprascrie 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ă (în mod transparent) pe un fir de execuție ce rulează în fundal. De asemenea, trebuie furnizat și un constructor implicit.
Line 453: Line 453:
  
 ==== Prioritatea unui Serviciu ==== ==== Prioritatea unui Serviciu ====
 +
 +În situația în care este necesar, sistemul de operare Android poate solicita memoria utilizată de un anumit serviciu, în funcție de prioritatea pe care acesta o are.
 +
 +Un serviciu de tip started are o prioritate mai mare decât o activitate inactivă, dar mai mică decât o activitate activă. Din acest motiv, este necesar ca programatorul să trateze cazurile în care serviciul este repornit, ca urmare a distrugerii sale de către sistemul de operare Android, în vederea satisfacerii necesarului de memorie.
 +
 +Un serviciu de tip bounded are de obicei o prioritate similară cu a activității cu care interacționează,​ deși aceasta poate fi controlată prin intermediul unor parametrii transmiși în momentul în care este realizată legătura. Este puțin probabil ca un serviciu atașat unei activități active să fie distrus la fel cum este destul de probabil ca un serviciu pentru care toate activitățile atașate sunt inactive să fie distrus.
 +
 +Un serviciu care rulează în prim-plan nu este aproape niciodată distrus.
  
 ==== Categorii de Procesări ==== ==== Categorii de Procesări ====
Line 462: Line 470:
 === Servicii ce Rulează în Prim-Plan === === Servicii ce Rulează în Prim-Plan ===
  
-Î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ă. ​+În situația în care un serviciu interacționează cu utilizatorul ​(sau utilizatorul este conștient de existența sa), prioritatea acestuia trebuie mărită, astfel încât sistemul de operare Android să nu poată reclama resursele pe care le utilizează. Un astfel de serviciu trebuie să poată oferi o notificare în bara de stare, care nu poate fi ascunsă decât atunci când serviciul este distrus sau nu mai rulează în prim-plan.
  
-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:​ +Un astfel de comportament poate fi obținut prin marcarea serviciului ca rulând în prim-plan, prin invocarea metodei ​[[http://​developer.android.com/​reference/​android/​app/​Service.html#​startForeground(int,​%20android.app.Notification)|startForeground()]] care primește ca parametri:​ 
-  * identificatorul unei notificări;​ +  * identificatorul unei notificări, care **trebuie să fie diferit de zero**; 
-  * 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.+  * un obiect de tip [[http://​developer.android.com/​reference/​android/​app/​Notification.html|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.
  
-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ă.+<code java> 
 +Notification ​notification = new Notification(R.drawable.icon,  
 +                                             "​...",​ 
 +                                             ​System.currentTimeMillis()); 
 +Intent intent = new Intent(this, SomeActivity.class); 
 +PendingIntent pendingIntent = PendingIntent.getActivity(this,​ 0, intent, 0); 
 +notification.setLatestEventInfo(this,​  
 +                                "​...",​ 
 +                                "​...",​  
 +                                pendingIntent);​ 
 +startForeground(NOTIFICATION_ID,​ notification);​ 
 +</​code>​
  
-<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>​+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)''​ (argumentul metodei indică dacă se dorește și terminarea notificării),​ aceasta anulând în mod automat notificarea asociată. 
 + 
 +<note tip>Nu este indicat ​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>​
  
 === Procesări Realizate în Fundal === === Procesări Realizate în Fundal ===
  
-Î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.+Î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.
  
 <​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>​ <​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>​
Line 481: Line 502:
  
 Android oferă mai multe mecanisme pentru gestiunea serviciilor care rulează în fundal: 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; +  - utilizarea clasei ​[[http://​developer.android.com/​reference/​android/​os/​AsyncTask.html|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 [[http://​developer.android.com/​reference/​android/​content/​Loader.html|Loader]];​ 
-  - definirea unei clase derivate din ''​Loader''​; +  - utilizarea clasei [[http://​developer.android.com/​reference/​android/​os/​Handler.html|Handler]]; 
-  - implementarea unui fir de execuție definit de utilizator, transmiterea valorilor către interfața grafică fiind realizat prin intermediul clasei ​''​Handler''​.+  - implementarea unui fir de execuție definit de utilizator, transmiterea valorilor către interfața grafică fiind realizat prin intermediul clasei ​[[http://​developer.android.com/​reference/​android/​os/​Handler.html|Handler]].
  
 == Clasa AsyncTask == == 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ă.+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>​ <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>​
Line 497: Line 518:
  
 Este necesară suprascrierea următoarelor metode: 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:​ +  * [[http://​developer.android.com/​reference/​android/​os/​AsyncTask.html#​doInBackground(Params...)|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 intermediul metodei ​[[http://​developer.android.com/​reference/​android/​os/​AsyncTask.html#​publishProgress(Progress...)|publishProgress()]], care primește ca parametru progresul realizat, valorile fiind transmise metodei ​[[http://​developer.android.com/​reference/​android/​os/​AsyncTask.html#​onProgressUpdate(Progress...)|onProgressUpdate()]]; 
-    * prin întoarcerea unui rezultat, atunci când procesarea este terminată, valoarea fiind transmisă metodei ​''​onPostExecute()''​;+    * prin întoarcerea unui rezultat, atunci când procesarea este terminată, valoarea fiind transmisă metodei ​[[http://​developer.android.com/​reference/​android/​os/​AsyncTask.html#​onPostExecute(Result)|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;   * ''​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;
 +  * ''​onPreExecute()''​ - apelată în contextului firului de execuție al interfeței grafice, înainte de metoda ''​doInBackground()'';​
   * ''​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.   * ''​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.
  
Line 509: Line 531:
     String result = new String();     String result = new String();
     int progress = 0;     int progress = 0;
-    for (int k = 1; k <= parameter[0].length(); ​k++) { +    for (int step = 1; step <= parameter[0].length(); ​step++) { 
-      progress = k; +      progress = step; 
-      result += parameter[0].charAt(parameter[0].length() - k);+      result += parameter[0].charAt(parameter[0].length() - step);
       try {       try {
         Thread.sleep(100);​         Thread.sleep(100);​
       } catch (InterruptedException interruptedException) {       } catch (InterruptedException interruptedException) {
-        Log.e(Constants.TAG,​ "An exception has occurred: "​+interruptedException.getMessage());​+        Log.e(Constants.TAG,​ "An exception has occurred: " + interruptedException.getMessage());​
       }       }
-      publishProgress(myProgress);+      publishProgress(progress);
     }     }
     return result;     return result;
Line 524: Line 546:
   @Override   @Override
   protected void onProgressUpdate(Integer... progress) {   protected void onProgressUpdate(Integer... progress) {
-    ​asyncTextView.setText(progress[0].toString());​+    ​progressTextView.setText(progress[0].toString());​ 
 +  } 
 + 
 +  @Override 
 +  protected void onPreExecute() { 
 +    // ...
   }   }
  
   @Override   @Override
   protected void onPostExecute(String result) {   protected void onPostExecute(String result) {
-    ​asyncTextView.setText(result);​+    ​progressTextView.setText(result);​
   }   }
 } }
Line 538: Line 565:
 <note important>​Fiecare obiect de tip ''​AsyncTask''​ poate fi rulat o singură dată. Apelurile ulterioare ale metodei ''​execute()''​ vor genera excepții. </​note>​ <note important>​Fiecare obiect de tip ''​AsyncTask''​ poate fi rulat o singură dată. Apelurile ulterioare ale metodei ''​execute()''​ vor genera excepții. </​note>​
  
-== Clasa Abstractă ​Loader ==+== Clasa Loader ==
  
 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). 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).
Line 547: Line 574:
  
 De regulă, se folosește o implementare a clasei ''​AsyncTaskLoader''​. De regulă, se folosește o implementare a clasei ''​AsyncTaskLoader''​.
 +
 +== Clasa Handler ==
 +
 +Clasa ''​Handler''​ gestionează transmiterea de mesaje sau execuția unor rutine asociate unor fire de execuție prin intermediul unei cozi de așteptare (de tipul [[http://​developer.android.com/​reference/​android/​os/​MessageQueue.html|MessageQueue]]). Un obiect de acest tip este asociat unui singur fir de execuție. Acesta este creat în momentul în care este realizată instanța, cătrea cesta fiind transmise toate mesajele, **secvențial**.
 +
 +Prin intermediul acestui obiect, se permite:
 +  * planificarea mesajelor spre a fi procesate la un moment fix din viitor (metodele de tip ''​send...()'':​ ''​sendEmptyMessage()'',​ ''​sendMessage()'',​ ''​sendMessageAtTime()'',​ ''​sendMessageDelayed()''​);​
 +  * încapsularea unei acțiuni care va fi executată pe un alt fir de execuție decât firul de execuție al interfeței grafice (metodele de tip ''​post...()'':​ ''​post()'',​ ''​postAtTime()'',​ ''​postDelayed()''​).
  
 == Utilizarea firelor de execuție definite de utilizator == == 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''​.+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'',​ ''​Handler''​ 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()''​. Î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> <code java>
-private void executeOnSeparateThread() { +private void executeOnDedicatedThread() { 
-  Thread ​separateThread ​= new Thread(new Runnable() {+  Thread ​dedicatedThread ​= new Thread(new Runnable() {
     @Override     @Override
     public void run() {     public void run() {
Line 562: Line 597:
     }     }
   });   });
-  ​separateThread.start();+  ​dedicatedThread.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: 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>+  - folosind metoda ​[[http://​developer.android.com/​reference/​android/​app/​Activity.html#​runOnUiThread(java.lang.Runnable)|Activity.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() { runOnUiThread(new Runnable() {
   @Override   @Override
Line 575: Line 610:
 }); });
 </​code>​ </​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>+  - utilizând un obiect de tip ''​Handler''​ pentru a realiza actualizări în contextul firului de execuție în care acesta a fost creat, utilizând metoda [[http://​developer.android.com/​reference/​android/​os/​Handler.html#​post(java.lang.Runnable)|post()]]: ​<code java>
 private Handler handler = new Handler(); // created on the main thread private Handler handler = new Handler(); // created on the main thread
  
Line 594: Line 629:
 } }
 </​code>​ Clasa ''​Handler''​ pune la dispoziție și metode pentru a executa anumite metode la un moment dat de timp: </​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);​ +  * [[http://​developer.android.com/​reference/​android/​os/​Handler.html#​postDelayed(java.lang.Runnable,​%20long)|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.+  * [[http://​developer.android.com/​reference/​android/​os/​Handler.html#​postAtTime(java.lang.Runnable,​%20long)|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.
  
 ==== Realizarea de Procesări prin Intermediul Alarmelor ==== ==== Realizarea de Procesări prin Intermediul Alarmelor ====
Line 607: Line 642:
 <​note>​În Android, alarmele rămân active chiar și atunci când dispozitivul mobil se găsește într-o stare de latență (//eng.// sleep mode), putând fi utilizate pentru a-l scoate din aceasta. Totuși, ele devin inactive în momentul în care dispozitivul mobil este repornit.</​note>​ <​note>​În Android, alarmele rămân active chiar și atunci când dispozitivul mobil se găsește într-o stare de latență (//eng.// sleep mode), putând fi utilizate pentru a-l scoate din aceasta. Totuși, ele devin inactive în momentul în care dispozitivul mobil este repornit.</​note>​
  
-Operațiile cu alarme sunt realizate prin intermediul serviciului de sistem ​''​AlarmManager'' ​care poate fi accesat prin intermediul metodei ​''​getSystemService()'' ​care primește ca parametru argumentul ​''​Context.ALARM_SERVICE''​.+Operațiile cu alarme sunt realizate prin intermediul serviciului de sistem ​[[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html|AlarmManager]] care poate fi accesat prin intermediul metodei ​[[http://​developer.android.com/​reference/​android/​content/​Context.html#​getSystemService%28java.lang.String%29|Context.getSystemService()]] care primește ca parametru argumentul ​[[http://​developer.android.com/​reference/​android/​content/​Context.html#​ALARM_SERVICE|Context.ALARM_SERVICE]].
  
 Există mai multe tipuri de alarme: Există mai multe tipuri de alarme:
-  * ''​RTC_WAKEUP'' ​- scoate dispozitivul mobil din starea de latență prin transmiterea unei intenții în așteptare, la un anumit moment de timp specificat;​ +  * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​RTC_WAKEUP|RTC_WAKEUP]] ​- scoate dispozitivul mobil din starea de latență prin transmiterea unei intenții în așteptare, la un anumit moment de timp specificat;​ 
-  * ''​RTC'' ​- transmite o intenție în așteptare, la un anumit moment de timp specificat, fără a scoate dispozitivul mobil din starea de latență;​ +  * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​RTC|RTC]] ​- transmite o intenție în așteptare, la un anumit moment de timp specificat, fără a scoate dispozitivul mobil din starea de latență;​ 
-  * ''​ELAPSED_REALTIME'' ​- transmite o intenție în așteptare, la un anumit interval de timp scurs de la momentul în care dispozitivul mobil a fost pornit, fără a-l scoate din starea de latență;​ +  * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​ELAPSED_REALTIME|ELAPSED_REALTIME]] ​- transmite o intenție în așteptare, la un anumit interval de timp scurs de la momentul în care dispozitivul mobil a fost pornit, fără a-l scoate din starea de latență;​ 
-  * ''​ELAPSED_REALTIME_WAKEUP'' ​- scoate dispozitivul mobil din starea de latență prin transmiterea unei intenții în așteptare, la un anumit interval de timp scurs de la momentul în care acesta a fost pornit.+  * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​ELAPSED_REALTIME_WAKEUP|ELAPSED_REALTIME_WAKEUP]] - scoate dispozitivul mobil din starea de latență prin transmiterea unei intenții în așteptare, la un anumit interval de timp scurs de la momentul în care acesta a fost pornit.
  
-În funcție de aceste valori, parametrul furnizat metodei ​''​set()'' ​a obiectului de tip ''​AlarmManager''​ reprezintă un moment de timp sau un interval.+În funcție de aceste valori, parametrul furnizat metodei ​[[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​set(int,​%20long,​%20android.app.PendingIntent)|set()]] ​a obiectului de tip ''​AlarmManager''​ reprezintă un moment de timp sau un interval.
  
 În momentul în care se declanșează,​ obiectul de tip ''​PendingIntent''​ este distribuit la nivelul tuturor componentelor sistemului de operare. În momentul în care se declanșează,​ obiectul de tip ''​PendingIntent''​ este distribuit la nivelul tuturor componentelor sistemului de operare.
Line 626: Line 661:
 </​code>​ </​code>​
  
-Anularea unei alarme se face prin intermediul metodei ​''​cancel()'' ​a obiectului de tip ''​AlarmManager''​ care primește ca parametru intenția în așteptare care nu mai trebuie transmisă.+Anularea unei alarme se face prin intermediul metodei ​[[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​cancel(android.app.PendingIntent)|cancel()]] ​a obiectului de tip ''​AlarmManager''​ care primește ca parametru intenția în așteptare care nu mai trebuie transmisă.
  
 <code java> <code java>
Line 633: Line 668:
  
 Utilizatorul are și posibilitatea de a indica anumite intervale de timp la care alarma este repetată, prin intermediul unor metode definite în clasa ''​AlarmManager'':​ Utilizatorul are și posibilitatea de a indica anumite intervale de timp la care alarma este repetată, prin intermediul unor metode definite în clasa ''​AlarmManager'':​
-  * ''​setRepeating()'' ​- utilizată când se dorește un control foarte exact asupra intervalului de timp la care alarma este repetată, exprimat la nivel de milisecunde;​ +  * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​setRepeating(int,​%20long,​%20long,​%20android.app.PendingIntent)|setRepeating()]] - utilizată când se dorește un control foarte exact asupra intervalului de timp la care alarma este repetată, exprimat la nivel de milisecunde;​ 
-  * ''​setInexactRepeating()'' ​- folosit pentru a economisi consumul de baterie realizat la scoaterea dispozitivului mobil din starea de latență de fiecare dată când este necesară realizarea unor sarcini planificate (care nu se suprapun); astfel, sistemul de operare Android va sincroniza mai multe alarme cu modul de repetare inexact, declanșându-le simultan; metoda primește ca parametru una dintre constantele:​ +  * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​setInexactRepeating(int,​%20long,​%20long,​%20android.app.PendingIntent)|setInexactRepeating()]] - folosit pentru a economisi consumul de baterie realizat la scoaterea dispozitivului mobil din starea de latență de fiecare dată când este necesară realizarea unor sarcini planificate (care nu se suprapun); astfel, sistemul de operare Android va sincroniza mai multe alarme cu modul de repetare inexact, declanșându-le simultan; metoda primește ca parametru una dintre constantele:​ 
-    * ''​INTERVAL_FIFTEEN_MINUTES''​ +    * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​INTERVAL_FIFTEEN_MINUTES|INTERVAL_FIFTEEN_MINUTES]] 
-    * ''​INTERVAL_HALF_HOUR''​ +    * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​INTERVAL_HALF_DAY|INTERVAL_HALF_HOUR]] 
-    * ''​INTERVAL_HOUR''​ +    * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​INTERVAL_HALF_HOUR|INTERVAL_HOUR]] 
-    * ''​INTERVAL_HALF_DAY''​ +    * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​INTERVAL_HALF_DAY|INTERVAL_HALF_DAY]] 
-    * ''​INTERVAL_DAY''​+    * [[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​INTERVAL_DAY|INTERVAL_DAY]]
 Ambele metode primesc ca parametrii tipul de alarmă, un moment de timp la care alarma va fi declanșată inițial și o intenție în așteptare care va fi transmisă. Ambele metode primesc ca parametrii tipul de alarmă, un moment de timp la care alarma va fi declanșată inițial și o intenție în așteptare care va fi transmisă.
  
Line 649: Line 684:
 <note important>​Impactul pe care alarmele recurente îl au asupra consumului de baterie poate fi semnificativ. De aceea, este recomandat ca frecvența de repetare a alarmei să fie cât mai mică, scoțând dispozitivul mobil din starea de latență numai atunci când este necesar și utilizând tipul de repetare inexact, dacă este posibil.</​note>​ <note important>​Impactul pe care alarmele recurente îl au asupra consumului de baterie poate fi semnificativ. De aceea, este recomandat ca frecvența de repetare a alarmei să fie cât mai mică, scoțând dispozitivul mobil din starea de latență numai atunci când este necesar și utilizând tipul de repetare inexact, dacă este posibil.</​note>​
  
-Anularea unei alarme recurente se face tot prin intermediul metodei ​''​cancel()'' ​a obiectului de tip ''​AlarmManager''​ care primește ca parametru intenția în așteptare care nu mai trebuie transmisă.+Anularea unei alarme recurente se face tot prin intermediul metodei ​[[http://​developer.android.com/​reference/​android/​app/​AlarmManager.html#​cancel(android.app.PendingIntent)|cancel()]] ​a obiectului de tip ''​AlarmManager''​ care primește ca parametru intenția în așteptare care nu mai trebuie transmisă.
  
 ===== Activitate de Laborator ===== ===== Activitate de Laborator =====
laboratoare/laborator05.1458861824.txt.gz · Last modified: 2017/02/20 20:44 (external edit)
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0