a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 系統 > Android > 正文

Android Mms之:短信發送流程(圖文詳解)

2020-04-11 12:21:58
字體:
來源:轉載
供稿:網友

信息的發送,對于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頁面來講可能沒有那么多狀態,它可能只顯示發送中,已發送和發送失敗。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 国产拍拍视频 | 欧美综合影院 | 国产片一区二区 | 在线看成人片 | 日本黄色大片免费 | 视频一区 国产精品 | 国产欧美一区二区精品性色 | 亚洲一区二区在线 | 婷婷伊人| 免费看一区二区三区 | 精品国产一区二区三区久久久蜜月 | 成人做爰www免费看视频网站 | 成人影院一区二区三区 | 国产免费拔擦拔擦8x高清 | 在线视频成人 | 激情欧美日韩一区二区 | 久久9热 | 福利视频一区 | 日摸夜操 | 日日操人人 | 岛国视频在线 | 精品日本一区二区 | 国产美女黄色片 | 欧美综合国产精品久久丁香 | 中文字幕三级在线看午夜 | 久久久久久久一区 | 色婷婷影院 | 在线91| 北条麻妃99精品青青久久 | av一区二区三区四区 | 日韩中文字幕视频在线观看 | 亚洲伦理一区 | 国产精品成人3p一区二区三区 | 久久蜜桃 | 欧美日在线 | 欧美亚洲日本国产 | 久久亚洲天堂 | 国产一区二区影院 | 国产日本在线视频 | 久久这里只有精品首页 | 国产第一二区 |