This is an old revision of the document!
Conceptul de intenție în Android este destul de complex (și unic), putând fi definit ca o acțiune având asociată o serie de informații, transmisă sistemului de operare Android pentru a fi executată sub forma unui mesaj asincron. În acest fel, intenția asigură interacțiunea între toate aplicațiile instalate pe dispozitivul mobil, chiar dacă fiecare în parte are o existență autonomă. Din această perspectivă, sistemul de operare Android poate fi privit ca o colecție de componente funcționale, independente și interconectate.
De regulă, o intenție poate fi utilizată pentru:
O intenție reprezintă o instanță a clasei android.content.Intent. Aceasta este transmisă ca parametru unor metode (de tipul startActivity() sau startService(), definite în clasa abstractă android.content.Context), pentru a invoca anumite componente (activități sau servicii). Un astfel de obiect poate încapsula anumite date (împachetate sub forma unui android.os.Bundle), care pot fi utilizate de componenta ce se dorește a fi executată prin intermediul intenției.
În programarea Android, un principiu de bază este de folosi intenții pentru a propaga acțiuni, chiar și în cadrul aceleiași aplicații, în detrimentul încărcării clasei corespunzătoare. În acest fel, se asigură cuplarea slabă a componentelor, oferind flexibilitate în cazul înlocuirii acestora, permițând totodată extinderea funcționalității cu ușurință.
În fișierul AndroidManifest.xml, orice activitate definește în cadrul elementului <html><intent-filter></html>, denumirea unei acțiuni care va putea fi folosită de o intenție pentru a o invoca.
<activity android:name="org.rosedu.dandroid.lab05.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="org.rosedu.dandroid.lab05.intent.action.MainActivity" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Pentru ca o funcționalitatea expusă de o activitate să poată fi invocată (în mod anonim) și din contextul altor componente ale sistemului de operare Android, pentru tipul de acțiune și pentru tipurile de date precizate, în cadrul secțiunii <html><intent-filter></html> trebuie precizat atributul android:label (șir de caractere care conține o descriere a funcționalității implementate), indicându-se ca tip de categorie valorile ALTERNATIVE, SELECTED_ALTERNATIVE sau ambele.
O activitate este în principiu invocată de o intenție care poate fi identificată prin apelul metodei getIntent(). Rezultatul acestei metode poate fi inclusiv null, în cazul în care activitatea nu a fost pornită prin intermediul unei intenții.
Prin intermediul unei intenții, o aplicație poate invoca atât o activitate din cadrul său, cât și o activitate aparținând altei aplicații.
startActivity(new Intent(this, AnotherActivity.class));
startActivity(new Intent("org.rosedu.dandroid.lab05.AnotherActivity"));
De remarcat faptul că în situația în care este pornită o activitate din cadrul aceleiași aplicații Android, obiectul de tip Intent
primește ca parametru și contextul curent (this
), în timp ce în cazul în care este lansată în execuție o activitate din cadrul altei aplicații Android acest parametru este omis.
În momentul în care este invocată metoda startActivity()
, activitatea respectivă este lansată în execuție (prin apelul metodelor onCreate()
, onStart()
, onResume()
) și plasată în vârful stivei care conține toate componentele care au rulate anterior, fără a fi fost terminate. În momentul în care se apelează metoda finish()
(sau se apasă butonul Back), activitatea este încheiată (prin apelul metodelor onPause()
, onStop()
, onDestroy()
), fiind scoasă din stivă, restaurându-se activitatea anterioară.
De asemenea, un obiect de tip Intent poate fi creat și prin intermediul unui URI care identifică în mod unic o anumită activitate:
Uri
uri
=
Uri.parse("myprotocol://mynamespace/myactivity");
Intent
intent
=
new
Intent(Intent.ACTION_VIEW,
uri);
intent.putExtra("someKey",
someValue);
startActivity(intent);
Pentru a putea fi apelată folosind acest mecanism, activitatea va trebui să definească elementul data în cadrul <html><intent-filter></html>:
De remarcat este faptul că în structura URI-ului, partea de după schemă:protocol/ poate conține orice șir de caractere, rolul său fiind strict acela de a respecta forma unui astfel de obiect (estetic), fără a influența în vreo formă funcționalitatea acestuia.
===== Transmiterea de informații între componente prin intermediul intențiilor =====
Intențiile pot încapsula anumite informații care pot fi partajate de componentele între care fac legătura (însă unidirecțional, de la componenta care invocă spre componenta invocată!) prin intermediul secțiunii extra care conține un obiect de tip Bundle. Obținerea valorii secțiunii extra corespunzătoare unei intenții poate fi obținute folosind metoda getExtras(), în timp ce specificarea unor informații care vor fi asociate unei intenții poate fi realizată printr-un apel al metodei putExtras().
<HTML>
<note>
</HTML>
În cazul în care o intenție are deja atașat un obiect de tip Bundle în momentul în care se apelează metoda putExtras(), perechile (cheie, valoare) vor fi transferate din cadrul parametrului metodei în obiectul deja existent.
<HTML>
</note>
</HTML>
Construirea unui obiect de tip Bundle care să fie transmis ca parametru al metodei putExtras() poate fi evitată prin utilizarea metodei putExtra() apelată pe obiectul Intent, primind ca parametrii denumirea cheii prin care datele vor fi identificate și o valoare având un tip compatibil cu android.os.Parcelable. Obținerea datelor se realizează apelând metoda pereche getExtra() căreia i se transmite denumirea cheii ce identifică în mod unic informațiile respective. De asemenea, sunt implementate și metode specifice pentru fiecare tip de dată (put * metoda
startActivityForResult()
va primi ca parametrii obiectul de tip
Intent
precum și un cod de cerere (de tip întreg), utilizat pentru a identifica în mod unic activitatea copil care a transmis un rezultat;
* metoda
onActivityResult()
care va fi apelată în mod automat în momentul în care activitatea copil a fost terminată; parametrii pe care îi furnizează aceasta sunt:
* codul de cerere (prin care se distinge între instanțe diferite ale activității copil);
* codul de rezultat transmis activității părinte (poate avea valorile
RESULT_OK
sau
RESULT_CANCELED
);
* un obiect
Intent
prin intermediul căruia pot fi furnizate date suplimentare.
<html><code java></html> final private static int ANOTHER_ACTIVITY_REQUEST_CODE = 2015;
@Override protected void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_main);
Intent intent = new Intent("org.rosedu.dandroid.lab05.AnotherActivity");
intent.putExtra("org.rosedu.dandroid.lab05.someKey", someValue);
startActivityForResult(intent, ANOTHER_ACTIVITY_REQUEST_CODE);
// start another activities with their own request codes
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch(requestCode) {
case ANOTHER_ACTIVITY_REQUEST_CODE:
if (resultCode == Activity.RESULT_OK) {
Bundle data = intent.getExtras();
// process information from data ...
}
break;
// process other request codes
}
} <html></code></html>
În **activitatea copil**, înainte de apelul metodei finish(), va trebui transmis activității părinte codul de rezultat (Activity.RESULT_OK, Activity.RESULT_CANCELED sau orice fel de rezultat de tip întreg) și obiectul de tip intenție care conține datele (opțional, în situația în care trebuie întoarse rezultate explicit), ca parametrii ai metodei setResult().
<html><code java></html> @Override protected void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_another);
// intent from parent
Intent intentFromParent = getIntent();
Bundle data = intentFromParent.getExtras();
// process information from data ...
// intent to parent
Intent intentToParent = new Intent();
intent.putExtra("org.rosedu.dandroid.lab05.anotherKey", anotherValue);
setResult(RESULT_OK, intentToParent);
finish();
} <html></code></html>
În cazul folosirii unor intenții în care activitățile sunt invocate prin intermediul unor URI-uri, datele vor putea fi concatenate direct în cadrul acestuia (fără a utiliza un obiect de tip Bundle), restricția constând în faptul că pot fi utilizate numai șiruri de caractere:
* în activitatea părinte Uri
uri
=
Uri.parse("myprotocol://mynamespace/myactivity?someKey=someValue&...");
Intent
intent
=
new
Intent(Intent.ACTION_VIEW,
uri);
startActivity(intent);
* în activitatea copil Uri
uri
=
getIntent().getData();
String
someValue
=
uri.getQueryParameter("someKey");
===== Gestiunea evenimentelor cu difuzare prin intermediul intențiilor =====
Intențiile reprezintă și un mecanism de comunicație inter-proces, asigurând transferul unor mesaje structurate. Astfel, intențiile pot fi distribuite către toate componentele de la nivelul sistemului de operare Android, pentru a notifica producerea unui eveniment (legat de starea dispozitivului mobil sau a unor aplicații), fiind procesate în cadrul unor obiecte ascultător dedicate tipului de mesaj respectiv.
<HTML>
<note tip>
</HTML>
Și sistemul de operare Android folosește acest mecanism pentru a notifica producerea unor modificări la nivelul stării curente (primirea unui apel telefonic / mesaj, schimbarea nivelului de încărcare al bateriei sau a conectivității).
<HTML>
</note>
<note>
</HTML>
Trebuie realizată distincția între intențiile cu difuzare transmise la nivelul întregului sistem de operare Android și a celor transmise doar la nivelul aplicației, prin intermediul unui obiect de tipul LocalBroadcastManager (a cărui instanță se obține prin intermediul metodei statice getInstance() ce primește ca parametru contextul aplicației curente). Acesta operează într-un mod similar, implementând metodele sendBroadcast() și registerReceiver(). În plus, dispune de o metodă ce permite trimiterea sincronă a notificărilor, apelul acesteia fiind blocant până la momentul în care toți ascultătorii le-au primit.
<HTML>
</note>
</HTML>
Pentru o aplicație Android, în momentul rulării, pot fi activate / dezactivate oricare dintre componente (deci inclusiv ascultătorii pentru intențiile cu difuzare) prin intermediul metodei setComponentEnabledSetting() din cadrul clasei PackageManager. Un astfel de comportament este util pentru a optimiza performanțele aplicației atunci când o anumită funcționalitate nu este necesară.
<html><code java></html> PackageManager packageManager = getPackageManager();
ComponentName someEventBroadcastReceiver = new ComponentName(this, SomeEventBroadcastReceiver.class);
packageManager.setComponentEnabledSetting(someEventBroadcastReceiver ,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
packageManager.setComponentEnabledSetting(someEventBroadcastReceiver ,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
<html></code></html>
==== Trimiterea unei intenții cu difuzare ====
Construirea unei intenții care urmează să fie difuzată la nivelul sistemului de operare Android poate fi realizată prin definirea unui obiect de tipul Intent, pentru care se vor specifica acțiunea, datele și categoria, astfel încât obiectele de tip ascultător să îl poată identifica cât mai exact. Ulterior, acesta va fi trimis tuturor proceselor aferente aplicațiilor instalate pe dispozitivul mobil prin intermediul metodei sendBroadcast(), căreia îi este atașat ca parametru.
<HTML>
<note tip>
</HTML>
Pot fi utilizate atât acțiuni predefinite (care vor fi procesate atât de aplicațiile Android native cât și de eventuale aplicații instalate din alte surse) cât și acțiuni definite de utilizator, pentru care trebuie implementate aplicații dedicate, responsabile cu procesarea acestora.
<HTML>
</note>
</HTML>
<html><code java></html> final public static String SOME_ACTION = “org.rosedu.dandroid.lab05.SomeAction.SOME_ACTION”;
Intent intent = new Intent(SOME_ACTION); intent.putExtra(“org.rosedu.dandroid.lab05.someKey”, someValue); sendBroadcast(intent); <html></code></html>
==== Primirea unui intenții cu difuzare ====
Pentru a putea primi o intenție cu difuzare, o componentă trebuie să fie înregistrată în acest sens, definind un filtru de intenții pentru a specifica ce tipuri de acțiuni și ce tipuri de date asociate intenției poate procesa.
Acesta poate fi precizat:
* în fișierul
AndroidManifest.xml
(caz în care nu este necesar ca aplicația să ruleze la momentul în care se produce evenimentul cu difuzare pentru a-l putea procesa); elementul
trebuie să conțină în mod obligatoriu filtrul de intenții prin care se indică acțiunea care poate fi procesată:
<html><file xml AndroidManifest.xml></html>
<html><manifest … ></html>
<html><application … ></html>
<html><receiver
android:name=”.SomeEventBroadcastReceiver”></html>
<html><intent-filter></html>
<html><action android:name=“org.rosedu.dandroid.lab05.SomeAction.SOME_ACTION” /></html>
<html></intent-filter></html>
<html></receiver></html>
<html></application></html>
<html></manifest></html> <html></file></html>
* programatic, în codul sursă (caz în care aplicația trebuie să fie în execuție la momentul în care se produce evenimentul cu difuzare pentru a-l putea procesa); o astfel de abordare este utilă când procesarea intenției cu difuzare implică actualizarea unor componente din cadrul interfeței grafice asociate activității:
<html><code java></html>
private SomeEventBroadcastReceiver someEventBroadcastReceiver = new SomeEventBroadcastReceiver(); private IntentFilter intentFilter = new IntentFilter(SOME_ACTION);
@Override protected void onResume() {
super.onResume();
registerReceiver(someEventBroadcastReceiver, intentFilter);
}
@Override protected void onPause() {
super.onPause();
unregisterReceiver(someEventBroadcastReceiver);
} <html></code></html>
<HTML>
<note tip>
</HTML>
O regulă este de a înregistra obiectul ascultător pe metoda onResume() și de a-l deînregistra pe metoda onPause(), astfel încât acesta să nu reacționeze decât atunci când activitatea este vizibilă.
<HTML>
</note>
</HTML>
O clasă capabilă să proceseze intenții cu difuzare este derivată din android.content.BroadcastReceiver, implementând metoda onReceive() pe care realizează rutina de tratare propriu-zisă:
<html><file java SomeEventBroadcastReceiver.java></html> import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent;
public class SomeEventBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// ...
}
} <html></file></html>
Metoda onReceive() va fi invocată în mod automat în momentul în care este primită o intenție cu difuzare, fiind executată pe firul de execuție principal al aplicației. De regulă, în cadrul acestei metode utilizatorul este anunțat asupra producerii evenimentului prin intermediul serviciului de notificare (//Notification Manager//), este lansat în execuție un serviciu sau sunt actualizate componente din cadrul interfeței grafice.
<HTML>
<note important>
</HTML>
Este necesar ca metoda onReceive() să se termine în maximum 5 secunde, în caz contrar fiind afișată o fereastră de dialog pentru a determina oprirea sa forțată.
<HTML>
</note>
</HTML>
==== Gestiunea intențiilor cu difuzare native ====
Cele mai multe servicii de sistem transmit intenții cu difuzare pentru a semnala faptul că s-au produs anumite modificări la nivelul stării dispozitivului mobil sau al aplicațiilor (primirea unui apel telefonic / mesaj, schimbarea nivelului de încărcare al bateriei, conectivitatea la Internet).
^ **ACȚIUNE** ^ **DESCRIERE** ^ | ACTION_BATTERY_CHANGED | acțiune transmisă în momentul în care se modifică nivelul de încărcare al bateriei; starea bateriei este disponibilă în secțiunea extra, prin intermediul cheii EXTRA_STATUS, putând avea valorile:
♦ BatteryManager.BATTERY_STATUS_CHARGING
♦ BatteryManager.BATTERY_STATUS_FULL | | ACTION_BATTERY_LOW | acțiune transmisă în momentul în care nivelul de încărcare al bateriei este scăzut, impunându-se încărcarea acesteia | | ACTION_BATTERY_OKAY | acțiune transmisă în momentul în care nivelul de încărcare al bateriei este acceptabil | | ACTION_BATTERY_CONNECTED | acțiune transmisă în momentul în care bateria este conectată la o sursă de energie externă | | ACTION_BATTERY_DISCONNECTED | acțiune transmisă în momentul în care bateria este deconectată de la o sursă de energie externă | | ACTION_BOOT_COMPLETED | acțiune transmisă în momentul în care a fost realizată complet secvența de pornire a dispozitivului mobil (aplicația poate primi o astfel de intenție cu difuzare dacă deține permisiunea RECEIVE_BOOT_COMPLETED) | | ACTION_CAMERA_BUTTON | acțiune transmisă în momentul în momentul în care este accesat butonul pentru pornirea camerei foto | | ACTION_DATE_CHANGED / ACTION_TIME_CHANGED | acțiuni transmise în momentul în care data calendaristică sau timpul sunt modificate manual (nu datorită progresului său natural) | | ACTION_DOCK_EVENT | acțiune transmisă în momentul în care dispozitivul mobil este ancorat, printr-un dispozitiv de birou sau de mașină, stare plasată în secțiunea extra prin intermediul cheii ETRA_DOCK_STATE | | ACTION_MEDIA_EJECT | acțiune transmisă în momentul în care este îndepărtat un mediu de stocare extern (util în situația în care aplicația scrie / citește de pe acesta, pentru a salva conținutul și pentru a le închide) | | ACTION_MEDIA_MOUNTED / ACTION_MEDIA_UNMOUNTED | acțiuni transmise de fiecare dată când dispozitive de stocare externe sunt adăugate sau îndepărtate cu succes | | ACTION_NEW_OUTGOING_CALL | acțiune transmisă în momentul în care urmează să fie format un număr de telefon, a cărui valoare este plasată în secțiunea extra, prin intermediul cheii EXTRA_PHONE_NUMBER (aplicația poate primi o astfel de intenție cu difuzare dacă deține permisiunea PROCESS_OUTGOING_CALLS | | ACTION_SCREEN_OFF / ACTION_SCREEN_ON | acțiuni transmise în momentul în care ecranul este închis, respectiv este deschis | | ACTION_TIMEZONE_CHANGED | acțiune transmisă în momentul în care zona de timp a telefonului este modificată, a cărui valoare (identificator) este plasată în secțiunea extra prin intermediul cheii time-zone |
<HTML>
<note tip>
</HTML>
Pentru aceste tipuri de intenții cu difuzare, înregistrarea și deînregistrarea unor obiecte de tip ascultător poate fi realizată numai programatic, în codul sursă.
<HTML>
</note>
</HTML>
În cazul unei aplicații Android, foarte importante sunt și modificările în privința conectivității la Internet (inclusiv parametrii precum lățimea de bandă, latența) întrucât acestea pot fi semnificative în privința luării unor decizii legate de realizarea anumitor actualizări sau de descărcarea unor fișiere având dimensiuni mari. O astfel de funcționalitate poate fi definită prin implementarea unui obiect ascultător, care procesează acțiunea android.net.conn.CONNECTIVITY_CHANGE (ConnectivityManager.CONNECTIVITY_ACTION). Se transmise o intenție cu difuzie nepersistentă care nu conține informații suplimentare cu privire la schimbarea stării.
ConnectivityManager
connectivityManager
=
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo
networkInfo
=
connectivityManager.getActiveNetworkInfo();
boolean
isConnected
=
networkInfo.isConnectedOrConnecting();
boolean
isMobile
=
(networkInfo.getType()
==
ConnectivityManager.TYPE_MOBILE);
====== Exerciții ======
[**0**]. Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la %%//%%www.github.com/andreirosucojocaru/DAndroid2015_Laborator05.git. În urma acestei operații, directorul Laborator05 va trebui să conțină subdirectorul labtasks (cu proiectele Android Studio MessageMe si DateAndTime), fișierele README.md și LICENSE. student@dandroid2015:~$
git
clone
''%%https://www.github.com/andreirosucojocaru/DAndroid2015_Laborator05.git%%'' Să se importe în mediul integrat de dezvoltare Android Studio proiectele MessageMe si DateAndTime.
[**1**]. Să se adauge o acțiune asociată evenimentului de apăsare a butonului notYetRegisteredButton, astfel încât să se lanseze în execuție activitatea RegisterActivity. În cadrul acesteia, un utilizator are posibilitatea de a-și crea un cont, prin completarea unor câmpuri. Pentru ca operația să fie realizată cu succes, este necesar ca toate atributele să fie specificate, iar valorile indicate în cadrul parolelor să corespundă. Rezultatul va fi transmis înapoi activității LoginActivity care îl va afișa pe ecran.
* * a)** În activitatea LoginActivity se va asocia butonului notRegisteredYetButton un obiect ascultător pentru evenimentele de tip apăsare (View.OnClickListener) care implementează metoda de callback onClick(View). În cadrul acesteia, se va constui o **intenție implicită** (definită pe baza acțiunii - Constants.REGISTER_ACTIVITY_INTENT_ACTION), după care se va lansa în execuție activitatea corespunzătoare în așteptarea unui rezultat (metoda setActivityForResult() primește ca parametri intenția și codul de cerere - Constants.REGISTER_ACTIVITY_REQUEST_CODE).
* * b)** În activitatea RegisterActivity se va proceda similar pentru butoanele registerButton, respectiv cancelButton:
* în cazul
registerButton
se verifică ca toate câmpurile să fi fost completate și ca parolele să corespundă, situație în care se transmite activității părinte rezultatul
Activity.RESULT_OK
, activitatea încheindu-și execuția (se apelează metoda
finish()
).
* în cazul
cancelButton
se transmite activității părinte rezultatul
Activity.RESULT_CANCELED
, activitatea încheindu-și execuția (se apelează metoda
finish()
).
* * c)** În clasa LoginActivity se va implementa metoda onActivityResult() ce verifică rezultatul cu care s-a terminat activitatea invocată, afișându-l în cadrul interfeței grafice.
@Override
public
void
onActivityResult(int
requestCode,
int
resultCode,
Intent
intent);
Metoda primește ca parametri:
*
requestCode
- codul de cerere transmis ca parametru în metoda
startActivityForResult()
, în funcție de care se identifică eventualele răspunsuri primite de la invocări diferite;
*
resultCode
- codul de răspuns (rezultatul);
*
Intent
- obiect prin intermediul căruia pot fi furnizate informații suplimentare.
<HTML>
<note tip>
</HTML>
Pentru afișarea unui mesaj se poate utiliza următorul cod sursă: Snackbar.make(notRegisteredYetButton,
getResources().getString(R.string.activity_returned_with_result)
+
"
"
+
resultCode,
Snackbar.LENGTH_LONG).show();
<HTML>
</note>
</HTML>
[**2**]. Să se adauge o acțiune asociată evenimentului de apăsare a butonului loginButton, astfel încât să se lanseze în execuție activitatea MainActivity. În acest scop, este necesar să se verifice faptul că numele de utilizator și parola au fost completate corespunzător. Pentru invocarea componentei, se va folosi o **intenție explicită** (indicată prin denumirea clasei care o implementează). Informațiile nume de utilizator și parolă trebuie incluse în câmpul extra al intenției (folosindu-se cheile Constants.USERNAME, respectiv Constants.PASSWORD).
[**3**]. În fragmentul ProfileFragment, să se obțină valorile corespunzătoare numelui de utilizator și parolei provenite de la activitatea care l-a invocat, prin intermediul intenției corespunzătoare. Să se afișeze aceste valori în câmpurile text usernameTextView, respectiv passwordTextView.
<HTML>
<note tip>
</HTML>
Toate aceste operații trebuie să fie realizate în cadrul metodei onActivityCreated() pentru că numai în acest moment se garantează faptul că activitatea din care face parte fragmentul poate fi accesată.
<HTML>
</note>
</HTML>
[**4**]. În fragmentul ProfileFragment, să se implementeze trei butoane prin care să se invoce, folosind mecanisme diferite, activitatea DateAndTimeActivity din contextul altei aplicații Android. Această activitate afișează data și ora curente, folosind un calendar și un ceas analogic.
* * a)** Se va folosi **o intenție** calificată prin intermediul acțiunii Constants.DATE_AND_TIME_INTENT_ACTION. Această valoare trebuie inclusă și în fișierul AndroidManifest.xml al proiectului DateAndTime, în cadrul unui alt filtru de intenție, ce va avea categoria android.intent.category.DEFAULT.
<html><code xml></html> <html><intent-filter></html>
<html><action android:name=“org.rosedu.dandroid.dateandtime.intent.action.DateAndTimeActivity” /></html>
<html><category android:name=“android.intent.category.DEFAULT” /></html>
<html></intent-filter></html> <html></code></html>
* * b)** Se va folosi **un ascultător de mesaje cu difuzare**. Tipul de acțiune utilizat va fi Constants.DATE_AND_TIME_BROADCAST_RECEIVER_ACTION. Este necesar să se utilizeze metoda sendBroadcast(). În fișierul AndroidManifest.xml al proiectului DateAndTime, este necesar să se defineacă un element
<html><intent-filter></html>
<html><action android:name=“org.rosedu.dandroid.dateandtime.broadcastreceiver.action.DateAndTimeActivity”/></html>
<html></intent-filter></html>
<html></receiver></html> <html></code></html>
Clasa DateAndTimeBroadcastReceiver (derivată din BroadcastReceiver) prelucrează mesajele cu difuzare care respectă anumite criterii, metoda onReceive() fiind apelată în mod automat. În cadrul acestei metode, trebuie să se invoce mai departe, tot prin intermediul unei intenții, activitatea DateAndTimeActivity. Fiind vorba de invocarea unei activități din cadrul aceleiași clase, se va utiliza o intenție explicită (definită prin denumirea clasei).
<HTML>
<note important>
</HTML>
Este necesar să se indice flag-ul Intent.FLAG_ACTIVITY_NEW_TASK, în caz contrar activitatea neputând fi lansată în execuție.
<HTML>
</note>
</HTML>
<html><file java DateAndTimeBroadcastReceiver.java></html> public class DateAndTimeBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent mainActivityIntent = new Intent(context.getApplicationContext(), DateAndTimeActivity.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(mainActivityIntent);
}
} <html></file></html>
* * c)** Se va folosi **un URI** (Uniform Resource Identifier). Invocarea se face prin intermediul unui identificator de resurse (conținut de obiectul Constants.DATE_AND_TIME_URI_ACTION), pe care se aplică acțiunea Intent.ACTION_VIEW. URI-ul conține același protocol și aceeași gazdă ca cele definite în secțiunea de date a fișierului AndroidManifest.xml din cadrul proiectului DateAndTime.
<html><code xml></html> <html><intent-filter></html>
<html><action android:name=“android.intent.action.VIEW” /></html>
<html><category android:name=“android.intent.category.DEFAULT” /></html>
<html><data
android:scheme=“dateandtimeprotocol”
android:host=“dandroid.rosedu.org” /></html>
<html></intent-filter></html> <html></code></html>
<HTML>
<note tip>
</HTML>
De remarcat este faptul că pentru aceeași activitate pot fi definite mai multe filtre de intenții având un conținut diferit.
<HTML>
</note>
<note tip>
</HTML>
Aplicația DateAndTime trebuie să fie instalată înainte de a se face invocările din aplicația MessageMe, în caz contrar fiind generată o excepție.
<HTML>
</note>
</HTML>
[**BONUS**]. Să se implementeze un ascultător pentru mesaje cu difuzare în aplicația MessageMe, care interceptează mesajele trimise de sistemul de operare Android cu privire la schimbările legate de conectivitatea la Internet. Acesta va jurnaliza toate operațiile care au fost detectate, cu ajutorul Logcat. Acțiunea care este transmisă în acest caz este android.net.conn.CONNECTIVITY_CHANGE. Astfel înregistrat, un obiect de acest tip va fi invocat în mod automat, furnizând informații legate de existența unei conexiuni precum și a unei rețele fără fir.
ConnectivityManager
connectivityManager
=
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo
activeNetwork
=
connectivityManager.getActiveNetworkInfo();
boolean
isConnected
=
activeNetwork
!=
null
&&
activeNetwork.isConnectedOrConnecting();
boolean
isWiFi
=
activeNetwork.getType()
==
ConnectivityManager.TYPE_WIFI;
<HTML>
<note important>
</HTML>
Informațiile cu privire la starea conectivității nu pot fi accesate decât în situația în care sunt acordate drepturile de acces corespunzătoare: <html><uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE” /></html>
<HTML>
</note>
</HTML>