BroadcastReceiver本质上是一个全局监听器,用于监听系统全局的广播消息(在android O系统之后进行了改动,启动BroadcastReceiver的Intent必须是显式Intent,就像启动service的intent一样。要么直接设置BroadcastReceiver类名,要么通过action和package来设置显式Intent)。
对比监听器onXXXlistener 和 BroadcastReceiver:
onXXXlistener监听器是程序级的,程序退出,监听器即关闭。BroadcastReceiver是系统级的,有自己的进程。只要匹配的Intent被广播出来,就会被触发。
注意:因为每次Broadcast事件发生后,系统会自动创建BroadcastReceiver实例并触发onRecevice方法,执行结束后销毁BroadcastReceiver实例。所以如果需要BroadcastReceiver实现一个耗时的工作最好考虑使用IntentService来完成,而不是开一个线程,因为BroadcastReceiver的生命周期很短,可能线程未执行完毕BroadcastReceiver就退出了,如果此时系统内存紧张可能优先结束掉该线程。
2 BroadcastReceiver配置/注册广播注册的方式分为两种:静态注册、动态注册。两者差异如下:
动态注册:是当用来注册的Activity关掉后,广播也就失效了。静态注册:无需担忧广播接收器是否被关闭,只要设备开启,广播接收器就有效。 2.1 静态注册
指的是在AndroidManifest.xml里声明,如下所示:
常见属性一般有name、exported(是否允许被其他应用调用),permission(启动service需要的权限)、process(该service所在进程,默认是在APP进程中,但可以指定其他进程),这里针对2个关键参数进行说明:
android:enabled属性:此broadcastReceiver能否接收其他App的发出的广播,默认值由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为false。intent-filter中的android:priority属性:取值范围1000~-1000,数值越大,优先级别就越高。 2.2 动态注册
不在xml文件中配置,而是在代码中进行注册和注销。在activity中动态注册关键流程如下所示:
public class MainActivity extends AppCompatActivity { private static String TAG = "MainActivity"; //1 定义receiver和filter MyReceiver myReceiver = new MyReceiver(); IntentFilter filter = new IntentFilter(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //... } @Override protected void onResume() { super.onResume(); //2 添加action filter.addAction("com.ags.myreceiver"); //3 注册receiver registerReceiver(myReceiver,filter); Log.d(TAG, "onResume: registerReceiver"); } @Override protected void onPause() { super.onPause(); //4 注销receiver unregisterReceiver(myReceiver); Log.d(TAG, "onPause: unregisterReceiver"); } }
注意:注销 *** 作unregisterReceiver不要再onStop和onDestroy *** 作中进行,因为如果应用在后台运行,此时内存不足进行回收时,可能导致不回执行onStop和onDestroy *** 作,进而导致内存泄露。
3 BroadcastReceiver关键方法BroadcastReceiver广播涉及2个角色:广播发送者 和 广播接收者。
3.1 广播发送者广播分为普通广播和有序广播
普通广播:异步执行的广播,所有广播几乎会在同一时刻接收到该通知。有序广播:同步执行的广播,多个广播接收器可以设置不同的优先级,同一时间只有一个广播接收器会收到通知。一个广播接收者处理完给到下一个广播接收器,以此类推。
发送正常广播用 sendBroadcast;有序广播用 sendOrderedBroadcast。均属于Context类的方法。其方式如下:
//1 普通广播,异步,receiver1 receiver2 receiver3 几乎同时收到 sendBroadcast(new Intent("com.ags.myreceiver")); //2 有序广播,同步,receiver1 receiver2 receiver3 依次收到 sendOrderedBroadcast(new Intent("com.ags.myreceiver"));3.2 广播接收者
onReceive函数实现,代码如下所示:
public class MyReceiver extends BroadcastReceiver { private static String TAG = "MyReceiver"; @Override public void onReceive(Context context, Intent intent) { //接收广播并进行处理,可以接收intent消息,也可以做其他各种处理 //注意:不要做耗时任务处理。如果有需要启动一个service来做 String content = intent.getStringExtra("msg"); Log.d(TAG, "onReceive content: "+content); } }4 LocalBroadcastManager本地广播
@1 LocalBroadcastManager是一种局部广播,广播的发送者和接收者都同属于一个App。
@2 LocalBroadcastManager的优劣势说明:
LocalBroadcastManager优势:广播是消耗资源较多的方式,若只在自己app内进行广播,可以采用本地广播。发送广播是在APP内,不会泄漏到别的APP中,且比BroadcastReceiver更高效。同时对于单个应用程序使用BroadcastReceiver存在安全风险。LocalBroadcastManager劣势:只能一个app内广播,不能跨进程通信。
@3 对比LocalBroadcastManager与BroadcastReceiver :
BroadcastReceiver底层是Binder机制,因此可以实现跨进程通信。LocalBroadcastManager底层是Handler机制,handleMessage中对广播进行处理。 4.1 LocalBroadcastManager发送端
public class MainActivity extends AppCompatActivity { private static String TAG = "MainActivity"; private Button btn_start; private MyReceiver myReceiver = new MyReceiver(); private IntentFilter filter = new IntentFilter(); private LocalBroadcastManager localBroadcastManager = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //1 本地广播管理者获取 localBroadcastManager = LocalBroadcastManager.getInstance(this); btn_start = findViewById(R.id.btn_start); btn_start.setonClickListener(new View.onClickListener() { @Override public void onClick(View v) { //Intent对象构建 Intent intent = new Intent(); intent.setAction("com.ags.myreceiver"); intent.setPackage("com.ags.myapplication"); intent.putExtra("msg","receivertest"); //4 本地广播发送 localBroadcastManager.sendBroadcast(intent); } }); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "onResume: registerReceiver"); filter.addAction("com.ags.myreceiver"); //2 本地广播注册 localBroadcastManager.registerReceiver(myReceiver,filter); } @Override protected void onPause() { Log.d(TAG, "onPause: unregisterReceiver"); super.onPause(); //3 本地广播注销 localBroadcastManager.unregisterReceiver(myReceiver); } }
看代码我们会发现本地广播采用动态注册的方式,这里只不过不使用Context的注册/注销方式和发送广播的方式,而是 LocalBroadcastManager的注册/注销方式和发送广播的方式。
4.2 LocalBroadcastManager接收端同上3.2,receiver部分并无差别,onReceive函数实现,代码依然如下所示:
public class MyReceiver extends BroadcastReceiver { private static String TAG = "MyReceiver"; @Override public void onReceive(Context context, Intent intent) { //接收广播并进行处理,可以接收intent消息,也可以做其他各种处理 //注意:不要做耗时任务处理。如果有需要启动一个service来做 String content = intent.getStringExtra("msg"); Log.d(TAG, "onReceive content: "+content); } }5 接收系统广播消息
所谓系统广播,即系统完成某项任务后执行sendBroadcast或sendOrderedBroadcast相关 *** 作。对于APP本身而言只需要 静态/动态 注册广播监听器和配置好相应的权限,实现监听器中onReceive函数即可。
Android系统中内置很多系统广播,涉及到手机的基本 *** 作如:开机、网络状态变化、拍照等等,都会发出相应的广播。更多系统广播关注文档:Android 系统Broadcast Intents (API Level 30)总结
6 粘性广播(Sticky Broadcast)粘性广播(Sticky Broadcast)在 android 5.0 就已经不再推荐使用,相应的还有粘性有序广播。
7官方文档索引关于Broadcast更多内容查看文档:Android 组件之broadcast组件
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)