Android开发之SmsManager和SmsMessage
Android的手机功能(通话与短信)都放在android.telephony包中,到了4.4时(也就是API19)android.provider.Telephony及相关类横空出世辅助电话功能以及制定安卓世界手机功能的新秩序。
短信功能用到了SmsManager和SmsMessage两个主要类。
接受短信广播,由Intent解析出短信内容明文, intent中的短信是以pud形式传出的,即byte[][]二位数组,
从Android 4.4开始,SmsMessage不推荐使用createFromPdu(byte[] pdu)
推荐使用createFromPdu(byte[], String)。
createFromPdu(byte[], String)
The message format is passed in the SMS_RECEIVED_ACTION as the format String extra, and will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format or "3gpp2" for CDMA/LTE messages in 3GPP2 format.
第一个参数:意图为SMS_RECEIVED_ACTION中的PDU信息,是一个byte[]数组
第二个参数:通过上面的那段英文可以知道,第二个参数为"3gpp"(GSM/UMTS/LTE)或者"3gpp2"(CDMA/LTE)。所以第二个参数想要获取,可以通过
String format = intent.getStringExtra("format");
获取到,然后传入到形参中。
发送短信via Intent
万能的intent能够帮我们做很多事,只要你有“意图”它就会满足你。
private void sendMessageViaSystem() {
Uri uri = Uri.parse("smsto:"+etNumber.getText());
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
intent.putExtra("sms_body",etMessage.getText().toString());
startActivity(intent);
}
发送短信via SmsManager
private void sendMessage() {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(etNumber.getText().toString(), null,
etMessage.getText().toString(), null, null);
}
最简单的发送短信条件就是有电话号码和短信内容,调用SmsManager的sendTextMessage方法即可。
监听短信的发送状态
sendTextMessage方法的后两个参数是PendingIntent,函数原型如下:
* @param sentIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is successfully sent, or failed.
* The result code will be <code>Activity.RESULT_OK</code> for success,
* or one of these errors:<br>
* <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
* <code>RESULT_ERROR_RADIO_OFF</code><br>
* <code>RESULT_ERROR_NULL_PDU</code><br>
* For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.<br>
* The per-application based SMS control checks sentIntent. If sentIntent
* is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
public void sendTextMessage(
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent)
而我们要监听发送状态就要用到这两个参数。与这个两个PendingIntent联系的是两个Broadcast Receiver,其会接收到发送过程中状态广播。就像上面参数解释的一样。
代码示例如下:
private String SMS_SEND_ACTIOIN = "SMS_SEND";
private String SMS_DELIVERED_ACTION = "SMS_DELIVERED"; private SmsStatusReceiver mSmsStatusReceiver;
private SmsDeliveryStatusReceiver mSmsDeliveryStatusReceiver; @Override
protected void onResume() {
super.onResume();
mSmsStatusReceiver = new SmsStatusReceiver();
registerReceiver(mSmsStatusReceiver,new IntentFilter(SMS_SEND_ACTIOIN)); mSmsDeliveryStatusReceiver = new SmsDeliveryStatusReceiver();
registerReceiver(mSmsDeliveryStatusReceiver,new IntentFilter(SMS_DELIVERED_ACTION));
} @Override
protected void onPause() {
super.onPause();
unregisterReceiver(mSmsStatusReceiver);
unregisterReceiver(mSmsDeliveryStatusReceiver);
} private void sendMessage() {
SmsManager smsManager = SmsManager.getDefault();
PendingIntent sentIntent = PendingIntent.getBroadcast(this, 0, new Intent(SMS_SEND_ACTIOIN), 0);
PendingIntent deliveryIntent = PendingIntent.getBroadcast(this, 0,
new Intent(SMS_DELIVERED_ACTION), 0);
smsManager.sendTextMessage(etNumber.getText().toString(), null,
etMessage.getText().toString(), sentIntent, deliveryIntent);
Log.d(TAG,"sent message.");
} public class SmsStatusReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG,"SmsStatusReceiver onReceive.");
switch(getResultCode()) {
case Activity.RESULT_OK:
Log.d(TAG, "Activity.RESULT_OK");
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Log.d(TAG, "RESULT_ERROR_GENERIC_FAILURE");
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Log.d(TAG, "RESULT_ERROR_NO_SERVICE");
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Log.d(TAG, "RESULT_ERROR_NULL_PDU");
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Log.d(TAG, "RESULT_ERROR_RADIO_OFF");
break;
}
}
} public class SmsDeliveryStatusReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG,"SmsDeliveryStatusReceiver onReceive.");
switch(getResultCode()) {
case Activity.RESULT_OK:
Log.i(TAG, "RESULT_OK");
break;
case Activity.RESULT_CANCELED:
Log.i(TAG, "RESULT_CANCELED");
break;
}
}
}
短信接收
与发送状态监听类似,短信的接收也是用广播接收器。为了一直对短信广播的接收,我采用了在Manifest中注册广播的方法。
android:priority系统默认最大值为1000,但是为了获得最高优先级,可以设置为int的最大值,即2147483647
<receiver android:name="com.linc.intercept.SmsReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
并且将用一个单独类作为短信接收类(这样的方式是不能将其放到内部类中的)。
public class SmsReceiver extends BroadcastReceiver {
private static final String TAG = "SmsReceiver";
public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG,"action: "+action);
if (SMS_RECEIVED_ACTION.equals(action)) {
Bundle bundle = intent.getExtras();
StringBuffer messageContent = new StringBuffer();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
for (Object pdu : pdus) {
SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu);
String sender = message.getOriginatingAddress();
Log.d(TAG,"sender: "+sender);
if ("10086".equals(sender) || "10010".equals(sender) ||
"10001".equals(sender)) {
messageContent.append(message.getMessageBody());
}
}
if(!messageContent.toString().isEmpty()) {
Log.d(TAG,"send message broadcast.");
Intent intentBroadcast = new Intent();
intentBroadcast.putExtra("message", messageContent.toString());
intentBroadcast.setAction("sms_received");
context.sendBroadcast(intentBroadcast);
Log.d(TAG, "send broadcast and abort");
// abortBroadcast();
}
}
}
}
}
但是这样做的弊端就是,接收到的短信如何显示到界面?路有多条,我最后还是选择了广播。
private SmsReceiver mSmsReceiver;
@Override
protected void onResume() {
super.onResume();
mSmsReceiver = new SmsReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("sms_received");
registerReceiver(mSmsReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mSmsReceiver);
}
public class SmsReceiver extends BroadcastReceiver {
public static final String SMS_RECEIVED_ACTION = "sms_received"; @Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG,"action: "+action);
if (SMS_RECEIVED_ACTION.equals(action)) {
Bundle bundle = intent.getExtras(); String messageContent = bundle.getString("message");
tvMessage.setText(messageContent);
}
}
}
Android开发之SmsManager和SmsMessage的更多相关文章
- Android开发之Java集合类性能分析
对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天Android吧(ard8. ...
- Android开发之InstanceState详解
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- Android开发之Git配置
Android开发之Git配置 1.首先git配置: 输入命令: git config --global user.name "xxx.xx" git config --globa ...
- 【Android UI】Android开发之View的几种布局方式及实践
引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...
- Android开发之旅: Intents和Intent Filters(理论部分)
引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...
- Android开发之ViewPager+ActionBar+Fragment实现响应式可滑动Tab
今天我们要实现的这个效果呢,在Android的应用中十分地常见,我们可以看到下面两张图,无论是系统内置的联系人应用,还是AnyView的阅读器应用,我们总能找到这样的影子,当我们滑动屏幕时,Tab可 ...
- Android开发之Java必备基础
Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...
- Android开发之PopupWindow
/* * Android开发之PopupWindow * * Created on: 2011-8-8 * Author: blueeagle * Email: liujiaxiang@g ...
- [置顶] Android开发之MediaPlayerService服务详解(一)
前面一节我们分析了Binder通信相关的两个重要类:ProcessState 和 IPCThreadState.ProcessState负责打开Binder 驱动,每个进程只有一个.而 IPCThre ...
随机推荐
- Linq小技巧
遍历集合ForEach: listAll.Items.Clear(); List<Users> list = DP.UsersDAO.GetInfoList(); list.ForEach ...
- 如何在mysql中退出当前窗口界面而不关闭窗口的方法
CTRL+Cexit;quit ;
- WPF中使用ValueConverter来实现“范围条件触发器”
在WPF中,我们知道界面层可以通过Trigger触发器实现“条件”——“赋值”的功能 属性触发器Property Trigger:当Dependency Property的值发生改变时触发.数据触发器 ...
- 关于6410的sd卡和nandflash启动的区别
今天在公司我们队长问我个问题,关于cortex的sd启动流程和nandflash的启动流程,一下想不起来了,中午闲来无事就整理了整理当初6410的两种启动方式的区别.在这里写一下.有不对的请指点,我对 ...
- 一个SQL Server 2008 R2 死锁的问题解决
问题场景:在客户那碰到一个操作卡死的现象 问题解决: 1.如何挂钩是死锁问题:通过代码跟踪,发现是指执行一个SQL语句超时,因此猜想可能是表锁住了 2.如果确认是思索问题:通过SQL发现死锁,以下是相 ...
- UML类图关系大全-转
1.关联 双向关联: C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法. 在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类关系来 ...
- android编程常见问题-No Launcher activity found!
新手编程常见的问题: 问题表现: console提示:No Launcher activity found! The launch will only sync the application pac ...
- Application、Session、Cookie、ViewState的特性
http://blog.csdn.net/zyw_anquan/article/details/7664132 Application的特性: 存储的物理位置:服务器端内存. 存储的类型限制:任意 ...
- Linux安装python 2.7.9
1.下载python wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz 2.解压.编译安装 tar -zxvf Python- ...
- spring @resource @ Autowired
Spring中什么时候用@Resource,什么时候用@service 当你需要定义某个类为一个bean,则在这个类的类名前一行使用@Service("XXX"),就相当于讲这个类 ...