為ComposeMessageActivity中confirmSendMessageIfNeeded部分的資訊發送流程。主要以接收者有效性的確認為主,然後轉向sendMessage方法進行發送。
ComposeMessageActivity.sendMessage
從可以看出,在這個方法中,主要做的事是確認手機狀態的有效性。最終調用WorkingMessage的send方法進行資訊的發送。
WorkingMessage.send
從可以看出,在本方法中,對於不同類型的訊息,分別調用不同的方法對其進行處理。並對多媒體訊息進行一些簡要的預先處理。
簡訊部分:
WorkingMessage.preSendSmsWorker
如所示,這是簡訊部分的發送流程。本方法中所涉及到的東西就比較多了。由於已經轉到了新線程中利用WorkingMessage進行訊息的發送,那麼原來ComposeMessage中的那個WorkingMessage就可以更新了。然後確認一下所屬的會話是否存在,如果不存在就建立一個。
接著,將接收者序列化,調用sendSmsWorker。建立一個SmsMessageSender,將訊息存入發送隊列中(type欄位設為6)。通知SmsReceiver發送。
SmsReceiver則調用SmsReceiverService發送隊列中的第一條簡訊。
在發送之前,還要根據手機卡的不同,將簡訊內容分成若干塊,保證每塊的大小不超過該卡的限制。在分段後的最後一條簡訊的sentIntent中,設定EXTRA_MESSAGE_SENT_SEND_NEXT為true。這樣當簡訊發送成功後,會調用SmsReceiverService的handleSmsSent方法,發送隊列中的第一條。
然後,對每塊都指定一個sentIntent,當發送出去之後,修改其狀態。若需要報告,還會指定一個deliveryIntent,用於訊息報告的處理。這兩個Intent都會被封裝到SmsTracker中,當發送成功後,在SMSDispatcher的handleSendComplete中被取出。sentIntent會被立即執行,將訊息狀態轉為已發送。而deliveryIntent則會被加入deliveryPendingList,等收到訊息報告後才被執行(具體代碼在不同的dispatcher中)。
發送完畢後,還要對簡訊上限、訊息顯示列表、草稿進行相應的處理。
SmsReceiverService.handleSmsSent 訊息發送後的處理
當sentIntent被執行後,會根據不同的結果更新訊息的所處信箱。
MessageStatusReceiver 訊息報告
當需要接收報告時,會在報告收到之後,在SMSDispatcher中根據不同類型手機從deliveryPendingList中取出並執行相應的deliveryIntent。
SmsReceiverService.handleSmsReceived 接收簡訊
當RILReceiver有訊息收到時,會從RIL向上傳遞,經由SMSDispatcher的dispatchPdus方法產生Intent調用PrivilegedSmsReceiver。
多媒體訊息部分:
WorkingMessage.sendMmsWorker
從可以看出,多媒體訊息發送的過程和簡訊過程有些類似。都需要重設WorkingMessage,擷取實際ThreadId。發送完都要刪除多餘的資訊,調用ComposeMessageActivity的onMessageSent。只是多媒體訊息沒另外建立一個類似preSendSmsWorker的方法,而是把所有內容都放在sendMmsWorker中處理。同時,刪除草稿的位置也有所不同。
TransactionService.onStartCommand
多媒體訊息的發送與簡訊不同,是以網路的方式發送的。
每次調用的時候,先取出所有due_time在目前時間之前的待發送的多媒體訊息。然後將它的Uri和transactionType封裝到TransactionBundle中,傳給ServiceHandler。類型設為EVENT_TRANSACTION_REQUEST。在ServiceHandler中建立一個SendTransaction對象。然後調用processTransaction方法,根據當前Transaction是否已在隊列中,以及當前的串連狀態確定該把這個SendTransaction對象放到哪個隊列中(mPending為待發送,mProcessing為發送中)。同時使用sendMessageDelayed方法發送一個標記為EVENT_CONTINUE_MMS_CONNECTIVITY的message來保持串連。
接著,將TransactionService放入該Transaction對象的觀察者列表,以便於在後面成功發送後,繼續發送待發送的多媒體訊息。
接下來,使用SendTransaction的Run方法從資料庫中擷取指定多媒體訊息,並構造SendReq,經由HttpUtils發送編碼後的多媒體訊息。根據發送結果,選擇是將錯誤狀態存入資料庫,還是將該多媒體訊息轉到已發送箱並通知TransactionService處理待發送的多媒體訊息。
TransactionService.update
該方法執行後,先將Transaction從mProcessing列表中移除。若mPending不空,說明有多媒體訊息處於已基本處理但未發送狀態,故調用mServiceHandler,設定EVENT_HANDLE_NEXT_PENDING_TRANSACTION進行處理。從mPending隊列中取出第一個,交由processTransaction處理。由於在之前說過,調用processTransaction的Transaction都會被加入mProcessing隊列,而這個Transaction發送成功後,由會再次通知其觀察者,進而調用TransactionService的update方法繼續發送mPending隊列中的資訊。故mPending隊列中的多媒體訊息會自動按順序發完。
然後對於成功發送的訊息,使用Notification通知使用者(包括訊息未讀,訊息報告等)。並發送android.intent.action.TRANSACTION_COMPLETED_ACTION的廣播(目前該廣播無人接收,應該是為了支援應用開發人員而提供的一種廣播)。
PushReceiver
android的多媒體訊息接收應用程式層部分從PushReceiver開始。當onReceive被調用後,讓螢幕亮5秒,然後建立一個ReceivePushTask並使用它的execute方法。ReceivePushTask是一個AsyncTask,實現了doInBackground方法。當傳入intent後,會在doInBackground中將其中的資料轉成GenericPdu,並根據其訊息類型做出不同的操作。
如果是發送報告或已讀報告,將其存入資料庫。
如果是多媒體訊息通知,若已存在,則不處理。否則將其存入資料庫。啟動TransactionService進行處理。
TransactionService中的處理主要是調用mServiceHandler,大體過程與發送多媒體訊息時相同,只是此處建立的是NotificationTransaction。
如果不支援自動下載或資料轉送沒開啟,僅通知mmsc。否則,下載相應多媒體訊息,刪除多媒體訊息通知,通知mmsc,刪除超過容量限制的多媒體訊息,通知TransactionService處理其餘待發送的多媒體訊息。
作者 haliluya4