系統中的廣播
在Android系統中,內置了很多Action產量,在觸發這些Action的時候,均會發布相應的Broadcast。一般而言,查看Android的API文檔中,關於Intent的說明即可找到對應Action的Broadcast,但是列舉的還不是很全,最好還是下載Android的源代碼,通過查看源代碼的方式查看需要攔截的Broadcast。
下面列舉一些常用的廣播:
下面通過兩個例子,來講解如何在Android下,攔截系統Broadcast並對其進行處理。
通過關鍵字攔截短信
從上面列舉的一些動作會發布的Broadcast,可以找到,當系統接收到一條短信的時候,會發布一個“android.provider.Telephony.SMS_RECEIVED”的Broadcast,之前已經介紹過了,一般系統Broadcast都是有序廣播,如果不被高優先級的BroadcastReceiver停止傳遞,會按照優先級順序傳遞下去。
而在這個示例中,通過監聽接收短信的廣播,當其內容有黑名單中的關鍵字的話,則阻止Broadcast繼續傳播,並使用Toast提示,否則正常提示短信信息。
通過上一篇博客了解到,onReceive方法的Intent參數包含了這條廣播傳遞的參數,對於短信信息而言,需要獲取key為"pdus"的數組,取出數組中每一項,它的每一項代表了一個byte[]格式的短信,需要使用SmsMessage類解析短信內容。
當然,攔截短信的Broadcast侵犯了隱私,需要注冊接收短信的權限:
1 <uses-permission android:name="android.permission.RECEIVE_SMS"/>
下面直接展示源代碼了,關鍵注釋已經寫的很清楚了,這裡不再累述:
MessageBroadcast.java:
1 package cn.bgxt.Broadcastdemo.MessageWarn;
2
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5 import android.content.BroadcastReceiver;
6 import android.content.Context;
7 import android.content.Intent;
8 import android.os.Bundle;
9 import android.telephony.SmsMessage;
10 import android.widget.Toast;
11
12 public class MessageBroadcast extends BroadcastReceiver {
13 // 在模擬器上,通過DDMS發送短信會產生亂碼,所以使用拼音代替
14 //在真機上不存在亂碼的問題
15 private final String[] blackKeyWord = new String[] { "baoxian", "chuxiao",
16 "jiangjia" };
17
18 @Override
19 public void onReceive(Context context, Intent intent) {
20 // 判斷當前接收到的Broadcast是否是收到短信的action
21 if (intent.getAction()
22 .equals("android.provider.Telephony.SMS_RECEIVED")) {
23 StringBuilder sb = new StringBuilder();
24 // 獲取Broadcast傳遞的數據
25 Bundle bundle = intent.getExtras();
26 if (bundle != null) {
27 Object[] pdus = (Object[]) bundle.get("pdus");
28 for (Object p : pdus) {
29 byte[] pud = (byte[]) p;
30 // 聲明一個SmsMessage,用於解析短信的byte[]數組
31 SmsMessage message = SmsMessage.createFromPdu(pud);
32 boolean flag = false;
33 for (String str : blackKeyWord) {
34 if (message.getMessageBody().contains(str) ) {
35 // 發現黑名單關鍵字,則標記為true
36 flag = true;
37 break;
38 }
39 }
40 if (flag) {
41 sb.append("發件人:n");
42 sb.append(message.getOriginatingAddress());
43 sb.append("n發送時間:n");
44 Date date = new Date(message.getTimestampMillis());
45 SimpleDateFormat format = new SimpleDateFormat(
46 "yyyy-MM-dd HH:mm:ss");
47 sb.append(format.format(date));
48 sb.append("n短信內容:n");
49 sb.append(message.getMessageBody());
50
51 Toast.makeText(context, sb.toString(),
52 Toast.LENGTH_SHORT).show();
53 // 如果存在黑名單關鍵字內容,停止Broadcast傳播
54 abortBroadcast();
55 }
56
57 }
58 }
59 }
60
61 }
62
63 }
在AndroidManifest.xml中配置Receiver。
1 <receiver android:name="cn.bgxt.Broadcastdemo.MessageWarn.MessageBroadcast"> 2 <!-- 設置優先級,短信優先級為0,大於0即可 --> 3 <intent-filter android:priority="200"> 4 <action android:name="android.provider.Telephony.SMS_RECEIVED"/> 5 </intent-filter> 6 </receiver>
效果展示,先發送一個包含黑名單中關鍵字的短信,再發送一個正常的短信。
IP撥號
再來看看IP撥號的示例,在Android中,如果觸發撥打電話的Action,則會發布一個"android.intent.action.NEW_OUTGOING_CALL"的Broadcast出來,只需要針對它進行攔截即可,然後在加上IP前綴,把處理過的號碼添加到數據傳遞給下一個Receiver。
處理接收撥打電話的Broadcast,需要對Android增加權限:
1 <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
下面直接上代碼了,注釋寫的很清楚,這裡不再累述了。
IpCallPhone.java:
1 package cn.bgxt.Broadcastdemo.IpCall;
2
3 import android.content.BroadcastReceiver;
4 import android.content.Context;
5 import android.content.Intent;
6
7 public class IpCallPhone extends BroadcastReceiver {
8 private final String STARTS="17951";
9 @Override
10 public void onReceive(Context context, Intent intent) {
11 // 獲取當前撥號的號碼
12 String number=getResultData();
13 // 此號碼沒有被加IP撥號的前綴
14 if(!number.startsWith(STARTS)){
15 // 設置加了IP號碼的號碼
16 String newnumber=STARTS+number;
17 // 把新號碼增加到返回結果數據中,用於傳遞給後面的Receiver
18 setResultData(newnumber);
19 }
20 }
21 }
AndroidManifest.xml配置Receiver:
1 <receiver android:name="cn.bgxt.Broadcastdemo.IpCall.IpCallPhone"> 2 <intent-filter android:priority="200"> 3 <action android:name="android.intent.action.NEW_OUTGOING_CALL"/> 4 </intent-filter> 5 </receiver>
效果展示: