android 資訊(mms)的故事(五)-- 發彩信
發彩信和發簡訊一樣,在ComposeMessageActivity.java介面都是從onclick()、sendMessage()開始,同樣的傳送前檢查收件人是否有效,和簡訊不一樣的是發彩信的時候郵件地址也是可以做為收件人的,接下來也是WorkingMessage.java的send()方法。
-
if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) {
-
// uaProfUrl setting in mms_config.xml must be present to send an MMS.
-
// However, SMS service will still work in the absence of a uaProfUrl address.
-
if (MmsConfig.getUaProfUrl() == null) { //UA user-agent是一定要有的,UA通常包括了手機廠商、硬體、軟體、系統和瀏覽器等資訊
-
//這個程式碼是4.0才有的,如果UA為空,可以傳送成功,但接收方無法收到。
-
String err = "WorkingMessage.send MMS sending failure. mms_config.xml is " +
-
"missing uaProfUrl setting. uaProfUrl is required for MMS service, " +
-
"but can be absent for SMS.";
-
RuntimeException ex = new ContentRestrictionException(err);
-
Log.e(TAG, err, ex);
-
// now, let's just crash.
-
throw ex;
-
}...........省略了部分程式碼.......................
-
// Do the dirty work of sending the message off of the main UI thread.
-
new Thread(new Runnable() {
-
public void run() {
-
final SendReq sendReq = makeSendReq(conv, subject);
-
slideshow.prepareForSend();
-
sendMmsWorker(conv, mmsUri, persister, slideshow, sendReq);
-
updateSendStats(conv);
-
}
-
}).start();
-
}
上面的程式碼只是準備,sendMmsWorker()是接下來的傳送入口,看下這個函式裡面有什麼吧,同樣省略了不是很重要的程式碼。
-
private void sendMmsWorker(Conversation conv, Uri mmsUri, PduPersister persister,
-
SlideshowModel slideshow, SendReq sendReq) {
-
...省略部分程式碼.....................
-
if (mmsUri == null) {
-
// Create a new MMS message if one hasn't been made yet.
-
mmsUri = createDraftMmsMessage(persister, sendReq, slideshow);
-
} else {
-
// Otherwise, sync the MMS message in progress to disk.
-
updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq);
-
}
-
...省略部分程式碼.....................
-
MessageSender sender = new MmsMessageSender(mActivity, mmsUri,
-
slideshow.getCurrentMessageSize());
-
try {
-
if (!sender.sendMessage(threadId)) {
-
// The message was sent through SMS protocol, we should
-
// delete the copy which was previously saved in MMS drafts.
-
SqliteWrapper.delete(mActivity, mContentResolver, mmsUri, null, null);
-
}
-
// Make sure this thread isn't over the limits in message count
-
Recycler.getMmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId);
-
} catch (Exception e) {
-
Log.e(TAG, "Failed to send message: " + mmsUri + ", threadId=" + threadId, e);
-
}
主要就是貼出來的這兩部分。createDraftMmsMessage()這個方法會把slideshow物件裡的幻燈片資訊轉化成PduPart的位元組陣列,也就是把彩信裡的媒體檔案(圖片、音訊、視訊和其它型別的檔案 )編碼,具體過程可以看SlideShowModel.java類的makePduBody(),至於為什麼寫那些欄位,就要看OMA的相關文件了,比如這個 WAP-209-MMSEncapsulation-20020105-a.pdf文件。再往下是TransactionService.java的事了。
TransactionService.java這個類我認為可以算彩信的關鍵程式碼了,這裡涉及網路狀態的判斷,beginMmsConnectivity()/endMmsConnectivity()對應彩信網路的開啟和關閉,彩信的傳送、接收(自動下載和手動下載)都在這裡判斷並轉給對應的sendTransaction.java、NotificationTransaction.java和RetriveTransaction.java的處理,把這個類裡面的log全開,你可以得到很多有用的資訊,試試就知道了。既然是傳送流程,我們關注sendTransaction.java這個類好了, 執行緒傳送是必須的,sendTransaction.java實現Runnable介面,那麼真正的傳送在run()方法裡面了,看下面給出的程式碼,其它的都是輔助功能,有用但不是最關鍵的。
byte[] response = sendPdu(SendingProgressTokenManager.get(tokenKey),new PduComposer(mContext, sendReq).make());
接下會跑到Transaction.java類的這個方法裡 ,到這裡彩信在資訊應用的路算是走完了,可以看到彩信是通過http協議來傳輸資料的。
-
protected byte[] sendPdu(long token, byte[] pdu,
-
String mmscUrl) throws IOException, MmsException {
-
if (pdu == null) {
-
throw new MmsException();
-
}
-
ensureRouteToHost(mmscUrl, mTransactionSettings);
-
return HttpUtils.httpConnection(
-
mContext, token,
-
mmscUrl,
-
pdu, HttpUtils.HTTP_POST_METHOD,
-
mTransactionSettings.isProxySet(),
-
mTransactionSettings.getProxyAddress(),
-
mTransactionSettings.getProxyPort());
-
}
傳送的流程大致就這些,當然彩信裡面細節知識還有很多,這裡只是個大概的流程,希望對剛接觸andorid mms的同學有所幫助 ,最後給出一個簡訊彩信完整的傳送流程圖,前面簡訊傳送那篇說好有個圖,一起放這裡了。