文章目錄
本文主要從以下幾個方面來學習MMS在android系統中的處理:MMS初始化、MMS發送、MMS接收(包括push MMS接收和從MMSC中提取MMS內容)、MMS儲存/刪除等資料操作。
Android MMS基本知識點
一、MMS概述
MMS是在短訊息業務基礎上發展起來的一種訊息業務,它可以用於傳送文字、圖片、動畫、音頻和視頻等多媒體資訊。MMS採用"儲存轉寄"的技術,使用者建立的資訊能夠自動、快速的在手機和手機之間傳送;資訊的傳送仍然按接收方手機號碼進行定位;當接收方關機或暫時不在服務區的情況下,資訊將儲存在多媒體訊息中心(MMSC),直到能夠正確送達為止。MMSMessage Service要求一個WAP網關,一個資料轉送網如電路交換網、GPRS或WCDMA網路,和一個多媒體訊息中心(MMSC)。在目前,MMS業務主要是以WAP作承載,以短訊息作提示通知,由MMS手機自動到多媒體訊息中心(MMSC)去提取來實現的。
在android中,MMS主要的處理都在app層,在framework層中主要涉及MMS pdu包的解析處理和發送和接受MMS時的網路處理。
MMS會使用telephony framework部分的類,詳細資料請參考《Android_telephony_framework》系列文檔。
二、MMS相關Service
1. TransactionService
主要是通過相應的transaction來處理MMS的發送、接收等請求。TransactionService包含一個ServiceHandler handler內部類,用來處理MMS相應事件。
三、MMS相關receiver
1. PushReceiver
接受Intent.WAP_PUSH_RECEIVED_ACTION,啟動TransactionService來傳遞對應的push資料。
2. MmsSystemEventReceiver
接受Mms.Intents.CONTENT_CHANGED_ACTION、TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED和intent.ACTION_BOOT_COMPLETED。
四、MMS相關handler
1. SMSDispatcher
對SMS/MMS上報事件的處理,它有兩個子類:GsmSMSDispatcher和CdmaSMSDispatcher,分別是GSMPhone和CdmaPhone的handler類。
2. WapPushOverSms
WapPushOverSms類雖然沒有繼承自handler類,但它的作用卻實實在在的是一個handler類的作用,是它通過SMSDispatcher的dispatch方法來實現的。該類的作用是把接收到的push PDU包通過intent方式派送到應用模組的receiver處理。
五、MMS相關transaction
1. Transaction
繼承自Observable類,是NotificationTransaction、ReadRecTransaction、RetrieveTransaction和SendTransaction的抽象類別。
2. NotificationTransaction
繼承自Transaction類,並實現Runnable介面。主要處理MMS的notifications (M-Notification.ind)訊息,也就是push多媒體訊息通知訊息。主要功能:
1)根據DownloadManager. mAutoDownload狀態判斷是否需要立即從MMSC中下載MMS內容。
2)發送GET請求給MMSC
3)擷取M-Retrieve.conf資料並解析
4)儲存接收到的MMS到inbox
5)刪除M-Notification.ind資訊
6)發送the M-NotifyResp.ind給MMSC
7)處理完成後通知TransactionService做相應處理。
3.ReadRecTransaction
繼承自Transaction類,並實現Runnable介面。主要處理MMS的read report notifications (M-read-rec.ind)。主要功能:
1)Loads the read report indication from storage (Outbox). 即從mmssms.db中取出read report indication pdu。
2)Packs M-read-rec.ind and sends it.
3)Notifies the TransactionService about succesful completion.
4. RetrieveTransaction
繼承自Transaction類,並實現Runnable介面。主要處理從MMSC中提取MMS(M-Retrieve.conf)。主要功能:
1)Sends a GET request to the MMSC server
2)Retrieves the binary M-Retrieve.conf data and parses it.
3)Persists the retrieve multimedia message.
4)Determines whether an acknowledgement is required.
5)Creates appropriate M-Acknowledge.ind and sends it to MMSC server.
6)Notifies the TransactionService about succesful completion.
5. SendTransaction
繼承自Transaction類,並實現Runnable介面。主要處理髮送MMS到MMSC(M-Send.req)。主要功能:
1)Loads the multimedia message from storage (Outbox).
2)Packs M-Send.req and sends it.
3)Retrieves confirmation data from the server (M-Send.conf).
4)Parses confirmation message and handles it.
5)Moves sent multimedia message from Outbox to Sent.
6)Notifies the TransactionService about successful completion.
六、MMS相關provider
檔案 |
類/介面名 |
超類/實現介面 |
說明 |
TelephonyProvider.java |
TelephonyProvider |
ContentProvider |
APN、Proxy等資訊的存取封裝 |
MmsProvider.java |
MmsProvider |
ContentProvider |
MMS的存取 |
MmsSmsProvider.java |
MmsSmsProvider |
ContentProvider |
提供MMS和SMS統一的讀取,不支援寫操作 |
七、Framework中MMS相關類
包或分類 |
路徑 |
說明 |
com.google.android.mms |
frameworks\base\core\java\com\google\android\mms |
MMS pdu包的通用content type類和MMS的異常處理類 |
com.google.android.mms.pdu |
frameworks\base\core\java\com\google\android\mms\pdu |
mms pdu包的解析處理類 |
com.google.android.mms.util |
frameworks\base\core\java\com\google\android\mms\util |
pdu包的儲存類 |
android.provider |
frameworks\base\core\java\android\provider |
對應的provider所需要的資料封裝類 |
android.net |
frameworks\base\core\java\android\net |
|
android.net.http |
frameworks\base\core\java\android\net\http |
|
com.google.android.mms
檔案 |
類/介面名 |
超類/實現介面 |
說明 |
ContentType.java |
ContentType |
|
定義pdu包內容部分的所支援的元素類型,其中包括所支援的image、audio的類型 |
InvalidHeaderValueException.java |
InvalidHeaderValueException |
MmsException |
對pdu header的異常處理,當header值無效時拋出 |
MmsException.java |
MmsException |
Exception |
MMS異常介面類 |
com.google.android.mms.pdu
檔案 |
類/介面名 |
超類/實現介面 |
說明 |
AcknowledgeInd.java |
AcknowledgeInd |
GenericPdu |
M-Acknowledge.ind PDU,接受者發送給MMSC的確認訊息 |
Base64.java |
Base64 |
|
base64字元的解析處理 |
CharacterSets.java |
CharacterSets |
|
MMS編碼類別型 |
DeliveryInd.java |
DeliveryInd |
GenericPdu |
M-Delivery.Ind Pdu,MMSC發送給寄件者的送達報告 |
MultimediaMessagePdu.java |
MultimediaMessagePdu |
GenericPdu |
Multimedia message PDU,MMS PDU實體類 |
NotificationInd.java |
NotificationInd |
GenericPdu |
M-Notification.ind PDU,MMS push通知訊息PDU |
NotifyRespInd.java |
NotifyRespInd |
GenericPdu |
M-NofifyResp.ind PDU,返回notification response 給MMSC |
SendConf.java |
SendConf |
GenericPdu |
M-Send.conf Pdu ,MMSC返回給寄件者的send confirmation訊息 |
PduBody.java |
PduBody |
|
處理pdu body部分 |
PduComposer.java |
PduComposer |
|
把對應的資料群組成對應的MMS PDU包 |
PduHeaders.java |
PduHeaders |
|
解析MMS pdu header |
PduParser.java |
PduParser |
|
MMS pdu包解析入口類 |
PduPersister.java |
PduPersister |
|
MMS pdu 儲存管理類 |
RetrieveConf.java |
RetrieveConf |
MultimediaMessagePdu |
M-Retrive.conf Pdu |
SendReq.java |
SendReq |
MultimediaMessagePdu |
M-Send.req pdu |
com.google.android.mms.util
檔案 |
類/介面名 |
超類/實現介面 |
說明 |
AbstractCache.java |
AbstractCache |
|
緩衝處理抽象類別 |
PduCache.java |
PduCache |
AbstractCache |
PDU cache |
PduCacheEntry.java |
PduCacheEntry |
|
PDU cache entry |
SqliteWrapper.java |
SqliteWrapper |
|
Sqlite的Wrapper類,提供通過ContentResolver對象對相應的contentprovider類的對象做處理 |
android.provider
檔案 |
類/介面名 |
超類/實現介面 |
說明 |
Telephony.java |
Telephony |
|
提供與SMS/MMS provider需要的資料和操作,包括對應的CONTENT_URI及其他一些資料 |
com.google.android.mms.utilcom.google.android.mms.util
這兩個包下的類主要是用來操作網路方面的。對於這方面,暫時還瞭解不多。
Android MMS基本處理
以下處理過程以GSMPhone為例。
一、MMS初始化
MMS的初始化基本上與SMS一致,只是在phoneApp初始化的過程中註冊一些事件,如EVENT_NEW_SMS和EVENT_NEW_SMS_STATUS_REPORT。在android平台中,MMS初始化的時候並沒有資訊資料的操作,android是以sqlite3作為儲存機制的,與MMS相關的所有資料都儲存在mmssms.db檔案中,此檔案是會長期存在於手機中,不會被刪除。對MMS的操作直接就是對mmssms.db資料庫的操作,所以在初始化部分對MMS資料沒有做相應處理。下面詳細的說明MMS初始化時的類的關係及事件註冊過程:
1. GSMPhone的建構函式中建立GsmSMSDispatcher的執行個體mSMS :mSMS = new GsmSMSDispatcher(this);
2.調用GsmSMSDispatcher建構函式,執行super(phone);由於GsmSMSDispatcher繼承自SMSDispatcher類,實際實行了SMSDispatcher建構函式。
3.在SMSDispatcher的建構函式裡,執行如下語句:
mCm = phone.mCM;//mCm是CommandsInterface介面類的對象
……………
mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
……………
CommandsInterface類的setOnNewSMS方法中會建立Registrant類的執行個體mSMSRegistrant,用來儲存SMSDispatcher handler對象、EVENT_NEW_SMS事件,在有新資訊訊息上報的時候,會通過mSMSRegistrant對象來擷取SMSDispatcher handler對象,並把EVENT_NEW_SMS事件和相應的資料通過訊息機制和handler處理機制發送給SMSDispatcher類的handleMessage方法處理。
二、MMS接收
1. push MMS接收
MMS通知訊息是以簡訊息PDU包的形式傳遞過來的(M-Notification.ind PDU)。Android中的具體處理流程如下:
1)當有新資訊來的時候,atchannel的reader線程會調用onUnsolicited()函數處理。
2)onUnsolicited()函數調用RIL_onUnsolicitedResponse()函數,並傳入RIL_UNSOL_RESPONSE_NEW_SMS值及相應資料。
3)RIL_onUnsolicitedResponse()調用sendResponse()函數,通過socket(socket名:SOCKET_NAME_RIL)向ril.java層傳遞資料。
4)ril java層通過RILReceiver接收器從socket中讀出資料,處理後調用ril類中的processResponse()方法,processResponse()方法調用processUnsolicited()方法。
5)在processUnsolicited()方法中,執行下面語句:
case RIL_UNSOL_RESPONSE_NEW_SMS: {
if (RILJ_LOGD) unsljLog(response);
String a[] = new String[2];
a[1] = (String)ret;
SmsMessage sms;
sms = SmsMessage.newFromCMT(a); //根據SMS協議解析PDU包
if (mSMSRegistrant != null) {
mSMSRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));
}
break;
其中mSMSRegistrant執行個體是在初始化的時候建立的,其中儲存著SMSDispatcher handler對象和EVENT_NEW_SMS事件資訊。隨後通過message訊息機制和handler處理機制把EVENT_NEW_SMS事件傳遞到了SMSDispatcher handler類 處理。
6)SMSDispatcher handler接收到EVENT_NEW_SMS事件,調用handleMessage()方法處理,handleMessage()方法調用其子類dispatchMessage()方法。
7)在dispatchMessage()中,根據smsHeader.portAddrs(PORT_WAP_PUSH = 2948)地址來判斷是否是PUSH資訊。
8)調用WapPushOverSms類的dispatchWapPdu()方法。
9)使用WspTypeDecoder類執行個體來對PUSH資訊進行解析,並根據content type來判斷是否是MMS PUSH資訊。
10)調用dispatchWapPdu_MMS()方法,通過SMSDispatcher類的dispatch()方法來廣播發送intent. WAP_PUSH_RECEIVED_ACTION。
11)PushReceiver接收到該intent,啟動ReceivePushTas並執行doInBackground()方法。
12)在doInBackground()方法中,通過PduParser類對象解析對應的PDU包,然後執行如下代碼:
case MESSAGE_TYPE_NOTIFICATION_IND: {
NotificationInd nInd = (NotificationInd) pdu;
if (!isDuplicateNotification(mContext, nInd)) {
Uri uri = p.persist(pdu, Inbox.CONTENT_URI); //MMS PUSH資訊儲存在inbox.
Intent svc = new Intent(mContext, TransactionService.class);//intent啟動的是TransactionService。
svc.putExtra(TransactionBundle.URI, uri.toString());
svc.putExtra(TransactionBundle.TRANSACTION_TYPE,
Transaction.NOTIFICATION_TRANSACTION);//transaction類型:NOTIFICATION_TRANSACTION
mContext.startService(svc);//啟動TransactionService服務
}
13)TransactionService類中的onStart()調用launchTransaction()方法
14)launchTransaction()方法傳遞給ServiceHandler EVENT_TRANSACTION_REQUEST事件。
15)ServiceHandler類的handleMessage()方法處理EVENT_TRANSACTION_REQUEST事件,根據Transaction的類型為NOTIFICATION_TRANSACTION,建立NotificationTransaction類執行個體,並根據URI從mmssms.db中取出PDU包。
16)調用processTransaction(transaction)方法,在processTransaction()方法中,執行如下代碼:
int connectivityResult = beginMmsConnectivity();//通過beginMmsConnectivity函數進行data connection。
if (connectivityResult == Phone.APN_REQUEST_STARTED) { //如果返回APN_REQUEST_STARTED結果,表示data connection正在串連,等待返回EVENT_DATA_STATE_CHANGED事件
mPending.add(transaction);//把transaction放入等待隊列中
return true; //返回,等待EVENT_DATA_STATE_CHANGED事件再繼續處理
}
transaction.attach(TransactionService.this); //因為Transaction 類和TransactionService 類都繼承自Observable類,此處是為了Transaction類的子類在處理完成後通知TransactionService相應的處理結果。
transaction.process(); //進入NotificationTransaction類中處理,建立一個新的線程來處理該transaction。
17)下面的處理請參照MMS相關transaction中的NotificationTransaction說明。
2. 從MMSC中提取MMS
根據DownloadManager類中的mAutoDownload變數的值,從MMSC中提取MMS有兩種情況:
1)如果mAutoDownload為TRUE,即允許自動提取,那麼在indication通知上來的時候,就會從MMSC向提取MMS資訊。即使在NotificationTransaction中所做的處理。具體請參照MMS相關transaction中的NotificationTransaction說明
2)否則,就需要手動去從MMSC中提取。具體處理如下:此時UI層會啟動TransactionService,並傳入Transaction.RETRIEVE_TRANSACTION類型。其他的處理流程參考第一條(push MMS接收)中的第13到第17步,只不過相應的transaction是RetrieveTransaction,而非NotificationTransaction。
三、MMS發送
MMS的發送動作是由UI來觸發的,主要是有ComposeMessageActivity類中的sendMmsWorker()方法來處理。具體處理流程如下:
1. sendMmsWorker()方法中,建立MmsMessageSender類執行個體sender,並調用MmsMessageSender類中的sendMessage()方法。
2.從mmssms.db中取出對應的PDU資料,把資訊移到outbox中(以前是儲存在draft下),然後啟動TransactionService服務進行transaction處理。
3.通過TransactionService處理進入了SendTransaction類的run()方法中處理。詳細處理請參照MMS相關transaction中的SendTransaction說明
四、MMS儲存/刪除等資料操作
MMS資訊的儲存是以SQLite3為基礎的,而且其mmssms.db資料庫在第一次建立後會一直存在,這就對MMS的儲存處理變得簡單很多,只需要執行相應的SQL語句就行。
MMS中的內容部分是儲存在file中的,並沒有放在mmssms.db資料庫中,資料庫中存放的是如下幾張表:
static final String TABLE_PDU = "pdu";//PDU相關資訊的表
static final String TABLE_ADDR = "addr";//MMS寄件者/收件者地址相關的表
static final String TABLE_PART = "part"; //body可能分成幾個部分,儲存part相關資訊的表,通過該part資訊,就可以從file中取到對應的內容部分
static final String TABLE_RATE = "rate"; // SENT_TIME資訊表
static final String TABLE_DRM = "drm";
上面的幾張表只是儲存了一些相關資訊,通過它們可以取到相應的MMS的基本資料,並能從檔案中讀取到對應的MMS body。
對MMS儲存機制的理解主要就是對content provider機制的理解,content provider機制中主要涉及到以下類:
檔案 |
類/介面名 |
超類/實現介面 |
說明 |
SQLiteDatabase.java |
SQLiteDatabase |
SQLiteClosable |
SQLLite資料庫實作類別 |
SQLiteOpenHelper.java |
SQLiteOpenHelper |
|
管理資料庫create、open、close、get,upgrade和版本資訊的輔助類 |
ContentProvider.java |
ContentProvider |
|
實現不同應用對資料庫的訪問 |
ContentResolver.java |
ContentResolver |
|
ContentProvider的封裝類,向application提供統一的提供者,ContentProvider會根據URI來取得對應的ContentProvider對象 |
SqliteWrapper.java |
SqliteWrapper |
|
向application提供的ContentResolver類的封裝類 |
MMS對應的資料庫類:見MMS相關provider及Telephony、MmsSmsDatabaseHelper
五 MMS參數設定
MMS的參數設定也是通過SQLite3資料庫進行操作的,其content provider類:TelephonyProvider,其DatabaseHelper類是其內部類。TelephonyProvider對應的CONTENT_URI在Telephony 類的Carriers內部類中。
MMS參數的設定主要在setting模組操作。