1. 程式人生 > >簡訊傳送流程

簡訊傳送流程

簡訊是手機通訊模組的重要組成部分,本次主要簡單談談簡訊的傳送流程,讓大家對簡訊模組有個簡單的瞭解。
資訊的傳送,對於Mms應用程式來講主要就是在資訊資料庫中建立並維護一條資訊記錄,真正的傳送過程交由底層(Frameworks層)函式來處理。
當資訊建立完成後,對於資訊通常有三個選擇,一個是放棄這個資訊;第二個就是儲存為草稿;最後一個就是傳送此資訊

1、簡訊在應用層的傳送
ComposeMessageActivity.java是會話介面,當點擊發送按鈕之後,簡訊的傳送就開始了。在會話介面,簡訊主要是通過呼叫sendMessage()方法來進行傳送出去的,在呼叫這一方法之前,簡訊還會呼叫confirmSendMessageIfNeeded()方法來判斷簡訊收件人中是否含有非法的收件人。
ComposeMessageActivity.confirmSendMessageIfNeeded()
在這裡插入圖片描述


ComposeMessageActivity
簡訊在呼叫confirmSendMessageIfNeeded()方法來判斷簡訊收件人中是否含有非法的收件人之後,就直接進入sendMessage()方法來進行傳送簡訊。 在sendMessage()方法中,還要判斷簡訊內容是否需為彩信以及手機是否處於緊急撥號的模式。若是簡訊內容為彩信,則需要進行彩信的傳送。若是處於緊急撥號模式,就會回撥介面彈出提示資訊(目前很多專案在緊急模式的情況下會對傳送鍵置灰,使簡訊無法傳送)。

在這裡插入圖片描述
在這裡插入圖片描述
WorkingMessage.java
在WorkingMessage.java中,拿到一個要傳送的訊息後,重新整理收信人,判斷資訊型別,然後就會對簡訊和彩信彩取不同的處理流程。對於簡訊,WorkingMessage除了重新整理聯絡人外,不會再做其他的事情,它會建立SmsMessageSender並呼叫其sendMessage()方法來發送資訊。在構造SmsMessageSender物件是傳入相關的引數收信人地址(是以分號分隔的一串字元),資訊內容和所在對話的ID(threadId) 。構造完成後,直接呼叫其sendMessage()方法即可,接下來SmsMessageSender會處理所有的事情。在交由SmsMessageSender處理之前,WorkingMessage會回撥UI一次,以讓UI重新整理收信人編輯框和資訊文字輸入框。
在WorkingNessage.send方法主要為區分簡訊彩信的傳送,簡訊傳送時就呼叫preSendSmsWorker()方法進行。
在這裡插入圖片描述


在這裡插入圖片描述
SmsMessageSender.java
SmsMessageSender.java主要工作為:
1、獲取傳送報告設定的狀態;
2、將訊息按照收件人拆開成多條訊息,並加入訊息佇列;
3、傳送廣播通知SmsReceiverService來發送簡訊。
在這裡插入圖片描述
SmsReceiverService.java
SmsMessageSender發出的廣播是由SmsReceiver來接收,當SmsReceiver接收到廣播之後,就會啟動服務SmsReceiverService。 SmsReceiverService是簡訊(SMS)處理的Service,負責簡訊的傳送和接收,在得到傳送簡訊息指令(ACTION_SEND_MESSAGE)後會從訊息佇列中讀出第一個簡訊,然後建立SmsSingleRecipientSender物件,傳入收信人地址,訊息內容,所屬的threadid和簡訊的Uri,並呼叫其sendMessage()傳送這個簡訊。
SmsReceiverService.java
在這裡插入圖片描述

在以上程式碼中,當得到傳送簡訊的指令後,handleSendMessage ()會對簡訊的傳送情況進行判斷,如果沒有簡訊正在傳送,就會呼叫sendFirstQueuedMessage()方法,查詢佇列中的資訊,並取出佇列中的第一條訊息後進行傳送。它傳送的只是單個聯絡人的資訊,具體的實現為呼叫SmsSingleRecipientSender.sendMessage()的方法。
SmsReceiverService.java
在這裡插入圖片描述
SmsSingleRecipientSender.java
SmsSingleRecipientSender會呼叫SmsManager的方法divideMessage()來把簡訊分成適合傳送的幾個部分,因為可能資訊過長,不能一次傳送完成,所以就需要分成幾部分來分次傳送。同時會把訊息移動到發件箱。然後會針對分割的每一部分都會建立兩個PendingIntent,這兩個PendingIntent都是給底層用的,一個用於當簡訊被髮送出去時廣播出來,另一個是在簡訊已被收信人接收到時廣播出來。所以兩個廣播的作用是,一個可用於標識簡訊已傳送,另一個則可以作為送達的通知。最後呼叫SmsManager.sendMultipartTextMessage交由底層來發送簡訊。

應用層
資訊已傳送廣播由SmsReceiverService監聽,但是資訊已送到收件人手上的廣播則是由MessageStatusReceiver監聽的。他們收到廣播之後,會從Intent中取得詳細的傳送和送達狀態,然後更新資料庫中資訊的狀態(status),UI當發現數據庫變化後,就會更新UI。
簡訊在底層(frameworks)的傳送

2、簡訊在底層(frameworks)的傳送
Frameworks層
在frameworks層,SmsManager會根據傳送的簡訊的情況分為長簡訊和非長簡訊兩種情況進行處理。
在這裡插入圖片描述

在android系統中,內建了CDMA和GSM兩種模式來進行簡訊的傳送處理
在這裡插入圖片描述
對於GSM,直接呼叫handleStatusReport方法處理,從傳入的AsyncResult物件中獲取SmsMessage進而獲取SmsTracker的索引,從deliveryPendingList中取出SmsTracker,傳送deliveryIntent併發送訊息確認。
對於CDMA,在handleMessage中轉到EVENT_NEW_SMS,呼叫dispatchMessage進行訊息的分發。
在這裡插入圖片描述
由於RIL.java是中間層和rild守護程序通訊的一個入口,從這可以將對應的操作在rild中去完成
在這裡插入圖片描述
到此為止RIL.java已經將傳送操作傳遞給守護程序rild,那剩下的操作就由守護程序和貓這端來完成了。
經過這些步驟已經能夠將簡訊傳送出去了。