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)。所以第二个参数想要获取,可以通过

  1. String format = intent.getStringExtra("format");

获取到,然后传入到形参中。

发送短信via Intent

万能的intent能够帮我们做很多事,只要你有“意图”它就会满足你。

  1. private void sendMessageViaSystem() {
  2. Uri uri = Uri.parse("smsto:"+etNumber.getText());
  3. Intent intent = new Intent(Intent.ACTION_VIEW,uri);
  4. intent.putExtra("sms_body",etMessage.getText().toString());
  5. startActivity(intent);
  6. }

发送短信via SmsManager

  1. private void sendMessage() {
  2. SmsManager smsManager = SmsManager.getDefault();
  3. smsManager.sendTextMessage(etNumber.getText().toString(), null,
  4. etMessage.getText().toString(), null, null);
  5. }

最简单的发送短信条件就是有电话号码和短信内容,调用SmsManager的sendTextMessage方法即可。

监听短信的发送状态

sendTextMessage方法的后两个参数是PendingIntent,函数原型如下:

  1. * @param sentIntent if not NULL this <code>PendingIntent</code> is
  2. * broadcast when the message is successfully sent, or failed.
  3. * The result code will be <code>Activity.RESULT_OK</code> for success,
  4. * or one of these errors:<br>
  5. * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
  6. * <code>RESULT_ERROR_RADIO_OFF</code><br>
  7. * <code>RESULT_ERROR_NULL_PDU</code><br>
  8. * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
  9. * the extra "errorCode" containing a radio technology specific value,
  10. * generally only useful for troubleshooting.<br>
  11. * The per-application based SMS control checks sentIntent. If sentIntent
  12. * is NULL the caller will be checked against all unknown applications,
  13. * which cause smaller number of SMS to be sent in checking period.
  14. * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
  15. * broadcast when the message is delivered to the recipient. The
  16. * raw pdu of the status report is in the extended data ("pdu").
  17. public void sendTextMessage(
  18. String destinationAddress, String scAddress, String text,
  19. PendingIntent sentIntent, PendingIntent deliveryIntent)

而我们要监听发送状态就要用到这两个参数。与这个两个PendingIntent联系的是两个Broadcast Receiver,其会接收到发送过程中状态广播。就像上面参数解释的一样。 
代码示例如下:

  1. private String SMS_SEND_ACTIOIN = "SMS_SEND";
  2. private String SMS_DELIVERED_ACTION = "SMS_DELIVERED";
  3.  
  4. private SmsStatusReceiver mSmsStatusReceiver;
  5. private SmsDeliveryStatusReceiver mSmsDeliveryStatusReceiver;
  6.  
  7. @Override
  8. protected void onResume() {
  9. super.onResume();
  10. mSmsStatusReceiver = new SmsStatusReceiver();
  11. registerReceiver(mSmsStatusReceiver,new IntentFilter(SMS_SEND_ACTIOIN));
  12.  
  13. mSmsDeliveryStatusReceiver = new SmsDeliveryStatusReceiver();
  14. registerReceiver(mSmsDeliveryStatusReceiver,new IntentFilter(SMS_DELIVERED_ACTION));
  15. }
  16.  
  17. @Override
  18. protected void onPause() {
  19. super.onPause();
  20. unregisterReceiver(mSmsStatusReceiver);
  21. unregisterReceiver(mSmsDeliveryStatusReceiver);
  22. }
  23.  
  24. private void sendMessage() {
  25. SmsManager smsManager = SmsManager.getDefault();
  26. PendingIntent sentIntent = PendingIntent.getBroadcast(this, 0, new Intent(SMS_SEND_ACTIOIN), 0);
  27. PendingIntent deliveryIntent = PendingIntent.getBroadcast(this, 0,
  28. new Intent(SMS_DELIVERED_ACTION), 0);
  29. smsManager.sendTextMessage(etNumber.getText().toString(), null,
  30. etMessage.getText().toString(), sentIntent, deliveryIntent);
  31. Log.d(TAG,"sent message.");
  32. }
  33.  
  34. public class SmsStatusReceiver extends BroadcastReceiver {
  35.  
  36. @Override
  37. public void onReceive(Context context, Intent intent) {
  38. Log.d(TAG,"SmsStatusReceiver onReceive.");
  39. switch(getResultCode()) {
  40. case Activity.RESULT_OK:
  41. Log.d(TAG, "Activity.RESULT_OK");
  42. break;
  43. case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
  44. Log.d(TAG, "RESULT_ERROR_GENERIC_FAILURE");
  45. break;
  46. case SmsManager.RESULT_ERROR_NO_SERVICE:
  47. Log.d(TAG, "RESULT_ERROR_NO_SERVICE");
  48. break;
  49. case SmsManager.RESULT_ERROR_NULL_PDU:
  50. Log.d(TAG, "RESULT_ERROR_NULL_PDU");
  51. break;
  52. case SmsManager.RESULT_ERROR_RADIO_OFF:
  53. Log.d(TAG, "RESULT_ERROR_RADIO_OFF");
  54. break;
  55. }
  56. }
  57. }
  58.  
  59. public class SmsDeliveryStatusReceiver extends BroadcastReceiver {
  60.  
  61. @Override
  62. public void onReceive(Context context, Intent intent) {
  63. Log.d(TAG,"SmsDeliveryStatusReceiver onReceive.");
  64. switch(getResultCode()) {
  65. case Activity.RESULT_OK:
  66. Log.i(TAG, "RESULT_OK");
  67. break;
  68. case Activity.RESULT_CANCELED:
  69. Log.i(TAG, "RESULT_CANCELED");
  70. break;
  71. }
  72. }
  73. }

短信接收

与发送状态监听类似,短信的接收也是用广播接收器。为了一直对短信广播的接收,我采用了在Manifest中注册广播的方法。

  1. android:priority系统默认最大值为1000,但是为了获得最高优先级,可以设置为int的最大值,即2147483647
  1. <receiver android:name="com.linc.intercept.SmsReceiver" >
  2. <intent-filter android:priority="1000" >
  3. <action android:name="android.provider.Telephony.SMS_RECEIVED" />
  4. </intent-filter>
  5. </receiver>

并且将用一个单独类作为短信接收类(这样的方式是不能将其放到内部类中的)。

  1. public class SmsReceiver extends BroadcastReceiver {
  2. private static final String TAG = "SmsReceiver";
  3. public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
  4.  
  5. @Override
  6. public void onReceive(Context context, Intent intent) {
  7. String action = intent.getAction();
  8. Log.d(TAG,"action: "+action);
  9. if (SMS_RECEIVED_ACTION.equals(action)) {
  10. Bundle bundle = intent.getExtras();
  11. StringBuffer messageContent = new StringBuffer();
  12. if (bundle != null) {
  13. Object[] pdus = (Object[]) bundle.get("pdus");
  14. for (Object pdu : pdus) {
  15. SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu);
  16. String sender = message.getOriginatingAddress();
  17. Log.d(TAG,"sender: "+sender);
  18. if ("10086".equals(sender) || "10010".equals(sender) ||
  19. "10001".equals(sender)) {
  20. messageContent.append(message.getMessageBody());
  21. }
  22. }
  23. if(!messageContent.toString().isEmpty()) {
  24. Log.d(TAG,"send message broadcast.");
  25. Intent intentBroadcast = new Intent();
  26. intentBroadcast.putExtra("message", messageContent.toString());
  27. intentBroadcast.setAction("sms_received");
  28. context.sendBroadcast(intentBroadcast);
  29. Log.d(TAG, "send broadcast and abort");
  30. // abortBroadcast();
  31. }
  32. }
  33. }
  34. }
  35. }

但是这样做的弊端就是,接收到的短信如何显示到界面?路有多条,我最后还是选择了广播。

  1. private SmsReceiver mSmsReceiver;
  2. @Override
  3. protected void onResume() {
  4. super.onResume();
  5. mSmsReceiver = new SmsReceiver();
  6. IntentFilter intentFilter = new IntentFilter();
  7. intentFilter.addAction("sms_received");
  8. registerReceiver(mSmsReceiver, intentFilter);
  9. }
  10. @Override
  11. protected void onPause() {
  12. super.onPause();
  13. unregisterReceiver(mSmsReceiver);
  14. }
  15. public class SmsReceiver extends BroadcastReceiver {
  16. public static final String SMS_RECEIVED_ACTION = "sms_received";
  17.  
  18. @Override
  19. public void onReceive(Context context, Intent intent) {
  20. String action = intent.getAction();
  21. Log.d(TAG,"action: "+action);
  22. if (SMS_RECEIVED_ACTION.equals(action)) {
  23. Bundle bundle = intent.getExtras();
  24.  
  25. String messageContent = bundle.getString("message");
  26. tvMessage.setText(messageContent);
  27. }
  28. }
  29. }

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. ASP.NET MVC +EasyUI 权限设计(二)环境搭建

    请注明转载地址:http://www.cnblogs.com/arhat 今天突然发现博客园出问题了,老魏使用了PC,手机,平板都访问博客园了,都是不能正常的访问,原因是不能加载CSS,也就是不能访问 ...

  2. 用 HTML 编写博客栏目

    “生活中不是缺少美,而是缺少发现美的眼睛. -----罗丹 在之前阅读师哥师姐们博客的时候,尤其是那些感觉非常优秀博客的时候就注意到了一个东西..... ----------------------- ...

  3. Notes of the scrum meeting(10/28)

    meeting time:4:00~6:00p.m.,October 28th,2013 meeting place:雕刻时光 attendees: 顾育豪                       ...

  4. Django 学习笔记之一 环境搭建

    以后的文章都是在windows系统进行的 首先下载安装Django包 方式1:使用 pip或easy_insatll来进行安装 同时按住win+R键,弹出命令行运行框输入,pip install Dj ...

  5. Eclipse 安装热部署JRebel

    开发环境 sts-3.7.2.RELEASE 安装步骤 1.打开应市场 2.搜索JRebel并进行下载 3.下载完成后点击JReble Configuation进入

  6. 完整实例(C# Socket)

    问题描述:          现在创建一个C# Socket实例,客户端断开服务器能立刻输出断开连接客户端信息 服务器端断开,客户端能立刻察觉服务器状态 问题解决: 服务器端代码: 客户端代码: 以上 ...

  7. vim分屏快捷键使用/增大/减小字体使用

    问题描述: vim分屏快捷键使用 问题解决:         (1)vim 分屏快捷键           (2)vim高度改变          (3)vim中增加和减少字体大小  使用快捷键Ctr ...

  8. Flex 教程(1)-------------控件拖动

    今天和大家分享下关于在Flex中 针对控件的拖动开发. 1.需要在 .mxml文件中编写一个Button按钮 如下代码: <s:Button id="button1" lab ...

  9. mysql之sql语句导入与导出讲解

    导出SQL:mysqldump -u root -p 数据库名 [表名1 表名2] > 输出地址其中表名可选 本机测试实例:

  10. RedHat Linux下注册Apache为系统服务并设为开机启动

    1.系统环境: 操作系统:Red Hat Enterprise Linux Server release 5.4 Apache版本:httpd-2.2.19 2.注册服务 #将apachectl复制到 ...