我已经知道如何发送和接收短信。为了发送短信息,我必须调用 SmsManager
类的 sendTextMessage()
和 sendMultipartTextMessage()
方法。要接收短信息,我必须在 AndroidMainfest.xml
文件中注册一个接收器。然后我不得不重写 BroadcastReceiver
的 onReceive()
方法。我在下面列举了一些例子。
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 ...
}
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>
但是,我想知道你是否可以发送和接收彩信类似的方式。在做了一些研究之后,博客上提供的许多示例只是简单地将 Intent
传递给本机 Messaging 应用程序。我试图发送彩信而不留下我的申请。似乎没有一个标准的方式来发送和接收彩信。有人能让这个起作用吗?
此外,我知道 SMS/MMS ContentProvider 并不是官方 Android SDK 的一部分,但我认为有人可能已经实现了这一点。非常感谢您的帮助。
我已经添加了一个 BroadcastReceiver
到 AndroidManifest.xml
文件接收彩信消息
<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()
方法只能获取发送消息的 phoneNumber。如何从 MMS 中获取其他重要信息,比如到媒体附件(图片/音频/视频)的文件路径,或者 MMS 中的文本?
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...
}
}
根据 电话服务提供商的文档:
广播行动: 一个新的基于文本的短信息已收到的设备。意图将具有以下额外值:
pdus
-byte[]
的Object[]
,包含组成消息的 PDU。额外的值可以使用
getMessagesFromIntent(android.content.Intent)
提取 如果 BroadcastReceiver 在处理此意图时遇到错误,则应适当地设置结果代码。@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
广播行动: 一个新的数据为基础的短信息已收到的设备。意图将具有以下额外值:
pdus
-byte[]
的Object[]
,包含组成消息的 PDU。可以使用 getMessagesFromInent (android.content. Inent)提取额外的值。 如果 BroadcastReceiver 在处理此意图时遇到错误,则应适当地设置结果代码。
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
广播动作: 设备已经接收到一条新的 WAP PUSH 消息。意图将具有以下额外值:
transactionId (Integer)
-WAP 事务 ID
pduType (Integer)
-WAP PDU 型
header (byte[])
-消息的头部
data (byte[])
-消息的数据有效负载
contentTypeParameters (HashMap<String,String>)
-与内容类型相关联的任何参数(从 WSP Content-Type 头解码)如果 BroadcastReceiver 在处理此意图时遇到错误,则应适当地设置结果代码。 ContentTypeParameter 额外值是由名称键控的内容参数的映射。 如果遇到任何未分配的已知参数,映射的关键字将是’未分配/0x...’,其中’...’是未分配参数的十六进制值。如果参数具有 No-Value,那么 map 中的值将为 null。
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
我已经知道如何通过额外的 PendingIntent
被接收到的 BroadcastReceiver
:
Android 挂起意图附加,BroadcastReceiver 没有接收到
然而,额外的传递给 发送广播接收器而不是 短信接收器。我怎样才能传递一个额外的 短信接收器?
收到彩信
因此,在做了更多的研究之后,我看到了一些注册 ContentObserver
的建议。这样,您就可以检测到 content://mms-sms/conversations
内容提供程序的任何更改,从而允许您检测传入的 MMS。这里有一个最接近的例子,让这个工作,我已经发现: 收到彩信
但是,有一个类型为 ServiceController
的变量 mainActivity
。在哪里实现了 ServiceController
类?已注册的 ContentObserver
是否有其他实现?
发送彩信
至于发送彩信,我遇到了这个例子: 发送彩信
问题是,我试图在我的 Nexus4上运行这段代码,它是在 Android v4.2.2上运行的,我收到了这个错误:
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 后引发错误。
final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);
显然你不能 在 Android 4.2中读取 APN
对于那些使用移动数据执行操作(如发送彩信)而不知道设备中默认 APN 设置的应用程序,有什么替代方案?
发送彩信
我已经尝试过以下这个例子: 发送彩信
正如@Sam 在他的回答中所建议的:
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.
所以现在我不再得到 SecurityException 错误。我现在正在安卓 KitKat 上测试 Nexus5。在运行示例代码之后,在调用
MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);
然而,我查了一下我试图发送彩信的人,他们说他们从来没有收到过彩信。