前言
上一篇博客,講了BroadcastReceiver的一些基礎內容,如何注冊以及發送一個廣播,那是基礎,不清楚的可以先看看:Android--BroadcastReceiver。但是在實際開發當中,大部分情況下是不需要自己發布一個Broadcast或者接收自己定義的Broadcast的,一般而言,都是攔截系統在做某個操作而發布的Broadcast,對其進行相應的處理。這篇博客就以兩個示例來講講Android系統中,如何攔截系統Broadcast並對其進行處理。
系統中的廣播
在Android系統中,內置了很多Action產量,在觸發這些Action的時候,均會發布相應的Broadcast。一般而言,查看Android的API文檔中,關於Intent的說明即可找到對應Action的Broadcast,但是列舉的還不是很全,最好還是下載Android的源代碼,通過查看源代碼的方式查看需要攔截的Broadcast。
下面列舉一些常用的廣播:
- android.intent.action.TIME_SET:系統時間被修改。
- android.intent.action.DATE_CHANGED:系統日期被修改。
- android.intent.action.BOOT_COMPLETED:系統啟動完成。
- android.intent.action.BATTERY_CHANGED:設備電量改變。
- android.intent.action.BATTERY_LOW:設備電量低。
- android.intent.action.ACTION_POWER_CONNECTED:設備連接電源。
- android.intent.action.ACTION_POWER_DISCONNECTED:設備斷開電源。
- android.provider.Telephony.SMS_RECEIVED:系統收到短信。
- android.intent.action.NEW_OUTGOING_CALL:撥打電話。
下面通過兩個例子,來講解如何在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撥號的示例,在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>
效果展示:


總結
Android系統中內置了非常多的Broadcast,用於對系統事件的響應、攔截、操作,這里只是介紹了兩個比較典型的例子。在實際開發中,可以根據需要,查找Android源代碼中相應的應用中的代碼找到需要的Broadcast,以及如何處理的例子,這里就不一一介紹了。

