Differences

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

Link to this comparison view

eim:colocvii:colocviu01 [2016/03/26 19:38]
tmp.andrei.cojocaru
eim:colocvii:colocviu01 [2020/03/29 20:33] (current)
andrei.bolojan
Line 7: Line 7:
 </​HTML>​ </​HTML>​
  
-{{url>http://​ocw.cs.pub.ro/​courses/​_media/​eim/​colocvii/​colocviu01/​eim2016-tp01-varsim.pdf 90%,800px}}+{{url>https://​ocw.cs.pub.ro/​courses/​_media/​eim/​colocvii/​colocviu01/​eim-colocviu1-exemplu.pdf 90%,800px}}
  
 <​HTML>​ <​HTML>​
Line 13: Line 13:
 </​HTML>​ </​HTML>​
  
-{{ :​eim:​colocvii:​colocviu01:​eim2016-tp01-varsim.pdf }}+{{ :​eim:​colocvii:​colocviu01:​eim-colocviu1-exemplu.pdf }}
  
 ===== Observații Generale ===== ===== Observații Generale =====
Line 19: Line 19:
 Pentru rezolvarea subiectelor propuse în cadrul colocviului 1, sunt necesare: Pentru rezolvarea subiectelor propuse în cadrul colocviului 1, sunt necesare:
   * un cont Github personal, pe care să existe drepturi de citire și de scriere;   * un cont Github personal, pe care să existe drepturi de citire și de scriere;
-  * SDK-ul de Android (cu o imagine pentru nivelul de API 16 Jelly Bean 4.1); +  * SDK-ul de Android (cu o imagine pentru nivelul de API 24 Nougat 7.0); 
-  * mediul de dezvoltare integrat ​(Eclipse împreună cu plugin-ul Android Developer Tools sau Android Studio);+  * mediul de dezvoltare integrat Android Studio;
   * un dispozitiv mobil:   * un dispozitiv mobil:
     * fizic (bring your own device);     * fizic (bring your own device);
Line 32: Line 32:
 ===== Rezolvări ===== ===== Rezolvări =====
  
-Proiectul ​Eclipse ​corespunzător aplicației Android ce conține rezolvările complete ale cerințelor colocviului ​este disponibil ​pe [[https://​github.com/​pdsd2015/​PracticalTest01|contul de Github al disciplinei]].+Proiectul ​Android Studio ​corespunzător aplicației Android ce conține rezolvările complete ale cerințelor colocviului ​sunt disponibile ​pe [[https://​github.com/​eim-lab/​PracticalTest01|contul de Github al disciplinei]].
  
-**A.1.** Se accesează [[https://​www.github.com|Github]] și se realizează autentificarea în contul personal, prin intermediul butonului //Sign in//.+**A.1.** **a)** Se accesează [[https://​www.github.com|Github]] și se realizează autentificarea în contul personal, prin intermediul butonului //Sign in//.
  
-{{ :​eim:​colocvii:​colocviu01:​github_authentication.png?​nolink&​700 }}+{{ :​eim:​colocvii:​colocviu01:​github_authentication_new.png?​nolink&​700 }}
  
 Se creează o zonă de lucru corespunzătoare unui proiect prin intermediului butonului //New Repository//​. Se creează o zonă de lucru corespunzătoare unui proiect prin intermediului butonului //New Repository//​.
Line 55: Line 55:
 {{ :​eim:​colocvii:​colocviu01:​github_repository_configuration.png?​nolink }} {{ :​eim:​colocvii:​colocviu01:​github_repository_configuration.png?​nolink }}
  
-**A.2.** Prin intermediul comenzii ''​git clone''​ se poate descărca întregul conținut în directorul curent (de pe discul local), inclusiv istoricul complet al versiunilor anterioare (care poate fi ulterior reconstituit după această copie, în cazul coruperii informațiilor stocate pe serverul la distanță).+**b)** Prin intermediul comenzii ''​git clone''​ se poate descărca întregul conținut în directorul curent (de pe discul local), inclusiv istoricul complet al versiunilor anterioare (care poate fi ulterior reconstituit după această copie, în cazul coruperii informațiilor stocate pe serverul la distanță).
  
 <​note>​În situația în care se dorește clonarea conținutului din depozitul la distanță în alt director decât cel curent, acesta poate fi transmis ca parametru al comenzii, după URL-ul la care poate fi accesat proiectul în Github.</​note>​ <​note>​În situația în care se dorește clonarea conținutului din depozitul la distanță în alt director decât cel curent, acesta poate fi transmis ca parametru al comenzii, după URL-ul la care poate fi accesat proiectul în Github.</​note>​
  
 <​code>​ <​code>​
-student@eim2016:~$ git clone https://​www.github.com/​perfectstudent/​PracticalTest01+student@eg106:~$ git clone https://​www.github.com/​perfectstudent/​PracticalTest01
 </​code>​ </​code>​
  
-**A.3.** Se urmăresc indicațiile disponibile în secțiunea [[:​eim:​laboratoare:​laborator01#​crearea_unei_aplicatii_android_in_eclipse_mars_1_451_-_obligatoriu|Crearea unei aplicații Android în Eclipse Mars 1 (4.5.1)]] sau [[:​eim:​laboratoare:​laborator01#​crearea_unei_aplicatii_android_in_android_studio_151_-_obligatoriu|Crearea unei aplicații Android în Android Studio ​1.5.1]].+**c)** Se urmăresc indicațiile disponibile în secțiunea [[:​eim:​laboratoare:​laborator01#​crearea_unei_aplicatii_android_in_android_studio_-_obligatoriu|Crearea unei aplicații Android în Android Studio]].
  
-**A.4.** Implementarea interfeței grafice va fi realizată prin intermediul unui fișier ''​.xml''​ care va fi plasat în directorul ''/​res/​layout''​ al proiectului.+**A.2.** Implementarea interfeței grafice va fi realizată prin intermediul unui fișier ''​.xml''​ care va fi plasat în directorul ''/​res/​layout''​ al proiectului.
  
 De cele mai multe ori, interfața grafică poate fi realizată în două moduri: De cele mai multe ori, interfața grafică poate fi realizată în două moduri:
Line 282: Line 282:
 În activitatea corespunzătoare,​ interfața grafică definită în fișierul ''​.xml''​ trebuie încărcată pe metoda ''​onCreate()''​ prin intermediul ''​setContentView()'',​ căreia i se transmite ca parametru identificatorul (referința) către această resursă (așa cum a fost generată în clasa abstractă ''​R.layout''​). În situația în care este necesar să se realizeze anumite operații pe controalele grafice componente (spre exemplu, să se încarce conținutul acestora), trebuie inițial să se obțină o referință către aceasta printr-un apel al metodei ''​findViewById()'',​ care primește de asemenea ca parametru identificatorul (referința) către această resursă (așa cum a fost generată în clasa abstractă ''​R.id''​). În activitatea corespunzătoare,​ interfața grafică definită în fișierul ''​.xml''​ trebuie încărcată pe metoda ''​onCreate()''​ prin intermediul ''​setContentView()'',​ căreia i se transmite ca parametru identificatorul (referința) către această resursă (așa cum a fost generată în clasa abstractă ''​R.layout''​). În situația în care este necesar să se realizeze anumite operații pe controalele grafice componente (spre exemplu, să se încarce conținutul acestora), trebuie inițial să se obțină o referință către aceasta printr-un apel al metodei ''​findViewById()'',​ care primește de asemenea ca parametru identificatorul (referința) către această resursă (așa cum a fost generată în clasa abstractă ''​R.id''​).
  
-<​note>​Nu este necesar să se implementeze metodele ''​onCreateOptionsMenu()'',​ respectiv ''​onOptionsItemSelected()''​, acestea fiind de regulă generate în mod automat de mediul integrat de dezvoltare Eclipse.</​note>​+<​note>​Nu este necesar să se implementeze metodele ''​onCreateOptionsMenu()'',​ respectiv ''​onOptionsItemSelected()''​.</​note>​
  
 <file java PracticalTest01Activity.java>​ <file java PracticalTest01Activity.java>​
-package ro.pub.cs.systems.eim.practicaltest01;​ +package ro.pub.cs.systems.eim.practicaltest01.view
-  + 
-import android.app.Activity;+import android.content.BroadcastReceiver;​ 
 +import android.content.Context;
 import android.content.Intent;​ import android.content.Intent;​
 +import android.content.IntentFilter;​
 +import android.support.v7.app.AppCompatActivity;​
 import android.os.Bundle;​ import android.os.Bundle;​
-import android.view.Menu; +import android.util.Log;
-import android.view.MenuItem;+
 import android.view.View;​ import android.view.View;​
 import android.widget.Button;​ import android.widget.Button;​
 import android.widget.EditText;​ import android.widget.EditText;​
 import android.widget.Toast;​ import android.widget.Toast;​
 +
 +import ro.pub.cs.systems.eim.practicaltest01.R;​
 +import ro.pub.cs.systems.eim.practicaltest01.general.Constants;​
 +import ro.pub.cs.systems.eim.practicaltest01.service.PracticalTest01Service;​
    
-public class PracticalTest01MainActivity extends ​Activity ​{+public class PracticalTest01MainActivity extends ​AppCompatActivity ​{
  
-  private EditText leftEditText ​= null+  private EditText leftEditText;​ 
-  private EditText rightEditText ​= null+  private EditText rightEditText;​ 
-  private Button ​leftButton = null; +  private Button ​pressMeButton,​ pressMeTooButton;
-  private Button rightButton = null;+
    
   @Override   @Override
Line 311: Line 316:
     leftEditText = (EditText)findViewById(R.id.left_edit_text);​     leftEditText = (EditText)findViewById(R.id.left_edit_text);​
     rightEditText = (EditText)findViewById(R.id.right_edit_text);​     rightEditText = (EditText)findViewById(R.id.right_edit_text);​
 +     
 +    pressMeButton = (Button)findViewById(R.id.press_me_button);​
 +    pressMeTooButton = (Button)findViewById(R.id.press_me_too_button);​
 +     
     leftEditText.setText(String.valueOf(0));​     leftEditText.setText(String.valueOf(0));​
     rightEditText.setText(String.valueOf(0));​     rightEditText.setText(String.valueOf(0));​
-    ​ 
-    leftButton = (Button)findViewById(R.id.left_button);​ 
-    rightButton = (Button)findViewById(R.id.right_button);​ 
-  } 
-      ​ 
-  @Override 
-  public boolean onCreateOptionsMenu(Menu menu) { 
-    getMenuInflater().inflate(R.menu.practical_test01,​ menu); 
-    return true; 
-  } 
-  
-  @Override 
-  public boolean onOptionsItemSelected(MenuItem item) { 
-    int id = item.getItemId();​ 
-    if (id == R.id.action_settings) { 
-      return true; 
-    } 
-    return super.onOptionsItemSelected(item);​ 
   }   }
 } }
 </​file>​ </​file>​
- 
-În mediul integrat de dezvoltare Eclipse, completarea automată a import-urilor necesare este realizată prin //​Ctrl+Shift+O//​. 
  
 În mediul integrat de dezvoltare Android Studio, completarea automată a import-urilor necesare este realizată prin //​Alt+Enter//​. În mediul integrat de dezvoltare Android Studio, completarea automată a import-urilor necesare este realizată prin //​Alt+Enter//​.
Line 350: Line 339:
  
 <code java> <code java>
-public class PracticalTest01MainActivity extends ​Activity ​{+public class PracticalTest01MainActivity extends ​AppCompatActivity ​{
  
   private ButtonClickListener buttonClickListener = new ButtonClickListener();​   private ButtonClickListener buttonClickListener = new ButtonClickListener();​
Line 356: Line 345:
     @Override     @Override
     public void onClick(View view) {     public void onClick(View view) {
 +      int leftNumberOfClicks = Integer.valueOf(leftEditText.getText().toString());​
 +      int rightNumberOfClicks = Integer.valueOf(rightEditText.getText().toString());​
 +
       switch(view.getId()) {       switch(view.getId()) {
-        case R.id.left_button: +        case R.id.press_me_button:
-          int leftNumberOfClicks = Integer.parseInt(leftEditText.getText().toString());​+
           leftNumberOfClicks++;​           leftNumberOfClicks++;​
           leftEditText.setText(String.valueOf(leftNumberOfClicks));​           leftEditText.setText(String.valueOf(leftNumberOfClicks));​
           break;           break;
-        case R.id.right_button: +        case R.id.press_me_too_button:
-          int rightNumberOfClicks = Integer.parseInt(rightEditText.getText().toString());​+
           rightNumberOfClicks++;​           rightNumberOfClicks++;​
           rightEditText.setText(String.valueOf(rightNumberOfClicks));​           rightEditText.setText(String.valueOf(rightNumberOfClicks));​
Line 377: Line 367:
     // ...     // ...
  
-    ​leftButton.setOnClickListener(buttonClickListener);​ +    ​pressMeButton.setOnClickListener(buttonClickListener);​ 
-    ​rightButton.setOnClickListener(buttonClickListener); ​      ​+    ​pressMeTooButton.setOnClickListener(buttonClickListener); ​    ​
   }   }
   ​   ​
Line 431: Line 421:
  
     if (savedInstanceState != null) {     if (savedInstanceState != null) {
-      if (savedInstanceState.containsKey("​leftCount"​)) { +      if (savedInstanceState.containsKey(Constants.LEFT_COUNT)) { 
-        leftEditText.setText(savedInstanceState.getString("​leftCount"​));+        leftEditText.setText(savedInstanceState.getString(Constants.LEFT_COUNT));
       } else {       } else {
         leftEditText.setText(String.valueOf(0));​         leftEditText.setText(String.valueOf(0));​
       }       }
-      if (savedInstanceState.containsKey("​rightCount"​)) { +      if (savedInstanceState.containsKey(Constants.RIGHT_COUNT)) { 
-        rightEditText.setText(savedInstanceState.getString("​rightCount"​));+        rightEditText.setText(savedInstanceState.getString(Constants.RIGHT_COUNT));
       } else {       } else {
         rightEditText.setText(String.valueOf(0));​         rightEditText.setText(String.valueOf(0));​
Line 449: Line 439:
   @Override   @Override
   protected void onSaveInstanceState(Bundle savedInstanceState) {   protected void onSaveInstanceState(Bundle savedInstanceState) {
-    savedInstanceState.putString("​leftCount"​, leftEditText.getText().toString());​ +    savedInstanceState.putString(Constants.LEFT_COUNT, leftEditText.getText().toString());​ 
-    savedInstanceState.putString("​rightCount"​, rightEditText.getText().toString());​+    savedInstanceState.putString(Constants.RIGHT_COUNT, rightEditText.getText().toString());​
   }   }
   ​   ​
   @Override   @Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {   protected void onRestoreInstanceState(Bundle savedInstanceState) {
-    if (savedInstanceState.containsKey("​leftCount"​)) { +    if (savedInstanceState.containsKey(Constants.LEFT_COUNT)) { 
-      leftEditText.setText(savedInstanceState.getString("​leftCount"​));+      leftEditText.setText(savedInstanceState.getString(Constants.LEFT_COUNT));
     } else {     } else {
       leftEditText.setText(String.valueOf(0));​       leftEditText.setText(String.valueOf(0));​
     }     }
-    if (savedInstanceState.containsKey("​rightCount"​)) { +    if (savedInstanceState.containsKey(Constants.RIGHT_COUNT)) { 
-      rightEditText.setText(savedInstanceState.getString("​rightCount"​));+      rightEditText.setText(savedInstanceState.getString(Constants.RIGHT_COUNT));
     } else {     } else {
       rightEditText.setText(String.valueOf(0));​       rightEditText.setText(String.valueOf(0));​
Line 473: Line 463:
 **c)** Pentru a simula faptul că sistemul de operare Android distruge activitatea pentru asigurarea necesarului de resurse, se poate proceda astfel: **c)** Pentru a simula faptul că sistemul de operare Android distruge activitatea pentru asigurarea necesarului de resurse, se poate proceda astfel:
   - se oprește activitatea prin accesarea butonului //Menu//, astfel încât activitatea să rămână în memorie, fără a fi însă vizibilă, asigurându-se totodată apelarea metodelor ''​onPause()''​ și ''​onStop()''​ și implicit a metodei ''​onSaveInstanceState()'';​   - se oprește activitatea prin accesarea butonului //Menu//, astfel încât activitatea să rămână în memorie, fără a fi însă vizibilă, asigurându-se totodată apelarea metodelor ''​onPause()''​ și ''​onStop()''​ și implicit a metodei ''​onSaveInstanceState()'';​
-  - în DDMSse identifică procesul corespunzător activății respective și se oprește ​forțat (prin intermediul butonului //Stop//);\\ {{ :​eim:​colocvii:​colocviu01:​ddms.png?​nolink&​400 }}+  - în Android Studioîn secțiunea //​AndroidMonitor//, ​se oprește ​aplicația Android ​prin intermediul butonului //Terminate Application//\\ {{ :​eim:​colocvii:​colocviu01:​android_monitor.png?​nolink&​900 }}
   - se (re)pornește activitatea din meniul dispozitivului mobil, astfel încât să  se apeleze metodele ''​onCreate()'',​ respectiv ''​onStart()''​ și ''​onResume()''​ (și, implicit, ''​onRestoreInstanceState()''​).   - se (re)pornește activitatea din meniul dispozitivului mobil, astfel încât să  se apeleze metodele ''​onCreate()'',​ respectiv ''​onStart()''​ și ''​onResume()''​ (și, implicit, ''​onRestoreInstanceState()''​).
  
 <note tip> <note tip>
-În mediul integrat de dezvoltare Eclipse, DDMS (Dalvik Debug Monitor System) este pornit din //Window// → //Open Perspective//​ → //Other// → //DDMS//. +În mediul integrat de dezvoltare Android Studio, ​AMS (Android Device ​Monitor) este pornit din //Tools// → //Android// → //Android Device Monitor//.
- +
-În mediul integrat de dezvoltare Android Studio, ​DDMS (Dalvik Debug Monitor ​System) este pornit din //Tools// → //Android// → //Android Device Monitor//.+
 </​note>​ </​note>​
- 
-**d)** În situația în care utilizatorul apasă butonul //Back//, se apelează metodele ''​onPause()'',​ ''​onStop()''​ și ''​onDestroy()'',​ fără a se invoca însă și metoda ''​onSaveInstanceState()''​ întrucât se consideră că în această situație utilizatorul nu își dorește să revină la starea curentă a activității. Din acest motiv, starea nu este salvată în obiectul de tip ''​Bundle''​ și acesta nu va conține informațiile respective care să poată fi astfel restaurate. 
- 
-Dacă se dorește salvarea / restaurarea stării în situația în care utilizatorul apasă tasta //Back//, se recomandă să se utilizeze un alt mecanism pentru asigurarea persistenței,​ cum ar fi baza de date SQLite sau un obiect de tipul ''​android.content.SharedPreferences''​. 
  
 **C.1.** Într-o aplicație Android, o activitate trebuie să fie precizată prin următoarele elemente: **C.1.** Într-o aplicație Android, o activitate trebuie să fie precizată prin următoarele elemente:
Line 491: Line 475:
   * o clasă derivată din ''​Activity'',​ în care să se implementeze cel puțin metoda ''​onCreate()'',​ pe care să se încarce interfața grafică definită anterior.   * o clasă derivată din ''​Activity'',​ în care să se implementeze cel puțin metoda ''​onCreate()'',​ pe care să se încarce interfața grafică definită anterior.
  
-Crearea ​acestor resurse este realizată în mod automat ​în mediul integrat de dezvoltare Eclipse ​în momentul în care se solicită definirea unei resurse de tip //Android Activity// (//File// → //New// → //Other// → //Android// → //​Android ​Activity//​). +În mediul integrat de dezvoltare Android Studio, crearea ​acestor resurse este realizată în mod automat în momentul în care se solicită definirea unei resurse de tip //Android Activity// (//File// → //New// → //Activity// → //Blank Activity//​).
- +
-{{ :​eim:​colocvii:​colocviu01:​eclipse_activity01.png?​nolink&​500 }} +
- +
-{{ :​eim:​colocvii:​colocviu01:​eclipse_activity02.png?​nolink&​500 }} +
- +
-{{ :​eim:​colocvii:​colocviu01:​eclipse_activity03.png?​nolink&​500 }}+
  
-{{ :​eim:​colocvii:​colocviu01:​eclipse_activity04.png?​nolink&​500 }}+{{ :​eim:​colocvii:​colocviu01:​androidstudio_activity.png?​nolink&​600 }}
  
 **a)** În fișierul ''​AndroidManifest.xml''​ se specifică activitatea printr-o element de tip ''<​activity>''​ în cadrul etichetei ''<​application>''​ pentru care se definesc: **a)** În fișierul ''​AndroidManifest.xml''​ se specifică activitatea printr-o element de tip ''<​activity>''​ în cadrul etichetei ''<​application>''​ pentru care se definesc:
Line 508: Line 486:
     * eticheta ''<​category>''​ clasifică activitatea,​ impunându-se să fie folosită valoarea ''​android.intent.category.DEFAULT''​ pentru ca activitatea să poată fi invocată prin intermediul unei intenții.     * eticheta ''<​category>''​ clasifică activitatea,​ impunându-se să fie folosită valoarea ''​android.intent.category.DEFAULT''​ pentru ca activitatea să poată fi invocată prin intermediul unei intenții.
  
-<note tip>​În ​cazul în care activitatea este generată folosind mediul integrat de dezvoltare Eclipse, în fișierul ''​AndroidManifest.xml''​ nu se completează în mod automat și filtrul de intenții, fiind necesar ca acesta să fie menționat de utilizator, manual.</​note>​+<note tip>În fișierul ''​AndroidManifest.xml''​ nu se completează în mod automat și filtrul de intenții, fiind necesar ca acesta să fie menționat de utilizator, manual.</​note>​
  
 <file xml AndroidManifest.xml>​ <file xml AndroidManifest.xml>​
 <​manifest ... > <​manifest ... >
   <​application ... >   <​application ... >
-    <​activity +    <​activity android:​name="​.view.PracticalTest01SecondaryActivity">​
-      ​android:​name="​.PracticalTest01SecondaryActivity+
-      android:​label="​@string/​title_activity_practical_test01_secondary" >+
       <​intent-filter>​       <​intent-filter>​
-        <action android:​name="​ro.pub.cs.systems.eim.intent.action.PracticalTest01SecondaryActivity"​ />+        <action android:​name="​ro.pub.cs.systems.eim.practicaltest01.intent.action.PracticalTest01SecondaryActivity"​ />
         <​category android:​name="​android.intent.category.DEFAULT"​ />         <​category android:​name="​android.intent.category.DEFAULT"​ />
       </​intent-filter>​       </​intent-filter>​
Line 574: Line 550:
  
 <file java PracticalTest01SecondaryActivity.java>​ <file java PracticalTest01SecondaryActivity.java>​
-package ro.pub.cs.systems.eim.practicaltest01;​ +package ro.pub.cs.systems.eim.practicaltest01.view
-  +
-import android.app.Activity;​+
 import android.content.Intent;​ import android.content.Intent;​
 +import android.support.v7.app.AppCompatActivity;​
 import android.os.Bundle;​ import android.os.Bundle;​
-import android.view.Menu;​ 
-import android.view.MenuItem;​ 
 import android.view.View;​ import android.view.View;​
 import android.widget.Button;​ import android.widget.Button;​
 import android.widget.TextView;​ import android.widget.TextView;​
-  + 
-public class PracticalTest01SecondaryActivity extends ​Activity ​+import ro.pub.cs.systems.eim.practicaltest01.R;​ 
-  +import ro.pub.cs.systems.eim.practicaltest01.general.Constants;​ 
-  private TextView numberOfClicksTextView ​= null+ 
-  private Button okButton ​= null; +public class PracticalTest01SecondaryActivity extends ​AppCompatActivity ​
-  private Button ​cancelButton ​= null+ 
- +  private TextView numberOfClicksTextView;​ 
 +  private Button okButtoncancelButton;​ 
   private ButtonClickListener buttonClickListener = new ButtonClickListener();​   private ButtonClickListener buttonClickListener = new ButtonClickListener();​
   private class ButtonClickListener implements View.OnClickListener {   private class ButtonClickListener implements View.OnClickListener {
     @Override     @Override
     public void onClick(View view) {     public void onClick(View view) {
-      switch(view.getId()) {+      switch (view.getId()) {
         case R.id.ok_button:​         case R.id.ok_button:​
           setResult(RESULT_OK,​ null);           setResult(RESULT_OK,​ null);
Line 604: Line 580:
       }       }
       finish();       finish();
-    ​}+      ​}
   }   }
-  ​+
   @Override   @Override
   protected void onCreate(Bundle savedInstanceState) {   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);​     super.onCreate(savedInstanceState);​
     setContentView(R.layout.activity_practical_test01_secondary);​     setContentView(R.layout.activity_practical_test01_secondary);​
-    ​+
     numberOfClicksTextView = (TextView)findViewById(R.id.number_of_clicks_text_view);​     numberOfClicksTextView = (TextView)findViewById(R.id.number_of_clicks_text_view);​
     Intent intent = getIntent();​     Intent intent = getIntent();​
-    if (intent != null && intent.getExtras().containsKey("​numberOfClicks"​)) { +    if (intent != null && intent.getExtras().containsKey(Constants.NUMBER_OF_CLICKS)) { 
-      int numberOfClicks = intent.getIntExtra("​numberOfClicks"​, -1);+      int numberOfClicks = intent.getIntExtra(Constants.NUMBER_OF_CLICKS, -1);
       numberOfClicksTextView.setText(String.valueOf(numberOfClicks));​       numberOfClicksTextView.setText(String.valueOf(numberOfClicks));​
     }     }
-    ​+
     okButton = (Button)findViewById(R.id.ok_button);​     okButton = (Button)findViewById(R.id.ok_button);​
     okButton.setOnClickListener(buttonClickListener);​     okButton.setOnClickListener(buttonClickListener);​
     cancelButton = (Button)findViewById(R.id.cancel_button);​     cancelButton = (Button)findViewById(R.id.cancel_button);​
     cancelButton.setOnClickListener(buttonClickListener);​     cancelButton.setOnClickListener(buttonClickListener);​
-  } 
-  
-  @Override 
-  public boolean onCreateOptionsMenu(Menu menu) { 
-    getMenuInflater().inflate(R.menu.practical_test01_secondary,​ menu); 
-    return true; 
-  } 
-  
-  @Override 
-  public boolean onOptionsItemSelected(MenuItem item) { 
-    int id = item.getItemId();​ 
-    if (id == R.id.action_settings) { 
-      return true; 
-    } 
-    return super.onOptionsItemSelected(item);​ 
   }   }
 } }
Line 681: Line 642:
  
 <code java> <code java>
-public class PracticalTest01MainActivity extends ​Activity ​{+public class PracticalTest01MainActivity extends ​AppCompatActivity ​{
            
-  ​private final static int SECONDARY_ACTIVITY_REQUEST_CODE = 1; +  private Button navigateToSecondaryActivityButton;​
-   +
-  ​private Button navigateToSecondaryActivityButton ​= null;+
   ​   ​
   private ButtonClickListener buttonClickListener = new ButtonClickListener();​   private ButtonClickListener buttonClickListener = new ButtonClickListener();​
-  private class ButtonClickListener implements ​Button.OnClickListener {+  private class ButtonClickListener implements ​View.OnClickListener {
                    
     @Override     @Override
Line 695: Line 654:
         case R.id.navigate_to_secondary_activity_button:​         case R.id.navigate_to_secondary_activity_button:​
           Intent intent = new Intent(getApplicationContext(),​ PracticalTest01SecondaryActivity.class);​           Intent intent = new Intent(getApplicationContext(),​ PracticalTest01SecondaryActivity.class);​
-   ​int numberOfClicks = Integer.parseInt(leftEditText.getText().toString()) + +          ​int numberOfClicks = Integer.parseInt(leftEditText.getText().toString()) +
                                ​Integer.parseInt(rightEditText.getText().toString());​                                ​Integer.parseInt(rightEditText.getText().toString());​
-          intent.putExtra("​numberOfClicks"​, numberOfClicks);​ +          intent.putExtra(Constants.NUMBER_OF_CLICKS, numberOfClicks);​ 
-          startActivityForResult(intent,​ SECONDARY_ACTIVITY_REQUEST_CODE);​+          startActivityForResult(intent, ​Constants.SECONDARY_ACTIVITY_REQUEST_CODE);​
           break;           break;
         // ...         // ...
Line 717: Line 676:
   @Override   @Override
   protected void onActivityResult(int requestCode,​ int resultCode, Intent intent) {   protected void onActivityResult(int requestCode,​ int resultCode, Intent intent) {
-    if (requestCode == SECONDARY_ACTIVITY_REQUEST_CODE) {+    if (requestCode == Constants.SECONDARY_ACTIVITY_REQUEST_CODE) {
       Toast.makeText(this,​ "The activity returned with result " + resultCode, Toast.LENGTH_LONG).show();​       Toast.makeText(this,​ "The activity returned with result " + resultCode, Toast.LENGTH_LONG).show();​
     }     }
Line 727: Line 686:
 </​code>​ </​code>​
  
-**D.1.** Pentru a putea fi utilizat, serviciul trebuie să fie declarat în fișierul ''​AndroidManifest.xml''​. Este obligatoriu să se definească proprietatea ''​android:​name''​ care desemnează clasa care gestionează serviciul.+**D.1.** **a)** Pentru a putea fi utilizat, serviciul trebuie să fie declarat în fișierul ''​AndroidManifest.xml''​. Este obligatoriu să se definească proprietatea ''​android:​name''​ care desemnează clasa care gestionează serviciul.
  
 Opțional, pot fi precizate și atributele: Opțional, pot fi precizate și atributele:
Line 739: Line 698:
   <​application ...>   <​application ...>
     <!-- other components -->     <!-- other components -->
-    <service  +    <​service 
-      android:​name="​ro.pub.cs.systems.eim.PracticalTest01Service"​+      android:​name="​.service.PracticalTest01Service"​
       android:​enabled="​true"​       android:​enabled="​true"​
       android:​exported="​false"​ />       android:​exported="​false"​ />
Line 757: Line 716:
 import android.content.Intent;​ import android.content.Intent;​
 import android.os.IBinder;​ import android.os.IBinder;​
 +
 +import ro.pub.cs.systems.eim.practicaltest01.general.Constants;​
  
 public class PracticalTest01Service extends Service { public class PracticalTest01Service extends Service {
Line 764: Line 725:
   @Override   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {   public int onStartCommand(Intent intent, int flags, int startId) {
-    int firstNumber = intent.getIntExtra("​firstNumber"​, -1); +    int firstNumber = intent.getIntExtra(Constants.FIRST_NUMBER, -1); 
-    int secondNumber = intent.getIntExtra("​secondNumber"​, -1);+    int secondNumber = intent.getIntExtra(Constants.SECOND_NUMBER, -1);
     processingThread = new ProcessingThread(this,​ firstNumber,​ secondNumber);​     processingThread = new ProcessingThread(this,​ firstNumber,​ secondNumber);​
     processingThread.start();​     processingThread.start();​
Line 793: Line 754:
 import android.content.Intent;​ import android.content.Intent;​
 import android.util.Log;​ import android.util.Log;​
 +
 +import ro.pub.cs.systems.eim.practicaltest01.general.Constants;​
  
 public class ProcessingThread extends Thread { public class ProcessingThread extends Thread {
Line 813: Line 776:
   @Override   @Override
   public void run() {   public void run() {
-    Log.d("​[ProcessingThread]"​, "​Thread has started!"​);​+    Log.d(Constants.PROCESSING_THREAD_TAG, "​Thread has started! ​PID: " + Process.myPid() + " TID: " ​+ Process.myTid());
     while (isRunning) {     while (isRunning) {
       sendMessage();​       sendMessage();​
       sleep();       sleep();
     }     }
-    Log.d("​[ProcessingThread]"​, "​Thread has stopped!"​);​+    Log.d(Constants.PROCESSING_THREAD_TAG, "​Thread has stopped!"​);​
   }   }
   ​   ​
Line 824: Line 787:
     Intent intent = new Intent();     Intent intent = new Intent();
     intent.setAction(Constants.actionTypes[random.nextInt(Constants.actionTypes.length)]);​     intent.setAction(Constants.actionTypes[random.nextInt(Constants.actionTypes.length)]);​
-    intent.putExtra("​message"​, new Date(System.currentTimeMillis()) + " " + arithmeticMean + " " + geometricMean);​+    intent.putExtra(Constants.BROADCAST_RECEIVER_EXTRA, 
 +            ​new Date(System.currentTimeMillis()) + " " + arithmeticMean + " " + geometricMean);​
     context.sendBroadcast(intent);​     context.sendBroadcast(intent);​
   }   }
Line 851: Line 815:
     - se transmite intenția cu difuzare la nivelul sistemului de operare Android prin invocarea metodei ''​sendBroadcast()''​ (definită în clasa ''​Context''​);​     - se transmite intenția cu difuzare la nivelul sistemului de operare Android prin invocarea metodei ''​sendBroadcast()''​ (definită în clasa ''​Context''​);​
   - așteptarea unui interval de timp (10.000 ms) până la următoarea iterație, prin intermediul unui apel ''​Thread.sleep()''​.   - așteptarea unui interval de timp (10.000 ms) până la următoarea iterație, prin intermediul unui apel ''​Thread.sleep()''​.
 +Trebuie implementată și o metodă pentru oprirea rulării firului de execuție în situația în care serviciul asociat este distrus.
 +
 +**b)** În clasa ''​PracticalTest01Acivity'',​ sunt plasate operațiile de pornire și de oprire a serviciului.
 +
 +Verificarea momentului în care trebuie pornit serviciul este realizată pe metoda ascultător a evenimentului de apăsare a unui buton. Se realizează suma dintre valorile conținute în cele două câmpuri text editabile și, în situația în care aceasta depășește pragul minim stabilit și dacă serviciul se găsește în starea oprit, atunci poate fi invocată metoda ''​startService()''​. Aceasta primește ca argument un obiect de tip ''​Intent''​ (explicit, instanțiat cu contextul și cu clasa aferentă serviciului) în care sunt plasate, în câmpul ''​extra'',​ valorile din câmpurile text editabile sub cheile ''​firstNumber''​ și ''​secondNumber''​.
 +
 +<code java>
 +private class ButtonClickListener implements View.OnClickListener {
 +  @Override
 +  public void onClick(View view) {
 +    int leftNumberOfClicks = Integer.parseInt(leftEditText.getText().toString());​
 +    int rightNumberOfClicks = Integer.parseInt(rightEditText.getText().toString());​
 +
 +    // ...
 +    ​
 +    if (leftNumberOfClicks + rightNumberOfClicks > Constants.NUMBER_OF_CLICKS_THRESHOLD
 +        && serviceStatus == Constants.SERVICE_STOPPED) {
 +      Intent intent = new Intent(getApplicationContext(),​ PracticalTest01Service.class);​
 +      intent.putExtra(Constants.FIRST_NUMBER,​ leftNumberOfClicks);​
 +      intent.putExtra(Constants.SECOND_NUMBER,​ rightNumberOfClicks);​
 +      getApplicationContext().startService(intent);​
 +      serviceStatus = Constants.SERVICE_STARTED;​
 +    }
 +  }
 +}
 +</​code>​
 +
 +Momentul la care este oprit serviciul coincide cu distrugerea activității,​ așadar pe metoda de callback ''​onDestroy()''​. Similar, această operație poate fi realizată și pe metoda de callback ''​onStop()''​. Metoda ''​stopService()''​ primește ca argument tot un obiect de tip ''​Intent''​ construit explicit, cu numele clasei care deservește serviciul.
 +
 +<code java>
 +@Override
 +protected void onDestroy() {
 +  Intent intent = new Intent(this,​ PracticalTest01Service.class);​
 +  stopService(intent);​
 +  super.onDestroy();​
 +}
 +</​code>​
 +
 +Dacă serviciul este oprit, el va fi distrus de sistemul de operare Android (deși ''​stopService()''​ nu implică invocarea unei metode de callback la nivelul serviciului,​ totuși acesta va fi oprit și ulterior distrus). Pe metoda ''​onDestroy()''​ a serviciului,​ trebuie să se aibă grijă ca rutina din cadrul firului de execuție asociat să se termine.
 +
 +**D.2.** Un ascultător pentru intenții cu difuzare este o clasă derivată din ''​android.content.BroadcastReceiver''​. Acesta poate fi declarat în fișierul ''​AndroidManifest.xml'',​ dacă se dorește ca acesta să fie invocat în mod automat chiar dacă aplicația Android din care face parte nu este instanțiată sau poate fi înregistrat / deînregistrat pe metodele de callback ''​onResume()''​ / ''​onPause()''​ dacă se dorește ca funcționarea sa să fie limitată la perioada în care activitatea este disponibilă pe suprafața de afișare a dispozitivului mobil.
 +
 +În momentul în care o intenție cu difuzare are aceeași acțiune ca cea indicată în filtrul de intenții asociat ascultătorului respectiv, este apelată în mod automat metoda de callback ''​onReceive(context,​ intent)''​. Aceasta va fi responsabilă exclusiv cu jurnalizarea valorii asociate cheii ''​message''​ din câmpul ''​extra''​ asociat intenției cu difuzare respective.
 +
 +<code java>
 +private MessageBroadcastReceiver messageBroadcastReceiver = new MessageBroadcastReceiver();​
 +private class MessageBroadcastReceiver extends BroadcastReceiver {
 +  @Override
 +  public void onReceive(Context context, Intent intent) {
 +     ​Log.d(Constants.BROADCAST_RECEIVER_TAG,​ intent.getStringExtra(Constants.BROADCAST_RECEIVER_EXTRA));​
 +  }
 +}
 +</​code>​
 +
 +Un ascultător pentru intenții cu difuzare trebuie să aibă asociat și un filtru de intenții. Acesta conține acțiunile asociate intențiilor cu difuzare, pe care ascultătorul respectiv trebuie să le proceseze.
 +
 +<code java>
 +public class PracticalTest01MainActivity extends Activity {
 +
 +  // ...
 +  ​
 +  private IntentFilter intentFilter = new IntentFilter();​
 +
 +  @Override
 +  protected void onCreate(Bundle savedInstanceState) {
 +    super.onCreate(savedInstanceState);​
 +    setContentView(R.layout.activity_practical_test01_main);​
 +
 +    for (int index = 0; index < Constants.actionTypes.length;​ index++) {
 +      intentFilter.addAction(Constants.actionTypes[index]);​
 +    }
 +  }
 +}
 +</​code>​
 +
 +Operațiile de activare, respectiv de dezactivare a ascultătorului pentru intenții cu difuzare, sunt realizate pe metodele de callback ale activității ''​onResume()'',​ respectiv ''​onPause()''​. În acest fel, se asigură faptul că ascultătorul pentru intenții cu difuzare nu va procesa decât mesajele transmise în perioada în care activitatea este afișată pe suprafața de afișare a dispozitivului mobil.
 +
 +<code java>
 +public class PracticalTest01MainActivity extends Activity {
 +
 +  // ...
 +
 +  @Override
 +  protected void onResume() {
 +    super.onResume();​
 +    registerReceiver(messageBroadcastReceiver,​ intentFilter);​
 +  }
 +  ​
 +  @Override
 +  protected void onPause() {
 +    unregisterReceiver(messageBroadcastReceiver);​
 +    super.onPause();​
 +  }
 +}
 +</​code>​
  
 **D.3.** Pentru încărcarea codului în contextul depozitului din cadrul contului Github personal: **D.3.** Pentru încărcarea codului în contextul depozitului din cadrul contului Github personal:
Line 860: Line 919:
  
 <​code>​ <​code>​
-student@eim2016:​~/​PracticalTest01$ git add * +student@eg106:​~/​PracticalTest01$ git add * 
-student@eim2016:​~/​PracticalTest01$ git commit -m "​finished tasks for PracticalTest01"​ +student@eg106:​~/​PracticalTest01$ git commit -m "​finished tasks for PracticalTest01"​ 
-student@eim2016:​~/​PracticalTest01$ git push origin master+student@eg106:​~/​PracticalTest01$ git push origin master
 </​code>​ </​code>​
  
Line 868: Line 927:
  
 <​code>​ <​code>​
-student@eim2016:​~/​PracticalTest01$ git config --global user.name "​Perfect Student"​ +student@eg106:​~/​PracticalTest01$ git config --global user.name "​Perfect Student"​ 
-student@eim2016:​~/​PracticalTest01$ git config --global user.email perfectstudent@cs.pub.ro+student@eg106:​~/​PracticalTest01$ git config --global user.email perfectstudent@cs.pub.ro
 </​code>​ </​code>​
eim/colocvii/colocviu01.1459013912.txt.gz · Last modified: 2016/03/26 19:38 by tmp.andrei.cojocaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0