彩信发送流程与短信不完全一致,WorkingMessage刷新收信人,生成彩信的可发送的Pdu—SendReq,接着会把彩信写入数据库,把要发送的SendReq也会写入数据库,后面会再从数据库中读取出SendReq,并标识为草稿;然后会构建MmsMessageSender,传入收信人和彩信的Uri,让其发送。这期间也会回调UI一次,以初始化收信人编辑框和信息编辑框。
MmsMessageSender先从数据库中读出彩信发送的Pdu—SendReq,Google的内置包com.google.Android.mms.*;里面封装了所有操作Pdu的方法,包括把Pdu写入数据库(PduPersister.persist()),从数据库中读取生成Pdu(PduPersister.load())。然后根据当前彩信的配置和其他信息对SendReq进行更新,比如设置Expiration,Priority,Date和Size等,把彩信移到Outbox,然后启动TransactionService来处理彩信。sendMessage()就此返回。WorkingMessage会再次回调UI的接口,因为此时彩信已被在数据库中,所以UI会刷新信息列表,显示刚刚的彩信,这时的状态应该是正在发送中。
TransactionService,与短信的SmsReceiverService类似,是负责处理彩信的服务,可以发送,接收等。对于TransactionService来讲,所有的需要处理的流程,无论是发送还是接收,都是一个Transaction。它内部有二个队列,一个是当前正在处理(processing)的Transaction,一个是待处理(pending)的Transaction。它维护这二个队列,并检查网络的连接,打开彩信网络连接,准备和检查环境,然后从待处理的队列中取出第一个,放入正在处理的队列中,并处理这个Transaction,也就是调用Transaction.process()。
发送彩信是一个SendTransaction,它的process()方法负责发送彩信,它会创建一个独立的线程来做,因此不会阻塞TransactionService,处理服务就可以再处理其他的Transaction。它会先从数据库中取出彩信Pdu,M-Send.req,(SendReq),更新一些字段,比如date,然后调用其父类Transaction.java中的方法sendPdu来把SendReq发送出去,sendPdu()会返回发送的结果(send confirmation)。Transaction.sendPdu()会先设置好网路,然后直接调用HttpUtils中的httpConnection()方法,用HTTP把彩信发送出去,同时取得返回消息(Response)给SendTransaction。SendTransaction会检查发送结果,返回结果(Send Confirmation),分析状态并更新至数据库(比如发送失败或发送成功)。UI会监听到状态变化,并更新信息列表。
到此,一个彩信发送完成。
前面有提到过TransactionSettings,它是对于一个处理流程的相关配置信息,里面含有MMSC(Multimedia Message Service Center),Proxy和ProxyPort。这些信息,特别对于发送和接收来说是十分重要的。因为对于手机的信息,并不是手机直接把信息发送到接收人的手机上,而是直接发给服务中心,后面就是由服务中心再把信息发送给对应的接收人的手机上。对于彩信也是这样,HttpUtils通过HTTP协议把彩信发送给MMSC,它是一个URL地址,之后对于发送方来讲,彩信就发送完了,彩信服务中心(MMSC)会处理接下来的发送过程,服务中心是与手机运营相关的,它由运营商来提供。对于Mms发送彩信,是不会特意指定TransactionSettings的,也就是说它不会指定MMSC和Proxy,那么TransactionService就会用系统默认的MMSC,Proxy作为TranscationSetting,MMSC,Proxy和ProxyPort需要从Telephony数据库中查询出来,它们是与具体手机的APN设置和具体的运营商相关。所以,这里如果想要改变彩信的配置信息,只能更改APN系统设置来完成。
而短信的发送就不涉及SMSC(短信服务中心),因为Frameworks中的工具已经封装好了SmsManager提供了几个发送短信的方法,可能它会去处理SMSC相关的东西。
总结,可以看出数据库在信息的发送过程中扮演了重要的角色,当信息离开编辑器后就马上写入了数据库,发送过程中的各个类都是先从数据库中加载信息,然后做相应处理,然后写回数据库或是更新状态,然后再交由下一个流程来处理。而所谓的Pending Message Queue其实没有相应的数据结构,它们都是数据库中的信息且状态是待发送而已。所以信息离开编辑器后就被写入了数据库,只不过状态一直在改变,从发送中到已发送,或发送失败,或如果Telephony服务不可用会仍处在待发送,但对于UI页面来讲可能没有那么多状态,它可能只显示发送中,已发送和发送失败。