Android7.0 Messaging源码分析(5) - MMS类库篇
2016-11-18 14:05
288 查看
在《Android7.0 Messaging源码分析(2) - Application 创建篇》中介绍了在 application 创建过程中会初始化MMS类库,这篇文章对 MMS 类库做简要分析。
初始化代码如下:
主要工作是设置了 Apn 、运营商、用户代理信息加载器。
在 com/android/messaging/mmslib 包下面有一个pdu包和util包;
在android/support/v7/mms 包下面也有一个pdu包以及 ApnSettingsLoader, MmsManager, MmsService 等类。对比发现两个 pdu 包的内容大致相同,不知为啥要放两处。
我们来看一下 android/support/v7/ 包下的几个类,
ApnSettingsLoader // 为默认 SMS SIM 加载 APN 提供接口
ApnsXmlParser // 内置 APN 列表 XML 资源文件解析器(MmsXmlResourceParser的子类)
CarrierConfigValuesLoader // 运营商配置加载器
CarrierConfigXmlParser // 运营商配置解析器 (比如 mms_config)(MmsXmlResourceParser的子类)
DefaultApnSettingsLoader // 默认 APN 配置加载器
DefaultCarrierConfigValuesLoader // 默认运营商配置加载器
DefaultUserAgentInfoLoader // 默认 UA, UAProfUrl加载器
UserAgentInfoLoader // UA, UAProfUrl加载器
DownloadRequest // MMS 下载请求(MmsRequest的子类)
MmsHttpClient // MMS 发送和下载使用的 HTTP client
MmsHttpException // HTTP 异常
MmsManager // MMS 库的公开接口
MmsNetworkException // MMS 网络异常
MmsNetworkManager // 在 L 之前的设备使用废弃的 API(从Android L开始废弃)管理 MMS 网络连接(或者被强制使用在 L 或以后的平台)
MmsRequest // MMS 请求的基类, 它会处理所有的 MMS 请求的执行;
MmsService // 在 L 之前的平台使用废弃的 API 执行 MMS 请求的 Service
MmsXmlResourceParser // XML 解析器基类
PhoneNumberHelper // 电话号码格式帮助类,使用了独立的类( com.google.i18n.PhoneNumberUtil 类),因为它依赖 libphonenumber
SendRequest // 发送 MMS 请求
Utils // 工具类
其中 MmsManager 会直接调用 framework层的 android.telephony.SmsManager来收发彩信。
APN包含的信息如下:名称、APN、代理、端口、用户名、密码、服务器、MMSC、彩信代理、彩信端口、MCC、MNC、身份验证类型、APN类型、APN协议、APN漫游协议、承载系统、MVNO系统、MVNO值、PPP拨叫号码;
来看一下 apn 相关的类,
DefaultApnSettingsLoader 提供了从本地 xml(apns.xml) 和 system 读取 apn 信息的方法;
BugleApnSettingsLoader 提供了从 system 和本地数据库(apn.db)读取 apn 信息的方法;
获取 apn name的方法如下:(MmsNetworkManager.java)
CarrierConfigValuesLoader 接口定义了运营商配置的key以及默认值;
DefaultCarrierConfigValuesLoader 类提供了从本地 xml(mms_config.xml) 和 system 读取 mms 配置信息的方法;
BugleCarrierConfigValuesLoader 类同样提供了从本地 xml(mms_config.xml) 和 system 读取 mms 配置信息的方法;
什么是UserAgent呢?它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
DefaultUserAgentInfoLoader 和 BugleUserAgentInfoLoader 都是默认从 TelephonyManager 获取 MmsUserAgent 和 MmsUAProfUrl,如果为空再取默认值。
AcknowledgeInd // M-Acknowledge.ind PDU 延迟下载确认 PDU(GenericPdu 子类)
Base64 // Base64 编码工具类
CharacterSets // 字符集 (http://www.iana.org/assignments/character-sets/character-sets.xhtml)
ContentType // 内容类型
DeliveryInd // M-Delivery.Ind Pdu 已发送彩信的发送状态报告PDU
EncodedStringValue // Encoded-string-value = Text-string | Value-length Char-set Text-string
GenericPdu // Pdu基类
InvalidHeaderValueException // 无效头部值异常
MmsException // Mms 客户端通用异常
MultimediaMessagePdu // 多媒体信息PDU(GenericPdu 子类)
NotificationInd // M-Notification.ind PDU 新的彩信提醒PDU(GenericPdu 子类)
NotifyRespInd // M-NofifyResp.ind PDU 消息接收完成回复Pdu(GenericPdu 子类)
PduBody // Pdu 主体
PduContentTypes // Pdu 内容类型
PduHeaders // Pdu头部
PduParser // Pdu 解析器
PduPart // Pdu 部分
QuotedPrintable //
ReadOrigInd // M-Read-Orig.ind MMS 代理中转站发送的阅读/删除报告Pdu(GenericPdu 子类)
ReadRecInd // M-ReadRec.ind pdu MMS客户端发送的阅读/删除报告Pdu(GenericPdu 子类)
RetrieveConf // M-Retrive.conf Pdu 确认收到Pdn(GenericPdu 子类)
SendConf // M-Send.conf 发送结果状态 Pdu(GenericPdu 子类)
SendReq // M-Send.req 发送请求(GenericPdu 子类)
上面的类一大半是 pdu 的实现类,每种类都对应一种 pdu,来看看什么是 PDU以及 PDU 的种类有哪些。(参考文章:MMS Protocol Overview)
一个(T)PDU 是一个封装的二进制块。在 MMS 代理(MMSC)与 MMS 客户端的每一次交互都是使用 PDU 来组成 MMS 信息的。下面是消息的类型:
- M-Send.req: 发送请求
- M-Send.conf: MMSC 发送给 MMS 客户端的交互结果状态码
- M-Notification.ind: 从 MMSC 发送的 MMS 提醒,代表一个新消息的可用性以及消息内容的地址。
- M-NotifyResp.ind :收到 M-Notification.ind 通知后发送给 MMCS 的已下载消息接收通知。
- M-Retrieve.conf: 包含一条新的 MMS,在自动下载模式下同 M-NotifyResp.ind 一起告知已收到。
- M-Acknowledgement .ind: 用于 MMS 引擎告知一个延期下载。
- m-Forward.reg: 用于转发仍在MMS中继或MMSC(没有下载)的彩信。并不是所有的运营商都支持这一功能。
- m-Forward.conf: 转发请求的返回状态码。
- M-Delivery.ind: 已发送彩信的发送状态报告。通过发送或转发时生成的网络消息 id 来标识。这个 id 可以用来
映射原始发送的消息。在 TPDU 里的状态值包含了已发送消息的实际状态,如已过期,已获取,已拒绝,已延期,未识别,
不明确,被转发,未送达等。
- M-Read-Rec.ind: MMS 客户端发送的阅读/删除报告
- M-Read-Orig.ind: MMS 代理发送的阅读/删除报告。
发送彩信流程:
1 构造一个 M-Send-req TPDU,确保必要的字段已设置,特别是收件人地址。
2 初始化一个与目标 MMSC 服务器交互的 HTTP POST 请求,并将该 TPDU 作为 post 数据发送。
3 当应用程序收到一个 M-Send.conf TPDU 回复,解析它的状态信息。如果结果是成功,应用程序可以获取到一个网络消息 ID,这个 ID 可以用于匹配一个已接收传送或者阅读报告。
接收彩信流程:
设备会通过 Wap-Push 或者 SMS 收到一个 M-Notification.ind TPDU,应用程序可以有两种回复方式:立即/自动下载或延时下载。
1 立即/自动下载模式下,内容地址获取和信息下载使用 HTTP GET 请求进行;M-NotifyResp.ind 通过 HTTP post 请求发送给 MMSC 告知彩信已收到。
注意:如果接收确认未发送,有些 MMSC 服务器会重复发送通知 TPDU。
2 在延时下载模式下,M-NotifyResp.ind Pdn 会附加一个延时标记来告知接收方。
注意:对于延时下载,应用程序应该发送一个 M-Acknowledgement.ind PDU 而不是 M-NotifyResp.ind,如果应用程序不发送 M-Acknowledgement.ind PDU,在信息下载后原始信息的发送方将无法收到接收报告。
2 相关内容包括 Apn、CarrierConfig、UserAgent 等配置信息的加载,以及彩信传送单元 Pdu。
初始化代码如下:
138 private static void initMmsLib(final Context context, final BugleGservices bugleGservices, 139 final CarrierConfigValuesLoader carrierConfigValuesLoader) { 140 MmsManager.setApnSettingsLoader(new BugleApnSettingsLoader(context)); 141 MmsManager.setCarrierConfigValuesLoader(carrierConfigValuesLoader); 142 MmsManager.setUserAgentInfoLoader(new BugleUserAgentInfoLoader(context)); 143 MmsManager.setUseWakeLock(true); 144 // If Gservices is configured not to use mms api, force MmsManager to always use 145 // legacy mms sending logic 146 MmsManager.setForceLegacyMms(!bugleGservices.getBoolean( 147 BugleGservicesKeys.USE_MMS_API_IF_PRESENT, 148 BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT)); 149 bugleGservices.registerForChanges(new Runnable() { 150 @Override 151 public void run() { 152 MmsManager.setForceLegacyMms(!bugleGservices.getBoolean( 153 BugleGservicesKeys.USE_MMS_API_IF_PRESENT, 154 BugleGservicesKeys.USE_MMS_API_IF_PRESENT_DEFAULT)); 155 } 156 }); 157 }
主要工作是设置了 Apn 、运营商、用户代理信息加载器。
在 com/android/messaging/mmslib 包下面有一个pdu包和util包;
在android/support/v7/mms 包下面也有一个pdu包以及 ApnSettingsLoader, MmsManager, MmsService 等类。对比发现两个 pdu 包的内容大致相同,不知为啥要放两处。
我们来看一下 android/support/v7/ 包下的几个类,
ApnSettingsLoader // 为默认 SMS SIM 加载 APN 提供接口
ApnsXmlParser // 内置 APN 列表 XML 资源文件解析器(MmsXmlResourceParser的子类)
CarrierConfigValuesLoader // 运营商配置加载器
CarrierConfigXmlParser // 运营商配置解析器 (比如 mms_config)(MmsXmlResourceParser的子类)
DefaultApnSettingsLoader // 默认 APN 配置加载器
DefaultCarrierConfigValuesLoader // 默认运营商配置加载器
DefaultUserAgentInfoLoader // 默认 UA, UAProfUrl加载器
UserAgentInfoLoader // UA, UAProfUrl加载器
DownloadRequest // MMS 下载请求(MmsRequest的子类)
MmsHttpClient // MMS 发送和下载使用的 HTTP client
MmsHttpException // HTTP 异常
MmsManager // MMS 库的公开接口
MmsNetworkException // MMS 网络异常
MmsNetworkManager // 在 L 之前的设备使用废弃的 API(从Android L开始废弃)管理 MMS 网络连接(或者被强制使用在 L 或以后的平台)
MmsRequest // MMS 请求的基类, 它会处理所有的 MMS 请求的执行;
MmsService // 在 L 之前的平台使用废弃的 API 执行 MMS 请求的 Service
MmsXmlResourceParser // XML 解析器基类
PhoneNumberHelper // 电话号码格式帮助类,使用了独立的类( com.google.i18n.PhoneNumberUtil 类),因为它依赖 libphonenumber
SendRequest // 发送 MMS 请求
Utils // 工具类
其中 MmsManager 会直接调用 framework层的 android.telephony.SmsManager来收发彩信。
APN简介
一般在手机设置的移动网络设置 - 接入点名称(APN)选项可以查看 APN 的信息,并进行新建、重置等操作。APN包含的信息如下:名称、APN、代理、端口、用户名、密码、服务器、MMSC、彩信代理、彩信端口、MCC、MNC、身份验证类型、APN类型、APN协议、APN漫游协议、承载系统、MVNO系统、MVNO值、PPP拨叫号码;
来看一下 apn 相关的类,
DefaultApnSettingsLoader 提供了从本地 xml(apns.xml) 和 system 读取 apn 信息的方法;
BugleApnSettingsLoader 提供了从 system 和本地数据库(apn.db)读取 apn 信息的方法;
获取 apn name的方法如下:(MmsNetworkManager.java)
244 public String getApnName() { 245 Network network = null; 246 synchronized (this) { 247 if (mNetwork == null) { 248 return null; 249 } 250 network = mNetwork; 251 } 252 String apnName = null; 253 final ConnectivityManager connectivityManager = getConnectivityManager(); 254 final NetworkInfo mmsNetworkInfo = connectivityManager.getNetworkInfo(network); 255 if (mmsNetworkInfo != null) { 256 apnName = mmsNetworkInfo.getExtraInfo(); 257 } 258 return apnName; 259 }
CarrierConfig简介
运营商配置包含了很多短信及彩信的配置,比如是否启用彩信、是否启用短信分组、超长短信是否分条发送等。CarrierConfigValuesLoader 接口定义了运营商配置的key以及默认值;
DefaultCarrierConfigValuesLoader 类提供了从本地 xml(mms_config.xml) 和 system 读取 mms 配置信息的方法;
BugleCarrierConfigValuesLoader 类同样提供了从本地 xml(mms_config.xml) 和 system 读取 mms 配置信息的方法;
UserAgent简介
UserAgentInfoLoader 接口用于加载用户代理和 UA Prof URL(用户代理简介地址)。什么是UserAgent呢?它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
DefaultUserAgentInfoLoader 和 BugleUserAgentInfoLoader 都是默认从 TelephonyManager 获取 MmsUserAgent 和 MmsUAProfUrl,如果为空再取默认值。
PDU简介
我们再来看一下 pdu 包下的内容,AcknowledgeInd // M-Acknowledge.ind PDU 延迟下载确认 PDU(GenericPdu 子类)
Base64 // Base64 编码工具类
CharacterSets // 字符集 (http://www.iana.org/assignments/character-sets/character-sets.xhtml)
ContentType // 内容类型
DeliveryInd // M-Delivery.Ind Pdu 已发送彩信的发送状态报告PDU
EncodedStringValue // Encoded-string-value = Text-string | Value-length Char-set Text-string
GenericPdu // Pdu基类
InvalidHeaderValueException // 无效头部值异常
MmsException // Mms 客户端通用异常
MultimediaMessagePdu // 多媒体信息PDU(GenericPdu 子类)
NotificationInd // M-Notification.ind PDU 新的彩信提醒PDU(GenericPdu 子类)
NotifyRespInd // M-NofifyResp.ind PDU 消息接收完成回复Pdu(GenericPdu 子类)
PduBody // Pdu 主体
PduContentTypes // Pdu 内容类型
PduHeaders // Pdu头部
PduParser // Pdu 解析器
PduPart // Pdu 部分
QuotedPrintable //
ReadOrigInd // M-Read-Orig.ind MMS 代理中转站发送的阅读/删除报告Pdu(GenericPdu 子类)
ReadRecInd // M-ReadRec.ind pdu MMS客户端发送的阅读/删除报告Pdu(GenericPdu 子类)
RetrieveConf // M-Retrive.conf Pdu 确认收到Pdn(GenericPdu 子类)
SendConf // M-Send.conf 发送结果状态 Pdu(GenericPdu 子类)
SendReq // M-Send.req 发送请求(GenericPdu 子类)
上面的类一大半是 pdu 的实现类,每种类都对应一种 pdu,来看看什么是 PDU以及 PDU 的种类有哪些。(参考文章:MMS Protocol Overview)
一个(T)PDU 是一个封装的二进制块。在 MMS 代理(MMSC)与 MMS 客户端的每一次交互都是使用 PDU 来组成 MMS 信息的。下面是消息的类型:
- M-Send.req: 发送请求
- M-Send.conf: MMSC 发送给 MMS 客户端的交互结果状态码
- M-Notification.ind: 从 MMSC 发送的 MMS 提醒,代表一个新消息的可用性以及消息内容的地址。
- M-NotifyResp.ind :收到 M-Notification.ind 通知后发送给 MMCS 的已下载消息接收通知。
- M-Retrieve.conf: 包含一条新的 MMS,在自动下载模式下同 M-NotifyResp.ind 一起告知已收到。
- M-Acknowledgement .ind: 用于 MMS 引擎告知一个延期下载。
- m-Forward.reg: 用于转发仍在MMS中继或MMSC(没有下载)的彩信。并不是所有的运营商都支持这一功能。
- m-Forward.conf: 转发请求的返回状态码。
- M-Delivery.ind: 已发送彩信的发送状态报告。通过发送或转发时生成的网络消息 id 来标识。这个 id 可以用来
映射原始发送的消息。在 TPDU 里的状态值包含了已发送消息的实际状态,如已过期,已获取,已拒绝,已延期,未识别,
不明确,被转发,未送达等。
- M-Read-Rec.ind: MMS 客户端发送的阅读/删除报告
- M-Read-Orig.ind: MMS 代理发送的阅读/删除报告。
发送彩信流程:
1 构造一个 M-Send-req TPDU,确保必要的字段已设置,特别是收件人地址。
2 初始化一个与目标 MMSC 服务器交互的 HTTP POST 请求,并将该 TPDU 作为 post 数据发送。
3 当应用程序收到一个 M-Send.conf TPDU 回复,解析它的状态信息。如果结果是成功,应用程序可以获取到一个网络消息 ID,这个 ID 可以用于匹配一个已接收传送或者阅读报告。
接收彩信流程:
设备会通过 Wap-Push 或者 SMS 收到一个 M-Notification.ind TPDU,应用程序可以有两种回复方式:立即/自动下载或延时下载。
1 立即/自动下载模式下,内容地址获取和信息下载使用 HTTP GET 请求进行;M-NotifyResp.ind 通过 HTTP post 请求发送给 MMSC 告知彩信已收到。
注意:如果接收确认未发送,有些 MMSC 服务器会重复发送通知 TPDU。
2 在延时下载模式下,M-NotifyResp.ind Pdn 会附加一个延时标记来告知接收方。
注意:对于延时下载,应用程序应该发送一个 M-Acknowledgement.ind PDU 而不是 M-NotifyResp.ind,如果应用程序不发送 M-Acknowledgement.ind PDU,在信息下载后原始信息的发送方将无法收到接收报告。
总结
1 本篇内容介绍了 MMS 类库,它调用了 framework 层的 SmsManager 为应用程序提供 MMS 支持。2 相关内容包括 Apn、CarrierConfig、UserAgent 等配置信息的加载,以及彩信传送单元 Pdu。
相关文章推荐
- Android7.0 Messaging源码分析(1) - 基础知识篇
- Android7.0 Messaging源码分析(2) - Application 创建篇
- Android7.0 Messaging源码分析(3) - 缓存管理篇
- Android7.0 Messaging源码分析(4) - DataModel篇
- Android7.0 Phone应用源码分析(一) phone拨号流程分析
- Android7.0 Messaging源码分析(0) - 启动篇
- Storm-源码分析- Messaging (backtype.storm.messaging)
- Android7.0去电流程源码分析(三)
- Android7.0 init进程源码分析
- Android7.0去电流程源码分析(一)
- Android7.0 拨号盘应用源码分析(一) 界面浅析
- Android7.0 Phone应用源码分析(二) phone来电流程分析
- Android7.0 Phone应用源码分析(三) phone拒接流程分析
- 基于Android7.0的Launcher3源码分析(3)——显示相关参数的初始化
- 基于Android7.0的Launcher3源码分析(2)——UI显示控件的组成
- Android7.0去电流程源码分析(二)
- Android多线程(三)AsyncTask源码分析(Android7.0)
- 基于Android7.0的Launcher3源码分析(1)——框架设计分析
- Android7.0 Phone应用源码分析(四) phone挂断流程分析
- JBPM源码分析(二)---acceptToken函数