J'ai compris comment envoyer et recevoir des SMS. Pour envoyer des SMS, j'ai dû appeler les méthodes sendTextMessage()
et sendMultipartTextMessage()
de la SmsManager
classe. Pour recevoir des SMS, j'ai dû enregistrer un destinataire dans le AndroidMainfest.xml
fichier. Ensuite, j'ai dû remplacer la onReceive()
méthode du 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 des messages MMS de la même manière. Après quelques recherches, de nombreux exemples fournis sur les blogs passent simplement un Intent
à l'application de messagerie native. J'essaye d'envoyer un MMS sans quitter mon application. Il ne semble pas y avoir de moyen standard d'envoyer et de recevoir des MMS. Quelqu'un a-t-il réussi à faire fonctionner cela?
De plus, je sais que le fournisseur de contenu SMS / MMS ne fait pas partie du SDK Android officiel, mais je pensais que quelqu'un aurait pu l'implémenter. Toute aide est grandement appréciée.
Mettre à jour
J'ai ajouté un BroadcastReceiver
au AndroidManifest.xml
fichier pour recevoir des messages MMS
<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 onReceive()
méthode ne peut récupérer que le phoneNumber à partir duquel le message a été envoyé. Comment récupérez-vous d'autres éléments importants d'un MMS comme le chemin du fichier vers la pièce jointe multimédia (image / audio / vidéo) ou le texte dans le 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 la documentation de android.provider.Telephony :
Action de diffusion: un nouveau message SMS textuel a été reçu par l'appareil. L'intention aura les valeurs supplémentaires suivantes:
pdus
- UnObject[]
debyte[]
s contenant les PDU qui composent le message.Les valeurs supplémentaires peuvent être extraites à l'aide de
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 les données a été reçu par l'appareil. L'intention aura les valeurs supplémentaires suivantes:
pdus
- UnObject[]
debyte[]
s contenant les PDU qui composent le message.Les valeurs supplémentaires peuvent être extraites à l'aide de 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)
- L'ID de transaction WAP
pduType (Integer)
- Le type de PDU WAP`
header (byte[])
- L'en-tête du message
data (byte[])
- La charge de données du message
contentTypeParameters (HashMap<String,String>)
- Tous les paramètres associés au type de contenu (décodés à partir de l'en-tête Content-Type du WSP)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 des paramètres de contenu indexés par 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 hexadécimale du paramètre non assigné. Si un paramètre n'a aucune valeur, la valeur de 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 # 2
J'ai compris comment passer des extras dans un PendingIntent
pour être reçu par un BroadcastReceiver
:
extras Android PendingIntent, non reçus par BroadcastReceiver
Toutefois, le supplément est transmis au SendBroadcastReceiver et non au SMSReceiver . Comment puis-je transmettre un supplément au SMSReceiver ?
Mise à jour n ° 3
Recevoir des MMS
Donc, après avoir fait plus de recherches, j'ai vu quelques suggestions d'enregistrement d'un fichier ContentObserver
. De cette façon, vous pouvez détecter les modifications apportées au content://mms-sms/conversations
fournisseur de contenu, ce qui vous permet par conséquent de détecter les MMS entrants. Voici l'exemple le plus proche pour que cela fonctionne que j'ai trouvé: Réception de MMS
Cependant, il existe une variable mainActivity
de type ServiceController
. Où la ServiceController
classe est-elle implémentée? Existe-t-il d'autres implémentations d'un enregistré 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 sur 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 est levée après avoir interrogé Carriers
ContentProvider dans la getMMSApns()
méthode de la 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 des données mobiles pour effectuer des opérations (comme l'envoi de MMS) et 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.
Alors maintenant, je n'obtiens plus les erreurs SecurityException. Je teste maintenant sur un Nexus 5 sur Android KitKat. Après avoir exécuté l'exemple de code, il me donne 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'avaient jamais reçu le MMS.