• 软件之间沟通的大喇叭:Android四大组件之广播机制


    前言

    前面我们讲过四大组件中的活动,本文讲解四大组件中的广播机制,通过本文了解广播机制的作用以及基本用法。

    五、软件之间沟通的大喇叭:Android四大组件之广播机制

    5.1 广播机制简介

    如该章标题,广播就像你村里的大喇叭,通过广播可以接收手机中其它软件的信息,也可以将自己的信息发送给你别的软件。广播与广播接收器是一对,广播用于发送信息,广播接收器用于接收广播发送的信息。

    Android中广播主要有两种类型:

    • 标准广播:一种完全异步执行的广播,既广播发出后,就不能再截断,它几乎会同一时刻到达所有广播接收器。就像早上村里的大喇叭发出的广播,村长只要在喇叭中说出某个信息,就不可能再阻止这个信息传播,并且在一定范围内所有的村民几乎会同时都会听到这个信息
      在这里插入图片描述
    • 有序广播:一种同步执行的广播,既广播是有先后顺序的发送给其中一个广播接收器,只有这个广播接收器完全接收信息后,才会向下一个广播接收器传递信息,因此也可以在某个广播接收器截断该信息继续向下传播。这种就好比村长挨家挨户向村民传递信息,当然可能在某户,村长被打晕了,那么下一家就得不到这个信息了。
      在这里插入图片描述

    5.2 接收系统广播,通过大喇叭听听其它软件的消息

    Android内置了很多系统级别的广播,比如开机完成后,网络发生变化后,电量变化后等都会发出一条广播,我们可以在程序中有选择的接收我们需要的广播。
    接收系统发出的广播有两个步骤:

    1. 注册广播,既通过对感兴趣的广播进行注册,进而获得该广播的信息。
    2. 创建广播接收器,用于接收我们上一步注册的广播所发出的信息。

    注册广播有两种方法:

    1. 动态注册:既在代码中注册,这种方式注册的广播必须在程序启动后才能接收广播。
    2. 静态注册:既在AndroidManifest.xml文件中进行注册,这种方式注册的广播,即便不启动程序,也能接收广播,比如接收开机完成的广播就需要用静态注册,因为开机时软件还没启动。

    5.2.1 基于动态注册广播方式接收系统广播的示例

    如当网络状态发送变化时,系统会发送一条广播,我们采用动态注册广播的方式接收该广播信息的流程如下:

    1. 创建广播接收器:本质就是创建一个继承自BroadcastReceiver的类,然后实现onReceive方法。
    
        //创建广播接收器,用于指定action的广播
        class NetworkChangeReceiver extends BroadcastReceiver{
    
            //系统发出的广播信息会在这个方法中接收到
            @Override
            public void onReceive(Context context, Intent intent) {
                ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
                if (activeNetworkInfo!=null && activeNetworkInfo.isAvailable())
                    Toast.makeText(context, "网络已连接", Toast.LENGTH_SHORT).show();
                else
                    Toast.makeText(context, "网络已断开", Toast.LENGTH_SHORT).show();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 动态注册广播
    //动态注册广播接收器,接收网络状态广播
    IntentFilter intentFilter=new IntentFilter();
    //指定我们想要接收的系统广播
    intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    networkChangeReceiver = new NetworkChangeReceiver();
    //将广播注册到广播接收器
    registerReceiver(networkChangeReceiver,intentFilter);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:
    a. 动态注册的广播接收器,不用的时候记得取消注册。

    unregisterReceiver(networkChangeReceiver);
    
    • 1

    b. 注册相应广播需要一定的权限,如注册网络状态广播需要在AndroidManifest.xml中添加网络权限。

        <!-- 添加访问网络状态的权限 -->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
    
    • 1
    • 2

    5.2.2 基于静态注册广播方式接收系统广播的示例

    可以利用Android studio工具完成静态注册广播,操作流程如下图。
    在这里插入图片描述
    如注册开机时系统发出的广播。

    1. AndroidManifest.xml中注册开机广播接收器
     
            <receiver
                android:name=".BootCompleteReceiver" 
                android:exported="true"> 
    
                
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                intent-filter>
            receiver>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 在广播接收器类中重写onReceive方法,完成接收到广播信息后的逻辑。
    public class BootCompleteReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO: This method is called when the BroadcastReceiver is receiving
            // an Intent broadcast.
            Toast.makeText(context, "开机完成", Toast.LENGTH_SHORT).show();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意,注册开机启动广播,同样需要在AndroidManifest.xml中添加相应权限

        <!-- 添加访问开机状态的权限 -->
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
    • 1
    • 2

    5.3 发送自定义广播,通过大喇叭向其它软件说自己的消息

    通过发送自定义广播,那么注册了这个自定义广播的所有软件就能收到该广播。所谓自定义广播其实就是自定义一个action字符串。

    1. 发送自定义广播核心代码
     //从SDK26开始,通过静态注册的广播接收器失效!
    Intent intent=new Intent("com.xiaomi.broadcasttest.MY_BROADCAST");
    //sendBroadcast(intent);//以标准广播方法发送自定义的广播
    sendOrderedBroadcast(intent,null);//以顺序广播方法发送自定义的广播
    
    • 1
    • 2
    • 3
    • 4
    1. 注册自定义广播并创建广播接收器,接收广播
      2.1 创建广播接收器
     //创建广播接收器,用于指定action的广播
        class MyBroadcastReceiver extends BroadcastReceiver{
    
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "收到自定义发送的广播", Toast.LENGTH_SHORT).show();
                //abortBroadcast();//发送顺序广播的情况下,通过这个方法,使得广播传播到此处就中断,未接收到广播的信息的就接收不到了
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.2 静态注册上面的自定义广播
    从SDK26开始,通过静态注册的自定义广播接收器失效!,因此,应该采用动态注册自定义广播接收器

     <receiver android:name=".MyBroadcastReceiver" 
     android:enabled="true" 
     android:exported="true">
                <intent-filter>
                    <action android:name="com.xiaomi.broadcasttest.MY_BROADCAST" />
                intent-filter>
            receiver>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.3 动态注册上面的自定义广播

     //动态注册广播接收器,接收自定义发送的标准广播
    intentFilter=new IntentFilter();
    intentFilter.addAction("com.xiaomi.broadcasttest.MY_BROADCAST");
    intentFilter.setPriority(100);//采用顺序广播方法发送广播,设置广播接收器的优先级,优先级越高,越先收到广播
    myBroadcastReceiver = new MyBroadcastReceiver();
    registerReceiver(myBroadcastReceiver,intentFilter);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5.4 使用本地广播,难以启齿的消息封在自己软件内部

    前面我们发送和接收的广播全部属于系统全局广播,即发出的广播可以被其它任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播。这样就很容易引起安全性的问题,比如说我们发送的一些携带关键性数据的广播有可能被其他的应用程序截获,或者其他的程序不停地向我们的广播接收器里发送各种垃圾广播。

    为了解决这个问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播,这样所有的安全性问题就都不存在了。

    本地广播实现非常简单,与常规广播实现类似,只是Android提供了一个LocalBroadcastManager类来管理广播的发送,注册,取消注册等。

    本地广播只能采用动态方式注册,这个也很容易理解,因此是在程序内部使用的,没有必要采用让程序在未启动情况下接收广播的静态注册方式。

    1. 发送本地广播核心代码:
    LocalBroadcastManager mLocalBroadcastManager;
    mLocalBroadcastManager=LocalBroadcastManager.getInstance(this);
    Intent intent=new Intent("com.xiaomi.LOCAL_BROADCAST");
    mLocalBroadcastManager.sendBroadcast(intent);
    
    • 1
    • 2
    • 3
    • 4

    参考书籍:第一行代码
    链接:https://pan.baidu.com/s/1aXtOQCXL6qzxEFLBlqXs1Q?pwd=n5ag
    提取码:n5ag2. 注册本地广播核心代码

    链接:https://pan.baidu.com/s/1aXtOQCXL6qzxEFLBlqXs1Q?pwd=n5ag
    提取码:n5ag
    LocalBroadcastReceiver mLocalBroadcastReceiver;
    //注册本地广播
    intentFilter=new IntentFilter();
    intentFilter.addAction("com.xiaomi.LOCAL_BROADCAST");
    mLocalBroadcastReceiver=new LocalBroadcastReceiver();
    mLocalBroadcastManager.registerReceiver(mLocalBroadcastReceiver,intentFilter);
    
    //取消注册本地广播 
    //mLocalBroadcastManager.unregisterReceiver(mLocalBroadcastReceiver);
    
    //创建广播接收器
    class LocalBroadcastReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "本地广播接收器", Toast.LENGTH_SHORT).show();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    参考书籍:第一行代码

    链接:https://pan.baidu.com/s/1aXtOQCXL6qzxEFLBlqXs1Q?pwd=n5ag
    提取码:n5ag

  • 相关阅读:
    visjs 数据的增删改筛选(DataSet & DataView)
    【通信原理】第三章 -- 随机过程[补充]
    百度文心一言
    【无标题】
    java学习之git的基本使用
    设计模式——原型模式
    详解数据结构之-「数组篇」
    java 的基本语法格式
    丢弃Excel,Pandas一行搞定
    2022年最新Python大数据之Python基础【六】函数与变量
  • 原文地址:https://blog.csdn.net/qq_34720818/article/details/127972298