安卓四大组件之广播


一、简介

1.1 什么是广播

广播是一种用于应用程序之间或应用程序内部进行通信的机制。它允许一个应用程序发送一个广播消息,而其他应用程序可以注册接收这个广播消息并做出相应的处理。广播可以用于很多场景,比如在系统状态变化时通知应用程序、在应用程序之间传递数据、在应用程序内部进行通信等。

1.2 广播的特性

广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框
最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉(耗时的较长的工作最好放在服务中完成)

需要注意的是,在安卓8.0之后(也就是API26),静态广播事件大部分都受限,官方文档建议使用动态广播来处理!

1.3 广播角色

广播分为两个角色:广播发送者、广播接收者

1.4 应用场景

包括但不限于以下几种:

  • 系统状态变化通知:应用程序可以注册系统广播接收者来监听系统状态的变化,比如网络连接状态变化、电池电量变化、屏幕解锁等,以便应用程序在状态变化时做出相应的处理。
  • 应用内部通信:应用程序内部的不同模块之间可以通过广播来进行通信,比如一个模块发送广播消息,而其他模块注册广播接收者来接收消息并做出相应的处理。
  • 跨应用程序通信:应用程序之间可以通过广播来进行跨应用程序的通信,比如一个应用程序发送广播消息,而其他应用程序注册广播接收者来接收消息并做出相应的处理。
  • 后台任务处理:应用程序可以使用广播来触发后台任务的执行,比如在特定的时间点发送一个定时广播来执行后台任务或发送一个系统事件广播来触发后台服务的处理。
  • 事件通知和交互:应用程序可以使用广播来发送事件通知,比如通知用户有新消息到达、用户完成了某个操作等,也可以通过广播实现应用程序之间的交互,比如启动其他应用程序或传递数据。

1.5 广播分类

  • 系统广播:Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广波,每个广播都有特定的Intent - Filter(包括具体的action)
  • 标准广播(Normal Broadcast):一种完全异步执行的广播方式,sendBroadcast()方法来发送,通过onReceive方法接收。消息传递效率比较高,但所有receivers(接收器)的执行顺序不确定,所有接收者几乎同时接收到广播消息。缺点在于:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播,直到没有匹配的接收器广播时才能停止传播。
  • 有序广播(Ordered Broadcast):用sendOrderedBroadcast发送,有如下特点:
    按照接收者的优先顺序来接收广播,优先级别在intentFilter中的priority中声明,-1000到1000之间,值越大优先级越高。
    可以终止广播的继续传播,接受者可以修改intent的内容。
    同级别接收顺序是随机的,级别低的后收到
    能截断广播的继续传播,高级别的广播接收器接收广播后能截断广播和处理广播

Android系统广播action如下:

系统操作action
监听网络变化android.net.conn.CONNECTIVITY_CHANGE
关闭或打开飞行模式Intent.ACTION_AIRPLANE_MODE_CHANGED
充电时或电量发生变化Intent.ACTION_BATTERY_CHANGED
电池电量低Intent.ACTION_BATTERY_LOW
电池电量充足(即从电量低变化到饱满时会发出广播 Intent.ACTION_BATTERY_OKAY
系统启动完成后(仅广播一次)Intent.ACTION_BOOT_COMPLETED
按下照相时的拍照按键(硬件按键)时Intent.ACTION_CAMERA_BUTTON
屏幕锁屏Intent.ACTION_CLOSE_SYSTEM_DIALOGS
设备当前设置被改变时(界面语言、设备方向等)Intent.ACTION_CONFIGURATION_CHANGED
插入耳机时Intent.ACTION_HEADSET_PLUG
未正确移除SD卡但已取出来时(正确移除方法:设置–SD卡和设备内存–卸载SD卡)Intent.ACTION_MEDIA_BAD_REMOVAL
插入外部储存装置(如SD卡)Intent.ACTION_MEDIA_CHECKING
成功安装APKIntent.ACTION_PACKAGE_ADDED
成功删除APKIntent.ACTION_PACKAGE_REMOVED
重启设备Intent.ACTION_REBOOT
屏幕被关闭Intent.ACTION_SCREEN_OFF
屏幕被打开Intent.ACTION_SCREEN_ON
关闭系统时Intent.ACTION_SHUTDOWN
重启设备Intent.ACTION_REBOOT

注:当使用系统广播时,只需要在注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播

1.6 注册方式

安卓广播可以通过静态注册和动态注册两种方式来实现广播接收者的注册。

静态注册广播接收者是通过在AndroidManifest.xml文件中声明广播接收者来实现的,系统会在应用程序安装时自动注册广播接收者。
动态注册广播接收者是通过代码动态注册广播接收者,可以在应用程序运行时注册和取消注册广播接收者。

注意:

从 Android 8.0(API 级别 26)开始,静态注册广播接收者的机制发生了变化,对于一些隐式广播(比如网络状态变化、电量变化等),静态注册广播接收者会受到限制。具体来说,静态注册的广播接收者无法接收以下隐式广播:

Android 系统不允许应用程序在清单文件中静态注册的广播接收者接收以下广播:

CONNECTIVITY_ACTION
ACTION_BATTERY_CHANGED
ACTION_TIME_TICK
ACTION_TIMEZONE_CHANGED
ACTION_BOOT_COMPLETED
ACTION_PACKAGE_REPLACED
ACTION_PACKAGE_RESTARTED
ACTION_PACKAGE_DATA_CLEARED

如果应用程序需要接收上述广播,必须通过动态注册广播接收者的方式来实现。

因此,对于一些系统级别的广播事件,建议使用动态注册广播接收者的方式来接收广播。对于其他自定义的广播事件,静态注册广播接收者仍然是一个有效的方式。需要根据具体的需求和场景来选择合适的注册方式。


二、广播的使用

讲了这么多知识点,赶紧看一下广播具体的使用方式吧。
广播的发送

广播 是 用”意图(Intent)“标识
定义广播的本质 = 定义广播所具备的“意图(Intent)”
广播发送 = 广播发送者 将此广播的“意图(Intent)”通过sendBroadcast()方法发送出去

广播的实现
继承自BroadcastReceivre基类,必须复写抽象方法onReceive()方法

广播接收器接收到相应广播后,会自动回调onReceive()方法
一般情况下,onReceive方法会涉及与其他组件之间的交互,如发送Notification、启动service等
默认情况下,广播接收器运行在UI线程,因此,onReceive方法不能执行耗时操作,否则将导致ANR

广播的终止:

// 终止广播,不再传递给下一个接收者
        abortBroadcast();

2.1 动态注册广播监听电量

拿一个最简单的例子——监听当前电量的情况,监听一个当前电量的广播,这个属于系统广播之一。

如何实现呢?

使用动态注册广播的方法:

首先,创建一个IntentFilter对象,将其action设置为我们想要监听的广播事件(这里是Intent.ACTION_BATTERY_CHANGED系统广播)
其次,创建一个继承BroadcastReceiver的类,如下是BatteryLevelReceiver,并且重写onReceive方法
最后,调用activity的registerReceiver方法,传入我们的广播接收者对象和意图过滤器对象,就完成了广播的接收的注册

需要注意,在当前activity被destroy的时候,需要取消注册,防止内存泄露!

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "henry-----";
    private BatteryLevelReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        receiver = new BatteryLevelReceiver();
        // 进行广播注册
        this.registerReceiver(receiver, intentFilter);
    }


    private class BatteryLevelReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "收到action == " + action);
            int state = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
            Log.d(TAG, "当前电量 == " + state);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 取消广播注册
        if (receiver != null) {
            this.unregisterReceiver(receiver);
        }
    }
}

这段代码实现了监听设备电池电量变化的功能,通过注册广播接收者 BatteryLevelReceiver 来监听 Intent.ACTION_BATTERY_CHANGED 广播,当电量变化时会触发 onReceive 方法,从中获取电量信息并打印到 Logcat 中。通过动态注册和取消注册广播接收者来实现对电量变化广播的监听。

模拟器改变电量:
在这里插入图片描述

观察log:
在这里插入图片描述

2.2 发送自定义广播并接收

上面的系统广播我们并未发送设备便能检测到,现在看一下发送广播的使用:

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/et_broadcastContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入需要广播的内容!" />

    <Button
        android:id="@+id/bt_broadcastTransmissionBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击发送一条广播~" />

</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "henry-----";
    private Button btn;
    private EditText content;
    private MessageReceiver messageReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        registerMessageBroadcast();
    }


    private void initView() {
        btn = this.findViewById(R.id.bt_broadcastTransmissionBtn);
        content = this.findViewById(R.id.et_broadcastContent);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendBroadcastMessage(v);
            }
        });
    }

    private void sendBroadcastMessage(View v) {
        // 被点击调用就去发送广播
        String s = content.getText().toString();
        Intent intent = new Intent();
        intent.setAction("henry.Broadcast.test");
        intent.putExtra("content", s);
        // 执行发送方法
        this.sendBroadcast(intent);
    }

    private void registerMessageBroadcast() {
        // 注册自己写的SEND_MSG广播
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("henry.Broadcast.test");
        messageReceiver = new MessageReceiver();
        // 执行注册方法
        this.registerReceiver(messageReceiver, intentFilter);
    }

    class MessageReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            // 如果是接收了SEND_MSG的广播
            if (intent.getAction().equals("henry.Broadcast.test")) {
                String content = intent.getStringExtra("content");
                Log.d(TAG, "接受到SEND_MSG广播,内容为:" + content);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 不要忘记取消注册噢~
        if (messageReceiver != null) {
            this.unregisterReceiver(messageReceiver);
        }
    }

}

在这里插入图片描述

2.3 有序广播

定义

发送出去的广播被广播接收者按照先后顺序接收
有序是针对广播接收者而言的

广播接受者接收广播的顺序规则:

按照Priority属性值从大-小排序;
Priority属性相同者,动态注册的广播优先;

特点:

接收广播按顺序接收
先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播;
先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播
具体使用
有序广播的使用过程与普通广播非常类似,差异仅在于广播的发送方式:

sendOrderedBroadcast(intent);

2.4 静态注册广播

发送广播方式不变:

Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//发送广播
sendBroadcast(intent);

区别是注册方式在Manifesxmlt.xml文件中

<receiver 
    //此广播接收者类是mBroadcastReceiver
    android:name=".mBroadcastReceiver" >
    //用于接收网络状态改变时发出的广播
    <intent-filter>
        <action android:name="BROADCAST_ACTION" />
    </intent-filter>
</receiver>

静态注册的一些属性:

<receiver 
    android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的发出的广播
//默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为false
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:label="string resource"
//继承BroadcastReceiver子类的类名
    android:name=".mBroadcastReceiver"
//具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;
    android:permission="string"
//BroadcastReceiver运行所处的进程
//默认为app的进程,可以指定独立的进程
//注:Android四大基本组件都可以通过此属性指定自己的独立进程
    android:process="string" >

//用于指定此广播接收器将接收的广播类型
//本示例中给出的是用于接收网络状态改变时发出的广播
 <intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
 </intent-filter>
</receiver>

三、总结

广播是 Android 系统中一种用于应用组件之间进行通信的机制。广播可以分为普通广播和有序广播两种类型。

  • 普通广播是一种完全异步的广播方式,广播发出后,所有注册了相应动作的接收者都会接收到广播,但接收者之间没有顺序关系,无法拦截或修改广播。
  • 有序广播是一种按照优先级顺序依次传递给接收者的广播方式,接收者可以对广播进行拦截、修改或终止传递。有序广播通过 abortBroadcast() 方法可以终止广播,不再传递给其他接收者。
  • 广播可以通过静态注册和动态注册两种方式进行注册,静态注册通过在 AndroidManifest.xml 文件中声明 < receiver> 元素,动态注册通过调用 registerReceiver() 和 unregisterReceiver() 方法。
  • 广播可以通过 Intent 来传递数据,接收者可以通过 Intent 的方法获取传递的数据。广播可以用于监听系统事件、应用内部通信、跨应用通信等场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值