Să presupunem că aveți o aplicație care depinde de o conexiune constantă la internet. Doriți ca aplicația dvs. să fie notificată atunci când conexiunea la internet se schimbă. Cum faci asta? O posibilă soluție ar fi un serviciu care verifică întotdeauna conexiunea la internet. Această implementare este proastă din diverse motive, așa că nici măcar nu o vom lua în considerare. Soluția la această problemă este un receptor de difuzare și va asculta modificările pe care le spuneți. Un receptor de difuzare va primi întotdeauna o notificare cu privire la o difuzare, indiferent de starea aplicației dvs. Nu contează dacă aplicația dvs. rulează în prezent, în fundal sau nu rulează deloc.

fundal

Receptoarele de difuzare sunt componente din aplicația dvs. Android care ascultă mesaje difuzate (sau evenimente) de la diferite puncte de vânzare:

  • Din alte aplicații
  • Din sistemul în sine
  • Din aplicația dvs.

Adică, sunt invocați atunci când a avut loc o anumită acțiune pe care au fost programați să o asculte (IE, o transmisie).

O transmisie este pur și simplu un mesaj înfășurat în interiorul unui obiect Intent. O difuzare poate fi implicită sau explicită.

  • Un difuzare implicită este una care nu vizează în mod specific aplicația dvs., deci nu este exclusivă aplicației dvs. Pentru a vă înregistra pentru unul, trebuie să utilizați un IntentFilter și declară-l în manifestul tău. Trebuie să faceți toate acestea, deoarece sistemul de operare Android trece peste toate filtrele de intenție declarate în manifest și vede dacă există o potrivire. Datorită acestui comportament, transmisiile implicite nu au un atribut țintă. Un exemplu pentru o transmisie implicită ar fi acțiunea unui mesaj SMS primit.
  • Un difuzare explicită este una care este direcționată special pentru aplicația dvs. pe o componentă cunoscută în prealabil. Acest lucru se întâmplă datorită atributului țintă care conține numele pachetului aplicației sau un nume de clasă componentă.

Există două moduri de a declara un receptor:

  1. Declarând unul în fișierul dvs. AndroidManifest.xml cu eticheta (numită și statică)
<receiver android:name=".YourBrodcastReceiverClass"  android:exported="true">
    <intent-filter>
        <!-- The actions you wish to listen to, below is an example -->
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
AndroidManifest.xml

Veți observa că receptorul de difuzare declarat mai sus are o proprietate de exportat = ”adevărat”. Acest atribut îi spune receptorului că poate primi emisiuni din afara scopului aplicației.

2. Sau dinamic înregistrând o instanță cu registerReceiver (ceea ce se numește context înregistrat)

public abstract Intent registerReceiver (BroadcastReceiver receiver, 
                IntentFilter filter);

Implementare

Pentru a vă crea propriul receptor de difuzare, trebuie mai întâi să extindeți clasa părinte BroadcastReceiver și să înlocuiți metoda obligatorie, onReceive:

public void onReceive(Context context, Intent intent) {
    //Implement your logic here
 }

Punând totul împreună rezultă:

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        StringBuilder sb = new StringBuilder();
        sb.append("Action: " + intent.getAction() + "n");
        sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "n");
        String log = sb.toString();
        Toast.makeText(context, log, Toast.LENGTH_LONG).show();

    }
}
MyBroadcastReceiver.java

⚠️Metoda onReceive rulează pe firul principal și, din această cauză, execuția sa ar trebui să fie scurtă.

Dacă se execută un proces lung, sistemul poate distruge procesul după revenirea metodei. Pentru a ocoli acest lucru, luați în considerare utilizarea goAsync sau programarea unui loc de muncă. Puteți citi mai multe despre programarea unui job în partea de jos a acestui articol.


Exemplu de înregistrare dinamică

Pentru a înregistra un receptor cu un context, trebuie mai întâi să instanțiați o instanță a receptorului dvs. de difuzare:

BroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();

Apoi, îl puteți înregistra în funcție de contextul specific dorit:

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
this.registerReceiver(myBroadcastReceiver, filter);
Primul parametru pentru IntentFilter este un șir care reprezintă o acțiune

Nu uitați să vă înregistrați receptorul de difuzare atunci când nu mai aveți nevoie de el

@Override
protected void onStop() {
  super.onStop();
  unregisterReceiver(myBroadcastReceiver);
}

Difuzarea unui eveniment

Punctul din spatele difuzării mesajelor din aplicația dvs. este de a permite aplicației dvs. să răspundă la evenimente așa cum se întâmplă în interiorul acesteia. Gândiți-vă la un scenariu în care într-o parte a codului, utilizatorul efectuează o anumită acțiune și, din cauza acesteia, doriți să executați o altă logică pe care o aveți într-un alt loc.

Există trei moduri de a trimite transmisii:

  1. sendOrderedBroadcast metoda, asigură că trimiteți transmisii către un singur receptor la un moment dat. Fiecare difuzare poate, la rândul său, transmite date către cel care o urmează sau pentru a opri propagarea difuzării către receptorii care urmează
  2. sendBroadcast este similar cu metoda menționată mai sus, cu o singură diferență. Toți receptorii de difuzare primesc mesajul și nu depind unul de celălalt
  3. LocalBroadcastManager.sendBroadcast metoda trimite doar transmisii către receptoare definite în interiorul aplicației dvs. și nu depășește domeniul de aplicare al aplicației dvs. Exemplu de trimitere a unei difuzări personalizate

https://giphy.com/gifs/23gUJhHyWkXEwl7UYV/html5


0*ywQVksVZ0m Np16m
Fotografie de John Gibbons pe Unsplash

Gotchas și lucruri la care să acorde o atenție

  • Nu trimiteți date sensibile printr-o difuzare implicită, deoarece orice aplicație care ascultă pentru ea va primi. Puteți preveni acest lucru fie prin specificarea unui pachet, fie prin atașarea unei permisiuni la difuzare
  • Nu începeți activitățile dintr-o transmisie primită, deoarece experiența utilizatorului lipsește. Alegeți să afișați o notificare în schimb.

Următoarele puncte glonț se referă la modificări ale receptoarelor de difuzare relevante pentru fiecare versiune de sistem de operare Android (începând de la 7.0). Pentru fiecare versiune, anumite limitări au luat loc și comportamentul s-a schimbat, de asemenea. Rețineți aceste limitări atunci când vă gândiți la utilizarea unui receptor de difuzare.

  • 7.0 și versiuni ulterioare (nivelul API 24) – Două transmisii de sistem au fost dezactivate,Action_New_Picture și Action_New_Video (dar au fost readuse în Android O pentru destinatarii înregistrați)
  • 8.0 și versiuni ulterioare (API nivel 26) – Majoritatea transmisiilor implicite trebuie înregistrate în mod dinamic și nu static (în manifestul dvs.). Puteți găsi difuzările care au fost listate în această listă albă legătură.
  • 9.0 și versiuni ulterioare (API nivel 28) – Mai puține informații primite despre difuzarea sistemului Wi-Fi și Network_State_Changed_Action.

Schimbările din Android O sunt cele pe care trebuie să le cunoașteți cel mai mult. Motivul pentru care au fost făcute aceste modificări a fost că a dus la probleme de performanță, la epuizarea bateriei și la durerea experienței utilizatorului. Acest lucru s-a întâmplat deoarece multe aplicații (chiar și cele care nu rulează în prezent) ascultau o schimbare la nivel de sistem și, atunci când s-a produs această schimbare, a urmat haosul. Imaginați-vă că fiecare aplicație înregistrată la acțiune a prins viață pentru a verifica dacă trebuie să facă ceva din cauza difuzării. Luați în considerare ceva de genul stării Wi-Fi, care se schimbă frecvent și veți începe să înțelegeți de ce au avut loc aceste modificări.


Alternative la receptoare de transmisie

Pentru a facilita navigarea tuturor acestor restricții, mai jos este prezentată o defalcare a altor componente pe care le puteți utiliza în absența unui receptor de difuzare. Fiecare are o responsabilitate și un caz de utilizare diferit, așa că încercați să identificați care dintre ele satisface nevoile dvs.

  • LocalBroadcastManager – După cum am menționat mai sus, acest lucru este valabil numai pentru transmisiile din cadrul aplicației dvs.
  • Programarea unui loc de muncă – O lucrare poate fi rulată în funcție de un semnal sau de un declanșator primit, astfel încât s-ar putea să constatați că transmisia pe care o ascultați poate fi înlocuită cu o lucrare. În plus, JobScheduler, va garanta că lucrarea dvs. se va termina, dar va lua în considerare diferiți factori ai sistemului (timpul și condițiile) pentru a determina când ar trebui să ruleze. Când creați un job, veți suprascrie o metodă numită onStartJob. Această metodă rulează pe firul principal, deci asigurați-vă că își termină activitatea într-un timp limitat. Dacă trebuie să efectuați o logică complexă, luați în considerare începerea unei sarcini de fundal. În plus, valoarea de returnare pentru această metodă este booleană, unde adevărat denotă că anumite acțiuni sunt încă în curs de realizare, iar fals înseamnă că lucrarea este terminată

Dacă doriți să experimentați din prima mână bucuria și mirarea care sunt receptoarele de difuzare, puteți urmări aceste linkuri către depozitele pe care le-am configurat:

  1. Difuzare personalizată (cu declarație manifest)
  2. Înregistrarea difuzării (fără a declara unul în manifest)
  3. LocalBroadcastManager

Difuzat peste.