先說下Android上短信接收的流程,直接從RILJ開始講。processUnsolicited方法接收到新短信消息後,BaseCommands中注冊的事件會通過消息機制執行。
RILJ中執行的是如下代碼:mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));所以我們只要看看哪些地方注冊了mGsmSmsRegistrant就可以找到,處理接收到新短信的地方。只有GsmSMSDispatcher調用了setOnNewGsmSms()進行注冊。由於GsmSMSDispatcher隱式繼承了handler類,所以我們只要看他的handlermessage方法和其父類handlermessage方法就行。當然我們也可以直接搜索注冊的事件:EVENT_NEW_SMS,在哪些地方進行處理,這樣也能找到處理收到新短信的方法。我們找到SMSDispatcher的handleMessage方法。一層層找下去,方法調用順序如下:dispatchMessage()-> dispatchNormalMessage()-> dispatchPdus()-> dispatchPdus()。到最後發送了一條有序廣播結束,方法如下:sendOrderedBroadcast()。
上面一段基本講解了framework側接收短信的流程,以及最終通過廣播的方式通知應用側。現在開始說說為什麼這裡發送的是sendOrderedBroadcast而不是我們android剛入門時候介紹的那種,這兩個有什麼不同。
聲明這個方法的時候,代碼裡面有說道:這個廣播一次只給一個接收者發送消息。所有的接收者按照次序來接收廣播,前面的甚至可以傳遞某些數據給後面的接收者。前面的接收者甚至可以直接丟棄這個廣播,這也將導致後面的接收者再也接收不到廣播了。總結了下:這種有序廣播就是同步的,必須得前面一個接收者處理完才能給後面的接收者。普通的廣播就是異步的。這種廣播的接收者有先後順序,也就是說接收者有優先級之分。我們平時使用廣播需要記住這兩種廣播才夠用。
再說說優先級的設定,看看配置文件裡面的intent-filter,原來它還有一個android:priority="integer"的屬性。查看說明可以發現這個就是設定注冊者優先級的,並且其強調了這只對同步消息有效,對異步消息無效。其取值范圍是-1000---1000,必須是整數一般默認值是0。原生短信中並沒有定義這個屬性,所以默認值是0。現在有很多應用可以攔截騷擾短信,猜想這些應用注冊時候優先級應該設置成了最高,並且檢查到是垃圾短信之後就不繼續往下傳。
補充一個:優先級不同的時候按照優先級的大小進行排序,如果兩個receiver的優先級一樣怎麼辦呢?android官方說明有著相同優先級的receiver,其接收到廣播的順序是隨機的。
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11