【Android】安卓四大组件之广播

【Android】安卓四大组件之广播

前言

这一大章节学习的是Android的广播事件,用来发送广播或者监听广播。

1、什么是广播

Broadcast是android中的四大组件之一,是在组件之间传播数据(Intent)的一种机制。广播的发送者和接收者事先是不需要知道对方的存在的。这样带来的好处便是,系统的各个组件可以松耦合地组织在一起,这样系统就具有高度的可扩展性,容易与其它系统进行集成。

广播具有以下特性:

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

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

广播可以分为下面几种:

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

1、动态注册广播并取消注册

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

如何实现呢?

我们使用的是动态广播的方法:

  • 首先,创建一个IntentFilter对象,将其action设置为我们想要监听的广播事件(这里是Intent.ACTION_BATTERY_CHANGED系统广播)
  • 其次,创建一个继承BroadcastReceiver的类,如下是BatteryLevelReceiver,并且重写onReceive方法
  • 最后,调用activity的registerReceiver方法,传入我们的广播接收者对象意图过滤器对象,就完成了广播的接收的注册
  • 需要注意,在当前activity被destroy的时候,我们需要取消注册,防止内存泄露!
public class BroadcastActivity extends AppCompatActivity {

    private static final String TAG = "BroadcastActivity";
    private BatteryLevelReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broadcast);

        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);
        }
    }
}

我们使用模拟器中电池电量的设置进行模拟:

image-20220119191311295

调用之后的效果如下:

image-20220119191220897

3、发送自定义广播并接收

这里的自定义广播也就是普通广播,我们自己来写一个!

注意细节,Android8.0之后要使用动态注册广播,使用registerReceiver()方法

xml页面文件

<?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"
    tools:context=".study.test.BroadcastActivity"
    android:orientation="vertical">

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

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

</LinearLayout>

BroadcastActivity类

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broadcast);

        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("top.woodwhale.test.SEND_MSG");
        intent.putExtra("content",s);
        // 执行发送方法
        this.sendBroadcast(intent);
    }

    private void registerMessageBroadcast() {
        // 注册自己写的SEND_MSG广播
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("top.woodwhale.test.SEND_MSG");
        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("top.woodwhale.test.SEND_MSG")) {
                String content = intent.getStringExtra("content");
                Log.d(TAG,"接受到SEND_MSG广播,内容为:"+ content);
            }
        }
    }

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

效果如下:

studio64_6gjWtDoO7G

4、有序广播

有序广播用的少噢,懒得写,有时间补上。

至于广播权限的授予,在manifest中设置权限

在sendBroadcast的第二个重载方法中,第二个参数就是receiverPermission,也就是广播接收权限

image-20220119211639375

相关文章

Android 如何解决dialog弹出时无法捕捉Activity的back事件 在...
Android实现自定义带文字和图片的Button 在Android开发中经常...
Android 关于长按back键退出应用程序的实现最近在做一个Andr...
android自带的时间选择器只能精确到分,但是对于某些应用要求...