一、Android SMS架构
二、短信数据结构
三、发送短信流程分析
四、接收短信流程分析
一、Android SMS架构
SMS(Short Messaging Service),短信息服务。在android源代码中已经实现了基本的短信、彩信的发送与接收以及状态报告等相关通信能力,并且将SMS、MMS功能集成在一个应用中的MMS应用。
SMS的分层结构与Android架构保持一致, 从上到下依次是:MMS应用层、Telephony Frameworks框架层、RIL层。app层如何将发送短信转换成RIL请求以及app如何接收RIL发出的新短信通知相关的代码主要集中在Java Frameworks层,因此本次学习主要关注Frameworks层。
SMS在Telephony Frameworks层主要有以下几个类:
1.SmsMessage.java(frameworks/opt/telephony/src/java/android/telephony):定义了短信在framework层的数据结构。
2.SmsMessageBase.java:容纳实际的短信数据。它有两个子类 SmsMessage.java(frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm)和SmsMessage.java(frameworks/opt/telephony/src/java/com/android/internal/telephony/cdma),负责帮助SmsMessage.java(frameworks/opt/telephony/src/java/android/telephony)来处理GSM/CDMA制式下的数据解析。
3.SmsManager.java:发送短信的唯一入口。SmsManager类在Telephony Frameworks层提供短信操作的相关接口供application层调用,application层通过获取此类的对象,完成对短信的操作。该类提供了短信拆分、短信发送、将短信复制到SIM卡、从SIM卡删除短信和小区广播等接口。
4.IccSmsInterfaceManager.java:抽象类,实现了ISms.stub接口,它有两个子类:RuimSmsInterfaceManager和SimSmsInterfaceManager,分别对应USIM卡和SIM卡的操作,不同之处在于电话卡中的短信存储和读取以及小区广播的实现逻辑。
5.SMSDispatcher.java:继承Handler类,有三个子类:ImsSMSDispatcher、GsmSMSDispatcher和CdmaSMSDispatcher。与RIL.java交互,完成短信的发送和接收。
6.RIL.java:通过socket与RILC交互,完成短信发送请求与RIL请求之间的转换。
二、短信数据结构
1.SMS数据结构
在telephony.java中,定义了SMS存储到数据库时的主要属性和方法。
SMS的属性:
1. TYPE //The type of the message
2. THREAD_ID //The thread ID of the message
3. ADDRESS //The address of the other party
4. PERSON_ID //The person ID of the sender
5. DATE //The date the message was received
6. READ //Has the message been read
7. STATUS //The status of the message
8. SUBJECT //The subject of the message
9. BODY //The body of the message
10.PROTOCOL //The protocol identifier code
11.SERVICE_CENTER // The service center
12.REPLY_PATH_PRESENT //Whether TP-Reply-Path bit was set
13.LOCKED //Has the message been locked
14.SUB_ID //
SMS的方法:
1.query() //
2.addMessageToUri() //将短信内容保存至数据库
3.moveMessageToFolder() //将短信内容转移另一个URI
4.isOutgoingFolder() //
2.SmsMessage数据结构
在SmsMessage.java(frameworks/opt/telephony/src/java/android/telephony)中,定义了SmsMessage向下传递数据时的主要属性和方法。
SmsMessage的属性:
1.mWrappedSmsMessage //SmsMessageBase对象,容纳实际的短信数据。
2.MessageClass //enum:UNKNOWN,CLASS_0,CLASS_1,CLASS_2,CLASS_3
3.ENCODING_XXX //XXbit编码:7BIT/8BIT/16BIT/UNKNOWN
4.MAX_USER_DATA_BYTES //短信最大字节数140
5.MAX_USER_DATA_BYTES_WITH_HEADER //带header的短信最大字节数134
6.MAX_USER_DATA_SEPTETS //短信最大7位字节数160
7.MAX_USER_DATA_SEPTETS_WITH_HEADER //带header的短信最大7位字节数153
8.FORMAT_3GPP/FORMAT_3GPP2 //短信format
9.mSubId //subId
SmsMessage的方法:
1.SmsMessage() //
2.createFromPdu() //
3.getXXX() //mWrappedSmsMessage.getXXX()
4.isXXX() //mWrappedSmsMessage.isXXX()
其中, 属性中的ENCODING_7BIT/ENCODING_8BIT/ENCODING_16BIT分别代表着手机短信的PDU编码方式:7-bit、8-bit和16-bit编码。7-bit编码用于发送普通的ASCII字符,即英文短信,最多可发送160字 符。8-bit编码通常用于发送数据消息。16-bit编码用于发送Unicode字符,可发送中文字符,最多发送70字符。PDU格式参照表1-1
元素 | 名称 | 长度 | 描述 |
SCA | Service Center Address | 1-12 | 短消息服务中心号码 |
PDU-Type | Protocol Data Unit | 1 | 协议数据单元类型 |
MR | Message Reference | 1 | 所有成功的短信发送参考数目(0..255) |
OA | Originator Address | 2-12 | 发送方地址(手机号码) |
DA | Destination Address | 2-12 | 接收方地址(手机号码) |
PID | Protocol Identifer | 1 | 参数显示消息中心以何种方式处理消息内容(比如FAX,Voice) |
DCS | Data Coding Scheme | 1 | 参数显示用户数据编码方案 |
SCTS | Service Center Time Stamp | 7 | 消息中心收到消息时的时间戳 |
VP | Validity Period | 0,1,7 | 参数显示消息有效期 |
UDL | User Data Lenghth | 1 | 用户数据长度 |
UD | User Data | 0-140 | 用户数据 |
表1 发送方PDU格式
在PDU中,DCS数据编码方案占据8bit。其中Bit N0.1与Bit No.0表示短信的类型,即属性中的MessageClass:
00-Class 0:Immediate Display,短信内容自动显示在屏幕上,看完自动消失
01-Class 1:Mobile Equipment-specific,会存储在设备上的短信
10-Class 2:SIM specific Message,会存储在SIM卡的短信
11-Class 3:Terminate Equipment-specific,直接到终端设备上的短信
而Bit No.3与Bit No.2则表示PDU编码方式,即属性中的 ENCODING_XXX:
00-ENCODING_7BIT:默认的字符集,每字符占7bit,此时最大可发送160字符(即属性MAX_USER_DATA_SEPTETS=160)
01-ENCODING_8BIT:8bit,此时最大可发送140字符(即属性MAX_USER_DATA_BYTES=140)
10-ENCODING_16BIT:16bit,发送双字节字符集
11-ENCODING_UNKNOWN:预留
3.SmsMessageBase
在SmsMessage中,有一个重要属性基本上所有的方法都会用到它:SmsMessageBase对象mWrappedSmsMessage。SmsMessageBase定义了SmsMessage基本的属性和方法。
SmsMessageBase的属性:
1.scAddress //SMSC
2.originatingAddress //sender
3.messageBody //messageBody
4.mPdu //The raw PDU of the message
5.userData //The raw bytes for the user data
…
SmsMessageBase的方法:
1.getXXX() //return 属性
2.isXXX() //
4.SmsMessageBase的两个子类
由于通信机制分为GSM和CDMA两种,所以SmsMessage也分了两种:
com.android.internal.telephony.cdma.SmsMessage
com.android.internal.telephony.gsm.SmsMessage
在SmsMessage的一些关于处理数据的方法中,会根据短信的format来判断调用gsm.SmsMessage的方法还是cdma.SmsMessage的方法。二者的主要区别就是对数据的解析方式实现不同,如parseXX()。
gsm.SmsMessage的parseUserData方法会根据ENCODING_XXX的不同,来调用不同的解析方法,得到正确的短信数据。
5.SmsTracker类
在SMSDispatcher和RIL交互的过程中,不管是将短信发送请求转换至RIL请求,还是回调短信状态,SmsTracker对象一直被传递。现在分析一下SmsTracker类的数据结构。
SmsTracker类是RIL.java的一个protected内部类。该类只有一个SmsTracker构造方法和一个判断是否是分段短信的isMultipart方法,其余的是声明的成员变量。
mData //包含着destAddr/scAddr/text/smsc/pdu的HASHMAP
mSentIntent //短信发送状态的回调intent
mDeliveryIntent //短信发送状态的回调intent
mRetryCount //短信重发次数计数
mAppInfo //app package info
mDestAddress //短信收件人
mFormat //GSM or CDMA
mImsRetry //
mMessageRef //