BroadcastReceiver
开发中,可能用到的知识点,可能遇到的问题进行总结。Android
开发过程中的难题。最后,希望大家都能有所收获,欢迎食用!
稀土掘金
简书
CSDN
博客园
等站点,都有新内容发布。所以大家可以直接关注该仓库,以免错过精彩内容!
Android
、JVM
、算法等,各位帅气的老铁支持一下!给个 Star !
BroadcastReceiver
,顾名思义就是“广播接收者”的意思,它是Android四大基本组件之一。app
发送的广播android
系统的 Binder
机制.SendOrderedBroadcast()
方法来发送广播,同时也可调用 abortBroadcast()
方法拦截该广播。可通过 标签中设置 android:property
属性来设置优先级,未设置时按照注册的顺序接收广播。setResultData
方法将数据传给下一个接收器。getStringExtra
函数获取广播的原始数据,通过 getResultData
方法取得上个广播接收器自己添加的数据,并可用 abortBroadcast
方法丢弃该广播,使该广播不再被别的接收器接收到。A > B > C
,Context.sendOrderedBroadcast ( intent , receiverPermission , resultReceiver , scheduler , initialCode , initialData , initialExtras )
时我们可以指定 resultReceiver
为最终广播接收者.onReceive
会执行两次sd
卡挂载, 低电量, 外拨电话, 锁屏等对前一部分 “ 请描述一下
BroadcastReceiver
” 进行展开补充
APP
内部的消息通信。
APP
之间的消息通信。
Android
系统在特定情况下与 APP 之间的消息通信。
BroadcastReceiver
,并实现抽象方法 onReceive ( context, intent )
。默认情况下,广播接收器也是运行在主线程,因此 onReceiver()
中不能执行太耗时的操作( 不超过 10s
),否则将会产生 ANR
问题。onReceiver()
方法中涉及与其他组件之间的交互时,可以使用发送 Notification
、启动 Service
等方式,最好不要启动 Activity
。
Android
系统内置了多个系统广播,只要涉及手机的基本操作,基本上都会发出相应的系统广播,如开机启动、网络状态改变、拍照、屏幕关闭与开启、电量不足等。在系统内部当特定时间发生时,系统广播由系统自动发出。
Intent
中的 Action
为如下值:
android.provider.Telephony.SMS_RECEIVED
ACTION_BATIERY_LOW
ACTION_BATTERY_CHANGED
ACTION_POWER_CO
Android 7.0
开始,系统不会再发送广播 ACTION_NEW_PICTURE
和 ACTION_NEW_VIDEO
,对于广播 CONNECTIVITY_ACTION
必须在代码中使用 registerReceiver
方法注册接收器,在 AndroidManifest
文件中声明接收器不起作用。Android 8.0
开始,对于大多数隐式广播,不能在 AndroidManifest
文件中声明接收器。APP
APP
不会受到局部广播,不用担心数据泄露的问题。APP
不可能向当前的 APP
发送局部广播,不用担心有安全漏洞被其他 APP
利用。Android v4
包中提供了 LocalBroadcastManager
类,用于统一处理 APP 局部广播,使用方式与全局广播几乎相同,只是调用注册 / 取消注册广播接收器和发送广播偶读方法时,需要通过 LocalBroadcastManager
类的 getInstance()
方法获取的实例调用。在 AndroidManifest.xml
文件中配置。
<receiver android:name=".MyReceiver" android:exported="true">
<intent-filter>
<!-- 指定该 BroadcastReceiver 所响应的 Intent 的 Action -->
<action android:name="android.intent.action.INPUT_METHOD_CHANGED"
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
android: exported
其作用是设置此 BroadcastReceiver
能否接受其他 APP
发出的广播 ,当设为 false
时,只能接受同一应用的的组件或具有相同 user ID
的应用发送的消息。这个属性的默认值是由 BroadcastReceiver
中有无 Intent-filter
决定的,如果有 Intent-filter
,默认值为 true
,否则为 false
。android: permission
如果设置此属性,具有相应权限的广播发送方发送的广播才能被此 BroadcastReceiver
所接受;如果没有设置,这个值赋予整个应用所申请的权限。Context
的 registerReceiver ( BroadcastReceiver receiver , IntentFilter filter )
方法指定。app
还在运行,那么会一直收到广播消息app
里: 自定义一个类继承 BroadcastReceiver
然后要求重写 onReveiver
方法public class MyBroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyBroadCastReceiver", "收到信息,内容是 : " + intent.getStringExtra("info") + "");
}
}
Action
, 就那么简单完成接收准备工作<receiver android:name=".MyBroadCastReceiver">
<intent-filter>
<action android:name="myBroadcast.action.call"/>
</intent-filter>
</receiver>
Activity
或者 Service
销毁了那么就会接收不到广播.app
里的 MainActivity
添加一个注册按钮 , 用来注册广播接收者Action
//onCreate创建广播接收者对象
mReceiver = new MyBroadCastReceiver();
//注册按钮
public void click(View view) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("myBroadcast.action.call");
registerReceiver(mReceiver, intentFilter);
}
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public void click(View view) {
Intent intent = new Intent();
intent.putExtra("info", "消息内容");
intent.setAction("myBroadcast.action.call");
sendBroadcast(intent);
}
app
之后:app
直接发广播就收到了app
先代码注册,然后另一个 app
直接发广播即可.-Android
中的广播使用了设计模式中的观察者模式:基于消息的发布 / 订阅事件模型。3
个角色:AMS
,即 Activity Manager Service
)Binder
机制在 AMS
( Activity Manager Service
) 注册;
Binder
机制向 AMS
发送广播;
AMS
根据广播发送者要求,在已注册列表中,寻找合适的 BroadcastReceiver
( 寻找依据:IntentFilter / Permission
);
AMS
将广播发送到 BroadcastReceiver
相应的消息循环队列中;
onReceive()
方法。
LocalBroadcastManager
来对广播进行管理,并提供了发送广播和注册广播接收器的方法。
BroadcastReceiver
子类,并重写 onReceive ( Context context, Intetn intent )
方法即可。
sendBroadcast()
、sendStickyBroadcast()
、sendOrderBroadcast()
方法发送广播消息时,如果该 BroadcastReceiver
也对该消息“感兴趣”,BroadcastReceiver
的 onReceive ( Context context, Intetn intent )
方法将会被触发。
Activity
时,需要为 Intent
加入 FLAG_ACTIVITY_NEW_TASK
标记,否则会报错,因为需要一个栈来存放新打开的 Activity
。Alertdialog
时,需要设置对话框的类型为 TYPE_SYSTEM_ALERT
,否则无法弹出。onReceiver()
方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,当 onReceiver()
方法运行了较长时间而没有结束时,程序就会报错。Android
引入了 StickyBroadcast
,在广播发送结束后会保存刚刚发送的广播( Intent
),这样当接收者注册完 Receiver
后就可以继续使用刚才的广播。
Action
的粘性广播,注册完成后只会收到一条该 Action
的广播,并且消息内容是最后一次广播内容。
Context
的 sendStickyBroadcast ( Intent )
接口发送,需要添加权限uses-permission android:name=”android.permission.BROADCAST_STICKY”
Context
的 removeStickyBroadcast ( Intent intent )
接口移除缓存的粘性广播APP
无法对你的 APP
发送该广播,因为你的APP根本就不可能接收到非自身应用发送的该广播,因此你不必担心有安全漏洞可以利用;
LocalBroadcastManager
内部协作主要是靠这两个 Map
集合:MReceivers
和 MActions
,当然还有一个 List 集合 MPendingBroadcasts
,这个主要就是存储待接收的广播对象。
LocalBroadcastManager
高效的原因主要是因为它内部是通过 Handler
实现的,它的 sendBroadcast()
方法含义并非和我们平时所用的一样,它的 sendBroadcast()
方法其实是通过 handler
发送一个 Message
实现的;
Handler
来实现广播的发送的,那么相比于系统广播通过 Binder
实现那肯定是更高效了,同时使用 Handler
来实现,别的应用无法向我们的应用发送该广播,而我们应用内发送的广播也不会离开我们的应用;
BroadcastReceiver
设计的初衷是从全局考虑可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver
是存在安全性问题的 ( 恶意程序脚本不断的去发送你所接收的广播 ) 。为了解决这个问题 LocalBroadcastManager
就应运而生了。
LocalBroadcastManager
是 Android Support
包提供了一个工具,用于在同一个应用内的不同组件间发送 Broadcast
。LocalBroadcastManager
也称为局部通知管理器,这种通知的好处是安全性高,效率也高,适合局部通信,可以用来代替 Handler
更新 UI
Android
系统中的广播可以跨进程直接通信,会产生以下两个问题:APP
可以接收到当前 APP
发送的广播,导致数据外泄。APP
可以向当前 APP
放广播消息,导致 APP
被非法控制。permission
,用于权限验证。Android 4.0
及以上系统中发送广播时,可以使用 setPackage()
方法设置接受广播的包名。permission
,用于权限验证。android:exported
的值为false。permission
APP
必须申请相应权限,这样才能收到对应的广播,反之亦然。app
端,自定义定义权限, 那么想要接收的另外 app
端必须声明权限才能收到.<permission android:name="broad.ok.receiver" android:protectionLevel="normal"/>
<uses-permission android:name="broad.ok.receiver" />
public void click(View view) {
Intent intent = new Intent();
intent.putExtra("info", "消息内容");
intent.setAction("myBroadcast.action.call");
sendBroadcast(intent, "broad.ok.receiver");
//sendOrderedBroadcast(intent,"broad.ok.receiver");
}
<uses-permission android:name="broad.ok.receiver"/>
onReceiver
方法里,直接调用判断方法得返回值public void onReceive(Context context, Intent intent) {
Log.d("MyBroadCastReceiver", "收到信息,内容是 : " + intent.getStringExtra("info") + "");
boolean isOrderBroadcast = isOrderedBroadcast();
}
BroadcastReceiver
一般处于主线程。ANR
BroadcastReceiver
启动时间较短。BroadcastReceiver
组件。并且在其中开启子线程执行耗时任务。BroadcastReceiver
知识总结了,前前后后投入了大量时间来完成。希望大家通过本次阅读都能有所收获。重点
:关于 Android
的四大组件,到现在为止我才总结完 Activity
、Service
、BroadcastRecevier
等,以及事件分发、滑动冲突、新能优化等重要模块,进行全面总结,欢迎大家关注 _yuanhao 的 CSDN ,方便及时接收更新CSDN
」「博客园」等站点,都有新内容发布。所以大家可以直接关注我的 GitHub
仓库,以免错过精彩内容!
Android
、JVM
、算法等,各位帅气的老铁支持一下!给个 Star !