短信監聽器就是當收到信息時獲取信息的內容、時間、發件人等信息然后對這些信息進行處理,可以屏蔽用戶看到該信息、轉發或發送到Web進行處理。Exciting function。。
我們看一下它的實現原理。
其實短信接收是通過Android系統中的廣播接收者來實現的,當系統收到短信時,會發出一個廣播Intent,Intent的action名稱為android.provider.Telephony.SMS_RECEIVED,該Intent存放了系統接受到的短信內容,我們可以使用名稱"pdus"即可從Intent中獲取到短信內容。
廣播可以分為普通廣播和有序廣播。普通廣播是完全異步的,可以在同一時刻(邏輯上)被所有接受者接收到,相對於有序廣播消息傳遞的效率比較高,但缺點是:接受者不能將出黎結果傳遞給下一個接受者,並且無法終止廣播Intent的傳播;有序廣播是按照接受者聲明的優先級別,被接受者依次接受廣播。優先級別在<intent-filter>的android:priority屬性中聲明,數值越大優先級別越高,取值范圍為-1000到1000,優先級別也可以調用IntentFilter對象的setPriority()進行設置。有序廣播的接受者可以終止Intent的傳播,廣播Intent的傳播一旦終止,后面的接受者就無法接收到廣播。另外,有序廣播的接受者可以將數據傳遞給下一個廣播。例如A得到廣播后,可以往它的結果對象中存入數據,當廣播傳給B時,B可以從A的結果對象中得到A存入的數據。
Context.sendBroadcast()
發送的是普通廣播,所有訂閱者都有機會獲得並進行處理。
Context.sendOrderedBroadcast()
發送的是有序廣播,系統會根據接受者聲明的優先級別按順序逐個執行接受者,前面的接受者有權終止廣播(BroadcastReceiver.abortBroadcast()),如果廣播被前面的接受者終止,后面的接受者就再也無法獲取到廣播。對於有序廣播,前面的接受者可以將數據通過setResultExtras(Bundle)方法存放進結果對象,然后傳給下一個接受者,下一個接受者通過代碼:Bundle bundle = getResultExtras(true)可以獲取上一個接受者存入在結果對象中的數據。
系統收到短信,發出的廣播屬於有序廣播。如果想阻止用戶收到短信,可以通過設置優先級,讓自定義的接受者先獲取到廣播,然后終止廣播,這樣用戶就接受不到短信了。
下面我們通過實例來講解如何實現這個功能:
首先在配置清單中加入以下權限:
1 <uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信權限 --> 2 <!-- 訪問internet權限 --> 3 <uses-permission android:name="android.permission.INTERNET"/>
在application中加入我們處理接收信息的receive以及設置其優先級,和Activity不一樣,我們加入的是receiver節點,表示廣播接受者:
1 <receiver android:name=".SMSBroadcastReceiver"> 2 <intent-filter android:priority="1000"> <!-- 設置優先級為最高 --> 3 <action android:name="android.provider.Telephony.SMS_RECEIVED"/> 4 </intent-filter> 5 </receiver>
在上面我們建立的SMSBroadcastReceiver不是Activity的子類,而是繼承自BroadcastReceiver。由於我們是監聽器,因此建立項目的時候不要選中Create Activity,不需要創建Activity:
核心代碼很簡單,只需要在當接收到信息時的onReceiver函數體內獲取內容並且對內容進行處理即可:
1 public class SMSBroadcastReceiver extends BroadcastReceiver { 2 3 /* (non-Javadoc) 4 * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent) 5 * 當接收到到信息時執行此方法 6 */ 7 @Override 8 public void onReceive(Context context, Intent intent) { 9 //從Intent中接受信息 10 Object[] pdus = (Object[]) intent.getExtras().get("pdus"); 11 for(Object p : pdus){ 12 byte[] sms = (byte[]) p; 13 SmsMessage message = SmsMessage.createFromPdu(sms); 14 15 //獲取短信內容 16 String content = message.getMessageBody(); 17 18 //獲取發送時間 19 Date date =new Date(message.getTimestampMillis()); 20 21 //獲取發件人號碼 22 String number = message.getOriginatingAddress(); 23
//處理數據...
24 //終止廣播 25 //abortBroadcast(); 26 } 27 } 28 29 }
上面我們只是獲取到了數據,數據處理可以使用之前博客中進行短信轉發或放到WebService中處理。
在最后一行代碼abortBroadcast()用於終止廣播,例如可以判斷電話號碼如果是黑名單或自己不希望的號碼時終止事件傳播,此時由於我們的優先級是最高的沒停止傳播以后就不會在上面的提示欄中的提示信息,手機也就接收不到信息了。