從軟體的功能角度來講,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---Factory 方法。
- 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是建立附件檢查的Factory 方法。外部通過這個工廠來建立一個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---把標點式的Emoji轉化為圖形的表情,比如把用表徵圖笑臉來代替。
- 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的地方並不多。