Android, A Complete Course, From Basics to Enterprise Edition

Appels Téléphoniques et SMS

Android, A Complete Course, From Basics to Enterprise Edition. 1

Appels Téléphoniques et SMS. 1

Communiquer avec le système. 1

1.1         Gestion des appels téléphoniques et des SMS. 1

 Cet article est extraie du livre « Android, A Complete Course », disponible sur Android2ee.com.

Les exemples ou les programmes présents dans cet ouvrage sont fournis pour illustrer les descriptions théoriques. Ce code est libre de toute utilisation mais n'est pas distribuable.

La distribution du code est reservée au site :

http://android2ee.com.

La propriété intellectuelle du code appartient à :

Mathias Séguy

L’utilisation de ces codes est sous votre unique responsabilité et personne d’autre que vous ne pourra être tenu responsable des préjudices ou dommages de quelques natures que ce soit pouvant résulter de son utilisation.

Tous les noms de produits ou marques cités dans cet ouvrage sont des marques déposés par leurs propriétaires respectifs.

Publié par http://android2ee.com

Titre Original : Android, A Complete Course, From Basics to Enterprise Edition. Édition Française.

ISBN : 979-10-90388-00-0

Copyright © 2011 by Mathias Séguy

 

Aucune représentation ou reproduction, même partielle, autre que celles prévues à l’article L. 122-5 2° et 3° a) du code de la propriété intellectuelle ne peut être faite sans l’autorisation expresse de Mathias Seguy ou, le cas échéant, sans le respect des modalités prévues à l’article L. 122-10 dudit code

Communiquer avec le système

1.1       Gestion des appels téléphoniques et des SMS

1.1.1       Téléphonie

Ce paragraphe est une vue succincte de la téléphonie, vous apprendrez à lancer l’activité du téléphone à partir de votre activité et à récupérer quelques informations concernant les paramètres de téléphonie.

1.1.1.1        Composer un numéro

Composer un numéro de téléphone se résume à demander à l’activité Android native de téléphonie de composer ce numéro. Cette demande s’effectue comme toujours par l’envoie d’un Intent :

/*****************************************************************************************/

/** Call the phone dialer Activity *******************************************************/

/*****************************************************************************************/

// Declaration of the attribute telephone number

String telNumber = "tel:0561437624";

Uri telNumberUri = Uri.parse(telNumber);

// Declaration of the Intent to call the Phone dialer activity

Intent phoneCallIntent = new Intent(Intent.ACTION_DIAL, telNumberUri);

// Calling the Phone Dialer Activity as a peer Activity

startActivity(phoneCallIntent);

Et voilà, l’activité de téléphone s’ouvre avec votre numéro de téléphone pré-renseigné.

1.1.1.2       Obtenir des informations sur la téléphonie de l’appareil

Vous pouvez obtenir les informations concernant la structure téléphonique de votre appareil, en autres :

·         Le type du téléphone

·         L’état de connexion

·         L’état de la carte SIM

Pour obtenir ces informations, l’objet à utiliser est le TelephonyManager.

Le code suivant montre un exemple de récupération d’informations :

/***************************************************************************************/

/** Looking for Phone parameters *******************************************************/

/***************************************************************************************/

// Find the Telephony Manager

TelephonyManager telephonyManager =

(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);

// Retrieveing the phone type:

//----------------------------

switch (telephonyManager.getPhoneType()) {

case (TelephonyManager.PHONE_TYPE_GSM):

//case (TelephonyManager.PHONE_TYPE_CDMA):

// retrieve the Device Id (iemi for GSM and meid for CDMA)

String deviceId = telephonyManager.getDeviceId();

// retrieve the software version of th device

String deviceSoftwareVersion = telephonyManager.getDeviceSoftwareVersion();

// retrieve the phone number

String phoneNumber = telephonyManager.getLine1Number();

break;

case (TelephonyManager.PHONE_TYPE_NONE):

break;

}

 

//Retrieving the state of the connection

//--------------------------------------

switch(telephonyManager.getDataState()){

case(TelephonyManager.DATA_CONNECTED)://I am connected

case(TelephonyManager.DATA_CONNECTING)://I am connecting

case(TelephonyManager.DATA_DISCONNECTED)://I am disconnected

case(TelephonyManager.DATA_SUSPENDED)://I am suspended

break;

}

 

//Retrieving the state of the SIM card

//------------------------------------

switch(telephonyManager.getSimState()){

case(TelephonyManager.SIM_STATE_ABSENT):

case(TelephonyManager.SIM_STATE_NETWORK_LOCKED):

case(TelephonyManager.SIM_STATE_PIN_REQUIRED):

case(TelephonyManager.SIM_STATE_PUK_REQUIRED):

case(TelephonyManager.SIM_STATE_UNKNOWN):

break;

case(TelephonyManager.SIM_STATE_READY):

//You can retrieve the Sim country Iso,the operator code, the operator name, the serial number of the card

telephonyManager.getSim***();

break;

}

1.1.1.3       Écouter les changements d’état du téléphone

Une bonne pratique pour s’interfacer avec le téléphone est de s’enregistrer en tant qu’écouteur de changement d’états. En effet votre activité, votre application, est alors amène à réagir à ses changements.

Pour cela, il vous suffit de déclarer un PhoneStateListener et de surcharger les méthodes qui correspondent aux changements d’états qui vous intéressent. Ensuite il faut enregistrer ce PhoneStateListener pour chacun des états qui vous intéressent au moyen du TelephonyManager. Et bien sûr, il ne faut pas oublier de le dé-enregistrer quand votre application n’a plus besoin d’écouter ces changements. Il faut aussi demander la permission de pouvoir lire les états du téléphone.

Dans le manifest.xml

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

Dans votre code Java :

/*********************************************************************/

/** Listening for phone states changes **********************************************/

/*********************************************************************/

//Define the phone state listener

PhoneStateListener phoneStateListener=new PhoneStateListener(){                   

/** * Listen for call state change    */

@Override

public void onCallStateChanged(int state, String incomingNumber) {

                //Watch the current state of the call

                switch(state){

                case(TelephonyManager.CALL_STATE_IDLE):

                               //The phone is not ringing neither calling

                case(TelephonyManager.CALL_STATE_OFFHOOK):

                               //The phone is in a call

                case(TelephonyManager.CALL_STATE_RINGING):

                               //the phone is ringing

                               break;

                }

                //the incoming call is the string incomingNumber

}

/** * Listen for data activity change             */

@Override

public void onDataActivity(int direction) {

                switch(direction){

                case(TelephonyManager.DATA_ACTIVITY_IN):

                case(TelephonyManager.DATA_ACTIVITY_INOUT):

                case(TelephonyManager.DATA_ACTIVITY_NONE):

                case(TelephonyManager.DATA_ACTIVITY_OUT):

                               break;

                }

                super.onDataActivity(direction);

}

/** * Listen for data connection change      */

@Override

public void onDataConnectionStateChanged(int state) {

                switch(state){

                case(TelephonyManager.DATA_CONNECTED)://I am connected

                case(TelephonyManager.DATA_CONNECTING)://I am connecting

                case(TelephonyManager.DATA_DISCONNECTED)://I am disconnected

                case(TelephonyManager.DATA_SUSPENDED)://I am suspended

                               break;

                }

                super.onDataConnectionStateChanged(state);

}

/** * Listen for service state changes            */

@Override

public void onServiceStateChanged(ServiceState serviceState) {

                switch(serviceState){

                case(ServiceState.STATE_EMERGENCY_ONLY):

                case(ServiceState.STATE_IN_SERVICE):

                case(ServiceState.STATE_OUT_OF_SERVICE):

                case(ServiceState.STATE_POWER_OFF):

                               break;

                }

                super.onServiceStateChanged(serviceState);

}

};

//Bind the listener using a bits field

telephonyManager.listen(phoneStateListener,

                PhoneStateListener.LISTEN_CALL_STATE|

                PhoneStateListener.LISTEN_DATA_ACTIVITY|

                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE|

                PhoneStateListener.LISTEN_SERVICE_STATE);

//Unbind the listener when you don't need it more (in onPause for exemple)

telephonyManager.listen(phoneStateListener,

                PhoneStateListener.LISTEN_NONE);

1.1.2       SMS et MMS

1.1.2.1       Envoyer un SMS

Il n’y pas grand-chose à faire, il suffit d’envoyer l’Intent ACTION_SENDTO avec le numéro de téléphone en URI et le corps du SMS en extra de type sms_body :

/*****************************************************************************************/

/** Sending SMS using Intents ************************************************************/

/*****************************************************************************************/

// URI Defintion

String phoneNumber = "sms:0663443634";

Uri phoneNumberUri = Uri.parse(phoneNumber);

// SMS Body definition

String smsBody = "My message i want to send";

// Intent Definition

Intent smsIntent = new Intent(Intent.ACTION_SENDTO, phoneNumberUri);

// Adding the body

smsIntent.putExtra("sms_body", smsBody);

// Launching the SMS Activity

startActivity(smsIntent);

1.1.2.2       Envoyer un MMS

Ce n’est pas tellement plus difficile, mais profondément différent. Il suffit d’envoyer un Intent de type Send_TO et avec pour URI celui du fichier à joindre. Ensuite, il faut ajouter à l’Intent les extras address, sms_body et extraStream (pour l’URI du fichier attaché), puis définir le type MIME du MMS :

/*****************************************************************************************/

/** Sending MMS using Intents ************************************************************/

/*****************************************************************************************/

// URI Defintion

phoneNumber = "0663443634";

// Attached file URI

String attachedFile = "content://media/external/images/media/1";

Uri attachedFileUri = Uri.parse(attachedFile);

// MMS Body definition

String mmsBody = "My message i want to send with an attached file";

// Intent Definition /!\ The action is SEND and the URI is the attached file

Intent mmsIntent = new Intent(Intent.ACTION_SEND, attachedFileUri);

// Adding the phone number

mmsIntent.putExtra("address", phoneNumber);

// Adding the body

mmsIntent.putExtra("sms_body", mmsBody);

// Adding the attached file

mmsIntent.putExtra(Intent.EXTRA_STREAM, attachedFileUri);

// Seeting the MIME Type

mmsIntent.setType("image/png");

// Launching the MMS Activity

startActivity(mmsIntent);

1.1.2.3       Envoyer un SMS à la main

L’envoi d’un SMS, sans passer par une activité prédéfinie, n’est pas très compliqué, par contre son suivi s’avère nécessiter plus d’objets à implémenter.

La seule chose à laquelle il faut être attentif, outre les demandes de permissions, est la longueur du SMS à envoyer, en effet celle-ci est limitée à 160 caractères.

1.1.2.4       Sans suivi du transfert ni de la livraison

Dans le manifest.xml, il faut ajouter la demande de permission :

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

Dans le fichier Java de votre activité :

/*****************************************************************************************/

/** Sending SMS manually ******************************************************************/

/** Needs to ask the permission SEND_SMS in your manifest.xml *****************************/

/*****************************************************************************************/

// Retrieveing the SMS Manager

SmsManager smsManager = SmsManager.getDefault();

// Address Defintion

phoneNumber = "0663443634";

// SMS Body definition

smsBody = "My message i want to send";

 

//Sending an SMS according to its size

if(smsBody.length()>=160){

                //your message has to be split in several parts:

                ArrayList<String> smsBodies=smsManager.divideMessage(smsBody);

                // send it with no following with the following parameters:

                // String destinationAddress : The address destination of the SMS

                // String scAddress: The address of the SMS center to use (if null, the default one is used)

                // ArrayList<String> text: The body of the message split in a list

                // ArrayList<PendingIntent> sentIntent: The list of Intent to follow the transfer of each message part

                // ArrayList<PendingIntent> deliveryIntent: The list of Intent to follow the delivery of each message part

                smsManager.sendMultipartTextMessage(phoneNumber, null, smsBodies, null, null);

}else{

                //no need to split your message

                // send an SMS with no following with the following parameters:

                // String destinationAddress : The address destination of the SMS

                // String scAddress: The address of the SMS center to use (if null, the default one is used)

                // String text: The body of the message

                // PendingIntent sentIntent: The Intent to follow the transfer

                // PendingIntent deliveryIntent: The Intent to follow the delivery

                smsManager.sendTextMessage(phoneNumber, null, smsBody, null, null);

}

1.1.2.5       Avec suivi du transfert et de la livraison

Dans le cas d’un suivi du transfert et de la livraison, un ensemble d’éléments sont à définir. Ces éléments sont à définir et pour le suivi de transfert et pour le suivi de la livraison, vous pouvez implémenter l’un ou l’autre ou les deux. Ces éléments sont :

·         Le nom de l’intention que vous écouterez,

·         L’intention elle-même

·         Le PendingIntent associé à votre intention

·         Le filtre d’intention pour pouvoir s’enregistrer comme écouteur de votre intention,

·         Et enfin, le BroadCastReceiver qui vous permettra d’écouter cette intention

Pour des raisons de synthèse, nous avons regroupé le code au sein d’une même méthode, mais il est évident que vous pouvez définir votre propre classe d’écoute (BroadCastReceiver) dans une classe indépendante.

Ce qui donne :

Dans le fichier manifest.xml :

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

 Dans le fichier Java :

/*****************************************************************************************/

/** Sending SMS manually with Lookup ************************************************/

/*****************************************************************************************/

// Sending an SMS using the transfer and delivery follow up:

// ---------------------------------------------------------

 

// Define the transfer follower

// ----------------------------

// First define your Intent name

final String transferFollowerIntentName = "Tr_Fo_In_Na";

// Define Intent to follow the transfer

Intent transferFollowerIntent = new Intent(transferFollowerIntentName);

// Define the PendingIntent associated

PendingIntent transferFollowerPendingIntent = PendingIntent.getBroadcast(

getApplicationContext(),// Application context could be this in an activity

0,// requestCode

transferFollowerIntent,// intent

0);// flags

// Define the Intent filter

IntentFilter transferFollowerIntentFilter = new IntentFilter(transferFollowerIntentName);

// Define and bind the Broadcast receiver associated to the intent

BroadcastReceiver transferFollowerBroadcastReceiver = new BroadcastReceiver() {

                @Override

                public void onReceive(Context context, Intent intent) {

switch (getResultCode()) {

case Activity.RESULT_OK:

               // The result is ok

case SmsManager.RESULT_ERROR_GENERIC_FAILURE:

               // A generic error occured

case SmsManager.RESULT_ERROR_RADIO_OFF:

               // The cell network is off

case SmsManager.RESULT_ERROR_NULL_PDU:

               // An error with the Protocol Description Unit occured

                break;

}             

                }

};

// Bind the BroadcastReceiver to the Intent

registerReceiver(transferFollowerBroadcastReceiver, transferFollowerIntentFilter);

 

// Define the Delivery follower

// ----------------------------

// First define your Intent name

final String deliveryFollowerIntentName = "De_Fo_In_Na";

// Define Intent to follow the transfer

Intent deliveryFollowerIntent = new Intent(deliveryFollowerIntentName);

// Define the PendingIntent associated

PendingIntent deliveryFollowerPendingIntent = PendingIntent.getBroadcast(

getApplicationContext(),// Application context could be this in an activity

0,// requestCode

deliveryFollowerIntent,// intent

0);// flags

// Define the Intent filter

IntentFilter deliveryFollowerIntentFilter = new IntentFilter(deliveryFollowerIntentName);

// Define and bind the Broadcast receiver associated to the intent

BroadcastReceiver deliveryFollowerBroadcastReceiver = new BroadcastReceiver() {

                @Override

                public void onReceive(Context context, Intent intent) {

// The SMS has been delivered: Do something

// The raw pdu of the status report is in the extended data ("pdu").

                }

};

// Bind the BroadcastReceiver to the Intent

registerReceiver(deliveryFollowerBroadcastReceiver, deliveryFollowerIntentFilter);

 

// THEN send your SMS

if(smsBody.length()<160){

                smsManager.sendTextMessage(phoneNumber, null, smsBody, transferFollowerPendingIntent,

deliveryFollowerPendingIntent);

}else{

                //You need to split it:

                ArrayList<String> smsBodies=smsManager.divideMessage(smsBody);

                //You need to declare several Pending Intent one for each smsBody part

                //To follow transfer and delivery

                ArrayList<PendingIntent> deliveryFollowerPendingIntents=new ArrayList<PendingIntent>();

                ArrayList<PendingIntent> transferFollowerPendingIntents=new ArrayList<PendingIntent>();

                for(int i=0;i<smsBodies.size();i++){

deliveryFollowerPendingIntents.add(deliveryFollowerPendingIntent);

transferFollowerPendingIntents.add(transferFollowerPendingIntent);

                }

                //Send your sms:

                smsManager.sendMultipartTextMessage(phoneNumber, null, smsBodies,

transferFollowerPendingIntents,

                deliveryFollowerPendingIntents);

}

 

1.1.2.6       Ecouter les SMS arrivants

L’écoute de SMS arrivants ressemble beaucoup à l’écoute du transfert et de la réception lorsque vous envoyer des SMS. Le principe est identique et s’appuie sur l’écoute d’intention. Seul le traitement diffère.

Dans le manifest.xml :

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

Dans le fichier Java :

/*****************************************************************************************/

/** Listen for incoming SMS ***************************************************************/

/** Needs to ask the permission RECEIVE_SMS in your manifest.xml *****************************/

/*****************************************************************************************/

//Define the SMS_RECEIVE's INTENT NAME

final String SMS_RECEIVE_INTENT_NAME="android.provider.telephony.SMS_RECEIVER";

// Define the Broadcast receiver associated to the RECEIVE SMS intent

BroadcastReceiver incomingSmsBroadcastReceiver = new BroadcastReceiver() {         

                @Override

                public void onReceive(Context context, Intent intent) {

//For exemple rebuild the messages received:

//Check you receive the right intent

if(intent.getAction().equals(SMS_RECEIVE_INTENT_NAME)){

                //Retrieve the bundle that handles the Messages

                Bundle bundle=intent.getExtras();

                if(bundle!=null){

//Retrieve the data store in the SMS

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

//Declare the associated SMS Messages

SmsMessage[] smsMessages=new SmsMessage[pdus.length];

//Rebuild your SMS Messages

for(int i=0;i<pdus.length;i++){

               smsMessages[i]=SmsMessage.createFromPdu((byte[])pdus[i]);

}

//Parse your SMS Message

SmsMessage currentMessage;

String body,from;

for(int i=0;i<smsMessages.length;i++){

               currentMessage=smsMessages[i];

               body=currentMessage.getDisplayMessageBody();

               from=currentMessage.getDisplayOriginatingAddress();

               currentMessage.getTimestampMillis();        

}

                }

}

                }

};

//Define the Intent Filter

IntentFilter smsReceiverIntentFilter= new IntentFilter(SMS_RECEIVE_INTENT_NAME);

//And Bind the BroadcastReciever to that IntentFilter

registerReceiver(incomingSmsBroadcastReceiver, smsReceiverIntentFilter);