将Android进行到底之广播(Broadcast)

在这里插入图片描述


前言

在VR的开发中,Android的广播扮演着很重要的角色,因为我们的VR开发中显示的Launcher界面通常是使用Unity3d开发的,所以很多时候当我们想要在VR眼镜中,去调试我们的功能的时候。想象下,以前我们是直接在Android上显示,在Activity中写个Button就行了,但是遇到咱们到了VR眼镜中,要调试的时候,就不能直接在眼镜中让Unity3d的同事给你加个调试的按钮吧,人家也没那时间给你加

下图就是使用Unity3d渲染出来的Launcher 界面

在这里插入图片描述


就算人家给你加了,但是假如这时候操作的手柄还没就位你咋去点击VR眼镜里面的按钮呢?所以这时候广播的作用就体现出来了。我们可以通过发广播的形式去调试我们写的功能。广播不仅有这些作用还有好多妙用,让我们一起去看看吧。


一、广播的介绍

1.广播的概念

在Android中,广播是一种广泛应用在应用程序之间传输信息的机制,我们发送的广播内容是一个Intent,在这个Intent中,我们可以携带我们要发送的数据。举个例子,Android系统会在发生各种系统事件的时候发送广播,例如:系统启动了,电量改变了,USB设备插入拔出。设备充电时等等。不仅如此,我们还可以通过发送自定义的广播来通知其他应用,让他们做些事情。比如当一些新数据已经下载完了后,可以通过自定义广播通知其他应用。

2.广播的分类

在这里插入图片描述

系统会在发生各种系统事件的时候自动发送广播,比如当系统进入和退出飞行模式的时候。系统广播会被发送给所有统一接收相关事件的应用,广播消息本身会被封装在一个Intent对象中 ,该对象会有一个标识
(例如:android.intent.action.AIRPLANE_MODE)这个Intent可能还包含绑定其extra字段中的附加信息。如飞行模式intent包含布尔值extra来标识是否已经开启了飞行模式。

在App内监听这些广播也非常简单,咱们接着往下看

3.广播的使用

(1)接收广播

Android应用可以通过两种方式接收广播:分别是清单文件(AndroidManifest.xml)中声明的接收器(也叫静态注册),和上下文注册的接收器(也叫动态注册),咱们分别来看下两种注册方式。

1.在清单文件(AndroidManifest.xml)中声明的接收器

step1:创建一个类继承自BroadcastReceiver,并实现onReceive(Context,Intent)方法。
代码如下:

 public class MyBroadcastReceiver
  extends BroadcastReceiver {
    
    
            @Override
            public void onReceive(Context context,
             Intent intent) {
    
    
            String action = intent.getAction();
            if(action.equls("android.intent.action.BOOT_COMPLETED"){
    
    
             //这样做是为了筛选出我们
            //想要监听的广播,然后做咱们的处理逻辑
            doSomeThings();
            }
        }
    }

注意:广播时运行在主线程,所以不能在onReceive()方法中做耗时操作,否则可能会引起ANR

step2:在清单文件中声明广播接收器

 <receiver android:name=".MyBroadcastReceiver"  android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
        </intent-filter>
    </receiver>

声明广播接收器还可以使用上下文的方式,也就是咱们平常说的动态注册的方式,代码如下:

 BroadcastReceiver br = new MyBroadcastReceiver();
 IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.android.intent.action.BOOT_COMPLETED);
        this.registerReceiver(br, filter);

注意:只要注册的上下文有效,那么使用该上下文注册的接收器就会收到广播,例如,如果在Activity的上下文中注册,只要Activity没有被销毁,就会收到广播。如果是在Application的上下文中注册。只要应用还活着,没有被杀死,就可以接收到广播

step3:停止接收广播,当我们需要停止接收广播的时候,需要调用unregisterReceiver(android.content.BroadcastReceiver)方法停止接收广播,一般我们都会在上下文不在有效的时候注销广播接收器。比如:在Activity销毁时,在activity的onDestroy()回调中注销掉广播。

注意:我们注册和销毁接收器的位置需要特别小心。我们一般都是在Activity的onCreate()方法中注册广播,在onDestroy()中注销广播,但是假如你是在Activity的onResume()方法中注册的广播,则需要在onPause中注销广播,防止多次注册接收器

(2)发送广播

在前面的广播种类中我们提到了三种广播,所以发送广播的时候也分三种方式。分别是:
有序广播:sendOrderedBroadcast(Intent, String)
无序广播:sendBroadcast(Intent)
本地广播:LocalBroadcastManager.sendBroadcast

使用的方式很统一,除了调用的函数名不同,其他大概相同:代码如下:

  Intent intent = new Intent();
    intent.setAction("com.example.broadcast.MY_NOTIFICATION");
    intent.putExtra("data","Notice me senpai!");
    sendBroadcast(intent);

注意: 广播消息封装在 Intent 对象中。Intent 的操作字符串必须提供应用的 Java 软件包名称语法,并唯一标识广播事件。我们可以使用 putExtra(String, Bundle) 向 intent 添加加其他信息。

二、广播的妙用

1.跨应用通信

这个最简单了,但是需要注意的是这里的跨应用通信指的可不是大数据量的通信哈,因为广播是挺耗性能的,所以尽量用来做些通知的事情。打个比方。广播相当于咱们在人群中大声喊出某条命令,确保所有人能听到,类似古代的传令兵,只能是喊有限的次数,可不能让人大声把兵法读给大家听吧。谁受得了呀。广播也是如此,咱们应该尽量让它做些短暂的命令通知就可以了

2.调试程序

广播调试程序可谓是一个字,爽。如何利用广播来调试程序呢?我们可以利用Android的调试工具adb来发送自定义的广播,在我们要调试的界面中写上广播接收器。然后接收到广播的时候执行咱们需要调试的内容就行了。

举个例子吧,假如咱们写了一个投屏的功能,使用广播的方式如何调试呢?以前的话咱们可能会写个按钮,点击的时候开始去投屏,这样很麻烦,在你自己的界面中还好,遇到我说的连接VR眼镜的时候,是不是就傻眼了。所以我们来看下利用广播如何做:

step1: 在要调试的类中去写上广播接收器:

private final static String ACTION_SAVE_DATA = 
    "action.save.data";
    private final static String ACTION_START_CAST = 
    "action.start.cast";
 private final BroadcastReceiver broadcastReceiver = new 
 BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent 
        intent) {
    
    
            String action = intent.getAction();
            Log.d(TAG,"ACTION==============saveData==>>"
             + action);
            if(action.equals(ACTION_SAVE_DATA)){
    
    
                Log.d(TAG,"save success====================>");
                RtpReadAndPush.getInstance().saveData();
            }

            if(action.equals(ACTION_START_CAST)){
    
    
                Log.d(TAG,"ACTION === START CAST==>" + 
                action);
                startCast(mCurrentLeLinkServiceInfo);
            }
        }
    };

step2:在onCreate()方法中注册它

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cast);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_SAVE_DATA);
        intentFilter.addAction(ACTION_START_CAST);
        registerReceiver(broadcastReceiver,intentFilter);
        }
        

step3:使用Adb发送自定义广播

adb shell am broadcast -a "action.start.cast"

step4:别忘了注销广播

  @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        unregisterReceiver(broadcastReceiver);
    }

3.配合service做容错处理

配合service做容错处理在咱们的前面也讲到了,其实很简单,因为service在配合AIDL做进程间通信的时候,通常都作为服务端,为客户端提供服务,假如服务端一直活着的情况下,客户端不出意外的话是百分百能够连接到服务端的,但是假如服务端意外死掉了,客户端这时候是不知道的,已经连接的客户端也不会重新去连接服务端,因为他们不知道服务端死掉了。所以这时候广播的作用就是告诉所有连接它的客户端,我发生异常重启了,你们重现连接下我再进行其他工作。

三、广播的注意事项

1.Android各版本的广播区别

随着 Android 平台的发展,它会不定期地更改系统广播的行为方式。如果应用以 Android 7.0(API 级别 24)或更高版本为目标平台,或者安装在搭载 Android 7.0 或更高版本的设备上,需要注意下面的版本变化:

Android 7.0
Android 7.0(API 级别 24)及更高版本不发送以下系统广播:
ACTION_NEW_PICTURE、ACTION_NEW_VIDEO
此外,以 Android 7.0 及更高版本为目标平台的应用必须使用 registerReceiver(BroadcastReceiver, IntentFilter) 注册 CONNECTIVITY_ACTION 广播。无法在清单中声明接收器。

Android 8.0
从 Android 8.0(API 级别 26)开始,系统对清单声明的接收器施加了额外的限制。如果应用以 Android 8.0 或更高版本为目标平台,那么对于大多数隐式广播(没有明确针对咱们应用的广播),不能使用清单来声明接收器。当用户正在活跃地使用的咱们开发的应用时,仍可使用动态注册的接收器。

Android 9
从 Android 9(API 级别 28)开始,NETWORK_STATE_CHANGED_ACTION 广播不再接收有关用户位置或个人身份数据的信息。此外,如果您的应用安装在搭载 Android 9 或更高版本的设备上,则通过 WLAN 接收的系统广播不包含 SSID、BSSID、连接信息或扫描结果。要获取这些信息,请调用 getConnectionInfo()。

2.不要滥用广播

一般来说,广播可作为跨应用和普通用户流之外的消息传递系统。但是,您必须小心,不要滥用在后台响应广播和运行作业的机会,因为这会导致系统变慢

总结

好了,以上就是今天的内容,篇幅有点长,希望能对正在阅读这篇文章的你带来收获,有疑问的可以在评论区一起交流。本人很热爱计算机,也很热爱我现在的职业。如果你和我志同道合,咱们一起共同交流,共同进步。

猜你喜欢

转载自blog.csdn.net/zxj2589/article/details/127823804