欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android广播那些事—开发者必须要知道的面试技巧

程序员文章站 2022-05-06 07:59:37
...

1、请描述一下 BroadcastReceiver

BroadCastReceiver 是 Android 四大组件之一,主要用于接收系统或者 app 发送的广播事件。

广播分两种:
  • 有序广播
  • 无序广播。
内部通信实现机制:
通过 Android 系统的 Binder 机制实现通信。复制代码
无序广播:

完全异步,逻辑上可以被任何广播接收者接收到。优点是效率较高。缺点是一个接收者不能将处理结果传递给下一个接收者,并无法终止广播 intent 的传播。

有序广播:

按照被接收者的优先级顺序,在被接收者中依次传播。比如有三个广播接收者 A,B,C,优先级是 A > B > C。那这个消息先传给 A,再传给 B,最后传给 C。每个接收者有权终止广播,比如 B 终止广播,C 就无法接收到。此外 A 接收到广播后可以对结果对象进行操作,当广播传给 B 时,B 可以从结果对象中取得 A 存入的数据。

在通过

Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,initialCode, initialData,initialExtras)复制代码

时我们可以指定 resultReceiver 广播接收者,这个接收者我们
可以认为是最终接收者,通常情况下如果比他优先级更高的接收者如果没有终止广播,那么他的onReceive会被执行两次,第一次是正常的按照优先级顺序执行,第二次是作为最终接收者接收。

如果比他优先级高的接收者终止了广播,那么他依然能接收到广播。

应用场景

在我们的项目中经常使用广播接收者接收系统通知,比如开机启动、sd 挂载、低电量、外播电话、锁屏等。

如果我们做的是播放器,那么监听到用户锁屏后我们应该将我们的播放之暂停等。

2、在 manifest 和代码中如何注册和使用 BroadcastReceiver

静态注册

在清单文件中注册广播接收者称为静态注册,在代码中注册称为动态注册。静态注册的广播接收者只要 app 在系统中运行则一直可以接收到广播消息,动态注册的广播接收者当注册的 Activity 或者 Service 销毁了那么就接收不到广播了。

在清单文件中进行如下配置

<receiver android:name=".BroadcastReceiver1" >
<intent-filter>
<action android:name="android.intent.action.CALL" >
</action>
</intent-filter>
</receiver>复制代码
动态注册

动态注册:在代码中进行如**册

receiver = new BroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CALL_ACTION);
context.registerReceiver(receiver, intentFilter);复制代码

3、BroadCastReceiver 的生命周期

a. 广播接收者的生命周期非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销
毁;

b. 广播接收者中不要做一些耗时的工作,否则会弹出 Application No Response 错误对话框;

c. 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉;

d. 耗时的较长的工作最好放在服务中完成;

4、Android 引入广播机制的用意

a. 从 MVC 的角度考虑(应用程序内)其实回答这个问题的时候还可以这样问,android 为什么要有那 4 大组件,现在的移动开发模型基本上也是照搬的 web 那一套 MVC 架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的 MVC 架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组
件的信息和数据交互。

b. 程序间互通消息(例如在自己的应用程序内监听系统来电)

c. 效率上(参考 UDP 的广播协议在局域网的方便性)

d. 设计模式上(反转控制的一种应用,类似监听者模式)

android 中什么是隐式广播

Intent intent = new Intent(); intent.setType("image/*"); //通过type来让系统选择 视频video/* intent.setAction(Intent.ACTION_GET_CONTENT);复制代码

Android7.0的自定义广播

Android7.0新增的广播权限验证问题

比如项目上需要使用广播进行跨进程通信,在7.0之前的版本测试都是OK,在7.0上搞死接收不到发送的广播,关键不是这个,关键是广播因为权限问题被拒接,系统不会报错,也不会抛异常(大概是因为异常被内部捕获了),最后在输出的log中进行全局搜索才确定的问题所在!!!

解决

解决方法其实很简单,就是在广播接受者所在的进程声明一个权限,在广播的发送者所在的进程内注册使用该权限,这样问题就可以解决了(这种广播权限问题只存在跨进程静态注册广播的方式上,动态注册的广播好像不存在这种问题!!!)

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.permissionbroadcastreceiver">

    <permission
        android:name="com.example.broadcast.permission"
        android:protectionLevel="normal" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".PermissionRecevicer"
            android:permission="com.example.broadcast.permission">
            <intent-filter>
                <action android:name="com.example.permissionbroadcastreceiver.message" />
            </intent-filter>
        </receiver>
    </application>

</manifest>复制代码

广播接收没有权限以完美解决!!!

更多阅读

热修复实战-史上讲解最详细的文章,强烈推荐

NDK项目实战—高仿360手机助手之卸载监听

一个强大的AutoLifecycle—让普通 Java 类自动感知 Activity Lifecycle

微信公众号:终端研发部

技术+职场