JavascriptProva

Visualizzazione post con etichetta BroadcastReceiver. Mostra tutti i post
Visualizzazione post con etichetta BroadcastReceiver. Mostra tutti i post

venerdì 11 novembre 2016

Ripasso BroadcastReceiver nel tentativo di intercettare il tasto Home.

Provo a creare un broadcastReceiver.
Lo creo nello stesso modulo.

L'ho nidificato nella classe dell'Activity:
    public class MyReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            
        }
    }
Il metodo onReceive viene dato di default.

Per la registrazione, bisogna prima istanziare la classe creata.
Ci provo...

Scrivo intanto un'azione per l'evento onReceive:
    public class MyReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            System.out.println("ricevuto");
        }
    }


Ecco:
public class MainActivity extends AppCompatActivity {

    MyReceiver myReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myReceiver=new MyReceiver();

    }
Ora devo definire un IntentFilter e registrare il Receiver insieme a questo IntentFilter in onResume, deregistrandolo in onPause
Provo a usare l'intentFilter che ho trovato nella costruzione dell'HomeWatcher:
        myReceiver=new MyReceiver();
        intentFilter=new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Quindi registro in onResume e deregistro in onPause:
    @Override
    protected void onResume(){
        super.onResume();
        registerReceiver(myReceiver,intentFilter);
    }

    @Override
    protected void onPause(){
        super.onPause();
        unregisterReceiver(myReceiver);
    }
Funziona. Intercetta la pressione del tasto Home.
Ma non mi previene la chiusura dell'activity.

venerdì 8 aprile 2016

Ciclo di vita dei BroadcastReceiver registrati su Manifest

Ed ecco come i BroadcastReceiver si rendono poi indipendenti dall'esecuzione o meno dell'App che li ha lanciati.
Ho creato una nuova applicazione che chiami i due BroadcastReceiver con la stessa Action:
 Intent intent=new Intent();
 intent.setAction("android.intent.action.Seconda");
 sendBroadcast(intent);
e lancio questa nuova applicazione curandomi bene che la prima non fosse più in esecuzione sull'emulatore.
I due BroadcastReceiver, il cui codice è rispettivamente:
public class receiver extends BroadcastReceiver{

 @Override
 public void onReceive(Context context, Intent intent) {
  Log.d("BROADCAST","RICEVUTO");
  
 }

}
...e:
public class receiver2 extends BroadcastReceiver{

 @Override
 public void onReceive(Context context, Intent intent) {
  Log.d("SECONDO BROADCAST", "RICEVUTO");
  
 }

}
vengono eseguiti ugualmente, essendo rimasti attivi sul dispositivo anche dopo la chiusura dell'applicazione nella quale sono stati creati:
04-08 10:35:12.325: D/BROADCAST(2317): RICEVUTO
04-08 10:35:12.353: D/SECONDO BROADCAST(2317): RICEVUTO


Sono andato poi a cambiare il loro codice per fare in modo che lanciassero dei Toast anziché scrivere in Logcat:
public class receiver extends BroadcastReceiver{

 @Override
 public void onReceive(Context context, Intent intent) {
  Toast.makeText(context, "PRIMO BROADCASTRECEIVER", Toast.LENGTH_LONG).show();
  
 }

}
e
public class receiver2 extends BroadcastReceiver{

 @Override
 public void onReceive(Context context, Intent intent) {
  Toast.makeText(context, "SECONDO BROADCASTRECEIVER", Toast.LENGTH_LONG).show();
  
 }

}
ma, rieseguendo il programma, non ottengo nessun Toast, bensì ancora la scrittura in LogCat:
04-08 10:39:56.533: D/BROADCAST(2317): RICEVUTO
04-08 10:39:56.537: D/SECONDO BROADCAST(2317): RICEVUTO

Questo testimonia che una volta registrato sul Manifest un BroadcastReceiver continua a funzionare indipendentemente dall'applicazione che l'ha generato.
E se io provo a eliminare l'apk dell'App che ha generato i BroadcastReceiver?

Fatto! Ho eliminato gli apk di ambedue le applicazioni, quella che ha creato i BroadcastReceiver e quella nuova che li richiamava.
Adesso faccio ripartire la nuova app che li richiamava, e vediamo se li richiama ancora...

Sembrerebbe di no...

Faccio ripartire la prima applicazione... ma stavolta con il codice dei BroadcastReceiver modificato per i Toast anziché per la scrittura in LogCat

Ed ecco cosa succede:





Questo significa che disinstallando dal dispositivo l'App che ha registrato il BroadcastReceiver si de-registra anche esso.
Voglio fare un'altra prova: creo un Intent con un'action immaginaria inesistente fra i BroadcastReceiver, per vedere se ottengo errore o no: dal momento che quando il BroadcastReceiver, nella mia ipotesi, era de-registrato, non ho ottenuto messaggi di errore, non vorrei aver condotto male la prova essendo il BroadcastReceiver comunque esistente dopo la disinstallazione dell'app creante...
  Intent intent=new Intent();
  intent.setAction("android.intent.action.Fasullo");
  sendBroadcast(intent);
No: non ottengo messaggi di errore.
Torno ad eseguire la nuova App con la precedente action:
  Intent intent=new Intent();
  intent.setAction("android.intent.action.Seconda");
  sendBroadcast(intent);
...e ottengo di nuovo i Toast! Credo di poter avere la conferma piena della mia ipotesi.

Due BroadcastReceiver con la stessa Action richiamati da un Intent.

Cosa succede con due BroadcastReceiver aventi la stessa action?

Ho creato un nuovo BroadcastReceiver:
public class receiver2 extends BroadcastReceiver{

 @Override
 public void onReceive(Context context, Intent intent) {
  Log.d("SECONDO BROADCAST", "RICEVUTO");
  
 }

}
Ora lo registro nel Manifest, dove è già registrato quello vecchio:
        <receiver android:name="receiver">
            <intent-filter>
                <action android:name="android.intent.action.Seconda" />
            </intent-filter>
        </receiver>
        
        <receiver android:name="receiver2">
            <intent-filter>
             <action android:name="android.intent.action.Seconda" />
            </intent-filter>
        </receiver> 
Ora uso il sendBroadcast con un Intent che abbia la action comune di ambedue:
  Intent intent=new Intent();
  intent.setAction("android.intent.action.Seconda");
  sendBroadcast(intent);
Vediamo...

Ecco il LogCat: come prevedevo, viene eseguita l'azione di ambedue.
04-08 09:31:29.678: D/BROADCAST(2317): RICEVUTO
04-08 09:31:29.727: W/EGL_emulation(2317): eglSurfaceAttrib not implemented
04-08 09:31:29.728: W/OpenGLRenderer(2317): Failed to set EGL_SWAP_BEHAVIOR on surface 0xa6c05880, error=EGL_SUCCESS
04-08 09:31:29.787: D/SECONDO BROADCAST(2317): RICEVUTO

domenica 3 aprile 2016

I Broadcast in Android

Credo che sia il caso di occuparsi dei Broadcast.

Ecco: come al solito il processo di apprendimento è stato piuttosto laborioso e sofferto, ma sono venuto a capo di qualcosa...

Abbiamo un Intent che viene mandato come Broadcast e un BroadcastReceiver che ne è il ricevitore e deve essere registrato.
Ho già scritto tutto il codice, ma come al solito rompo tutto come se fosse un "Mandala" buddhista e mi esercito a riscriverlo, perché così mi si facilita la ritenzione in memoria:
  receiver=new BroadcastReceiver(){

   @Override
   public void onReceive(Context context, Intent intent) {
    Log.d("BROADCAST","RICEVUTO");
    
   }
   
  };
Finora ho scritto questo, che è il codice di un BroadcastReceiver elementare, nel contesto del metodo onCreate.

Quindi questo ricevitore esegue un'azione (scrive in LogCat le stringhe "BROADCAST" e "RICEVUTO") e stop.
Ora, dunque, bisogna registrarlo, e nella registrazione si specifica l'azione alla quale risponde.
Vediamo se ci riesco:
  IntentFilter filtro=new IntentFilter();
  filtro.addAction("azione");
  
  registerReceiver(receiver,filtro);
Le prime due righe definiscono il filtro dell'azione alla quale deve rispondere il receiver, la seconda registra il receiver con il suo filtro per l'azione.
Ecco il codice finora scritto:
public class MainActivity extends Activity {
 
 BroadcastReceiver receiver;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  receiver=new BroadcastReceiver(){

   @Override
   public void onReceive(Context context, Intent intent) {
    Log.d("BROADCAST","RICEVUTO");
    
   }
   
  };
  
  IntentFilter filtro=new IntentFilter();
  filtro.addAction("azione");
  
  registerReceiver(receiver,filtro);
 }
}
Ecco tutto: ho scritto, in parole semplici, quello che fa il broadcastReceiver quando riceve il broadcast, e il broadcast al quale risponde.

In parole semplici, mentre l'intent normalmente è una chiamata personale a qualcun altro, il broadcast è mettersi in piazza e urlare per farsi sentire da tutti. Se poi fra i passanti ce ne sono alcuni che sono disposti ad accogliere il messaggio si metteranno in azione, mentre gli altri lo ignoreranno.
Esempio dalla vita pratica: c'è in piazza uno che si sente male, e il suo amico che stava vicino a lui vede tra la folla un suo amico medico, così va da lui e lo chiama per farlo accorrere (Intent); oppure può capitare che non ci sia nessun medico conosciuto nelle vicinanze, e così l'amico si mette a urlare a squarciagola verso la folla: "EHI! QUI C'E' UNO CHE STA MALE, C'E' UN MEDICO?" (Broadcast).
Ecco, finora ho definito il medico e il richiamo al quale risponde.
Ora diamo voce all'amico dell'ammalato: si fa con un Intent:
  Intent intent=new Intent();
  intent.setAction("azione");
  sendBroadcast(intent);
Ecco, vediamo se funziona...

Funziona!
04-03 09:42:32.952: D/BROADCAST(3045): RICEVUTO



E adesso per gioco voglio mimare la situazione del malore che mi sono fatto come esempio:
public class MainActivity extends Activity {
 
 BroadcastReceiver medico;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  
  medico=new BroadcastReceiver(){

   @Override
   public void onReceive(Context context, Intent intent) {
    Log.d("ECCOMI","COS'E' SUCCESSO?");
   }
   
  };
  
  IntentFilter filtro=new IntentFilter();
  filtro.addAction("c'è un medico?");
  registerReceiver(medico,filtro);
  
  Intent intent=new Intent();
  intent.setAction("c'è un medico?");
  sendBroadcast(intent);
  
 }
 
 protected void onDestroy(){
  super.onDestroy();
  unregisterReceiver(medico);
 }
  


}
...aggiungendo la de-registrazione del receiver con il metodo onDestroy, sempre doverosa!

martedì 19 gennaio 2016

Approccio con i BroadcastReceiver

Ho scritto questo codice:
public class AirplaneReceiver extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
 }
}
L'ho chiamato AirplaneReceiver, ma avrei potuto chiamarlo pure Pasquale, se avessi voluto.
Anzi, facciamo una cosa: lo chiamo veramente Pasquale! O meglio con un nome mio di fantasia, sempre pertinente...
public class Ricevitore extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
 }
}
Scrivo il codice delle azioni da fare al ricevimento del Broadcast:
public class Ricevitore extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
  Toast.makeText(context, "Ciao, bella gente!", Toast.LENGTH_SHORT).show();
 }
}
(con la scusa, ho ripassato un po' la sintassi del Toast)

E adesso, seguendo il tutorial, andiamo alla parte della registrazione.
Per prima cosa scrivo il tag %lt;receiver>
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <receiver>
            
        </receiver> 
Il questo tag devo specificare android:name
        <receiver android:name=>
           
        </receiver> 
e ottengo a questo punto una lista di suggerimenti:



...dalla quale scelgo il primo:
        <receiver android:name="com.example.broadcast.Ricevitore"           
        </receiver> 
Fondamentale è notare che questo android:name è uguale al nome del package più il nome della classe che estende BroadcastReceiver!


Poi si va avanti con un <intent-filter></intent-filter> nel quale ci va un <action>.
Ecco:
        <receiver android:name="com.example.broadcast.Ricevitore"> 
            <intent-filter >
                <action android:name=""
            </intent-filter>         
        </receiver> 
E qui c'è un elemento decisivo: il nome del Broadcast che viene ascoltato!
        <receiver android:name="com.example.broadcast.Ricevitore"> 
            <intent-filter >
                <action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
            </intent-filter>         
        </receiver> 
Ho scelto un Broadcast diverso da quello del tutorial, con l'intenzione di provarlo.

Dunque, il codice che do in Java serve a stabilire la risposta del BroadcastReceiver al messaggio Broadcast, ma non individua l'azione.
Abbiamo il nome e l'azione. Punto. Quindi nella registrazione si mettono insieme il nome del BroadcastReceiver e come intent-filter si stabilisce il messaggio che viene ascoltato dal BroadcastReceiver.

Non è difficile: xml dice: "C'è un messaggio di tipo SMS ricevuto, attivare il receiver Ricevitore. Attivato questo receiver, esso ha specificata l'azione da intraprendere, ossia la creazione di un messaggio Toast.

Vediamo se funziona!