0
点赞
收藏
分享

微信扫一扫

Android 之 sms 短信



 

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. "android.provider.Telephony.SMS_RECEIVED" />  
  4.      </intent-filter>  
  5. </receiver>  


来看下时序图:

 



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. ".SmsReceiverService");  
12. false);  
13.     }  
14.     mStartingService.acquire();  
15.     context.startService(intent);  
16.   }  
17. }



 

在接收到短信的时候,需要有一些提示,比如指示灯点亮、屏幕点亮、键盘点亮等。这个主要通过PowerManager来控制。关于PowerManager,可以参看我之间写的一篇文章:javascript:void(0)

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

 




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. new SmsMmsMessage(context, messages,System.currentTimeMillis()));  
11.       }  
12.     }  
13.   }


 

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




1. /**
2.    * 从包装了SMS_RECEIVED_ACTION的intent中获取pdu信息
3.    */  
4. public static final SmsMessage[] getMessagesFromIntent(Intent intent) {  
5. "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. byte[]) messages[i];  
15.     }  
16. byte[][] pdus = new byte[pduObjs.length][];  
17. int pduCount = pdus.length;  
18. 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中

 




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

 

短信发送

 




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. new ArrayList<PendingIntent>(messageCount);  
33. new ArrayList<PendingIntent>(messageCount);  
34. // 140个字节,70字符。  
35. if (splitMessage) {  
36. for (int j = 0; j < messageCount;j++) {  
37. 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. null;  
47. if (requestDeliveryReport) {  
48.             deliveryReportIntent =  
49. 0,  
50.                   newIntent(MESSAGING_STATUS_RECEIVED_ACTION, uri)  
51. 0);  
52.           }  
53.           PendingIntent sentIntent =  
54. 0,  
55.                 newIntent(SmsReceiverService.MESSAGE_SENT_ACTION, uri)  
56. class), 0);  
57.           smsManager.sendTextMessage(  
58.               mDests[i], mServiceCenter,messages.get(j), sentIntent, deliveryReportIntent);  
59.         }  
60.       }  
61. return false;  
62.   }


 

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




举报

相关推荐

0 条评论