Bootstrap

Android——动态注册广播

BroadcastReceiver

发送一条广播,可以被不同的广播接收者所接收,广播接收者收到广播后再进行逻辑判断。

标准广播

通过 new BroadcastReceiver() 创建广播
通过 registerReceiver() 注册广播
通过 sendBroadcast() 发送广播
通过 unregisterReceiver() 注销广播

    @Override
    protected void onStart() {
        super.onStart();
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent != null && intent.getAction().equals(BroadStandardActivity.BROAD_ACTION_COME)) {
                    btn_send.setText("来了");
                }
            }
        };
        // 创建一个意图过滤器,只处理 BROAD_ACTION_COME 的广播
        IntentFilter filter = new IntentFilter(BroadStandardActivity.BROAD_ACTION_COME);
        //注册接收器
        registerReceiver(receiver, filter);
    }
发送标准广播
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(BroadStandardActivity.BROAD_ACTION_COME);
        sendBroadcast(intent);
    }

案例代码

有序广播

  • 一个广播存在多个接收器,这些接收器需要排队收听广播,这意味着该广播是条有序广播。
  • 先收到广播的接收器A,既可让其他接收器继续收听广播,也可中断广播不让其他接收器收听。

通过 sendOrderedBroadcast() 发送广播
通过 setPriority()设置优先级,数字越大,优先级越高

    @Override
    protected void onStart() {
        super.onStart();
        /*
        * 多个接收器处理有序广播的规则:
        * 1、优先级越大的接收器,越早收到有序广播
        * 2、优先级相同的时候,越早注册的接收器越早收到有序广播
        * */

        /*
        * 创建接收器A
        * */
        receiverA = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent != null && intent.getAction().equals(ORDER_ACTION)) {
                    btn_send_order.setText("来了A");
                }
            }
        };
        IntentFilter filterA = new IntentFilter(ORDER_ACTION);
        filterA.setPriority(8);
        registerReceiver(receiverA, filterA);


        /*
         * 创建接收器B
         * */
        receiverB = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent != null && intent.getAction().equals(ORDER_ACTION)) {
                    btn_send_order.setText("来了");
                    abortBroadcast();// 中断广播,此时后面的接收器无法收到该广播
                }
            }
        };

        IntentFilter filterB = new IntentFilter(ORDER_ACTION);
        filterB.setPriority(10);
        registerReceiver(receiverB, filterB);

    }

abortBroadcast():中断广播,让其它广播接收者无法收到该广播
clearAbortBroadcast():这个方法是针对上面的abortBroadcast()方法的,用于取消截获广播。这样它的下一级广播接收者就能够收到该广播了。
getAbortBroadcast():判断是否调用了 abortBroadcast,如果先调用 abortBroadcast,接着再调用 getAbortBroadcast,将返回 true; 如果在调用 abortBroadcastclearAbortBroadcastgetAbortBroadcast,将返回 false;

发送有序广播
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(ORDER_ACTION);
        /*
         * 发送有序广播
         * 第二个参数:广播接收者所需要的权限(有些广播的是需要权限的)
         * */
        sendOrderedBroadcast(intent, null);
    }

案例代码

系统分钟到达广播

安卓系统每到1分钟就会发送一条广播,此时我们可以接受这个广播。

通过 Intent.ACTION_TIME_TICK 进行Action过滤

	IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_TICK);

网络变更广播

    private void netWorkReceiver() {
        receiverNet = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent != null) {
                    NetworkInfo networkInfo = intent.getParcelableExtra("networkInfo");
                    String text = String.format(
                            "网络大类为%s,网络小类为%s,网络状态为%s",
                            networkInfo.getTypeName(),
                            networkInfo.getSubtypeName(),
                            networkInfo.getState().toString());

                    tv_tip.setText(text);
                }
            }
        };
        IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
        registerReceiver(receiverNet, filter);
    }

定时管理器

Android提供了专门的定时管理器 AlarmManager,它利用系统闹钟定时发送广播,常见方法:

  • set:设置一次性定时器
  • setAndAllowWhileIdle:设置一次性定时器,即使设备处于空闲状态,也会保证执行定时器。
  • setRepeating:设置重复定时器,但系统不保证按时发送广播。
  • cancel:取消指定延迟意图的定时器。

注册接收者 AlarmReceiver

        // 上下文传 getApplicationContext() ,而非 this(当前Activity),为了避免内存泄漏
        alarmReceiver = new AlarmReceiver(getApplicationContext());
        IntentFilter filter = new IntentFilter(AlarmReceiver.ALARM_ACTION);
        registerReceiver(alarmReceiver, filter);
发送闹钟广播

定时管理使用了PendingIntent,它与Intent之间的差异主要有下列三点:

  • PendingIntent 代表延迟意图,它指向的组件不会马上激活;而Intent代表实事的意图,它指向的组件会马上激活
  • PendingIntent 是一类消息的组合,不但包含目标的Intent对象, 还包含请求代码、请求方式等信息。
  • PendingIntent 对象在创建之时便已知晓将要用于活动还是广播。
    public void sendAlarm() {
        Intent intent = new Intent(ALARM_ACTION);
        // 创建一个用于广播的延迟意图
        // 针对 S+ (版本1000及更高版本)要求创建 PendingIntent 时指定 FLAG_IMMUTABLE 或 FLAG_MUTABLE
        // 强烈考虑使用 FLAG_IMMUTABLE,仅当某些功能依赖于 PendingIntent,是可变时才使用 FLAG_MUTABLE
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE);

        // 从系统服务中获取闹钟管理器
        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 允许在空闲时发送广播,Android6.0之后新增的方法
            alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, 3000, pendingIntent);
        } else {
            // 设置一次性闹钟,延迟若干秒后,携带延迟意图发送闹钟广播(但Android6.0之后,set方法在暗屏时不保证发送广播,必须调用setAndAllowWhileIdle方法)
            alarmManager.set(AlarmManager.RTC_WAKEUP, 3000, pendingIntent);
        }
    }
设置重复闹钟
// 设置重复闹钟,每隔一定间隔就发送闹钟广播(但从Android4.4开始,setRepeating方法不保证按时发送广播)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, pendingIntent);
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null && intent.getAction().equals(ALARM_ACTION)) {
            Log.d("AAAA", "收到广播了");

            // setRepeating 有问题,在接收到广播后又调用一次
            sendAlarm();
        }
    }

案例代码

;