android MMS源码分析

  • Post author:
  • Post category:其他



从软件的功能角度来讲,


Mms


分为对话列表,消息列表,短信编辑,彩信编辑,短信显示,彩信显示和配置。


从实现的角度来看,它分为


GUI


展示层,发送


/


接收,彩信解析,彩信附件,信息数据等,这些分类对应着源码中的各种包。


源码导航


Mms


的源码的位置在于


android/packages/apps/Mms


其中


Mms/src/com/android/mms


里面都是


Mms


相关的代码,而


Mms/src/org/w3c/dom


里面是一个类库,主要用于彩信格式的解析和显示。这里主要讲一下


Mms/src/com/android/mms


下面的一些包和类的主要用途。



ui



—GUI


展示层,用于展示对话列表,消息列表,消息编辑页,彩信附件编辑,彩信展示,播放幻灯片。负责直接与用户交互。


  • ConversationListAdapter.java—


    对话列表的


    Adapter


    用于给显示层


    ConversationList


    绑定数据。

  • ConversationListItemData.java—


    代表对话列表中的每一项的数据结构,里面含有要在对话列表中展示的信息。

  • ConversationList.java——


    这是对话列表的显示窗口


    Activity


    ,它是一个


    ListActivity


    ,这几个类都是对话列表的相关类,用于显示,编辑和管理所有的对话。

  • ComposeMessageActivity.java—-


    这个是核心的窗口


    Activity


    ,编辑信息,显示一条对话


    Thread


    中的所有往来信息。


    MessageListView


    会加在其上面,另外,


    AttachmentEditor


    也会加在其上面。这个


    Activity


    也负责响应外部应用程序,发送


    SENDTO





    SEND


    等请求


    Intent


    ,比如外部应用想要发送信息,等就由这个


    Activity


    来响应。

  • MessageItem.java—


    代表一个信息的抽象数据,它包含了信息相关的所有内容,比如信息的主题,消息内容,来信地址,附件内容等等。它的所有数据都是公共的内部成员,都可以直接访问。

  • MessageListAdapter.java—


    用于给消息列表显示层(由


    ComposeMessageActivity


    创建,绑定到


    MessageListView


    上)绑定数据。

  • MessageListView.java—


    用于显示消息列表,继承自


    ListView


    ,其生命周期由


    ComposeMessageActivity


    来控制,显示与否也由它来控制。

  • MessageListItem.java—


    是一个布局,用于显示和控制消息列表中的每一个消息的显示。

  • AttachmentTypeSelectorAdapter.java—


    用于添加附件件时的一个支持的附件列表,它就是一个菜单。

  • AttachmentEditor.java—


    用于在编辑


    MMS


    彩信信息时,显示已添加的附件,它的生命周期由


    ComposeMessageActivity


    来控制,显示与否也是由


    ComposeMessageActivity


    来控制,当有彩信附件时,它就会显示,否则就被


    Hide


    。它是一个布局管理器,管理着下面四个布局,根据附件的类型动态的显示下面四个


    View


    中的某一个。

  • AudioAttachmentView.java—


    在编辑信息器中用于显示音频附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。

  • ImageAttachmentView.java—


    在编辑信息器中用于显示图片附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。

  • SlideshowAttachmentView.java—


    在编辑信息器中用于显示幻灯片附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。

  • VideoAttachmentView.java—


    在编辑信息器中用于显示视频附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。

  • SlideshowActivity.java—


    用来全屏播放幻灯片,也即幻灯片的展示,因为彩信的创建和播放都是以幻灯片的方式进行的,也即一张一张的,每张上面可以文字,图片,视频和音频,每一张有浏览时长。

  • SlideshowEditActivity.java—


    以列表方式管理幻灯片,也即是把所有的幻灯片用列表显示出来,用户可添加一页幻灯片,也可以点击进入编辑某页幻灯片,用于创建和编辑幻灯片。

  • SlideshowEditor.java—


    用于编辑某页幻灯片,比如添加元素,删除元素和替换元素,这里的元素可以是图片,视频,音频和文字。也可以用于编辑整页幻灯片,比如删除某页幻灯片,调整这页幻灯片在所有幻灯片中的位置等。它是一个具体操作幻灯片的封装,


    SlideEditorActivity


    创建它并使用它来完成纪灯片的编辑。

  • SlideshowPresenter.java—


    用于展示所有的幻灯片,也就是播放所有的幻灯片。由


    SlideshowActivity


    来创建和使用。

  • SlideViewInterface.java—


    定义了一些用于显示一页幻灯片中的内容的接口,如设置图像,设置视频,设置音频,播放视频,播放音频,暂停,随机定位等等。附件显示的


    View





    AudioAttachmentView





    ImageAttachmentView





    SlideshowAttachmentView





    VideoAttachmentView


    均实现了此接口,这样


    AttachmentEditor


    就可以用统一的接口来控制内容的播放,而不用关心具体的内容是什么。

  • SlideEditorActivity.java—


    用于编辑某页幻灯片,比如添加音频,添加视频,添加图像,添加文字等。它只是提供用户界面,让用户来操作各种按扭以达到添加元素,替换元素或是删除元素。而对具体的幻灯片的操作是通过


    SlideshowEditor


    来完成的,它主要负责与用户交互。

  • SlideListItemView.java— SlideshowEditActivity


    中列表的每一项的布局管理,继承自


    LinearLayout




  • MmsThumbnailPresenter.java—


    用于在消息列表中,显示彩信的缩略图,因为彩信的内容不固定,可能是图片,可能是音频,可能是视频也可能是幻灯片,所以用这个类来处理并显示彩信的缩略图。

  • MessagingPreferenceActivity.java—Mms


    的配置信息编辑器,用来编辑和更改配置信息,继承息


    PreferenceActivity


    。它负责与用户交互,显示和更改配置。在


    Mms


    启动时,


    MmsConfig


    会从


    SharedPreference


    中读出配置信息,在运行时其他的类的配置信息都是从


    MmsConfig


    中获取的,


    MmsConfig


    提供了很多


    Get


    方法以获取配置信息。

  • Presenter.java—


    用来展示附件的一个抽象类。

  • PresenterFactory.java—


    工厂方法。

  • RecipientsAdapter.java

  • RecipientsEditor.java—


    用于显示信息编辑页面上面的收信人的编辑框,它可以有自动补全的功能,补全的数据由


    RecipientsAdapter


    来提供。

  • ViewInterface.java—


    代表一个


    View


    的基类,用于


    Slideshow


    显示内容或是取缩略图。可以取


    View


    的长宽高等。

  • BasicSlideEditorView.java—


    编辑某一页幻灯片时所用的布局,也就是在


    SlideEditorActivity.java


    中使用。

  • EditSlideDurationActivity.java—


    顾名思义,用于编辑某一页幻灯片的浏览时长。

  • ManageSimMessages.java—


    这个是在设置中使用的,用来管理


    SIM


    里的消息。在设置中有一项是管理


    SIM


    卡上面的消息。在


    Mms


    的设置


    Settings


    中有一个选项可以设置是把信息存储在


    SIM


    卡,还是存储在手机里。在收信时


    SmsReceiverService


    会查看这个设置然后把收到的信息写到相应的地址。


    ManageSimMessages


    也是以列表方式显示


    SIM


    里面的信息,提供了二个菜单:把信息存入手机和删除。

  • NumberPickerButton.java—


    用于显示选择数字的按扭,在配置里面用。

  • NumberPickerDialog.java—


    用于显示选择数字的对话框,在配置里面用。

  • NumberPicker.java—


    用于在配置的时候选择数字。这几个


    NumerPicker


    主要是用于


    Settings


    中的。

  • DeliveryReportActivity.java—


    信息发送情况报告。以列表的方式来显示

  • DeliveryReportAdapter.java—


    相应的


    Adapter

  • DeliveryReportItem.java—


    相应的数据,每一项的数据

  • DeliveryReportListItem.java—


    相应每一项的布局。



data






用于操作当前正在编辑的信息的相关数据,比如联系人列表,比如当前对话,比如当前消息。负责管理当前正在编辑的信息和当前所处的对话以及当前信息用到的联系人。这些类都是在编辑信息的时候使用,由于这些多半都是用来管理数据的,而又无法直接做为对象传递给编辑器。所以它们的很多方法都是静态的,也就是这些类都近似单键。


  • WorkingMessage.java—


    用来管理当前正在编辑的消息,它从创建,草稿到发送完成后一直存在,只要打开了编辑信息的页面就会创建一个


    WorkingMessage


    ,直到退出编辑页面。

  • Conversation.java—


    用来管理对话


    Threads


    ,通常用来管理当前的对话,也就是进入的对话和正在进行操作的对话,它也用来管理对话列表,比如查询对话列表。

  • Contact.java—


    用来代表一个联系人的信息,和管理联系人,加载联系人信息,其中还有相应的


    Cache


    。因为一个联系人的数据是比较多的包含名字,名,姓,各种电话号码,各种地址等等。因为


    Mms


    中直接使用


    Contact


    来作为联系人,所有信息都是直接从其中获取。另外,由于信息交互中也会涉及到联系人,因为收发信时可以直接使用一串电话号码,这时就需要有如添加联系人的功能。


    Contact


    中有很多异步的操作,比如加载联系人信息的时候或者更新


    Cache


    的时候都需要异步操作以不阻塞调用者。

  • ContactList.java—


    是一个


    Contact





    List


    列表它继承自


    ArrayList<Contact>


    。用来管理一个


    Contact


    列表,或管理多个


    Contact


    。因为每个信息可以发送给多个联系人,这时就需要用到


    ContactList


    来管理这些收信人。也提供了一些方便存储和传递


    Contact


    的方法,比如把多个


    Contact


    转成


    String


    ,或者转成


    String


    数组等。

  • RecipientIdCache.java—


    用于保存所用到的


    Contact





    Id


    和地址(电话)。每次


    WorkingMessage


    会更新这个


    Cache


    ,然后


    ContactList


    会优先从这个


    Cache


    中查询联络人。



dom






用于解析彩信内容


smil


的工具包



drm






用于处理


DRM


的媒体文件的工具包



layout






为了满足特殊需要而改写的布局元素



model






这里面定义了彩信支持的附件数据结构和附件的组织方式。彩信可包含的内容有图片,视频,音频和文字。这些内容可以单独存在,也可以组合在一起。如果组合在一起就变成了幻灯片。用户可以用幻灯片的方式来创建含有多个媒体的附件,图文并茂的展示。每张幻灯片上面可以加视频,音频,图片和文字,但通常一张幻灯片上面只允许加一个图片或视频,文字是都可以添加的,音频在没有视频的情况下只可以添加的。播放的时候可以设置每张幻灯片的播放时长,以及文字的滚动速度等等。


  • CarrierContentRestriction.java—


    是具体的彩信附件检查站,对于不支持的附件,或者附件大小超出限制,或者图像分辨率不对,或者图像超出尺寸,会抛出异常:


    UnsupportedContentTypeException





    ResolutionException





    ExceedMessageSizeException





    ContentRestrictionException




  • ContentRestriction.java


    是用于检查附件的接口,外部直接使用这相接口,而具体实现是


    CarrierContentRestriction

  • ContentRestrictionFactory.java


    是创建附件检查的工厂方法。外部通过这个工厂来创建一个


    ContentRestriction


    对象,然后使用其中定义的检查方法来进行附件内部检查。

  • SmilHelper.java


    用于解析和处理附件中的


    Smil


    的工具类。

  • IModelChangedObserver.java


    接口,用于监听附件内容有变化。

  • Model.java—


    彩信附件的数据组织方式和管理方式是每一个附件都是一个


    Model


    的子类,它不但用于管理附件的具体数据,比如


    Uri


    ,大小,文件名,位置等,也可以用于在


    GUI


    显示附件和查看附件。

  • LayoutModel.java—


    继承自


    Model


    用于管理可视的附件的布局的类。它用来管理


    RegionModel


    等的基本元素。它就好比


    ViewGroup





    LinearLayout





    RelativeLayout


    等一些布局管理器,用来组织并管理布局基本元素也就是


    RegionModel


    的子类


    ImageModel





    TextModel





    VideoModel




  • RegionModel.java—


    继承自


    Model


    用于管理可视附件和布局,比如图像,视频和文字。特别是在显示可视附件的时候,用于控制可视附件在屏幕中的位置。一个


    RegionModel


    代表着一张幻灯片上的一块区域,它是幻灯片上的布局基本元素。好比


    UI


    元素中的


    View


    ,但多在使用时都是使用它的子类,也就是


    ImageModel





    TextModel





    VideoModel




  • RegionMediaModel.java—


    继承自


    MediaModel


    ,是用于多媒体附件中的可视部分的布局控制,主要用在附件的显示和播放幻灯片时的控制。它的子类是


    ImageModel





    TextModel





    VideoModel




  • MediaModel.java—


    继承自


    Model


    ,代表媒体的数据结构,管理具体的附件数据,同时也用于管理附件的显示控制,比如图像的显示,音频和视频的播放控制等。

  • MediaModelFactory.java—


    用于从一个


    Pdu


    附件中解析出来


    MediaModel


    ,也就是把


    Pdu


    转化为


    Mms


    内部的附件数据。

  • ImageModel.java—


    继承自


    RegionMediaModel


    用于管理图像附件和控制图像附件的显示。

  • VideoModel.java—


    继承自


    RegionMediaModel


    用于管理视频附件和控制视频附件的播放。

  • AudioModel.java—-


    继承自


    MediaModel


    用于管理音频附件和控制音频附件的播放

  • SlideModel.java—-


    继承自


    Model


    用于管理一组附件,这些附件同一次显示给用户。就好像幻灯片的一片一样,每一个


    SlideModel


    里面有一个可以存储


    Model


    的列表,可以包含文字,音频,图像或视频,其上面的附件同时显示出来。

  • SlideshowModel.java—


    继承自


    Model


    ,用于管理一个彩信中的所有附件。其内含有一个存储


    SlideModel


    的列表,用于保存和控制一条彩信中的所有附件。另外它也负责显示这些附件,把一个个


    SlideModel


    组织起来,播放。它也负责着把这些


    Mms


    形式的附件(各种


    Model


    )转化为


    Android


    的附件


    Pdu


    ,和从


    Pdu


    提出各自


    Model


    ,因为


    Slideshow


    是应用程序层的彩信处理方式,而能发送和接收的彩信数据是


    Pdu




  • TextModel.java—


    继承自


    RegionMediaModel


    用于管理文字附件和控制文字附件的显示,比如按时间来滚动



util






这里面是整个


Mms


共享的工具类,其中全部都是单键或是直接使用类,不可以创建对象和以对象方式来使用


  • AddressUtils.java—


    关于地址的工具类,目前只有一个


    getFrom()


    方法,用于获取发信人地址。

  • DraftCache.java—


    用于标识哪些对话


    Thread





    Draft


    ,哪些没有,也就是用于管理和查询对话的草稿状态,有草稿还是没有。它里面维护了一个


    HashSet


    ,里面包含了所有含有草稿的


    Thread Id


    。它里面也有一个


    HashSet


    用于存储


    OnDraftChangedListener


    ,即当


    Thread





    Draft


    状态有变化时,


    DraftCache


    会调用相应的


    Listener


    以告知相应模块,这个对话的草稿状态有所变化。可以通过


    DraftCache.setDraftState(threadId, state)


    来设置某个对话的草稿状态


    ;


    可以通过


    DraftCache.hasDraft(threadId)


    来查询某个对话是否含有草稿。

  • Recycler.java—


    是一个抽象的工具类,里面定义了


    SmsRecycler





    MmsRecycler


    ,用于删除陈旧的消息,或者删除超过信息数量限制的信息。使用方法都是


    Recycler.getSmsRecycler.deleteOldMessages(context)


    或者


    Recycler.getMmsRecycler.deleteOldMessages(context)

  • SmileyParser.java—


    把标点式的表情符号转化为图形的表情,比如把


    J


    用图标笑脸来代替。

  • DownloadManager.java—


    不要被名字骗到,它并不是真正意义上的下载管理器,因为它并不负责任何与下载文件过程或下载文件的管理。它是用于管理与下载相关的配置信息,比如是否是自动下载,以及下载过程的各种通知,比如


    Notification Bar





    Toast


    提示等。

  • RateController.java

  • SendingProgressTokenManager.java



transaction






对于


Mms


来讲是最底层的一个包,用户不可见,它负责发信息的最后处理和收信息的最初处理。主要是负责发送信息和接收信息。它并不是真正的发送和接收信息。是由系统


Frameworks


里面来负责接收和发送信息。这个包只是对于


Mms


应用层来讲是发送和接收。


  • AbstractRetryScheme.java

  • DefaultRetryScheme.java—


    这二个类是实现一种


    Retry


    机制,因为信息的发送与接收会受到环境的限制,比如现在手机没信号,或是网络连接不成功,那么就会把信息放到


    Pending


    队列里面,等一段时间再重新尝试发送与接收。这里的二个类就是为了实现此


    Retry


    机制。

  • HttpUtils.java—


    彩信发送与接收的最底层实现者,它负责用


    HTTP


    协议接收和发送彩信到


    MMSC


    彩信服务中心。

  • MessageSender.java—


    像其名字所预示的那样,它是为了发送信息而封装的一个接口,它里面只有一个方法


    sendMessage()





    UI


    层只需要调用实现了这个接口的类即可发送信息。

  • MessagingNotification.java—


    专门负责在


    Status Bar


    上面做


    Notification


    ,比如新接收到了信息,或是信息发送失败,或是接收失败等。它被


    UI


    层,和底逻辑层共用着。

  • MmsMessageSender.java—


    继承自


    MessageSender


    ,专门用于发送彩信。它并不是做发送的事情,而是做一些错误检查和前期准备工作,然后启动


    TransactionService


    来做发送相关的事情。

  • NotificationTransaction.java—


    继承自


    Transaction


    ,负责接收彩信和更新通知


    (Notification)


    。当有一个新彩信时,


    Frameworks


    会先发出一个短信,称作彩信通知


    (NotificationIndication)


    ,其内含有彩信相关的信息


    (MMSC,


    彩信的


    ContentLocation(URL)





    )


    ,之后是由应用程序自己去


    MMSC





    ContentLocation


    取彩信。这个


    NotificationTransaction


    就是专门用于处理彩信通知的,它会从


    MMSC


    上取出彩信数据(


    Pdu


    ),把它写入数据库中,然后更新


    Notification


    。需要注意的是,只有彩信的设置是自动获取


    (“auto retrieve”)


    时,它才会去下载彩信,否则,它只处理彩信通知


    (Notification Indication)


    ,而不去下载彩信。

  • Observable.java—


    里面定义了观察对象,


    Transaction


    是它的一个子类,其他的实体


    Transaction


    都是观察对象,里面有一个列表保存着观察者的引用,当一个


    Transaction


    完成时,或是有异常时就会调用


    notifyObservers()


    方法来把状态通知给观察者。

  • Observer.java—


    观察者,


    TransactionService


    实现了这个接口。它是所有


    Transaction


    的观察者,以监听他们的状态和处理结果,因为所有的


    Transaction







    是异步的,所以才用观察模式来通知


    Transaction


    的处理结果。

  • PrivilegedSmsReceiver.java—


    继承自


    SmsReceiver


    短信收信的事件监听者,负责监听新短信事件


    android.provider.Telephony.Intents.SMS_RECEIVED_ACTION(“android.provider.Telephony.SMS_RECEIVED”);


    当接收到这个


    Intent


    时表明有一个新短信。它会唤起


    SmsReceiverServier


    来处理短信。

  • ProgressCallbackEntity.java

  • PushReceiver.java—


    一个


    BroadcastReceiver


    专门用于接收彩信事件


    android.provider.Telephony.WAP_PUSH_RECEIVED_ACTION(“android.provider.Telephony.WAP_PUSH_RECEIVED”)


    ,它会先做一些预处理,然后启动


    TransactionService





    TransactionService


    又会创建


    NotificationTransaction


    来处理这个彩信通知。

  • ReadRecTransaction.java

  • RetrieveTransaction.java—


    继承自


    Transaction


    ,用于主动获取彩信数据。当彩信设置为非自动获取时,需要用户触发获取,


    TransactionService


    会创建一个


    RetrieveTransaction


    来获取彩信数据


    (Pdu)


    ,存入数据库,更新


    Notification


    等。

  • RetryScheduler.java

  • SendTransaction.java—


    继承自


    Transaction


    ,用于发送彩信数据。

  • SimFullReceiver.java

  • SmsMessageSender.java—


    发送短信的封装,继承自


    MessageSender


    。它会启动


    SmsReceiverService


    来发送。

  • SmsReceiver.java—


    是一个


    BroadcastReceiver


    ,不要被其名字唬到,它并不负责接收新短信通知,相反,它用于发送信息,接收发送信息请求,并唤起


    SmsReceiverService


    来处理发送。这里可能是


    Android


    命名规则的原因,


    Android


    里的四大组件都喜欢把其组件的名字加上,比如


    ComposeMessageActivity


    ,是一个


    Activity





    TransactionService


    是一个


    Service


    ,而这里


    SmsReceiver


    是一个


    BroadcastReceiver


    ,它与接收短信


    (receiving Sms)


    没有关系。当然了,这完全是一个糟糕的命名。

  • SmsReceiverService.java—


    它是一个


    Service


    ,专门用于处理短信的发送与接收。它是由


    SmsReceiver





    PrivilegedSmsReceiver


    监听事件,然后启动它的,自己并不会监听


    Intent


    事件。

  • SmsRejectedReceiver.java

  • SmsSingleRecipientSender.java—


    继承自


    SmsMessageSender


    ,它针对一个收信人,调用


    Frameworks


    层接口发送信息,对于


    Mms


    应用来说,这是发送短信的最后一站,对就是说对于应用来说,它会把短信发送出去。

  • TransactionBundle.java—Transaction


    所用的一个数据结构,用于给


    Transaction


    传送数据。

  • Transaction.java—


    各种


    Transaction


    的基类,它里面定义了二个方法


    getPdu()





    sendPdu()


    这二个方法是从


    MMSC


    取彩信数据,和向


    MMSC


    发送数据。它是对


    HttpUtils


    的一层包装。

  • TransactionService.java—


    是一个


    Service


    ,接收各种


    Transaction


    请求,然后处理


    Transaction


    。每个


    Transaction







    会开启新的线程异步的处理,所以当处理完成时又会通过


    Observer


    来通知


    TransactionService




  • TransactionSettings.java—


    彩信相关配置信息的数据结构,比如


    MMSC





    Proxy





    Port


    等。请求方可能会提供这些数据,如果提供就使用;否则就会从


    Telephony


    数据库加载默认的数据,这些数据与运营商和


    APN


    的设置有关。

  • TransactionState.java—


    标识每一个


    Transaction


    处理情况的数据结构,很简单,只是标明处理成功还是失败,用于


    Transaction


    回调


    Observer(TransactionService)


    时用。


还有


com/android/mms


根目录下面的一些文件,其中绝大多数是定义的基类异常和一些公共的类。


  • MmsApp.java—Mms Application


    会在应用进程启动的时候做一些必要的初始化工作,比如配置,下载,联系人,对话,


    Smiley


    解析器和通知等。

  • MmsConfig.java—


    管理


    Mms


    的一些常用配置,比如彩信大小上限,彩信图片尺寸上限,收信人的个数上限等等。这些配置信息是保存在在


    res/xml/mms_config.xml


    里面。


    MmsApp


    在初始化时会调用


    MmsConfig.init()


    ,在这里面会调用


    loadMmsSettings


    来解析


    mms_config.xml


    从而得到所需要的配置信息。其他的模块只通过


    MmsConfig


    来访问这些配置信息。

  • LogTag.java—


    有关日志跟踪信息的控制。它可以方便的控制日志输出级别。但是实际上整个


    Mms


    代码中使用这个


    LogTag


    的地方并不多。