Composing and editing
MMS在Android Mms應用裏面的具體實現形式,或數據結構是SlideshowModel,它是一個每一個節點爲SlideModel的ArrayList,SlideModel是一個Model的List,也就是它能夠接收任何Model的子類,Audio,Video,Image和Text均可以放到SlideModel上面。SlideModel主要用於管理其上面的各個媒體,好比它們的佈局,它們的播放控制,而SlideshowModel主要用於管理全部的附件,好比把全部的附件轉化成爲Android的MMS協議的數據類型Pdu,以及從Pdu轉化成爲SlideshowModel。
Pdu是實現了MMS協議的標準格式,它能夠直接的發送給MMSC,從MMSC取回來的也是一個Pdu格式的數據。應用層Mms不須要關心Pdu的具體實現方式,Android中有一個內部的包com.google.android.mms.*下面的類都是專門用於處理Android平臺上的MMS。裏面提供了工做能夠把應用層的數據,好比媒體文件等,進行包裝成Pdu,再把Pdu分解成爲媒體文件。Pdu的數據結構包括PduBody,這個是用於存放多媒體文件的地方,其裏面是PduPart的集合,每一個PduPart表明一個文件。PduPersister用於操做這些數據結構,包括寫入數據庫,從數據庫中讀取等。
SlideshowModel或俗稱幻燈片是應用層的MMS的實現形式,或者它是應用層MMS用來建立,編輯,顯示和管理多媒體的一個數據結構。建立和發送MMS的時候,就是建立一個SlideshowModel,構建MediaModel,TextModel等加入到SlideshowModel中。在發送時,SlideshowModel會把其內的媒體文件取出來,轉化爲PduPart放入PduBody中。收到信息後從PduBody中取出PduPart,還原成媒體文件,生成MediaModel,加入到SlideshowModel中,也就是還原爲幻燈片。應用拿到幻燈片後能夠作顯示和播放。
附件類型
關於附件類型,Mms應用中全部的MMS都有一個幻燈片,其內含有全部的附件文件。可是Mms作了一些特殊的處理,對於一個MMS信息,它的附件類型分爲IMAGE, AUDIO, VIDEO,和SLIDESHOW,這些從添加附件對話框的列表中能夠看出,並且展示方式也有所不一樣。可是實際的實現上面並無這麼多的類型,只有一個SlideshowModel,全部的附件都在裏面。它處理的規則是這樣的,若是隻添加了一個媒體(image, audio和video)時,會把類型設置爲相應的媒體類型,而只有在附件對話框中明確選擇添加幻燈片時而且添加了多張幻燈片後,附件類型纔會是幻燈片。這個附件類型只在給MMS添加附件時和發送MMS前有效,主要用於在消息列表中如何展現媒體文件,若是是具體媒體類型,就直接顯示,不然顯示爲幻燈片,這個附件類型僅存在於應用中顯示媒體所用,並不會在發送出去的Pdu中有痕跡。當收到MMS後,也是根據轉化後的SlideshowModel裏面的內容來推測出附件類型,而後再作顯示。因此,對於一個MMS來講它始終都有一個SlideshowModel,用戶所感覺到的附件類型僅是附件媒體顯示上面的一個處理而已。
建立和編輯MMS
與傳統手機不一樣,建立MMS並不須要特殊的方式。由於Mms應用對MMS和SMS並不作嚴格的區分,而是以統一的對話中的一個消息來對待,因此MMS與SMS的區別也很簡單,就看一個消息中只否有附件(WorkingMessage.hasAttachment())。建立MMS也十分簡單,只需點擊Composer而的Attach菜單添加媒體便可。在列表中選擇image, audio和video後就只有一個媒體文件,都會跑到其餘的Activity去選擇文件,而後會返回其Uri給Composer,Composer會調用WorkingMessage.setAttachment()來作具體的添加,用Uri建立MediaModel而後加入到SlideshowModel中,並設置類型。另外,若是選擇了Attach幻燈片,就會直接進入編輯幻燈片的而面,能夠添加刪除幻燈片頁,給幻燈片頁加媒體文件,設置佈局等,以後Composer會把SlideshowModel顯示出來,此時的附件類型也是SLIDESHOW,這些都是經過WorkingMessage.load()來完成的。
WorkingMessage在把媒體加到幻燈片裏之後,就會回調一個接口 onAttachmentChanged(),Composer實現了此接口,這個接口主要用於通知Composer附件已發生變化,刷新UI以正確顯示附件。Composer會建立AttachmentEditor來顯示附件的內容,由於全部的附件都放在Slideshow裏面這個Slideshow在WorkingMessage中,能夠經過WorkingMessage.getSlideshow()來獲取。AttachmentEditor會根據Slideshow裏面的內容來建立不一樣的View以展現不一樣的附件,若是Slideshow中只有一個Video,Audio或Image,就直接建立VideoAttachmentView,AudioAttachmentView或ImageAttachmentView,而對於幻燈片中頁數大於1時就會建立SlideshowAttachmentView。還有相應的按扭能夠用來編輯,替換或刪除,對於單個媒體有查看/播放,選擇後能夠查看原圖和播放音頻視頻,替換能夠從新重選擇一個附件,刪除會移除掉附件;對於Slideshow有編輯和刪除,編輯會直接進入幻燈片的編輯頁面,那裏能夠一頁一頁的對每頁幻燈片進行詳細的編輯,刪除會移除掉附件。
編輯完附件後有三種處理方式,一個是發送信息,一個是保存爲草稿另外一個就是放棄信息。發送信息和保存草稿都會對幻燈片進行打包,轉成Pdu,並保存到數據庫,以後的幻燈片都須要從數據庫加載並把Pdu解包成爲SlidehshowModel。
Packaging and unpackaging MMS
要發送信息前,或是保存草稿時,都須要把SlideshowModel進行打包生成Pdu格式,並保存至數據庫。這個稱爲MMS的打包(Packaging),是由SlideshowModel.makePduBody()方法來完成,它會把幻燈片裏面的內容一個一個的取出來,轉成一個PduPart,再 放入PduBody中,以生成PduBody,一個媒體對應一個PduPart,同時還能夠設置PduPart的屬性以描述媒體的文件,好比ContentType,這是一個用於標識媒體MIME類型的字串;Filename文件的名字; ContentLocation文件的路徑。這些信息都用於描述PduPart中數據的元信息(MetaData),也就是數據具體是什麼,以便讓解包的時候對數據進行正確的處理。
以後PduPersister會經過其persist()方法把PduBody存入到數據庫中,它會把PduPart中的描述性信息做數據庫字段寫入,把文件存儲在TelephonyProvider文件夾下面(/data/data/android.providers.telephony/app_parts),並把存儲後的路徑做爲_data字段寫入數據庫,這樣一條MMS的數據就都寫入了數據庫中。這之後,MMS的數據都是從數據庫中加載,因此原SlideshowModel中的數據庫再也不有效,如Uri在原SlideshowModel中可能指向一個文件,或是其餘數據庫,在PduPersister.persist()以後就再也不有效了。
當PduPersister.persist()以後,MMS的附件就都從數據中加載,PduPersister.load()會從數據庫把數據加載成爲一個PduBody,SlideshowModel的方法createFromPduBody()就是用於把PduBody轉化成爲一個SlideshowModel,從PduPart取出媒體信息以獲得正確的媒體格式,和相關信息,能夠經過Uri來獲取具體文件(流)。
接收到的MMS過程也差很少當NotificationTransaction或RetrieveTransaction用HttpUtils從MMSC獲取到MMS數據後會用PduParser來解析數據生成Pdu,再用PduPersister.persist()把其寫入數據庫,以後會再從數據庫中加載。 html
SMIL語言支持
對於每條MMS還有一個很重要的數據就是SMIL語言,SMIL是同步多媒體集成語言的簡稱(Synchronized Multimedia Integration Language),它與HTML文檔很相似,是W3C(World Wide Web Consortium)組織規定的多媒體操縱標準語言。MMS也是用它來管理和播放多媒體。來看一個具體的SMIL語言實例:
- <smil xmlns="http://www.w3.org/2000/SMIL20/CR/Language">
- <head>
- <layout>
- <root-layout width="360" height="615"/>
- <region id="Image" width="347" height="260" top="14" left="7" fit="meet"/>
- <region id="Text" width="326" height="320" top="281" left="7" fit="scroll"/>
- </layout>
- </head>
- <body>
- <par dur="60s">
- <img src="0.jpg" region="Image"/>
- <text src ="0.txt" region="Text"/>
- </par>
- <par dur="60s">
- <text src ="1.txt" region="Text"/>
- </par>
- <par dur="60s">
- <text src ="2.txt" region="Text"/>
- </par>
- <par dur="60s">
- <text src ="3.txt" region="Text"/>
- </par>
- <par dur="60s">
- <text src ="4.txt" region="Text"/>
- </par>
- </body>
- </smil>
SMIL語言播放多媒體時一般是一頁頁的,與幻爲播放十分相似,由於不少SMIL播放器都會作成幻燈片形式。由於MMS用SMIL來傳送多媒體,因此Mms終端應用都會以幻燈片的方式來播放MMS。這也就是爲何Mms應用中會出來SlideshowModel的緣由。幻燈片方式顯示彩信是一種經常使用的方法,即便某些終端應用沒有用幻燈片放映的方式顯示彩信,可是對於運營商或彩信平臺發出來彩信都有頁碼標識,另外其餘的一些手機,好比非智能手機查看彩信的方式也是以幻燈片一頁一頁的放映。
它主要記載着用於幻燈片的佈局信息。這個SMIL語言就是用於幻燈片佈局的,也就是說SMIL會像HTML文檔佈局網頁那樣來講明如何佈局幻燈片,它有這些TAG:head, layout, body, par,head是頭信息,裏面有TAG layout用來講明這個幻燈片是如何佈局的,具體的它用一些子TAG如root-layout, region等來講明幻燈片中的每個元素如Image或Text如何佈局。TAG body中列出了幻燈片的全部媒體元素和詳細內容,好比image, audio, text等,每一par是一頁,它的子TAG說明這一頁有哪些內容,固然SMIL語言還有不少內容能夠參考Wikipedia上的講解。
當打包幻燈片時,也就是把SlideshowModel轉化爲Pdu時,會根據SlideshowModel的內容生成一個SMIL語言,經過SmilHelper.getDocument()來生成SMIL文檔,把其加入到PduBody中並做爲第一個PduPart,它的ContentType(MIME)是application/smil,它的內容就是SMIL文檔。須要注意的是SMIL文檔老是會在PduBody的第一個Part,而且它直接把文檔內容寫到PduPart中,而不是以文件的形式存在。
當解包的時候,會先取出SMIL文檔,對其進行解析,生成幻燈片。
由於SMIL是一個標準的文檔,因此W3C有其相應的規範,也有相應的庫來解析和生成。在Mms應用中能夠看到這樣的二個Package: org.w3c.dom.*和com.
Android
.mms.dom.*;其中org.w3c.dom是SMIL語言的一些標準庫,而com.android.mms.dom.*;是對org.w3c.dom一些標準接口的實現,或者說是爲了Mms應用而作的一些適配。那麼在com.android.mms.model.*裏面的一些類也是根據SMIL標準而寫的,好比SmilHelper就是專門用於解析SMIL文檔和生成SMIL文檔,固然它會用到前面提到的二個Package裏面的東西。還有如ImageModel,TextModel和RegionModel也都是基於SMIL標準的,好比它們分別 對應SMIL文檔中的標籤img, text和region。
固然,這都是具體的終端應用的實現,可能不一樣的應用會有不一樣的方式,但發送出去的和接收到的都應該是標準的Pdu,而SMIL文檔僅是一個其中一個PduPart而已。