Envoi et réception de SMS et MMS en Android (pré Kit Kat Android 4.4)

j'ai trouvé comment envoyer et recevoir des messages SMS. Pour envoyer des messages SMS, j'ai dû appeler les méthodes sendTextMessage() et sendMultipartTextMessage() de la classe SmsManager . Pour recevoir des messages SMS, j'ai dû enregistrer un récepteur dans le fichier AndroidMainfest.xml . Puis j'ai dû annuler la méthode onReceive() de la BroadcastReceiver . J'ai inclus des exemples ci-dessous.

activité principale.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 avoir fait quelques recherches, de nombreux exemples fournis sur les blogs passent simplement un Intent à L'application de messagerie native. J'essaie d'envoyer un MMS sans laisser ma candidature. Il ne semble pas être un moyen standard de l'envoi et de la réception de MMS. Quelqu'un a eu cela fonctionne?

en outre, je suis conscient que le SMS/MMS ContentProvider ne fait pas partie du SDK officiel Android, mais je pensais que quelqu'un pourrait avoir été en mesure de mettre en œuvre cela. Toute aide est grandement appréciée.

mise à Jour

j'ai ajouté un BroadcastReceiver au AndroidManifest.xml fichier pour recevoir les 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 le MMSReceiver classe, la méthode onReceive() n'est capable de saisir que le numéro de téléphone à partir duquel le message a été envoyé. Comment saisir d'autres choses importantes d'un MMS comme le chemin du fichier vers la pièce jointe mé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 d'android.Fournisseur.Téléphonie :

Action de diffusion: un nouveau message SMS textuel a été reçu par l'appareil. L'intention aura les valeurs supplémentaires suivantes:

pdus - Un Object[] de "1519230920 contenant les Pdu qui composent le message.

les valeurs supplémentaires peuvent être extraites en utilisant getMessagesFromIntent(android.content.Intent) Si un émetteur-récepteur de radiodiffusion rencontre une erreur pendant le traitement de cette intention, il devrait définir le code de résultat de façon appropriée.

 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
 public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";

"1519450920 de la" Diffusion d'Action: Une nouvelle base de données de message de SMS a été reçu par l'appareil. L'intention aura les valeurs supplémentaires suivantes:

pdus - Un Object[] de "1519230920 contenant les Pdu qui composent le message.

les valeurs supplémentaires peuvent être extraites en utilisant getMessagesFromIntent(android.contenu.Intention.) Si un émetteur-récepteur rencontre une erreur lors du traitement de cette intention il doit établir le code de résultat de façon appropriée.

@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";

"1519450920 de la" Diffusion d'Action: Un nouveau WAP PUSH message a été reçu par l'appareil. L'intention aura les valeurs supplémentaires suivantes:

transactionId (Integer) - Le WAP ID de transaction

pduType (Integer) - the WAP PDU type

header (byte[]) - l'en-tête du message

data (byte[]) - la charge utile de données du message

contentTypeParameters (HashMap<String,String>) - tout paramètre associé au type de contenu (décodé à partir de l'en-tête contenu-Type de WSP)

si un émetteur-récepteur de radiodiffusion rencontre une erreur pendant le traitement de cette intention, il doit définir le code de résultat de façon appropriée. La valeur supplémentaire contentTypeParameters est la carte des paramètres de contenu saisis par leurs noms. Si des paramètres bien connus non attribués sont rencontré, la clé de la carte sera " non affecté/0x...', où.' ..'est la valeur hexadécimale du paramètre non attribué. Si un paramètre n'a Pas de 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 trouvé comment passer des extras dans un PendingIntent à recevoir par un BroadcastReceiver : Android PendingIntent extras, not received by broadcasting

Toutefois, le supplément est passé au SendBroadcastReceiver et non au SMSReceiver . Comment puis-je transmettre un supplément au SMSReceiver ?

mise à Jour #3

la Réception de MMS

donc après avoir fait plus de recherche, j'ai vu quelques suggestions d'enregistrer un ContentObserver . De cette façon, vous pouvez détecter quand il ya des changements à la content://mms-sms/conversations fournisseur de contenu, ce qui vous permet de détecter les MMS entrants. Voici l'exemple le plus proche pour obtenir cela à travailler que j'ai trouvé: réception MMS

cependant, il existe une variable mainActivity de type ServiceController . Où la classe ServiceController est-elle mise en œuvre? Y a-t-il d'autres implémentations d'un ContentObserver enregistré ?

Envoi de MMS

quant à l'envoi de MMS, je suis tombé sur cet exemple: envoyer 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 lancée après avoir interrogé le Carriers ContentProvider dans la méthode getMMSApns() de la classe APNHelper .

final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);

apparemment vous ne pouvez pas lire APNs dans Android 4.2

Quelle est l'alternative pour toutes les applications qui utilisent des données mobiles pour effectuer des opérations (comme envoyer des MMS) et ne connaissent pas le paramètre APN par défaut présent dans l'appareil?

mise à Jour #4

Envoi de MMS

j'ai essayé de suivre cet exemple: envoyer 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.

donc maintenant je ne reçois plus les erreurs SecurityException. Je teste maintenant un Nexus 5 sur Android KitKat. Après avoir lancé le code échantillon il me donne un code de réponse de 200 après l'appel à

MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);

cependant, j'ai vérifié avec la personne à qui j'ai essayé d'envoyer le MMS. Et ils ont dit qu'ils n'avaient jamais reçu le MMS.

127
demandé sur toobsco42 2013-01-22 10:29:07

6 réponses

j'ai eu exactement le même problème que vous décrivez ci-dessus (Galaxy Nexus sur t-mobile USA) c'est parce que les données mobiles est désactivé.

En Jelly Bean, il est: Paramètres > utilisation des données > données mobiles

notez que je dois activer les données mobiles avant d'envoyer un MMS ou d'en recevoir un. Si je reçois un MMS avec des données mobiles désactivées, je recevrai la notification d'un nouveau message et je recevrai le message avec un bouton de téléchargement. Mais si je le fais pas avoir des données mobiles sur prior, la pièce jointe MMS entrante ne sera pas reçue. Même si je l'allume après la réception du message.

pour une raison quelconque, lorsque votre fournisseur de téléphone vous permet d'envoyer et de recevoir des MMS, vous devez avoir les données mobiles activé, même si vous utilisez le Wifi, si les données mobiles est activé, vous serez en mesure de recevoir et d'envoyer des MMS, même si le Wifi est affiché comme votre internet sur votre appareil.

C'est une vraie douleur, comme si vous ne l'avez pas, le message peut accrocher beaucoup, même en allumant des données mobiles, et pourrait exiger un redémarrage de l'appareil.

15
répondu Manan Sharma 2015-02-11 00:13:21

il n'y a pas de support api officiel, ce qui signifie qu'il n'est pas documenté pour le public et que les bibliothèques peuvent changer à tout moment. Je sais que vous ne voulez pas quitter la candidature mais voici comment vous le faites avec une intention pour quiconque se demande.

public void sendData(int num){
    String fileString = "..."; //put the location of the file here
    Intent mmsIntent = new Intent(Intent.ACTION_SEND);
    mmsIntent.putExtra("sms_body", "text");
    mmsIntent.putExtra("address", num);
    mmsIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(fileString)));
    mmsIntent.setType("image/jpeg");
    startActivity(Intent.createChooser(mmsIntent, "Send"));

}

Je n'ai pas complètement compris comment faire des choses comme suivre la livraison du message, mais cela devrait être envoyé.

vous pouvez être alerté à la réception de mms le même manière que les sms. Le filtre d'intention sur le récepteur devrait ressembler à ceci.

<intent-filter>
    <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
    <data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
7
répondu user1959417 2014-08-14 05:50:33

pour envoyer un mms pour Android 4.0 api 14 ou plus sans permission d'écrire les paramètres apn, vous pouvez utiliser cette bibliothèque : Récupérer les codes mnc et mcc d'android, puis appeler

Carrier c = Carrier.getCarrier(mcc, mnc);
if (c != null) {
    APN a = c.getAPN();
    if (a != null) {
        String mmsc = a.mmsc;
        String mmsproxy = a.proxy; //"" if none
        int mmsport = a.port; //0 if none
    }
}

pour utiliser ceci, ajouter Jsoup et pot de prisme droïde au chemin de construction, et importer com.droidprism.* ;

4
répondu Sam Adams 2013-10-24 11:36:20

Je ne pense pas qu'il existe un support sdk pour l'envoi de mms sous android. Regardez ici au Moins je n'ai pas encore trouvé. Mais un gars prétend avoir. Jetez un oeil à ce post.

envoyer MMS de mon application dans android

3
répondu Sahil Mahajan Mj 2017-05-23 12:18:27

Je ne comprends pas les frustrations. Pourquoi ne pas simplement faire un diffuseur qui filtre pour cette intention:

android.provider.Telephony.MMS_RECEIVED

j'ai vérifié un peu plus loin et vous pourriez avoir besoin d'un accès au niveau du système pour obtenir ce (téléphone enraciné).

0
répondu j2emanue 2014-02-27 22:15:08

SmsListenerClass

public class SmsListener extends BroadcastReceiver {

static final String ACTION =
        "android.provider.Telephony.SMS_RECEIVED";

@Override
public void onReceive(Context context, Intent intent) {

    Log.e("RECEIVED", ":-:-" + "SMS_ARRIVED");

    // TODO Auto-generated method stub
    if (intent.getAction().equals(ACTION)) {

        Log.e("RECEIVED", ":-" + "SMS_ARRIVED");

        StringBuilder buf = new StringBuilder();
        Bundle bundle = intent.getExtras();
        if (bundle != null) {

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

            SmsMessage[] messages = new SmsMessage[pdus.length];
            SmsMessage message = null;

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

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    String format = bundle.getString("format");
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format);
                } else {
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                }

                message = messages[i];
                buf.append("Received SMS from  ");
                buf.append(message.getDisplayOriginatingAddress());
                buf.append(" - ");
                buf.append(message.getDisplayMessageBody());
            }

            MainActivity inst = MainActivity.instance();
            inst.updateList(message.getDisplayOriginatingAddress(),message.getDisplayMessageBody());

        }

        Log.e("RECEIVED:", ":" + buf.toString());

        Toast.makeText(context, "RECEIVED SMS FROM :" + buf.toString(), Toast.LENGTH_LONG).show();

    }
}

activité

@Override
public void onStart() {
    super.onStart();
    inst = this;
}

public static MainActivity instance() {
    return inst;
}

public void updateList(final String msg_from, String msg_body) {

    tvMessage.setText(msg_from + " :- " + msg_body);

    sendSMSMessage(msg_from, msg_body);

}

protected void sendSMSMessage(String phoneNo, String message) {

    try {
        SmsManager smsManager = SmsManager.getDefault();
        smsManager.sendTextMessage(phoneNo, null, message, null, null);
        Toast.makeText(getApplicationContext(), "SMS sent.", Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        Toast.makeText(getApplicationContext(), "SMS faild, please try again.", Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }
}

manifeste

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

<receiver android:name=".SmsListener">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>
-2
répondu Narendra Sorathiya 2016-03-28 08:39:32