Android Mms之:簡訊發送流程(圖文詳解)_Android

來源:互聯網
上載者:User

資訊的發送,對於Mms應用程式來講主要就是在資訊資料庫中建立並維護一條資訊記錄,真正的發送過程交由底層(Frameworks層)函數來處理。

總體的來講,當資訊建立完成後,對於資訊通常有三個去處,一個是放棄這個資訊,也就是使用者不想要此資訊,一旦選擇,資訊將不會被儲存;第二個去處就是儲存為草稿;最後一個去處就是發送此資訊。

當點擊了發送後,UI層暫不會有變化,UI層要監聽負責發送的各個類的回調資訊和資料庫的變化資訊來更新UI。資訊發送的第一站是WorkingMessage,它會先處理一下資訊的相關內容,比如重新整理收信人(Sync Recipients)以保證都是合法收信人,把附件(Slideshow)轉成可發送的多媒體訊息附件Pdu(SendReq),makeSendReq。然後針對,不同的資訊類型(簡訊,多媒體訊息)調用不同的處理類來處理。處理的流程也比較類似,都是先把訊息放到一個隊列中,然後啟動相應的Service來處理。Service會維護資訊隊列,然後處理每個資訊。簡訊是由Frameworks中的SmsManager發送出去,而多媒體訊息是通過Http協議發送。

簡訊發送
在WorkingMessage拿到一個要發送的訊息後,做了簡單處理(重新整理收信人),然後就會對簡訊和多媒體訊息彩取不同的處理流程。對於簡訊,WorkingMessage除了重新整理連絡人外,不會再做其他的事情,它會建立SmsMessageSender並調用其sendMessage()方法來發送資訊,相關的參數收信人地址(是以分號分隔的一串字元),資訊內容和所在對話的ID(thread id)在構造SmsMessageSender對象是傳入的,構造完成後,直接調用其sendMessage()方法即可,接下來SmsMessageSender會處理所有的事情。

在交由SmsMessageSender處理之前,WorkingMessage會回調UI一次,以讓UI重新整理收信人編輯框和資訊文本輸入框。

SmsMessageSender的主要任務就是,把資訊進行按收信人拆分,也就是說,簡訊是要給每個收信人都發一封,雖然你可能只編輯一個簡訊,但是當收信人不只一個時,就變成了多條簡訊,就要發出多條簡訊,要給每一個收信人都發一封簡訊。因此,SmsMessageSender的第一個任務就是分析收信人地址,得到收信人的個數,然後把資訊按每個收信人都放入待發送的隊列中。這樣就得到了一個簡訊發送隊列,簡訊的數目就是收信人的個數。事實上,SmsMessageSender的工作僅此而已,當把資訊都放入發送隊列後也就是寫進資料庫,然後資訊的狀態是正在發送中,它會發送Intent喚起SmsReceiverService來處理隊列,它的工作就完成了,sendMessage()也就此返回。SmsMessageSender的sendMessage()返回後,WorkingMessage會再次回調UI的介面,因為此時簡訊已被寫入資料庫,所以UI會重新整理資訊列表,顯示剛剛的簡訊,這時的狀態應該是正在發送中,因為是從待發送隊列中拿到的。從這以後,發送流程的類不會再直接與UI進行通訊,發送服務SmsReceiverService等會直接更新資料庫中簡訊的狀態,而UI會監聽資料庫的變化,一旦資訊資料發生變化,UI就會重新整理列表中的訊息,更新狀態,比如將發送中變成已發送,或是標明發送失敗等,而這些狀態都是發送服務在更新。

SmsReceiverService,不要被其名字虎住,它並不只負責接收資訊,它是簡訊(SMS)處理的Service,負責簡訊的發送和接收,在得到傳送簡訊息指令(ACTION_SEND_MESSAGE)後會從隊列中讀出第一個簡訊,然後建立SmsSingleRecipientSender對象,傳入收信人地址,訊息內容,所屬的threadid和簡訊的Uri,並調用其sendMessage()發送這個簡訊。

SmsSingleRecipientSender會調用SmsManager的方法divideMessage()來把簡訊分成適合發送的幾個部分,因為可能資訊過長,不能一次發送完成,所以就需要分成幾部分來分次發送。同時會把訊息移動到Outbox。然後會針對分割的每一部分都會建立二個PendingIntent,這二個PendingIntent都是給底層用的,一個用於當簡訊被發送出去時廣播出來,另一個是在簡訊已被收信人接收到時廣播出來。所以二個廣播的作用是,一個可用於標識簡訊已發送,另一個則可以作為送達的通知。最後調用SmsManager.sendMultipartTextMessage交由底層來傳送簡訊。

SmsReceiverService並不是自己去監聽SEND_MESSAGE_ACTION和MESSAGE_SENT_ACTION的,而是由SmsReceiver來監聽這二個廣播事件,然後通過StartService再把這二個事件傳送給SmsReceiverService進行處理。

資訊已發送廣播和資訊已送達廣播分別由SmsReceiverService監聽和MessageStatusReceiver。它們收到廣播後,會從Intent中取得詳細的發送和送達狀態,然後更新資料庫中資訊的狀態(status),UI當探索資料庫變化後,就會更新UI。

至此,一個簡訊發送完成。

多媒體訊息發送
多媒體訊息發送流程與簡訊不完全一致,WorkingMessage重新整理收信人,產生多媒體訊息的可發送的Pdu—SendReq,接著會把多媒體訊息寫入資料庫,把要發送的SendReq也會寫入資料庫,後面會再從資料庫中讀取出SendReq,並標識為草稿;然後會構建MmsMessageSender,傳入收信人和多媒體訊息的Uri,讓其發送。這期間也會回調UI一次,以初始化收信人編輯框和資訊編輯框。

MmsMessageSender先從資料庫中讀出多媒體訊息發送的Pdu—SendReq,Google的內建包com.google.android.mms.*;裡面封裝了所有操作Pdu的方法,包括把Pdu寫入資料庫(PduPersister.persist()),從資料庫中讀取產生Pdu(PduPersister.load())。然後根據當前多媒體訊息的配置和其他資訊對SendReq進行更新,比如設定Expiration,Priority,Date和Size等,把多媒體訊息移到Outbox,然後啟動TransactionService來處理多媒體訊息。sendMessage()就此返回。WorkingMessage會再次回調UI的介面,因為此時多媒體訊息已被在資料庫中,所以UI會重新整理資訊列表,顯示剛剛的多媒體訊息,這時的狀態應該是正在發送中。

TransactionService,與簡訊的SmsReceiverService類似,是負責處理多媒體訊息的服務,可以發送,接收等。對於TransactionService來講,所有的需要處理的流程,無論是發送還是接收,都是一個Transaction。它內部有二個隊列,一個是當前正在處理(processing)的Transaction,一個是待處理(pending)的Transaction。它維護這二個隊列,並檢查網路的串連,開啟多媒體訊息網路連接,準備和檢查環境,然後從待處理的隊列中取出第一個,放入正在處理的隊列中,並處理這個Transaction,也就是調用Transaction.process()。

發送多媒體訊息是一個SendTransaction,它的process()方法負責發送多媒體訊息,它會建立一個獨立的線程來做,因此不會阻塞TransactionService,處理服務就可以再處理其他的Transaction。它會先從資料庫中取出多媒體訊息Pdu,M-Send.req,(SendReq),更新一些欄位,比如date,然後調用其父類Transaction.java中的方法sendPdu來把SendReq發送出去,sendPdu()會返回傳送的結果(send confirmation)。Transaction.sendPdu()會先設定好網路,然後直接調用HttpUtils中的httpConnection()方法,用HTTP把多媒體訊息發送出去,同時取得返回訊息(Response)給SendTransaction。SendTransaction會檢查發送結果,返回結果(Send Confirmation),分析狀態並更新至資料庫(比如發送失敗或發送成功)。UI會監聽到狀態變化,並更新資訊列表。

到此,一個多媒體訊息發送完成。

前面有提到過TransactionSettings,它是對於一個處理流程的相關配置資訊,裡面含有MMSC(Multimedia Message Service Center),Proxy和ProxyPort。這些資訊,特別對於發送和接收來說是十分重要的。因為對於手機的資訊,並不是手機直接把資訊發送到接收人的手機上,而是直接發給服務中心,後面就是由服務中心再把資訊發送給對應的接收人的手機上。對於多媒體訊息也是這樣,HttpUtils通過HTTP協議把多媒體訊息發送給MMSC,它是一個URL地址,之後對於發送方來講,多媒體訊息就發送完了,多媒體訊息服務中心(MMSC)會處理接下來的發送過程,服務中心是與手機運營相關的,它由電訊廠商來提供。對於Mms發送多媒體訊息,是不會特意指定TransactionSettings的,也就是說它不會指定MMSC和Proxy,那麼TransactionService就會用系統預設的MMSC,Proxy作為TranscationSetting,MMSC,Proxy和ProxyPort需要從Telephony資料庫中查詢出來,它們是與具體手機的APN設定和具體的電訊廠商相關。所以,這裡如果想要改變多媒體訊息的配置資訊,只能更改APN系統設定來完成。

而簡訊的發送就不涉及SMSC(簡訊服務中心),因為Frameworks中的工具已經封裝好了SmsManager提供了幾個傳送簡訊的方法,可能它會去處理SMSC相關的東西。



總結,可以看出資料庫在資訊的發送過程中扮演了重要的角色,當資訊離開編輯器後就馬上寫入了資料庫,發送過程中的各個類都是先從資料庫中載入資訊,然後做相應處理,然後寫回資料庫或是更新狀態,然後再交由下一個流程來處理。而所謂的Pending Message Queue其實沒有相應的資料結構,它們都是資料庫中的資訊且狀態是待發送而已。所以資訊離開編輯器後就被寫入了資料庫,只不過狀態一直在改變,從發送中到已發送,或發送失敗,或如果Telephony服務不可用會仍處在待發送,但對於UI頁面來講可能沒有那麼多狀態,它可能只顯示發送中,已發送和發送失敗。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.