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 ...
随机推荐
- 总线(BUS)和总线操作
1.什么是总线? 答:总线是运算部件之间数据流通的公共通道. 2.总线的作用? 答:提高专用信号处理逻辑电路的运算能力和速度. 3.总线与部件之间是怎么连接的? 答:各运算部件和数据寄存器组是通过带控 ...
- matlab实现不动点迭代、牛顿法、割线法
不动点迭代 function xc = fpi( g, x0, tol ) x(1) = x0; i = 1; while 1 x(i + 1) = g(x(i)); if(abs(x(i+1) - ...
- Daily Scrum 11.6
摘要:在本次meeting时,所有代码的修改工作已经接近尾声,接下来是进行的就是单元测试以及进行alpha版本的改进.本次的Task列表如下: Task列表 出席人员 Today's Task Tom ...
- Codeforces Round #352 (Div. 2) D. Robin Hood
题目链接: http://codeforces.com/contest/672/problem/D 题意: 给你一个数组,每次操作,最大数减一,最小数加一,如果最大数减一之后比最小数加一之后要小,则取 ...
- AnkhSVN 安装
为 visual Studio 2013 添加 AnkhSVN 步骤 到 https://ankhsvn.open.collab.net/downloads 下载 2.6x或以上 安装 AnkhSvn ...
- 多线程Java Socket编程示例(转)
这篇做为学习孙卫琴<<Java网络编程精解>>的学习笔记吧.其中采用Java 5的ExecutorService来进行线程池的方式实现多线程,模拟客户端多用户向同一服务器端发送 ...
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
缓存的范围? 1.事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结 ...
- Chp18: Hard
18.1 Write a function that adds two numbers. You should not use + or any arithmetic operators. Solut ...
- POJ3468 A Simple Problem With Integers 树状数组 区间更新区间询问
今天学了很多关于树状数组的技巧.一个是利用树状数组可以简单的实现段更新,点询问(二维的段更新点询问也可以),每次修改只需要修改2个角或者4个角就可以了,另外一个技巧就是这题,原本用线段树做,现在可以用 ...
- 核稀疏表示分类(KSRC)
参考:<Kernel SparseRepresention-Based Classifier> 原文地址:http://www.cnblogs.com/Rosanna/p/3372153. ...