J'ai compris comment envoyer et recevoir SMS messages. Pour envoyer SMS messages, j'ai dû appeler le sendTextMessage()
et sendMultipartTextMessage()
méthodes de l SmsManager
classe. Pour recevoir SMS j'ai dû enregistrer un récepteur dans l'application AndroidMainfest.xml
fichier. Ensuite, j'ai dû remplacer le onReceive()
de la méthode BroadcastReceiver
. J'ai inclus des exemples ci-dessous.
MainActivity.java
public class MainActivity extends Activity {
private static String SENT = "SMS_SENT";
private static String DELIVERED = "SMS_DELIVERED";
private static int MAX_SMS_MESSAGE_LENGTH = 160;
// ---sends an SMS message to another device---
public static void sendSMS(String phoneNumber, String message) {
PendingIntent piSent = PendingIntent.getBroadcast(mContext, 0, new Intent(SENT), 0);
PendingIntent piDelivered = PendingIntent.getBroadcast(mContext, 0,new Intent(DELIVERED), 0);
SmsManager smsManager = SmsManager.getDefault();
int length = message.length();
if(length > MAX_SMS_MESSAGE_LENGTH) {
ArrayList<String> messagelist = smsManager.divideMessage(message);
smsManager.sendMultipartTextMessage(phoneNumber, null, messagelist, null, null);
}
else
smsManager.sendTextMessage(phoneNumber, null, message, piSent, piDelivered);
}
}
//More methods of MainActivity ...
}
SMSReceiver.java
public class SMSReceiver extends BroadcastReceiver {
private final String DEBUG_TAG = getClass().getSimpleName().toString();
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private Context mContext;
private Intent mIntent;
// Retrieve SMS
public void onReceive(Context context, Intent intent) {
mContext = context;
mIntent = intent;
String action = intent.getAction();
if(action.equals(ACTION_SMS_RECEIVED)){
String address, str = "";
int contactId = -1;
SmsMessage[] msgs = getMessagesFromIntent(mIntent);
if (msgs != null) {
for (int i = 0; i < msgs.length; i++) {
address = msgs[i].getOriginatingAddress();
contactId = ContactsUtils.getContactId(mContext, address, "address");
str += msgs[i].getMessageBody().toString();
str += "\n";
}
}
if(contactId != -1){
showNotification(contactId, str);
}
// ---send a broadcast intent to update the SMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
public static SmsMessage[] getMessagesFromIntent(Intent intent) {
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++) {
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++) {
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
/**
* The notification is the icon and associated expanded entry in the status
* bar.
*/
protected void showNotification(int contactId, String message) {
//Display notification...
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myexample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.WRITE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:debuggable="true"
android:icon="@drawable/ic_launcher_icon"
android:label="@string/app_name" >
<activity
//Main activity...
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
//Activity 2 ...
</activity>
//More acitivies ...
// SMS Receiver
<receiver android:name="com.myexample.receivers.SMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Cependant, je me demandais si vous pouviez envoyer et recevoir MMS de manière similaire. Après avoir fait quelques recherches, de nombreux exemples fournis sur les blogs font simplement passer un Intent
à l'application native de la messagerie. J'essaie d'envoyer un MMS sans quitter mon application. Il ne semble pas y avoir de moyen standard pour envoyer et recevoir MMS . Quelqu'un a-t-il réussi à faire fonctionner ce système ?
De plus, je suis conscient que le ContentProvider SMS/MMS ne fait pas partie de la version officielle de l'interface utilisateur. Android SDK
mais je me disais que quelqu'un avait peut-être réussi à le mettre en œuvre. Toute aide est grandement appréciée.
Mise à jour
J'ai ajouté un BroadcastReceiver
à la AndroidManifest.xml
pour recevoir MMS messages
<receiver android:name="com.sendit.receivers.MMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
Dans la classe MMSReceiver, la fonction onReceive()
est seulement capable de récupérer le numéro de téléphone d'où le message a été envoyé. Comment récupérer d'autres éléments importants d'un MMS comme le chemin d'accès à la pièce jointe (image/audio/vidéo) ou le texte de l'en-tête du message. MMS ?
MMSReceiver.java
public class MMSReceiver extends BroadcastReceiver {
private final String DEBUG_TAG = getClass().getSimpleName().toString();
private static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED";
private static final String MMS_DATA_TYPE = "application/vnd.wap.mms-message";
// Retrieve MMS
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String type = intent.getType();
if(action.equals(ACTION_MMS_RECEIVED) && type.equals(MMS_DATA_TYPE)){
Bundle bundle = intent.getExtras();
Log.d(DEBUG_TAG, "bundle " + bundle);
SmsMessage[] msgs = null;
String str = "";
int contactId = -1;
String address;
if (bundle != null) {
byte[] buffer = bundle.getByteArray("data");
Log.d(DEBUG_TAG, "buffer " + buffer);
String incomingNumber = new String(buffer);
int indx = incomingNumber.indexOf("/TYPE");
if(indx>0 && (indx-15)>0){
int newIndx = indx - 15;
incomingNumber = incomingNumber.substring(newIndx, indx);
indx = incomingNumber.indexOf("+");
if(indx>0){
incomingNumber = incomingNumber.substring(indx);
Log.d(DEBUG_TAG, "Mobile Number: " + incomingNumber);
}
}
int transactionId = bundle.getInt("transactionId");
Log.d(DEBUG_TAG, "transactionId " + transactionId);
int pduType = bundle.getInt("pduType");
Log.d(DEBUG_TAG, "pduType " + pduType);
byte[] buffer2 = bundle.getByteArray("header");
String header = new String(buffer2);
Log.d(DEBUG_TAG, "header " + header);
if(contactId != -1){
showNotification(contactId, str);
}
// ---send a broadcast intent to update the MMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("MMS_RECEIVED_ACTION");
broadcastIntent.putExtra("mms", str);
context.sendBroadcast(broadcastIntent);
}
}
}
/**
* The notification is the icon and associated expanded entry in the status
* bar.
*/
protected void showNotification(int contactId, String message) {
//Display notification...
}
}
Selon le Documentation de Android.provider.Telephony :
Action de diffusion : Un nouveau message SMS a été reçu par l'appareil. L'intention aura les valeurs supplémentaires suivantes :
pdus - An Object[] od byte[]s containing the PDUs that make up the message.
Les valeurs supplémentaires peuvent être extraites en utilisant getMessagesFromIntent(Android.content.Intent). Si un BroadcastReceiver rencontre une erreur lors du traitement de cette intention, il doit définir le code de résultat de manière appropriée.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
Action de diffusion : Un nouveau message SMS basé sur des données a été reçu par le dispositif. L'intention aura les valeurs supplémentaires suivantes :
pdus - An Object[] of byte[]s containing the PDUs that make up the message.
Les valeurs supplémentaires peuvent être extraites en utilisant getMessagesFromIntent(Android.content.Intent). Si un BroadcastReceiver rencontre une erreur lors du traitement de cette intention, il doit définir le code de résultat de manière appropriée.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
Action de diffusion : Un nouveau message WAP PUSH a été reçu par l'appareil. L'intention aura les valeurs supplémentaires suivantes :
transactionId (Integer) - The WAP transaction ID
pduType (Integer) - The WAP PDU type
header (byte[]) - The header of the message
data (byte[]) - The data payload of the message
contentTypeParameters (HashMap<String,String>) - Any parameters associated with the content type (decoded from the WSP Content-Type header)
Si un BroadcastReceiver rencontre une erreur lors du traitement de cette intention, il doit définir le code de résultat de manière appropriée. La valeur supplémentaire contentTypeParameters est une carte de paramètres de contenu dont la clé est leur nom. Si des paramètres connus non attribués sont rencontrés, la clé de la carte sera "unassigned/0x...", où "..." est la valeur hexagonale du paramètre non attribué. Si un paramètre a une valeur nulle, la valeur dans la carte sera nulle.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
Mise à jour n°2
J'ai trouvé comment passer des extras dans un fichier de type PendingIntent
à recevoir par un BroadcastReceiver
: Extras PendingIntent d'Android, non reçus par BroadcastReceiver
Cependant, le supplément est transmis à la SendBroadcastReceiver pas le Récepteur de SMS . Comment puis-je passer un extra à la Récepteur de SMS ?
Mise à jour n°3
Réception de MMS
Après avoir approfondi mes recherches, j'ai vu qu'il était possible d'enregistrer un nom de domaine. ContentObserver
. De cette façon, vous pouvez détecter quand il y a des changements dans les content://mms-sms/conversations
fournisseur de contenu, ce qui vous permet de détecter les MMS entrants. Voici l'exemple le plus proche de ce fonctionnement que j'ai trouvé : Réception de MMS
Cependant, il existe une variable mainActivity
de type ServiceController
. Où se trouve le ServiceController
mis en œuvre ? Existe-t-il d'autres implémentations d'une classe enregistrée ContentObserver
?
Envoi de MMS
Quant à l'envoi de MMS, je suis tombé sur cet exemple : Envoyer des MMS
Le problème est que j'ai essayé d'exécuter ce code sur mon Nexus 4, qui est sous Android v4.2.2, et je reçois cette erreur :
java.lang.SecurityException: No permission to write APN settings: Neither user 10099 nor current process has android.permission.WRITE_APN_SETTINGS.
L'erreur se produit après l'interrogation de la base de données de l'UE. Carriers
ContentProvider dans le getMMSApns()
de la méthode APNHelper
classe.
final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);
Apparemment, vous ne pouvez pas Lire les APN dans Android 4.2
Quelle est l'alternative pour toutes ces applications qui utilisent les données mobiles pour effectuer des opérations (comme l'envoi de MMS) et qui ne connaissent pas le paramètre APN par défaut présent dans l'appareil ?
Mise à jour n°4
Envoi de MMS
J'ai essayé de suivre cet exemple : Envoyer des MMS
Comme @Sam l'a suggéré dans sa réponse :
You have to add jsoup to the build path, the jar to the build path and import com.droidprism.*; To do that in android, add the jars to the libs directory first, then configure the project build path to use the jars already in the libs directory, then on the build path config click order and export and check the boxes of the jars and move jsoup and droidprism jar to the top of the build order.
Maintenant, je n'ai plus d'erreurs SecurityException. Je teste maintenant sur un Nexus 5 sous Android KitKat. Après avoir exécuté l'exemple de code, j'obtiens un code de réponse 200 après l'appel à
MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);
Cependant, j'ai vérifié auprès de la personne à qui j'ai essayé d'envoyer le MMS. Et ils ont dit qu'ils n'ont jamais reçu le MMS.