Android lezione 11 – Ricevere gli SMS

Nella lezione precedente abbiamo visto come spedire un sms dal nostro android, ora come promesso vi spiegherò come riceverli. Per implementare la ricezione degli sms useremo un nuovo oggetto specifico di android. Il BroadcastReceiver. Si tratta di una classe astratta, che viene utilizzata dalle applicazioni android qualora queste vogliano ricevere dati dalle intent che vengono spedite dalla sendBroadcast().

 

Dal momento che le intent che si possono ricevere (o spedire) sono molte, possiamo istruire la nostra applicazione per rispondere solo ad alcune di esse. E questo lo si puó agevolmente fare  tramite il Manifest. In questo caso le intent che dovranno essere ricevute dal nostro BroadcastReceiver vanno inserite all’interno del tag chiamato appunto <receiver …> che viene utilizzato appunto per configurare questo tipo di oggetti. Quindi quello che dovremo aggiungere sarà:

  • Un oggetto di tipo reciever:
    <receiver android:name=".SmsReceiver" android:enabled="true">
       ...
    </receiver>

    Dove in android:name andiamo ad indicare la nostra classe che implementa il BroadCastReceiver (.SmsReceiver). In pratica questo tipo di tag indica al sistema una classe che dovrá ricevere le intent spedite inviate in modalitá “broadcast” dala sistema.

  • All’interno di questo dobbiamo aggiungere un intent filter, nel quale andremo a specificare le singole action alle quali dovrà rispondere il nostro receiver. In questo caso l’action che ci interessa è:
    android.provider.Telephony.SMS_RECEIVED

    Questo causerá che ogni volta che il telefonino riceverá un SMS l’invocazione fra le altre cose del nostro receiver.
    Ovviamente se aggiungevamo altre action, queste a loro volta avrebbe chiamato il nostro receiver.

Quindi il pezzo di codice che andremo a inserire è:

<receiver android:name=".SMSReceiver" android:enabled="true">
        	<intent-filter>
	        	<action android:name="android.provider.Telephony.SMS_RECEIVED" />
        	</intent-filter>
        </receiver>

In pratica in questo modo stiamo istruendo il sistema android di installare un BroadCastReceiver (SmsReceiver) , abilitarlo (perchè possiamo anche decidere di non abilitarlo sin da subito, ma solo su richiesta dell’utente) e farlo rispondere alle Intent che contengono come action appunto:

android.provider.Telephony.SMS_RECEIVED

Inoltre per accedere alla funzionalitá di ricezione degli sms, dobbiamo chiedere il permesso ad android (come gia fatto precedentement con la spedizione), quindi sempre nel manifest (al di fuori del tag application) aggiungiamo:

 <uses-permission android:name="android.permission.RECEIVE_SMS"/>

Vediamo ora in dettaglio cosa è il BroadCastReceiver. Si tratta innanzitutto di una classe astratta, quindi per utilizzarla dobbiamo creare noi una classe che la implementa. Nel nostro esempio si tratta di SMSReceiver. Questo tipo di classe serve per ricevere le intent inviate con sendBroadcast() 

Il metodo che dobbiamo implementare è il seguente:

abstract void onReceive(Context context, Intent intent);

Questo metodo è quello che viene invocato quando si riceverá l’intent con al suo interno la action SMS_RECEIVED. Come vedete questo metodo prende due variabili:

  • Context context
  • Intent intent: questa verrá utilizzata per prendere il contenuto del messaggio.

Quindi iniziamo a scrivere la nostra classe, per ora avremo:

 

public class SmsReceiver extends BroadcastReceiver {
 
    public void onReceive(Context context, Intent intent) {
    }
 
}

Il messaggio appena ricevuto è stato inserito fra gli extended data della intent, quindi per prima cosa  dobbiamo recuperarlo da questo. Quindi per prendere questi dati occorre utilizzare all’interndo di onReceive, come prima cosa il metodo getExtras() che restituisce un oggetto di tipo Bundle:

	Bundle bundle = intent.getExtras();

Se è la prima volta che incontrare l’oggetto bundle, si tratta essenzialmente di una mappa che contiene coppie chiave/valore. Ovviamente questa oggetto potrebbe contenere anche altre informazioni oltre l’sms. Ma quella che per ora ci interessa è l’sms, e la chiave che li identifica é “pdus”. Utilizzando il metodo get dell’oggetto bundle prendiamo l’array che conterrá gli sms:

    Object[] pdus = (Object[])bundle.get("pdus");

Per accedere al contenuto dell’sms,  utilizziamo una classe che ci aiuta nella loro gestione: SmsMessage. Quindi a partire dal vettore Object ne creiamo uno di tipo SMSMessage.

SmsMessage[] messages = new SmsMessage[pdus.length];
for(int i = 0; i &lt; pdus.length; i++){
	messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}

Il metodo SmsMessage.createFromPdu(…); si occupa di creare un SMS a partire da una pdu raw, quindi quello che abbiamo fatto è semplicemente un ciclo che a per ogni elemento pdus[i] ha creato il relativo SmsMessage e lo ha inserito in messages[i].

A questo punto possiamo semplicemente passare a leggere il contenuto dell’sms.

for(SmsMessage message: messages){
    String messagestr = message.getMessageBody();
    String sender = message.getOriginatingAddress();
    Toast.makeText(context, sender + ": " + messagestr, Toast.LENGTH_SHORt).show;
}

Quindi con message.getMessageBody() prendiamo il contenuto del messaggio, mentre con getOriginatingAddress() prendiamo il mittente. Infine mostriamo il contenuto del messaggio con una semplice messaggio sullo schermo.

Il codice completo della funzione onReceive della classe SMSReceiver è il seguente:

	@Override
	public void onReceive(Context context, Intent intent) {
		Bundle bundle = intent.getExtras();
		Object[] pdus = (Object[])bundle.get("pdus");
		SmsMessage[] messages = new SmsMessage[pdus.length];
		for(int i = 0; i &lt; pdus.length; i++){
			messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
		}
		for(SmsMessage message: messages){
		    String messagestr = message.getMessageBody();
		    String sender = message.getOriginatingAddress();
		    Toast.makeText(context, sender + ": " + messagestr, Toast.LENGTH_SHORT).show();
		}
	}

Ora per testare l’applicazione con gli emulatori, dobbiamo avviare due emulatori. Con uno lanciamo l’applicazione che abbiamo creato, mentre il secondo lo useremo solo per inviare l’sms. Il numero da comporre per spedire é quello che si trova nella barra del titolo, quindi se l’emulatore con la nostra applicazione avrá come titolo “5554 …” il numero a cui dovremo inviare l’sms sará appunto 5554. In figura trovate un esempio di esecuzione del programma a destra, mentre nell’emulatore a sinistra vedete il messaggio che è stato spedito.

Prima di chiudere voglio porre l’attenzione su un ultima cosa, l’esempio che trovate on-line contiene un activity praticamente vuota, notate che se la vostra applicazione non ha bisogno di interagire con l’utente (come per esempio con la ricezione degli SMS appunto) non avete bisogno di creare per forza un activity. Vi è sufficente il receiver.

I sorgenti di questa lezione li trovate qua: https://github.com/inuyasha82/ItalialinuxExample/tree/master/LezioniAndroid Il progetto si chiama SMSRecvExample.

Bene con questo capitolo concludo la parte relativa agli SMS. Arrivederci alla prossima lezione.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.