Android基础 - BroadcastReceiver

老婆保佑,代码无BUG

目录

  • 什么是广播
  • 如何使用广播
  • 注册广播的方式
  • 广播的类型
  • 不同注册方式的广播接收器回调
  • 不同Android API版本中广播机制相关API重要变迁

一.什么是广播

作为Android 4大组件之一,压力山大。

系统或者本应用程序通过发送广播的形式告诉其他app现在系统或者本app的状态
这种方式称为广播的发送

举个例子

比如:老村长拿个喇叭喊话,谁家羊丢了?(发送广播的人),所有村名都听到了(其他单独的app)

二.如何使用广播

广播的三要素

  • 发送广播
  • 接受广播
  • 处理广播

下面一一分析

如何使用广播

public class MainActivity extends AppCompatActivity {

    private TestBroadCast broadCast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //发送广播
        findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //1.模拟发送广播 (一般写的都是action条件,不用组件名)
                //自定义action条件
                //在任何app,只要接收器的条件是allens都可以接收数据
                Intent intent = new Intent("allens");
                intent.putExtra("data", "测试发送广播...");
                //核心方法
                sendBroadcast(intent);
            }
        });

        

        //动态注册广播
        findViewById(R.id.register).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 第一个参数:自定义接收器的实例化对象
                 * 第二个参数:构建IntentFliter条件
                 */
                IntentFilter filter = new IntentFilter();
                //添加的action条件,匹配频道使用
                filter.addAction("allens");
                //设置优先级
                filter.setPriority(Integer.MAX_VALUE);
                broadCast = new TestBroadCast();
                registerReceiver(broadCast, filter);
            }
        });

        
        //取消注册
        findViewById(R.id.unregister).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              if (broadCast != null) {
                    unregisterReceiver(broadCast);
                    broadCast = null;
                }
            }
        });
    }
}

public class TestBroadCast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String value = intent.getStringExtra("data");
        Log.e("TAG","data--->" + value);
    }
}

三.注册广播的方式

  • 动态注册
    在上面的例子中 可以看到 我们使用代码动态注册了广播,也动态的取消注册广播,这是一中方式,当然还有其他的方式

  • 静态注册

manifest中配置

 <receiver
            android:name=".broadcast.TestBroadCast"
            android:enabled="false"
            android:exported="true"
            android:icon="@drawable/ic_launcher_background"
            android:label="@string/app_name"
            android:permission="@string/app_name"
            android:process="@string/app_name">
            <intent-filter android:priority="2000">
                <action android:name="allens" />
            </intent-filter>
 </receiver>

参数解释

参数 说明
intent-filter 过滤器,筛选广播条件
android:name 这里的name 要和我们发送广播的action 相同,不然收不到广播
android:priority 2000到-2000 ,通过priority设置优先级
android:enabled true (默认的是true)设置为true广播接收器才能够被启用,false该广播接收器会被禁止实例化(不能使用)
android:exported 是否能够接收来自应用程序外部的消息
android:icon 定义一个代表广播接收器的图标
android:label 这个属性给广播接收器设定一个用户可读的懂的文本标签
android:name 这个属性值要用广播接收器的实现类的类名来设置
android:permission 把消息发送给该广播接收器的广播器所必须要有的权限
android:process 这个属性用于设置该广播接收器应该运行在那个进程中的进程名

当然这些属性,也不用全写上,更具实际情况,

参考
http://blog.csdn.net/think_soft/article/details/7583047

对比

类型 优点 缺点
静态注册 常驻广播,不受生命周期影响 耗电,占内存
动态注册 灵活, 必须跟随组件的生命周期,及时释放资源
来个美女提提神,不然你们都快睡觉了都,哈哈

so 继续

四. 广播的类型

普通广播(Normal Broadcast)
系统广播(System Broadcast)
有序广播(Ordered Broadcast)
粘性广播(Sticky Broadcast)
App应用内广播(Local Broadcast)

1.普通广播

定义:开发者自己定义的intent,像上面我们使用的就是普通广播

Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction("自定义的action");
//发送广播
sendBroadcast(intent);
<receiver 
    //此广播接收者类是开发者自定义的BroadcastReceiver
    android:name=".BroadcastReceiver" >
    <intent-filter>
        <action android:name="自定义的action" />
    </intent-filter>
</receiver>

总结

1.顺序是无序的
2.需要在intent-filter自定义action
3.如果发送广播时有相应的权限要求,BroadCastReceiver如果想要接收此广播,也需要有相应的权限

2.系统广播

Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。如:开启启动,网络状态改变,拍照,屏幕关闭与开启,点亮不足等等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出

android 系统广播action

3.有序广播

有序广播的有序广播中的“有序”是针对广播接收者而言的,指的是发送出去的广播被BroadcastReceiver按照先后循序接收。有序广播的定义过程与普通广播无异只是其的主要发送方式变为

sendOrderedBroadcast(intent);

特点

1.按照Priority属性值从大-小排序;
2.Priority属性相同者,动态注册的广播优先;
3.先接收的BroadcastReceiver可以对此有序广播进行截断,使后面的BroadcastReceiver不再接收到此广播,也可以对广播进行修改,使后面的BroadcastReceiver接收到广播后解析得到错误的参数值。当然,一般情况下,不建议对有序广播进行此类操作,尤其是针对系统中的有序广播

4.粘性广播

定义:广播的信息内容系统会存放一段时间,任何时间内app都可以获取数据

sendStickyBroadCast

由于在Android5.0 & API 21中已经失效,相应的还有粘性有序广播,所以不建议使用,在这里也不作过多的总结。

5.App应用内广播

由前文阐述可知,Android中的广播可以跨进程甚至跨App直接通信,且注册是exported对于有intent-filter的情况下默认值是true,由此将可能出现安全隐患如下

1 .其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理

2.其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息

常见改进方式

1.对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的此广播不被接收

2.在广播发送和接收时,都增加上相应的permission,用于权限验证;

3.发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。

说了那么多,所以才有了App应用内广播,其特点如下

1.安全性更高;
2.更加高效

如何使用呢?

//注册应用内广播接收器
//步骤1:实例化BroadcastReceiver子类 & IntentFilter mBroadcastReceiver 
mBroadcastReceiver = new mBroadcastReceiver(); 
IntentFilter intentFilter = new IntentFilter(); 

//步骤2:实例化LocalBroadcastManager的实例
localBroadcastManager = LocalBroadcastManager.getInstance(this);

//步骤3:设置接收广播的类型 
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

//步骤4:调用LocalBroadcastManager单一实例的registerReceiver()方法进行动态注册 
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

//取消注册应用内广播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

//发送应用内广播
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
localBroadcastManager.sendBroadcast(intent);

五. 不同注册方式的广播接收器回调onReceive(context, intent)中的context具体类型

类型 context具体类型
静态注册的ContextReceiver ReceiverRestricted Context
全局广播的动态注册的ContextReceiver Activity Context
通过LocalBroadcastManager动态注册的ContextReceiver Application Context

注意:对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册的ContextReceiver才有可能接收到(静态注册或其他方式动态注册的ContextReceiver是接收不到的)

六. 不同Android API版本中广播机制相关API重要变迁

Android 3.1开始

  • 自Android3.1开始,静态注册的广播接收器,app已经退出,有相应的广播发出,接收不到

原因:自Android3.1开始,系统本身则增加了对所有app当前是否处于运行状态的跟踪。在发送广播时,不管是什么广播类型,系统默认直接增加了值为FLAG_EXCLUDE_STOPPED_PACKAGES的flag,导致即使是静态注册的广播接收器,对于其所在进程已经退出的app,同样无法接收到广播

Android 3.1开始系统在Intent与广播相关的flag增加了参数,分别是

  • FLAG_INCLUDE_STOPPED_PACKAGES:包含已经停止的包(停止:即包所在的进程已经退出)

  • FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已经停止的包

android 5.0开始

  • Android5.0/API level 21开始粘滞广播和有序粘滞广播过期,以后不再建议使用;

android 7.0开始

  • 彻底没有静态注册的方式啦,哈哈 为了省电

写在最后

关于7.0 以上的广播方案,会在后面慢慢补充,实话说啊,这东西真的好好看,抽个空静下心好好研究一下,这些细节上的事情,都是平时开发时候的坑啊。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容