Android面试之Broadcast
- 1.广播是什么
- 1.1 定义
- 1.2 广播的使用场景
- 2 广播的种类
- 2.1 无序广播
- 2.2 有序广播
- 2.3 本地广播
- 2.4 系统广播
- 2.5 粘性广播:
- 3. 广播接收器
- 3.1 静态注册
- 3.2 动态注册
- 4. 源码角度分析广播机制
- 4.1 系统广播的源码角度分析
- 4.2 本地广播的源码角度分析
- 4.3 广播发送和接收的原理 ?(Binder机制、AMS)
1.广播是什么
1.1 定义
在 Android 中,广播是一种广泛运用在应用程序之间 传输信息的机制,Android 中我们发送广播内容是一个 Intent ,这个 Intent 中可以携带我们要发送的数据。
1.2 广播的使用场景
- 同一app内有多个进程的不同组件之间的消息通信。
- 不同app之间的组件之间消息的通信。
2 广播的种类
2.1 无序广播
//不可被拦截,当然发送的数据,接收者是不能进行修改的。 context.sendBroadcast(Intent);
2.2 有序广播
发送出去的广播被广播接收者按照先后顺序接收,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,
优先级(priority)高的广播接收器会先收到广播消息。有序广播可以被接收器截断使得后面的接收器无法收到它;
context.sendOrderBroadcast(Intent)
可被拦截,而且接收者是可以修改其中要发送的数据,修改和添加都是可以的,这就意味着优先接收者对数据修改之后,下一个接收者接受的数据是上一个接收者已经修改了的,这必须明白。
2.3 本地广播
localBroadcastManager.sendBroadcast(Intent);
只在app内传播。数据更加安全,效率更高,但 只能采用动态注册的方式;
本地广播的发送和注册广播接收器都需要使用
LocalBroadcastManager
类,
//本地广播的发送: public static void sendLocalBroadcast(Context context,String action){ Intent intent = new Intent(action); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); localBroadcastManager.sendBroadcast(intent); } //本地广播的接收器的注册: IntentFilter intentFilter = new IntentFilter(); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); intentFilter.addAction(new BroadcastUtil().action_next); nasbr = new NextAndStartBroadcastReceiver(); //注册本地广播接收器 localBroadcastManager.registerReceiver(nasbr, intentFilter);
2.4 系统广播
普通广播:开发者自身定义 intent的广播(最常用),所有的广播接收器几乎会在同一时刻接受到此广播信息,接受的先后顺序随机
监听网络变化 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 成功安装APK Intent.ACTION_PACKAGE_ADDED 成功删除APK Intent.ACTION_PACKAGE_REMOVED 重启设备 Intent.ACTION_REBOOT 屏幕被关闭 Intent.ACTION_SCREEN_OFF 屏幕被打开 Intent.ACTION_SCREEN_ON 关闭系统时 Intent.ACTION_SHUTDOWN 重启设备 Intent.ACTION_REBOOT ……
2.5 粘性广播:
这种广播会一直滞留,当有匹配该广播的接收器被注册后,该接收器就会收到此条广播
3. 广播接收器
广播接收器是专门用来接收广播信息的,它可分为静态注册和动态注册:
3.1 静态注册
首先创建一个广播接收器类,实例代码如下:
public class BootCompleteReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show(); } }
在 onReceive() 方法中对广播进行处理。
静态的广播接收器一定要在 AndroidManifest.xml 文件中注册,AndroidManifest.xml 文件中注册静态广播代码如下:
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.example.broadcasttest" android:versionCode="1" android:versionName="1.0" > …… <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > …… <receiver android:name=".BootCompleteReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> </application> </manifest>
所有静态的广播接收器都是在这里进行注册的。它的用法其实和标签非常相似,也是通过 android:name
来指定具体注册哪一个广播接收器,而 enabled 和 exported 属性则是创建 receiver 时自动生成的。
3.2 动态注册
如何创建一个广播接收器呢?新建一个类,让它继承自 BroadcastReceiver,并重写父类的 onReceive() 方法。
有广播到来时,onReceive() 方法就会得到执行,具体的逻辑就可以在这个方法中处理。来个简单的例子:监听网络变化,
其实就是新建一个广播接收器去接收来自系统网络变化的广播即可,代码如下所示:
public class MainActivity extends AppCompatActivity{ private IntentFilter intentFilter; private NetWorkChangeReceiver netWorkChangeReceiver; @Override protected void onCreate(Bundle savedInstanceState){ super.Oncreata(savedInstanceState); setContentView(R.layout.activity_main); intentFilter = new IntentFilter(); intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); networkChangeReceiver = new NetWorkChangeReceiver(); registerReceiver(networkChangeReceiver, intentFilter);//注册广播接收器 } @Overrid protected void onDestroy(){ unregisterReceiver(networkChangeReceiver);//一定要记得取消广播接收器的注册 super.onDestroy(); } class NetworkChangeReceiver extends BroadcastReceiver{//广播接收器类 @Override public void onReceiver(Context context,Intent intent){ //这里需要权限,需要在AndroidManifest.xml中进行网络访问权限申请: //<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.isAvailable()) { //有网 Toast.makeText(context, "network is available",Toast.LENGTH_SHORT).show(); } else { //无网 Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show(); } } } }
动态注册广播接收器的优点以及缺点:
- 动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大优势,
- 缺点:即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在 onCreate() 方法中的。那么有没有广播能在程序未启动的情况下就能接收到广播呢?静态注册的广播接收器就可以做到。
4. 源码角度分析广播机制
4.1 系统广播的源码角度分析
- 自定义广播接收者 BroadcastReceiver ,并且重写 onReceiver() 方法。
- 通过 Binder 机制向 AMS(Activity Manager Service) 进行注册。
- 广播发送者通过 Binder 机制向 AMS 发送广播。
- AMS 查找符合条件 (IntentFilter/Permission等) 的 BroadcastReceiver,将广播发送到相应的 BroadcastReceiver (一般情况下是Activity)的消息队列中。
- 消息循环执行拿到此广播,回调 BroadcastReceiver 中的 onReceiver() 方法。
4.2 本地广播的源码角度分析
相比于系统广播而言,本地广播更加安全,更加高效,
以下是本地广播的特点以及内部的实现机制:
特点:
- 使用它发送的广播将只在自身app内传播,不必担心泄漏隐私的数据。
- 其他app无法对你的app发送该广播,因此你的app根本不可能收到非自身app 发送的该广播,不必担心有安全漏洞可以利用。
- 比系统广播更加高效。
内部实现机制:
-
LocalBroadcast 高效 的原因:因为它内部是通过 Handler 实现的,它的 sendBroadcast() 方法含义并非和系统的sendBroadcast()一样,它的 sendBroadcast() 方法其实就是通过 Handler 发送了一个 Message 而已。
-
LocalBroadcast 安全 的原因:既然它是通过Handler实现广播发送的,那么相比系统广播通过Binder机制实现那肯定更加高效,同时使用Handler来实现,别的app无法向我们应用发送该广播,而我们app内部发送的广播也不会离开我们的app。
LocalBroadcast 内部协作主要是靠两个 Map 集合:mReceivers 和 mActions ,当然还有一个 List 集合 mPendingBroadcasts,这个主要存储待接收的广播对象。
4.3 广播发送和接收的原理 ?(Binder机制、AMS)
声明:android开发分享Android之Broadcast总结篇整理自网络,如有侵权请及时联系。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/addevelopment/895783.html