簡訊監聽器就是當收到資訊時擷取資訊的內容、時間、寄件者等資訊然後對這些資訊進行處理,可以屏蔽使用者看到該資訊、轉寄或發送到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()用於終止廣播,例如可以判斷電話號碼如果是黑名單或自己不希望的號碼時終止事件傳播,此時由於我們的優先順序是最高的沒停止傳播以後就不會在上面的提示欄中的提示資訊,手機也就接收不到資訊了。