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的更多相关文章

  1. Android开发之Java集合类性能分析

    对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天Android吧(ard8. ...

  2. Android开发之InstanceState详解

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  3. Android开发之Git配置

    Android开发之Git配置 1.首先git配置: 输入命令: git config --global user.name "xxx.xx" git config --globa ...

  4. 【Android UI】Android开发之View的几种布局方式及实践

    引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...

  5. Android开发之旅: Intents和Intent Filters(理论部分)

    引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...

  6. Android开发之ViewPager+ActionBar+Fragment实现响应式可滑动Tab

     今天我们要实现的这个效果呢,在Android的应用中十分地常见,我们可以看到下面两张图,无论是系统内置的联系人应用,还是AnyView的阅读器应用,我们总能找到这样的影子,当我们滑动屏幕时,Tab可 ...

  7. Android开发之Java必备基础

    Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...

  8. Android开发之PopupWindow

      /* *  Android开发之PopupWindow * *  Created on: 2011-8-8 *  Author: blueeagle *  Email: liujiaxiang@g ...

  9. [置顶] Android开发之MediaPlayerService服务详解(一)

    前面一节我们分析了Binder通信相关的两个重要类:ProcessState 和 IPCThreadState.ProcessState负责打开Binder 驱动,每个进程只有一个.而 IPCThre ...

随机推荐

  1. IOS开发经验分享

    一些IOS开发的心得: 1) [Multiple Threads] IOS多线程注意, 所有的UI操作都必须在主线程上: Any code that will update the UI should ...

  2. cocos2dx中的CCRect的用法

    CCRect是cocos2dx中的一块矩形区域 常用于碰撞检测及渲染时限定纹理的大小 CCRect rect=spr.boundingBox(); CCRect rect=CCRect(0,0,spr ...

  3. SqlBulkCopy批量写入25万条数据只需3s

    Microsoft SQL Server 提供一个称为 bcp 的流行的命令提示符实用工具,用于将数据从一个表移动到另一个表(表既可以在同一个服务器上,也可以在不同服务器上).SqlBulkCopy  ...

  4. java连接sqlserver2008报错 java.sql.SQLException: 对象名 '表名' 无效.

    注意:c3p0的数据库配置方式为: <named-config name="sqlsvr"> <property name="driverClass&q ...

  5. FreePlan Windows下默认乱码解决方案

    FreePlan 做为一个开源的跨平台的思维导图软件非常好用. 笔者最近在Windows下使用时发现,新建导图文件时默认总是乱码,每次新建元素都需要手动设置一下字体才行. 研究一下,估计是默认模板问题 ...

  6. C# Lambda Expressions 简介

    C# Lambda Expressions 简介 原文http://msdn2.microsoft.com/en-us/library/bb397687.aspx 翻译:朱之光 (larry1zhu@ ...

  7. hdu 1233 还是畅通工程(最小生成树,基础)

    题目 //也是标准的最小生成树啊,我就改一点点,不重新再打一遍增加熟练度了 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #inclu ...

  8. Oracle 9 - 分析undo和snapshot too old错误

    什么操作会生成undo INSERT生成的UNDO最少,只要记录新的rowid UPDATE生成的undo多一点,它要记录修改前的数据中的那部分. DELETE生成最多的undo, 因为它要记录整行被 ...

  9. 套题T4

    Problem 1 无聊的gcd(gcd.c/cpp/pas) 话说出题人不会被查水表吧. 简单的问题描述:从N个正整数里面取出K个数的最大公因数最大是多少.(请将答案乘上k之后输出哦,谢谢合作.) ...

  10. 可持久化trie 学习总结

    QAQ 以前一直觉得可持久化trie很难,今天强行写了一发觉得还是蛮简单的嘛 自己的模板是自己手写的,写了几道题目并没有出过错误 THUSC的第二题的解法五貌似就是可持久化trie,时间复杂度O(60 ...