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 ...
随机推荐
- matlab实现贝塞尔曲线绘图pdf查看
贝塞尔曲线绘图方法: %Program 3.7 Freehand Draw Program Using Bezier Splines %Click in Matlab figure window to ...
- iOS 系统二维码扫描(可限制扫描区域)
使用 AVFoundation系统库来进行二维码扫描并且限制扫描二维码的范围.(因为默认的是全屏扫描) -(void)beginCode { //1.摄像头设备 AVCaptureDevice *de ...
- NOIP2015-stone(二分答案)
这道题在考试时二分答案写炸了,结果得了20分.....同学有用贪心写的(对,贪心!!)都得了30,我感到了深深的恶意.这段时间在忙转语言,现在重新整理一下NOIP的题. 题目来源:vijos 题目如下 ...
- tomcat内存溢出,设置
tomcat/bin/catalina.bat里找到echo Using CATALINA_BASE: "%CATALINA_BASE%" ,在上方设置: set JAV ...
- javascript_22_for_二维数组
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
// test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...
- 查看系统网络连接打开端口、系统进程、DOS打开文件
问题描述: DOS查看系统网络连接打开端口.打开的服务 问题解决: (1)DOS查看系统网络连接打开端口 注: 使用 netstat 命令,可以查看系统打开的端口 (2)查看和关闭系统打开进程 ...
- 【BZOJ】【2594】【WC2006】水管局长数据加强版
LCT 动态维护MST嘛……但是有删边= =好像没法搞的样子 离线记录所有修改&询问,倒序处理,就可以变删边为加边了- 论如何用LCT维护最小生成树:先搞出一棵最小生成树,然后每次加边(u,v ...
- maven+springMVC+mybatis+junit详细搭建过程 ***
springMVC+mybatis框架搭建 在上一遍博客中以及讲诉了新建maven项目的流程,现在紧跟上一遍文章,接着搭建spring项目 首先我们先要弄清搭建项目的一般流程,需要注意哪些方面,想要什 ...
- 剑指offer--面试题9
题目一:求斐波那契数列第n项 自己所写代码如下: #include "stdafx.h" #include<iostream> long Fibonacci(unsig ...