天天看點

Android Mms 源碼結構

   注:本文轉自 開源中國——http://www.oschina.net/question/54100_36978

【廈門】 12月22日(周六下午)OSC 源創會 我要報名»

從軟體的功能角度來講,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---把标點式的表情符号轉化為圖形的表情,比如把用圖示笑臉來代替。

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來處理短信。 www.2cto.com

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的地方并不多。