问题描述
我已经知道如何发送和接收短信了.要发送 SMS 消息,我必须调用 SmsManager
类的 sendTextMessage()
和 sendMultipartTextMessage()
方法.要接收 SMS 消息,我必须在 AndroidMainfest.xml
文件中注册一个接收器.然后我不得不重写 BroadcastReceiver
的 onReceive()
方法.我在下面提供了示例.
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 消息.该意图将具有以下额外值:
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);
对于所有使用移动数据执行操作(例如发送彩信)并且不知道设备中存在的默认 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 之前)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!