Android四大组件之BroadcastReceiver

概述

该组件本质上是一种全局的监听器,用于监听系统全局的广播消息。

  • 用于接收应用App发出的广播消息,并做出响应。

  • 实现BroadcastReceiver方法很简单,只需要重写它的onReceive(Context context,Intent intent)方法即可。

  • 生命周期很短。当系统Broadcast事件发生后,系统会创建对应的BroadcastReceiver的实例,并自动触发onReceive()方法,当该方法执行完后,BroadcastReceiver的实例就会被销毁。

  • 如果onReceive()方法不能在10s内执行完成,会弹出ANR,因此不要在该方法中执行一些耗时的操作。

应用场景

  • 不同组件之间的通信(App内/不同App之间)

  • 多线程通信

注册方式

  • 静态注册:在AndroidManifest.xml文件中配置。
        <receiver
            <!--继承BroadcastReceiver子类的类名-->
            android:name=".MyReceiver"
            <!--是否启用此broadcastReceiver-->
            android:enabled="true"
            <!--此broadcastReceiver能否接收其它App发出的广播,对于有intent-filter情况下默认值为true-->
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
        </receiver>
  • 动态注册:在代码中调用Context.registerReceiver(BroadcastReceiver receiver, IntentFilter filter)方法。
     MyReceiver receiver = new MyReceiver();

     IntentFilter intentFilter = new IntentFilter();
     intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
     //IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");

     registerReceiver(receiver , intentFilter);
     //unregisterReceiver(receiver);

动态注册最好在Activity的onResume()注册,onPause()注销。

区别

  • 静态注册:应用程序关闭后,如果有广播来,依旧会被调用。不受任何组件的生命周期影响。需要时刻监听广播。

  • 动态注册:跟随组件的生命周期变化,在组件结束前必须移除广播接收器。需要特定时刻监听广播。

注意:Android 8.0对广播进行了限制。因此当使用静态注册失效时,可以改成动态注册方式。

Android 8.0

来源:https://developer.android.google.cn/about/versions/oreo/background

广播类型:

  • 普通广播(Normal Broadcast):是完全异步的,可以在同一时刻被所有接收者接收到,消息传递的效率比较高,且无法被截断。缺点是不能传递。
    普通广播发送只需要调用Context的sendBroadcast(Intent intent)方法即可,该广播将会启动intent参数所对应的BroadcastReceiver。
Intent intent = new Intent();
intent.setAction("android.intent.action.BOOT_COMPLETED");
sendBroadcast(intent);
  • 有序广播(Ordered Broadcast):是一种同步执行的广播。在广播发出后同一时刻只有一个广播接收器能够接收到, 优先级高的广播接收器会优先接收,当优先级高的广播接收器的 onReceiver() 方法运行结束后,广播才会继续传递,且前面的广播接收器可以选择截断广播。
    (1) 优先级别声明在<intent-filter.../>元素的android:priority属性中,数越大优先级别越高。也可调用IntentFilter对象的setPriority()进行设置。
    (2) 优先级的大小设置范围为-1000~1000。
    (3) 发送广播调用sendOrderedBroadcast()方法。
    (4) 可以调用setResultExtras(bundle)方法存入数据使得下一个广播能够接收。
    (5) 在onReceiver() 方法中调用aboryBroadcast()方法截断广播,使得不再传递下去。

  • 本地广播(Local Broadcast):
    之前所说的都是属于全局广播,即发出的广播可以被其它应用接收到,也可以接收其它应用发出的广播,会存在数据安全问题。
    在某些情况下,使用本地广播,该广播只能在应用内部进行传递,而且也只能接收本应用内发出的广播。
    实现1:全局广播 --> 本地广播
    (1) 注册广播时将exported属性设置为false,使得非本应用内部发出的此广播不被接收。
    (2) 在广播发送和接收时,增设相应权限permission,用于权限验证。
    (3) 发送广播时指定该广播接收器所在的包名,此广播将只会发送到此包中的应用内与之相匹配的有效广播接收器中。
    实现2:使用LocalBroadcastManager类
    注册时调用LocalBroadcastManager的registerReceiver方法替代全局广播调用context的registerReceiver方法。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
        localReceiver = new LocalReceiver();
        IntentFilter filter = new IntentFilter(LOCAL_ACTION);
        manager.registerReceiver(localReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(localReceiver);
    }
    
    public void sendLocalBroadcast(View view) {
        Intent intent = new Intent(LOCAL_ACTION);
        localBroadcastManager.sendBroadcast(intent);
    }

  • 系统广播(System Broadcast)

Android的大量系统事件都会对外发送标准广播。以下是常见的广播Action:

  • android.net.conn.CONNECTIVITY_CHANGE:监听网络变化
  • Intent.ACTION_AIRPLANE_MODE_CHANGED:关闭或打开飞行模式时的广播
  • Intent.ACTION_BOOT_COMPLETED:在系统启动完成后,这个动作被广播一次(只有一次)
  • Intent.ACTION_DATE_CHANGED:系统日期发生改变
  • Intent.ACTION_TIME_CHANGED:系统时间发生改变
  • Intent.ACTION_TIMEZONE_CHANGED:系统时区发生改变
  • Intent.ACTION_LOCALE_CHANGED:设备当前区域设置已更改
  • Intent.ACTION_BATTERY_CHANGED:充电状态,或者电池的电量发生变化
  • Intent.ACTION_BATTERY_LOW:表示电池电量低
  • Intent.ACTION_BATTERY_OKAY:表示电池电量充足,即从电池电量低变化到饱满
  • Intent.ACTION_CONFIGURATION_CHANGED:设备当前设置被改变时(包括:界面语言,设备方向,等)
  • Intent.ACTION_REBOOT:重启设备
  • Intent.ACTION_SCREEN_OFF:屏幕被关闭
  • Intent.ACTION_SCREEN_ON:屏幕被打开
  • Intent.ACTION_SHUTDOWN:关闭系统
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容