Android基础 - BroadcastReceiver

老婆保佑,代码无BUG

目录

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

一.什么是广播

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

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

Android基础 - BroadcastReceiver_第1张图片
举个例子

比如:老村长拿个喇叭喊话,谁家羊丢了?(发送广播的人),所有村名都听到了(其他单独的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中配置

 
            
                
            
 

参数解释

参数 说明
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

对比

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

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);

    
        
    

总结

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

你可能感兴趣的:(Android基础 - BroadcastReceiver)