zoukankan      html  css  js  c++  java
  • Android--拦截系统BroadcastReceiver

    前言

      上一篇博客,讲了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并对其进行处理。

    1. 通过关键字拦截短信
    2. IP拨号

    通过关键字拦截短信

      从上面列举的一些动作会发布的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("发件人:
    ");
    42                         sb.append(message.getOriginatingAddress());
    43                         sb.append("
    发送时间:
    ");
    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("
    短信内容:
    ");
    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>

      效果展示:

      源码下载

    总结

      Android系统中内置了非常多的Broadcast,用于对系统事件的响应、拦截、操作,这里只是介绍了两个比较典型的例子。在实际开发中,可以根据需要,查找Android源代码中相应的应用中的代码找到需要的Broadcast,以及如何处理的例子,这里就不一一介绍了。

  • 相关阅读:
    【leetcode】1295. Find Numbers with Even Number of Digits
    【leetcode】427. Construct Quad Tree
    【leetcode】1240. Tiling a Rectangle with the Fewest Squares
    【leetcode】1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold
    【leetcode】1291. Sequential Digits
    【leetcode】1290. Convert Binary Number in a Linked List to Integer
    【leetcode】1269. Number of Ways to Stay in the Same Place After Some Steps
    【leetcode】1289. Minimum Falling Path Sum II
    【leetcode】1288. Remove Covered Intervals
    【leetcode】1287. Element Appearing More Than 25% In Sorted Array
  • 原文地址:https://www.cnblogs.com/plokmju/p/android_SystemBroadcastReceriver.html
Copyright © 2011-2022 走看看