Gestire gli SMS

1 novembre 2014

La comunicazione via SMS potrebbe apparire un po’ old-style in questi tempi così “social”. Eppure si tratta della forma di messaggistica più diffusa al mondo, utilizzata con disinvoltura da persone appartenenti ad ogni fascia di età e disponibile su ogni dispositivo che disponga di funzionalità telefoniche. Relativamente al mondo Android, l’utilità in campo professionale dell’interazione via SMS è ancora ampia. Per fare un esempio, esistono molti dispositivi per la domotica, come caldaie, sistemi antifurto, etc. che notificano lo stato dell’impianto o il verificarsi di situazioni particolari via SMS. Ecco: in un caso del genere un’app Android potrebbe rimanere in attesa di tali messaggi, ed utilizzarli interagendo con l’utente.

In questo capitolo, si affronterà proprio l’invio e la ricezione di SMS in un’app Android.

BroadcastReceiver

Delle quattro componenti che costituiscono un’applicazione Android, finora ne abbiamo viste tre: Activity, ContentProvider e Service. Qui introdurremo la quarta: il BroadcastReceiver.

Si tratta di un oggetto che si registra presso il sistema operativo, per essere allertato non appena si verifica una determinata circostanza. L’attivazione avviene mediante il classico meccanismo degli Intent, includendo altri elementi già visti come il PendingIntent e gli IntentFilters.

Un BroadcastReceiver – utile in tantissime circostanze, non solo per gli SMS – viene creato estendendo la classe omonima ed implementando il metodo onReceive. Tale metodo riceve in input due parametri: il Context per l’interazione con il sistema e un Intent. Quest’ultimo contiene tutte le informazioni riguardanti l’evento.

Affinchè funzioni, il BroadcastReceiver deve essere registrato nel sistema e ciò può essere fatto in due modi:

  • via XML, nell’AndroidManifest, mediante il tag <receiver>;
  • in Java, usando il metodo registerReceiver.

In questo capitolo ci avvarremo di entrambe le modalità di registrazione.

Invio di SMS

Per prima cosa impareremo ad inviare SMS da un’app. Per fare ciò, utilizzeremo una classe di sistema denominata SmsManager, adoperandola per due operazioni significative:

  • ci faremo resituire un riferimento all’SmsManager;
  • invieremo per suo tramite un messaggio di testo, con il numero del destinatario ed il testo.

Da non dimenticare che è necessario dichiarare l’apposita permission:

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

Per completezza, queste due operazioni saranno integrate con l’uso di BroadcastReceiver per notificare il successo nell’invio.

String numero = "3301234567"; // di pura fantasia
String testo = "Ciao, come stai?";
SmsManager smsManager = SmsManager.getDefault();
			
PendingIntent inviato = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent("SMS_INVIATO"), 0);
PendingIntent consegnato = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent("SMS_CONSEGNATO"), 0);
			
suInvio=new BroadcastReceiver() 
{
  @Override
  public void onReceive(Context arg0, Intent arg1) 
  {
	if (getResultCode()==Activity.RESULT_OK)
	  Toast.makeText(arg0, "SMS inviato correttamente", Toast.LENGTH_LONG).show();
	else
	  Toast.makeText(arg0, "Errore in invio", Toast.LENGTH_LONG).show();
  }
};
	        
suConsegna=new BroadcastReceiver() 
{
  @Override
  public void onReceive(Context arg0, Intent arg1) 
  {
    if (getResultCode()==Activity.RESULT_OK)
	Toast.makeText(arg0, "SMS consegnato", Toast.LENGTH_LONG).show();
    else
	Toast.makeText(arg0, "Errore", Toast.LENGTH_LONG).show();
  }
};

registerReceiver(suInvio, new IntentFilter("SMS_INVIATO"));
registerReceiver(suConsegna, new IntentFilter("SMS_CONSEGNATO"));
			
smsManager.sendTextMessage(numero, null, testo, inviato, consegnato);

Il codice proposto è una modalità completa per gestire l’invio di un SMS. Il numero del destinatario ed il testo sono contenuti in due stringhe, che abbiamo chiamato rispettivamente numero e testo. Le due righe di codice essenziali sono:

SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(numero, null, testo, inviato, consegnato);

La prima riga individua l’SmsManager e la seconda si occupa dell’invio. Tutto ciò che si trova tra loro serve a gestire la notifica di invio e consegna.

Ognuna di queste due fasi viene gestita con:

  • un PendingIntent che congela un Intent relativo ad azioni personalizzate (SMS_INVIATO per l’invio e SMS_CONSEGNATO per la consegna), che sarà inviato al momento del completamento di ognuna delle due fasi;
  • un BroadcastReceiver che si registrerà per essere informato del lancio del PendingIntent corrispondente.

Nell’Activity sono stati definiti due membri di classe BroadcastReceiver:

private BroadcastReceiver suInvio = null;
private BroadcastReceiver suConsegna = null;

La loro inizializzazione vera e propria è stata effettuata in fase di invio. Il metodo onReceive in questo caso apre un Toast di notifica.

Affinchè il BroadcastReceiver sia attivo è necessario che venga registrato. Visto che ci sono due coppie BroadcastReceiverPendingIntent, avverranno due registrazioni, ognuna delle quali assocerà un Receiver con il corrispondente IntentFilter relativo all’azione richiesta:

registerReceiver(suInvio, new IntentFilter("SMS_INVIATO"));
registerReceiver(suConsegna, new IntentFilter("SMS_CONSEGNATO"));

Infine possiamo richiedere che nel metodo onPause vengano cancellate le registrazioni dei BroadcastReceiver, nel seguente modo:

@Override
protected void onPause() 
{
  super.onPause();
  unregisterReceiver(suInvio);
  unregisterReceiver(suConsegna);
}

Ricezione

Per quanto riguarda la ricezione di SMS, non aggiungeremo concetti nuovi, dal momento che utilizzeremo nuovamente la classe BroadcastReceiver.

Prima di tutto, specifichiamo le permission nel Manifest; questa volta occorrono le seguenti:

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

Poi creiamo una classe Java che eredita da BroadcastReceiver:

public class IncomingSMS extends BroadcastReceiver
{
	@Override
	public void onReceive(Context context, Intent intent) 
	{
		Bundle extras = intent.getExtras();
        
       if ( extras != null )
        {
        	Object[] smsExtra = (Object[]) extras.get( "pdus");
            for ( int i = 0; i < smsExtra.length; ++i )
            {
                SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
                String testo = sms.getMessageBody().toString();
                String numero = sms.getOriginatingAddress();
		    /* Svolgimento di operazioni 
			 sul messaggio*/
            }
        }
	}
}

Infine registriamo presso il sistema il BroadcastReceiver, inserendo un apposito tag nel manifest:

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

L'azione inclusa nell'IntentFilter, questa volta, non è definita da noi come nel caso dell'invio. Rimaniamo in attesa dell'evento SMS_RECEIVED definito nel package Telephony.

Per quanto riguarda più in dettaglio il codice scritto in Java, tra gli Extras dell'Intent ce n'è uno con etichetta pdus. Dobbiamo trasformare le varie PDU arrivate – in pratica gli SMS grezzi - in oggetti di classe SmsMessage. Questo permetterà anche di poterli leggere in maniera agevole con metodi ad hoc. Dopo la conversione, infatti, per ottenere il testo del messaggio è sufficiente invocare il metodo getMessageBody, mentre per il numero del mittente si ricorre a getOriginatingAddress.

Tutte le lezioni

1 ... 58 59 60 ... 83

Se vuoi aggiornamenti su Gestire gli SMS inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Gestire gli SMS

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy