在 Android 中发送和接收短信和彩信(Kit Kat Android 4.4 之前) [英] Sending and Receiving SMS and MMS in Android (pre Kit Kat Android 4.4)

查看:30
本文介绍了在 Android 中发送和接收短信和彩信(Kit Kat Android 4.4 之前)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经知道如何发送和接收短信了.要发送 SMS 消息,我必须调用 SmsManager 类的 sendTextMessage()sendMultipartTextMessage() 方法.要接收 SMS 消息,我必须在 AndroidMainfest.xml 文件中注册一个接收器.然后我不得不重写 BroadcastReceiveronReceive() 方法.我在下面提供了示例.

I have figured out how to send and receive SMS messages. To send SMS messages I had to call the sendTextMessage() and sendMultipartTextMessage() methods of the SmsManager class. To receive SMS messages, I had to register a receiver in the AndroidMainfest.xml file. Then I had to override the onReceive() method of the BroadcastReceiver. I have included examples below.

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 += "
";
                }
            }   

            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>

但是,我想知道您是否可以以类似的方式发送和接收彩信.在做了一些研究之后,博客上提供的许多示例只是简单地将 Intent 传递给本机 Messaging 应用程序.我试图在不离开我的应用程序的情况下发送彩信.似乎没有发送和接收彩信的标准方式.有没有人让这个工作?

However, I was wondering if you could send and receive MMS messages in a similar fashion. After doing some research, many examples provided on blogs simply pass an Intent to the native Messaging application. I am trying to send an MMS without leaving my application. There doesn't seem to be a standard way of sending and receiving MMS. Has anyone gotten this to work?

另外,我知道 SMS/MMS ContentProvider 不是官方 Android SDK 的一部分,但我认为有人可能已经能够实现这一点.非常感谢任何帮助.

Also, I am aware that the SMS/MMS ContentProvider is not a part of the official Android SDK, but I was thinking someone may have been able to implement this. Any help is greatly appreciated.

我在 AndroidManifest.xml 文件中添加了一个 BroadcastReceiver 来接收彩信

I have added a BroadcastReceiver to the AndroidManifest.xml file to receive 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>

在 MMSReceiver 类中,onReceive() 方法只能获取发送消息的电话号码.您如何从彩信中获取其他重要信息,例如媒体附件(图像/音频/视频)的文件路径或彩信中的文本?

In the MMSReceiver class, the onReceive() method is only able to grab the phoneNumber that the message was sent from. How do you grab other important things from an MMS such as the file path to the media attachment (image/audio/video), or the text in the 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...
    }
}

根据android.provider.Telephony 的文档:

广播操作:设备已收到一条新的基于文本的 SMS 消息.该意图将具有以下额外值:

Broadcast Action: A new text based SMS message has been received by the device. The intent will have the following extra values:

pdus - byte[]Object[] 包含组成消息的 PDU.

pdus - An Object[] of byte[]s containing the PDUs that make up the message.

可以使用 getMessagesFromIntent(android.content.Intent) 提取额外的值如果 BroadcastReceiver 在处理这个意图时遇到错误,它应该适当地设置结果代码.

The extra values can be extracted using getMessagesFromIntent(android.content.Intent) If a BroadcastReceiver encounters an error while processing this intent it should set the result code appropriately.

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

<小时>

广播操作:设备已收到一条新的基于数据的 SMS 消息.该意图将具有以下额外值:


Broadcast Action: A new data based SMS message has been received by the device. The intent will have the following extra values:

pdus - byte[]Object[] 包含组成消息的 PDU.

pdus - An Object[] of byte[]s containing the PDUs that make up the message.

可以使用 getMessagesFromIntent(android.content.Intent) 提取额外的值.如果 BroadcastReceiver 在处理这个意图时遇到错误,它应该适当地设置结果代码.

The extra values can be extracted using getMessagesFromIntent(android.content.Intent). If a BroadcastReceiver encounters an error while processing this intent it should set the result code appropriately.

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

<小时>

广播动作:设备收到一条新的 WAP PUSH 消息.该意图将具有以下额外值:


Broadcast Action: A new WAP PUSH message has been received by the device. The intent will have the following extra values:

transactionId (Integer) - WAP 交易 ID

transactionId (Integer) - The WAP transaction ID

pduType (Integer) - WAP PDU 类型`

pduType (Integer) - The WAP PDU type`

header (byte[]) - 消息的头部

data (byte[]) - 消息的数据负载

contentTypeParameters (HashMap) - 与内容类型相关的任何参数(从 WSP Content-Type 标头解码)

contentTypeParameters (HashMap<String,String>) - Any parameters associated with the content type (decoded from the WSP Content-Type header)

如果 BroadcastReceiver 在处理这个意图时遇到错误,它应该适当地设置结果代码.contentTypeParameters 额外值是按名称键控的内容参数映射.如果遇到任何未分配的众所周知的参数,映射的键将是未分配/0x...",其中..."是未分配参数的十六进制值.如果参数没有值,则映射中的值将为空.

If a BroadcastReceiver encounters an error while processing this intent it should set the result code appropriately. The contentTypeParameters extra value is map of content parameters keyed by their names. If any unassigned well-known parameters are encountered, the key of the map will be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter. If a parameter has No-Value the value in the map will be null.

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

更新 #2

我已经想出了如何在 PendingIntent 中传递额外内容以被 BroadcastReceiver 接收:Android PendingIntent extras,未由 BroadcastReceiver 接收

Update #2

I have figured out how to pass extras in a PendingIntent to be received by a BroadcastReceiver: Android PendingIntent extras, not received by BroadcastReceiver

然而,额外的部分会传递给 SendBroadcastReceiver 而不是 SMSReceiver.如何向 SMSReceiver 传递额外信息?

However, the extra gets passed to the SendBroadcastReceiver not the SMSReceiver. How can I pass an extra to the SMSReceiver?

接收彩信

所以在做了更多的研究之后,我看到了一些注册 ContentObserver 的建议.通过这种方式,您可以检测 content://mms-sms/conversations 内容提供程序何时发生任何更改,从而允许您检测传入的 MMS.这是我发现的最接近的例子:接收彩信

So after doing more research I saw some suggestions of registering a ContentObserver. That way you can detect when there are any changes to the content://mms-sms/conversations Content Provider, consequently allowing you to detect incoming MMS. Here is the closest example to get this to work that I have found: Receiving MMS

然而,有一个 ServiceController 类型的变量 mainActivity.ServiceController 类在哪里实现?注册的 ContentObserver 是否还有其他实现?

However, there is a variable mainActivity of type ServiceController. Where is the ServiceController class implemented? Are there any other implementations of a registered ContentObserver?

发送彩信

关于发送彩信,我遇到过这个例子:Send MMS

As for sending MMS, I have come across this example: Send MMS

问题是我尝试在 Android v4.2.2 上的 Nexus 4 上运行此代码,但收到此错误:

The problem is that I tried running this code on my Nexus 4, which is on Android v4.2.2, and I am receiving this error:

java.lang.SecurityException: No permission to write APN settings: Neither user 10099 nor current process has android.permission.WRITE_APN_SETTINGS.

APNHelper 类的getMMSApns() 方法中查询Carriers ContentProvider 后抛出错误.

The error gets thrown after querying the Carriers ContentProvider in the getMMSApns() method of the APNHelper class.

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

显然你不能在 Android 4.2 中读取 APNs

对于所有使用移动数据执行操作(例如发送彩信)并且不知道设备中存在的默认 APN 设置的应用程序,有什么替代方案?

What is the alternative for all those applications which use mobile data to perform operations (like sending MMS) and don't know the default APN setting present in the device?

发送彩信

我尝试过以下示例:发送彩信

正如@Sam 在他的回答中所建议的:

As @Sam suggested in his answer:

你必须将jsoup添加到构建路径,jar添加到构建路径并导入com.droidprism.*;要在 android 中做到这一点,首先将 jars 添加到 libs 目录,然后配置项目构建路径以使用 libs 目录中已有的 jars,然后在构建路径配置上单击 order 和 export 并选中 jars 的框并移动jsoup 和 droidprism jar 到构建顺序的顶部.

所以现在我不再收到 SecurityException 错误.我现在正在 Android KitKat 上的 Nexus 5 上进行测试.运行示例代码后,它会在调用

So now I no longer get the SecurityException errors. I am testing now on a Nexus 5 on Android KitKat. After running the sample code it gives me a 200 response code after the call to

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

但是,我与我尝试向其发送彩信的人进行了核实.他们说他们从未收到彩信.

However, I checked with the person I tried sending the MMS to. And they said they never received the MMS.

推荐答案

我遇到了与您上面描述的完全相同的问题(美国 t-mobile 上的 Galaxy Nexus),因为移动数据已关闭.

I had the exact same problem you describe above (Galaxy Nexus on t-mobile USA) it is because mobile data is turned off.

在果冻豆中是:设置 > 数据使用 > 移动数据

In Jelly Bean it is: Settings > Data Usage > mobile data

请注意,我必须在发送彩信或接收彩信之前打开移动数据.如果我在关闭移动数据的情况下收到彩信,我会收到一条新信息的通知,并且我会收到带有下载按钮的信息.但是如果我之前没有移动数据,则不会收到传入的彩信附件.即使我在收到消息后打开它.

Note that I have to have mobile data turned on PRIOR to sending an MMS OR receiving one. If I receive an MMS with mobile data turned off, I will get the notification of a new message and I will receive the message with a download button. But if I do not have mobile data on prior, the incoming MMS attachment will not be received. Even if I turn it on after the message was received.

出于某种原因,当您的电话提供商允许您发送和接收彩信时,您必须启用移动数据,即使您使用的是 Wifi,如果启用了移动数据,您将能够接收和发送彩信,即使 Wifi 在您的设备上显示为您的互联网.

For some reason when your phone provider enables you with the ability to send and receive MMS you must have the Mobile Data enabled, even if you are using Wifi, if the Mobile Data is enabled you will be able to receive and send MMS, even if Wifi is showing as your internet on your device.

这真的很痛苦,如果您没有打开它,即使打开移动数据,消息也会挂很多,并且可能需要重新启动设备.

It is a real pain, as if you do not have it on, the message can hang a lot, even when turning on Mobile Data, and might require a reboot of the device.

这篇关于在 Android 中发送和接收短信和彩信(Kit Kat Android 4.4 之前)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆