摘要:Android系统通过广播接收器能实时监听系统中的广播信息,人们在使用手机时,如遇电话或者短信,系统会将电话或短信设计为优先级最高的程序。广播接收器是Android四大组件之一,在Android系统中内置了很多系统级别的广播,为更好地掌握Android系统中广播,笔者分析了BroadcastReveiver的概念、分类和广播生命周期,最后通过“电台和收音机”的案例来演示自定义广播的发送和接收过程。
关键词:广播;广播接收器;常驻型广播;非常驻型广播;自定义广播
0 广播接收器的概念
广播接收器(BroadcastReveiver)是用来过滤、接收并响应广播的一类组件,通过广播接收器可以监听系统中的接收广播消息,在不同组件之间进行通信。同样,在Android系统中内置了很多系统级别的广播,例如,手机开机完成后会发送一条广播,电池电量不足时也会发送一条广播等。为了监听这些广播事件,Android中提供了一个BroadcastReveiver组件,该组件可以监听来自系统或者应用程序的广播。
图1 广播的发送与接收过程
如图1所示,当Android系统产生一个广播事件时,可以有多个对应的BroadcastReveiver接收并进行处理。这些广播接收器只需要在清单文件或者代码中进行注册并指定要接收的广播事件,再通过一个类继承自BroadcastReveiver类,并使用onReveive()方法进行处理。
1 广播接收器创建和注册
1.1 广播接收器创建
要对监听的广播事件进行处理,需要创建一个类继承自BroadcasReceiever,然后重写onReceive()方法,具体代码如下所示:
当监听到有广播发出时,系统就会自动调用onReceive(),在onReceive()中对事件进行处理。
1.2 广播接收器注册
要使用广播接收器接收其他应用程序发出的广播,先要在本应用中创建广播接收器并进行注册。注册广播有两种方式,常驻型广播(静态注册)和非常驻型广播(动态注册)。
(1)注册常驻型广播
常驻型广播是当应用程序关闭后,一旦接受到其他应用程序发出的广播,该程序便会自动重新启动,在应用程序中的AndroidManifest.xml注册,称其为“静态注册”。常驻型广播需要在清理文件中注册,具体代码如下所示:
上述代码是在清理文件中注册的监听短信接收的广播,android:name=“cn.itcast.xxx”是创建的广播接收器的全路径名;与定义隐式意图一样,广播接收器也需要注册一个<intent-filter>,在过滤器中指定要接收的广播事件,“Android.provider.Telephony.SMS_RECEIVED”是系统内定义的短信接收的广播事件;Android.provider=“20”是该广播的优先级,这个值越大代表接收的优先级越高,优先级的作用会在后边介绍。
(2)注册非常驻型广播
非常驻型广播依赖于注册广播的组件的生命周期,例如,在Activiyty中的onCreate或者OnResume注册广播接收器,通过onDestory销毁广播接收器,销毁后广播随之被移除,称其为“动态注册”,其需调用context中的registerReceiver方法。
这种广播事件在代码中注册,具体代码如下所示:
上述代码就是在代码中注册广播事件,MyBroadCastReceiver是自己定义的继承子BroadCastReceiver的类。代码中IntentFilter的含义是对象负责过滤掉组件无法响应和处理的Intent,只处理自己关心的隐式Intent(显式的Intent是直接传送到目标组件)。Android组件中有一个或多个IntentFilter,IntentFilter之间是相互独立的,仅需一个一个验证通过则可。
与清单文件中注册一样,代码注册广播同样需要进行过滤,IntentFilter接收的是监听的广播事件。最后用registerReceiver函数进行注册。
与清单文件注册广播不同的是,代码有注册也有移除,比如在Activity的onCreate()中注册广播,就要在onDestory()中进行解除广播,如下代码所示:
需要注意的是,广播接收器的生命周期是非常短暂的,从创建到onReceive()方法结束之后销毁。常驻型广播在应用程序关闭后,接收到广播会重新自动创建。非常驻型广播则依赖于与注册广播组件的生命周期和调用unregisterReceiver()方法手动移除。动态注册的广播的优先级总是高于静态注册得优先级,不管静态注册的广播优先级有多高。
总之,常驻型广播是在xml中注册的,当appBack退出后,还能够接收到其他app发送的广播;而非常驻型广播,广播接收器是随着Activity的生命周期创建而创建,销毁而销毁的。activity组件在注册一个广播接收器时,并不是真的将广播接收器注册到ActivityManagerService中,而是将与它相关联的IntentReceiver对象注册到ActivityManagerService中,当ActivityManagerService接受到一个广播的时候,ActivityManagerServiceb必须先根据广播的类型在内部找到对应的IntentReceiver对象,然后再找到广播接收器。动态注册使用隐式intent方式的,静态注册可以使用显示Intent和隐式Intent,但通常使用隐式Intent去发送广播。
2 广播接收器的生命周期
BroadcastReceiver是在Android中的一个特色功能,其生命周期很短,仅在执行这个方法时处于活跃状态,创建执行完毕后立刻销毁,如图2所示:
图2 广播接收者生命周期
动态注册可以理解为通过代码注册的广播是和注册者关联在一起的,一个监听SDcard状态的广播接收器,使用动态注册的BroadcastReceiver可以随时加入到代码中,比较方便。但是要注意,必须适时的unregister,否则会有内存泄漏,再者,其生命周期是有限的。
静态注册的BroadcastReceiver,需要在manifest文件中标出,并继承BroadcastReceiver类,此方法生成的对象,只在调用onReceive()时有效,一旦返回就无效,一定程度上可以认为此receiver一直有效。Application对象虽然可以保存一些全局数据,生命周期也比较长,但是在清理数据方面可能会有问题,使用时也要慎重。
需要注意的是,广播接收器的生命周期是非常短暂的,在接收到广播的时候创建,onCreate()方法结束之后销毁。常驻型广播在应用程序关闭后,接收到广播会重新自动创建。非常驻型广播则依赖于注册广播组件的生命周期和调用unregisterReceiver()方法手动移除。动态注册的广播的优先级总是高于静态注册得优先级,不管静态注册的广播优先级有多高。
3 自定义广播
在实际开发中,有时为了满足一些特殊的需求还需要自定义广播,比如屏幕关闭,电池电量低等广播,同样可以发起自定义“由开发者定义的”广播。广播是从一个应用内部向另一个应用发送消息的途径之一。
3.1 自定义广播的发送与接收
Android系统中自带了很多广播,如果需要监听某个广播,只需创建对应的广播接收器即可。当这些系统级别的广播事件不能满足实际需求时,还可以自定义广播,需要注意的是自定义广播必须要有对应的广播接收器。
BroadcastReceiver是一个可以监听和响应广播的组件,下面举例来阐述如何发送自定义广播以及如何通过编程和使用Manifest文件定义一个BroadcastReceiver来监听这一广播。
图3 自定义广播的发送与接收过程
当自定义广播发送一条消息时,这个广播消息会存在于一个公共区域中,有广播接收器监听这个消息区时,就会及时地接收到广播消息(如图3所示)。因此,可以通过这种自定义的广播来处理程序中的特殊功能。
3.2 自定义广播的应用
下面简单介绍“电台与收音机”的案例,演示自定义广播的发送与接收过程。
3.2.1 创建程序
(1)创建一个名为“电台与收音机”的应用程序,将包名修改为cn.itcast.broadcast,设计用户相互界面。(2)创建电台与收音机程序对应的布局文件(activity-main.xml),定义一个Button按钮,并为该按钮注册一个点击事件send,当用户点击按钮时,会发送一条广播。采用MainActivity的send()方法完成广播的发送功能,首先创建一个Inter对象,然后通过Inter.setAction(“www.itcast.cn”)语言指定广播事件的类型,最后通过sendBroadcast(intent)语句将广播发送出去。
3.2.2 添加广播接收器
添加广播接收器MyBroadcasReceiver,接收电台发送的广播,当接收到广播事件时输出“自定义的广播接收器…”,在onReceive()方法里输入两个Log,当MyBroadcastReceiver接收到广播时就会输入这些Log。在清单文件中注册广播接收器MyBroadcastReceiver,并通过意图过滤器来指定广播的事件类型为“www.itcast.cn”。
3.2.3 运行程序发送广播
运行程序,单击“电台发送自定义广播”按钮,发送一个自定义广播,此时观察LogCat窗口中打印的提示信息,自定义的广播接收器MyBroadReceiver成功地接收到电台发送的广播,并输出对应的广播事件。需要注意的是,自定义广播的类型与广播接收器在清单文件中配置的类型要一致,否则无法接受到广播。
4 结语
近年来,针对Android组件安全的研究不断深入,但对于作为Android的四大组件之一的广播接收器研究确少之又少。本文对Android的广播机制进行了全面的分析,阐述了注册广播两种方式的区别与应用和广播的生命周期,重点阐述了自定义广播的发送和接收过程。重点提出一些在操作中应该注意的细节,如:在Android4.0以下的系统中,当进程不存在时,只要有广播发出,进程就会自动创建并接收广播进行处理;在Android4.0以上系统中,则当在任务管理界面强行停止进程后,再有广播发出也不会打开进程进行接收了。