本文主要從如下幾個方面來學習MMS在android系統中的處理:MMS初始化、MMS發送、MMS接收(包括push MMS接收和從MMSC中提取MMS內容)、MMS存儲/刪除等數據操做。 java
Android MMS基本知識點 android
1、MMS概述 sql
MMS是在短消息業務基礎上發展起來的一種消息業務,它能夠用於傳送文字、圖片、動畫、音頻和視頻等多媒體信息。MMS採用"存儲轉發"的技術,用戶建立的信息可以自動、快速的在手機和手機之間傳送;信息的傳送仍然按接收方手機號碼進行定位;當接收方關機或暫時不在服務區的狀況下,信息將存儲在多媒體消息中心(MMSC),直到可以正確送達爲止。MMS消息服務要求一個WAP網關,一個數據傳輸網如電路交換網、GPRS或WCDMA網絡,和一個多媒體消息中心(MMSC)。在目前,MMS業務主要是以WAP做承載,以短消息做提示通知,由MMS手機自動到多媒體消息中心(MMSC)去提取來實現的。 數據庫
在android中,MMS主要的處理都在app層,在framework層中主要涉及MMS pdu包的解析處理和發送和接受MMS時的網絡處理。 緩存
MMS會使用telephony framework部分的類,詳細信息請參考《Android_telephony_framework》系列文檔。 網絡
2、MMS相關Service
1. TransactionService
主要是經過相應的transaction來處理MMS的發送、接收等請求。TransactionService包含一個ServiceHandler handler內部類,用來處理MMS相應事件。 app
3、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。 socket
4、MMS相關handler
1. SMSDispatcher
對SMS/MMS上報事件的處理,它有兩個子類:GsmSMSDispatcher和CdmaSMSDispatcher,分別是GSMPhone和CdmaPhone的handler類。
2. WapPushOverSms
WapPushOverSms類雖然沒有繼承自handler類,但它的做用卻實實在在的是一個handler類的做用,是它經過SMSDispatcher的dispatch方法來實現的。該類的做用是把接收到的push PDU包經過intent方式派送到應用模塊的receiver處理。 ide
5、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. 函數
6、MMS相關provider
文件 |
類/接口名 |
超類/實現接口 |
說明 |
TelephonyProvider.java |
TelephonyProvider |
ContentProvider |
APN、Proxy等信息的存取封裝 |
MmsProvider.java |
MmsProvider |
ContentProvider |
MMS的存取 |
MmsSmsProvider.java |
MmsSmsProvider |
ContentProvider |
提供MMS和SMS統一的讀取,不支持寫操做 |
7、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 |
|
文件 |
類/接口名 |
超類/實現接口 |
說明 |
ContentType.java |
ContentType |
|
定義pdu包內容部分的所支持的元素類型,其中包括所支持的image、audio的類型 |
InvalidHeaderValueException.java |
InvalidHeaderValueException |
MmsException |
對pdu header的異常處理,當header值無效時拋出 |
MmsException.java |
MmsException |
Exception |
MMS異常接口類 |
文件 |
類/接口名 |
超類/實現接口 |
說明 |
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 |
文件 |
類/接口名 |
超類/實現接口 |
說明 |
AbstractCache.java |
AbstractCache |
|
緩存處理抽象類 |
PduCache.java |
PduCache |
AbstractCache |
PDU cache |
PduCacheEntry.java |
PduCacheEntry |
|
PDU cache entry |
SqliteWrapper.java |
SqliteWrapper |
|
Sqlite的Wrapper類,提供經過ContentResolver對象對相應的contentprovider類的對象作處理 |
文件 |
類/接口名 |
超類/實現接口 |
說明 |
Telephony.java |
Telephony |
|
提供與SMS/MMS provider須要的數據和操做,包括對應的CONTENT_URI及其餘一些數據 |
這兩個包下的類主要是用來操做網絡方面的。對於這方面,暫時還了解很少。
如下處理過程以GSMPhone爲例。
1、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方法處理。
2、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。
3、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說明
4、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參數設置