Android 之 sms 短信

  • 概述

    SMS(Short Messaging Service), 即我们经常使用的短信服务。它是一种存储和转发服务。也就是说,短消息并不是直接从发送人发送到接收人,而始终通过 SMS 中心进行转发的。如果接收人处于未连接状态(可能电话已关闭),则消息将在接收人再次连接时发送。

    短信长度一般为140个字节,70个字符。既然我们经常使用短信,那么今天我们就来分析一下短信的实现。

    说明:本文主要根据android应用层的sms代码来进行分析的,并结合了SMSpopup.有不到位的地方欢迎指正并补充

    短信结构

    _id                 // 短消息序号   

    thread_id           // 对话的序号   

    address             // 收件人   

    person              //   

    date                // 日期   

    protocol            // 协议   

    read                // 是否阅读   

    status              // 状态   

    type                // 类型 (收发)  

    reply_path_present  //    

    subject             // 主题   

    body                // 短消息内容   

    service_center      // 服务中心  

    相关类图


    上面几个类是涉及到sms的部分类的类图,其中涉及到键盘锁定状态、指示灯提示、通话状态等的判断,从而决定短信来的时候该怎么样去处理和提示。

    短信接收

    先来看看短信的接收,在android中,短信的接收需要在manifest.xml中配置广播接收器,如下:     

[java]  view plain copy
  1. <receiver android:name=".SmsReceiver">  
  2.      <intent-filter>  
  3.          <action android:name="android.provider.Telephony.SMS_RECEIVED" />  
  4.      </intent-filter>  
  5. </receiver>  
  • 来看下时序图:

     

    [java]  view plain copy
    1.   /** 
    2.      *  接收到短信的处理放在该service中去进行处理 
    3.      */  
    4. public static void beginStartingService(Context context, Intent intent) {  
    5.   synchronized (mStartingServiceSync) {  
    6.     if (Log.DEBUG) Log.v("SMSReceiverService: beginStartingService()");  
    7.     if (mStartingService == null) {  
    8.         //电源管理,决定是否亮指示灯、键盘、屏幕等  
    9.       PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);  
    10.       mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,  
    11.           Log.LOGTAG+".SmsReceiverService");  
    12.       mStartingService.setReferenceCounted(false);  
    13.     }  
    14.     mStartingService.acquire();  
    15.     context.startService(intent);  
    16.   }  
    17. }  

    在接收到短信的时候,需要有一些提示,比如指示灯点亮、屏幕点亮、键盘点亮等。这个主要通过PowerManager来控制。关于PowerManager,可以参看我之间写的一篇文章:http://blog.csdn.net/xieqibao/article/details/6562256

    ServiceHandler的handleMessage方法中处理消息,判断消息的类型是mms、sms,在handleSmsReceived中处理接收到的sms短信

    [java]  view plain copy
    1. /** 
    2.    * 处理接收到的短信息 
    3.    */  
    4.   private void handleSmsReceived(Intent intent) {  
    5.     Bundle bundle = intent.getExtras();  
    6.     if (bundle != null) {  
    7.      //获得消息  
    8.       SmsMessage[] messages = SmsPopupUtils.getMessagesFromIntent(intent);  
    9.       if (messages != null) {  
    10.            notifyMessageReceived(new SmsMmsMessage(context, messages,System.currentTimeMillis()));  
    11.       }  
    12.     }  
    13.   }  

    下面方法中主要是从pdu中获取信息,关于pdu的详细信息可以参考:http://wenku.baidu.com/view/d0d0093e0912a216147929b1.html

    [java]  view plain copy
    1. /** 
    2.    * 从包装了SMS_RECEIVED_ACTION的intent中获取pdu信息 
    3.    */  
    4.   public static final SmsMessage[] getMessagesFromIntent(Intent intent) {  
    5.     Object[] messages = (Object[]) intent.getSerializableExtra("pdus");  
    6.     if (messages == null) {  
    7.       return null;  
    8.     }  
    9.     if (messages.length == 0) {  
    10.       return null;  
    11.     }  
    12.     byte[][] pduObjs = new byte[messages.length][];  
    13.     for (int i = 0; i < messages.length; i++) {  
    14.       pduObjs[i] = (byte[]) messages[i];  
    15.     }  
    16.     byte[][] pdus = new byte[pduObjs.length][];  
    17.     int pduCount = pdus.length;  
    18.     SmsMessage[] msgs = new SmsMessage[pduCount];  
    19.     for (int i = 0; i < pduCount; i++) {  
    20.       pdus[i] = pduObjs[i];  
    21.       msgs[i] = SmsMessage.createFromPdu(pdus[i]);  
    22.     }  
    23.     return msgs;  
    24.   }  

    最终获取到短信息后决定该怎么去进行展示,在smspopup中,是通过弹窗的形式,把短信息显示在activity中

    [java]  view plain copy
    1. /** 
    2.    * 获取短信息并加入到view上 
    3.    */  
    4.   private void setupMessages(Bundle b, boolean newIntent) {  
    5.     // Store bundle  
    6.     bundle = b;  
    7.     // 从bundle中获取短消息  
    8.     SmsMmsMessage message = new SmsMmsMessage(getApplicationContext(), bundle);  
    9.     mSmsPopups.addMessage(message);  
    10.     if (!newIntent) {  
    11.       // TODO: move off UI thread  
    12.       mSmsPopups.addMessages(  
    13.           SmsPopupUtils.getUnreadMessages(this, message.getMessageId()));  
    14.     }  
    15.     mSmsPopups.refreshPrivacy();  
    16.   }  

    短信发送

 

[java]  view plain copy
  1. /** 
  2.    * 回复短信息 
  3.    * 
  4.    */  
  5.   public boolean replyToMessage(StringquickReply) {  
  6.       //首先要标记短信为已读  
  7.     setMessageRead();  
  8.     // 发送新的短信息  
  9.     SmsMessageSender sender =  
  10.       new SmsMessageSender(context, newString[] {fromAddress}, quickReply, getThreadId());  
  11.     return sender.sendMessage();  
  12.   }  
  13.   /** 
  14.    * 发送短信息入口 
  15.    * @return 
  16.    */  
  17.   @SuppressWarnings("deprecation")  
  18.   public boolean sendMessage() {  
  19.     if (!(mThreadId > 0)) {  
  20.       return false;  
  21.     }  
  22.     //如果消息文本为空,那就不发消息了  
  23.     if ((mMessageText == null) ||(mNumberOfDests == 0)) {  
  24.       return false;  
  25.     }  
  26.     //获得短信管理器  
  27.     SmsManager smsManager =SmsManager.getDefault();  
  28.     for (int i = 0; i < mNumberOfDests; i++){  
  29.         //按照短信息允许的最大字数来拆分短信  
  30.       ArrayList<String> messages =smsManager.divideMessage(mMessageText);  
  31.       int messageCount = messages.size();  
  32.       ArrayList<PendingIntent>deliveryIntents = new ArrayList<PendingIntent>(messageCount);  
  33.       ArrayList<PendingIntent>sentIntents = new ArrayList<PendingIntent>(messageCount);  
  34.       // 140个字节,70字符。  
  35.       if (splitMessage) {  
  36.         for (int j = 0; j < messageCount;j++) {  
  37.           Uri uri = null;  
  38.           try   
  39.             //把短信息加入到provider中  
  40.             uri =addMessage(mContext.getContentResolver(), mDests[i], messages.get(j),  
  41.                   null, mTimestamp,requestDeliveryReport, mThreadId);  
  42.           } catch (SQLiteException e) {  
  43.             // TODO: show error here  
  44.             //SqliteWrapper.checkSQLiteException(mContext, e);  
  45.           }  
  46.           PendingIntent deliveryReportIntent =null;  
  47.           if (requestDeliveryReport) {  
  48.             deliveryReportIntent =  
  49.              PendingIntent.getBroadcast(mContext, 0,  
  50.                   newIntent(MESSAGING_STATUS_RECEIVED_ACTION, uri)  
  51.              .setClassName(MESSAGING_PACKAGE_NAME, MESSAGING_STATUS_CLASS_NAME), 0);  
  52.           }  
  53.           PendingIntent sentIntent =  
  54.            PendingIntent.getBroadcast(mContext, 0,  
  55.                 newIntent(SmsReceiverService.MESSAGE_SENT_ACTION, uri)  
  56.             .setClass(mContext,SmsReceiver.class), 0);  
  57.           smsManager.sendTextMessage(  
  58.               mDests[i], mServiceCenter,messages.get(j), sentIntent, deliveryReportIntent);  
  59.         }  
  60.       }  
  61.     return false;  
  62.   }  

总结
1. sms短信主要涉及到短信的发送、接收、提示,以及短信的本地保存等,涉及到的点相对还是比较多的。了解下还是很有必要的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值