Envoyer des sms sous android

 

Pour les tests en développement, il sera possible de simuler l'envoi d'un SMS vers votre émulateur.

 

Envoyer un SMS via les applications existantes

La première solution pour envoyer des SMS, est d'utiliser les applications déjà existantes. Nous allons faire une intention, à android de trouver l'application qui sera capable d'envoyer notre SMS.

Intent i = new Intent(android.content.Intent.ACTION_VIEW);

Il reste à passer tous les paramètres nécessaire pour l'envoi d'un SMS, soit le(s) numéro(s) de téléphone qui doivent recevoir ces SMS (séparateur est le ;)
i.putExtra(“address”, “0611223344;0622113344;”);

Puis le corps du message
i.putExtra(“sms_body”, “Bonjour tout le monde !”);

Et enfin préciser le MIME pour qu'android sâche quelle application utiliser.
i.setType(“vnd.android-dir/mms-sms”);

Allez, à Android de se dépatouiller avec tout cela...
startActivity(i);


Envoyer un SMS depuis son application

Sécurité

Pour envoyer un SMS, il faut d'abord autoriser l'application (Cf. permission):

Dans le fichier AndroidManifest.xml:

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

 

SmsManager

SmsManager est la classe qui va gérer les SMS. Il n'est pas possible d'avoir une instance de cette classe, mais il faudra utiliser une méthode statique SmsManager.getDefault() pour en récupérer une par défaut.

SmsManager sms = SmsManager.getDefault();

Image non trouvée !Bien utiliser android.telephony.SmsManager, et non android.telephony.gsm.SmsManager qui est dépréciée depuis l'API 4 !

 

Envoyer un SMS

Les SMS ont une taille de 160 caractères maximum. Au delà, il sera nécessaire de découper le texte en bloc de 160 caractères et de les envoyer les uns après les autres.

Image non trouvée !Les messages envoyés par cette solution n'apparaîtront pas dans l'historique des SMS envoyés de l'application standard de gestion des SMS.

 

SMS conventionnel (jusqu'à 160 caractères)

Pour envoyer un SMS, il reste à passer par la méthode sendTextMessage()

public void sendTextMessage (String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)

En entrée:

destinationAddress Adresse (n° de téléphone) qui doit recevoir le SMS
scAddress Adresse du service de gestion des SMS. Positionnée généralement à NULL pour utiliser SMSC par défaut
text pour le texte à envoyer

Vu plus loin, les paramètres qui suivent servent à avertir que le message est envoyé et reçu ou non par le destinataire. La mise en oeuvre étant un peu plus lourde, ils seront positionnés dans un premier temps à NULL.

En sortie:

Une exception peut se produire si l'adresse de destination "destinationAddress" ou le texte sont vides.

Exemple:

sms.sendTextMessage(numTelephone, null, message, null, null);

Ici, un émulateur AVD va envoyer un SMS vers un autre émulateur AVD, le n°5556.

 

SMS volumineux (au delà de 160 caractères)

Pour envoyer un SMS de plus de 160 caractères, le plus simple sera d'utiliser la méthode sendMultipartTextMessage prévue à cet effet:

public void sendMultipartTextMessage (String destinationAddress, String scAddress, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents)

destinationAddress Adresse (n° de téléphone) qui doit recevoir le SMS
scAddress Adresse du service de gestion des SMS. Positionnée généralement à NULL pour utiliser SMSC par défaut
parts Tableau de String contenant le texte à envoyé, découpé en bloc de 160 caractères et ordonné pour pouvoir récupérer le texte dans son ensemble

Vu plus loin, les paramètres qui suivent servent à avertir que les messages sont envoyés et reçus ou non par le destinataire. La mise en oeuvre étant un peu plus lourde, ils seront positionnés dans un premier temps à NULL. Sinon, il s'agit de tableaux composés d'autant de PendingIntent qu'il y a de blocs de texte à envoyer (parts).

En sortie:

Une exception peut se produire si l'adresse de destination "destinationAddress" ou le texte sont vides.

Pour faire le tableau de String, rien de plus simple puisque là aussi, une méthode est prévue à cet effet:

ArrayList<String> parts = sms.divideMessage(monMessageText);

Exemple de code:

Image non trouvée !Le code fonctionne bien sur de vrais appareils. Par contre, il semble y avoir un bug avec les AVD (émulateur android de Google), vous obtiendrez des caractères parasites sur l'avd recevant le sms !

(Cf. http://code.google.com/p/android/issues/detail?id=13737).

 

Suivi de l'envoi d'un SMS

Ok, le SMS est maintenant envoyé, mais est-il arrivé à destination ? Rien ne l'indique, du moins pour le moment ; )

Deux paramètres ont été définis dans les méthodes sendTextMessage() et sendMultipartTextMessage():

Il s'agit de PendindIntent sentIntent et PendingIntent deliveryIntent.

Ils sont tous deux des instances de PendingIntent et vont permettre à l'activité de gestion des SMS d'envoyer des intentions nous indiquant à quelle étape de l'envoi du SMS il en est et dans quel état:

L'instance sentIntent() lancera une intention indiquant l'étape "envoi du SMS": "SMS envoyé, le résultat de l'opération le voici".

Pour répondre à cela, il est nécessaire d'avoir une intention sur "SENT_SMS" (Je vous informe qu'un SMS a été envoyé).

 

L'instance deliveryIntent() lancera une intention indiquant l'étape "message délivré": "SMS délivré, le résultat l'opération le voici".

Pour répondre à cela, il est nécessaire d'avoir une intention sur "SMS_DELIVERED" (Je vous informe qu'un SMS a été délivré).

 

Ces intentions doivent être diffusées à toutes applications gérant les SMS. A elles de voire ensuite si elles sont concernées ou pas. Il s'agit donc d'utiliser un PendindIntent pour pouvoir démarrer un broadcast: Soit la méthode static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags). Les applications abonnées à ce broadcast seront dès lors informées suivant les règles du broadcast.

Exemple:

SmsManager sms = SmsManager.getDefault();

PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent("SMS_SENT"), 0);

PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0, new Intent("SMS_DELIVERED"), 0);

sms.sendTextMessage("5556", null, message, sentPI, deliveredPI);

 

Dans notre cas, pour connaître l'état des différentes étapes de l'envoi du SMS, il faudra abonner l'application à ces deux intentions et donc développer des "broadcast receivers":

Un pour traiter "SMS_SENT" et un pour traiter "SMS_DELIVERED"

BroadcastReceiver smsSentReceiver

BroadcastReceiver smsDeliveredReceiver;

Les abonnements se feront dans le onResume (c'est le meilleur endroit pour gérer les broadcast receivers par rapport au cycle de vie d'une activité):

registerReceiver(smsSentReceiver, new IntentFilter("SMS_SENT"));
registerReceiver(smsDeliveredReceiver, new IntentFilter("SMS_DELIVERED"));

Reste à déclarer les broadcast receivers:

smsSentReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {...}

smsDeliveredReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) { ...}

Ces broadcast receivers devront traiter le résultat de l'activité:

switch (getResultCode())
{

[...]

}

La gestion du code retrour va dépendre de l'étape en cours.

Dans le cas de SMS_SENT:

L'envoi a réussi: Activity.RESULT_OK, sinon:

int RESULT_ERROR_GENERIC_FAILURE Echec générique
int RESULT_ERROR_NO_SERVICE Echec sur le service qui est incorrect ou ne répond pas
int RESULT_ERROR_NULL_PDU Aucun PDU (protocole description unit) fourni
int RESULT_ERROR_RADIO_OFF Echec car la radio est sur off...la radio étant tout simplement le réseau du mobile.

Dans le cas de SMS_DELIVERED:

Plus classique, il suffit de tester:

Activity.RESULT_OK ou Activity.RESULT_CANCELED

 

Enfin, le désabonnement dans le onPause()

unregisterReceiver(smsSentReceiver);
unregisterReceiver(smsDeliveredReceiver);

 

 

Image non trouvée !Avec les émulateurs AVD, deliveryIntent ne sera jamais exécutée.

 

Exemple de réception avec contrôle

 

Annexes

Il pourra être intéressant de contrôler le mode hors ligne ou mode avion avant d'envoyer un SMS.

Enfin, voyez les explications pour recevoir des SMS.