android 基础04-BroadCastReceiver

时间:2023-03-08 18:53:02

Android 系统中的广播(BroadCast) 是组件与组件进行的一种可跨线程的通信方式。类似于 广播者-订阅者(publish-subscribe) 的实现,当系统或者某个应用的状态发生改变时,发出一个消息来通知其它应用来处理或适应这种改变。发出的这个消息就是 BroadCast. 例如,当系统的电量发生变化时,系统就会发出一个广播,系统的网络状态发生变化时会发出一个 广播。应用可以对自己感兴趣的广播进行接收并处理。

Android 中 广播的分类

  Android 中的广播可以分为两种:标准广播和有序广播

  • 标准广播(Normal BroadCast

  是一种完全以异步方式实现的广播。当广播消息发出后,所有的接收者几乎会在同一时间接收到这个广播,没有任何的先后顺序

  • 有序广播(Ordered BroadCast)

  这种广播以同步的方式来实现。当广播消息发出后,优先级高的接受者总是先于优先级低的接受者收到广播,这种情况下必须上一级的接受者的处理工作完成后才能继续往下传递。甚至优先级高的接受者可以对广播进行截断,被截断后的广播将不再往下传播了。其它的接受者将无法接受到该广播。


  在注册 BroadCastReceiver 时,可以在 Intent-Filter 节点的 android:priority 属性来设置该 Receiver 的优先级(介于 -1000~1000 的整数)


系统广播

  当各种系统事件发生的时候,系统会自动的发出一个广播.广播的信息被包裹在一个 Intent 对象中,Intent 对象的标识字符串(Identity string)会指明所发生的事件,例如,android.intent.action.BOOT_COMPLETED,表明系统启动完成,在 Android SDK目录下的 BROADCAST_ACTIONS.txt 文件中,你可以看到所有的系统 Broadcast-Action。

接受系统广播

  下面的例子,当系统的网络状态发生变化时,在 LogCat 中输出当前的网络状态

  首先,我们需要定义一个广播接收器类(Broadcast Receiver),对接受的广播进行处理

	public class NetWorkStatusChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo(); if(info !=null && info.isAvailable()){
Log.i(TAG,"当前通过 " + info.getTypeName() + " 网络访问");
}else{
Log.i(TAG,"网络连接已断开");
} }
}

  在 AndroidManifest.xml 进行配置,包括两个部分,一部分是获取访问网络状态的权限,一部分是 BrocastReceiver 的注册

  获取权限

	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

  BrocastReceiver 的注册

	 <receiver android:name=".NetWorkStatusChangeReceiver"
android:enabled="true"
android:exported="true"
>
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>

  在模拟器设置中打开关闭移动网络时,便可以在 LogCat 中看到输出的信息。


  这个例子中我们使用的注册 BrocastReceiver 的方式称为 静态注册(Manifest-declared receivers),既写在 AndroidManifest.xml 文件中。使用此种注册方式注册的 BroadcastReceiver, Android 系统会通过系统包管理器 (System Package Manager) 在应用安装时注册,注册的 Receiver 会成为除了点击应用图标启动应用外的一个独立的应用启动入口。当有广播发出时,如果应用没有在运行,系统可以启动该应用,然后将广播传递给它。

  当收到一条广播时,系统总是会实例化一个新的 BroadCastReceiver 组件去处理该广播。需要注意的是这个 BroadCastReceiver 组件仅在其 onReceiver 内是有效的,如果代码从该方法返回,那么系统就会认为该组件不再处于激活状态了。


BoradCastReceiver 的动态注册

  有静态注册,肯定就有 动态注册 (Context-registered receivers). 动态注册指的是在应用程序运行期间对 BroadCastReceiver 进行注册。

  这里我们使用 动态注册的方法对上面的例子进行重写。

	NetWorkStatusChangeReceiver receiver = new NetWorkStatusChangeReceiver();
IntenFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(receiver,filter);

  做完这些就算是完成了 BroadCastReceiver 动态注册的过程.(不要忘记权限的配置)

  通过这种方式注册的 BroadCastReceiver 的生存期长短与其注册时的上下文(Context)有关。如果在一个 Activity 中注册,那么只要这个 Activity 没有被销毁,在其中所注册的 BroadCastReceiver 便是有效的。如果通过 APPContext 进行注册,那么其在整个应用的运行期间都是有效的。


注意: 动态方式注册的 BroadCastReceiver 在不再需要使用或者其上下文无效的时候手动解除注册(UnResiger).例如,如果注册的上下文是一个 Activity,如果在 onCreate(Bundle) 中进行注册,则必须在 onDestory 中解除注册。防止 BroadCastReceiver 脱离上下文而存在。如果在 onResume 中进行注册,则必须在 onPaused 中解除注册。以避免 BroadCastReceiver 被重复注册。


发送广播

  发送一个自定义广播之前需要先定义一个 BroadCastReceiver 来接受该广播,否则发出的广播没有人接受那是没有意义的。下面的例子展示如何发送一个广播

	Intent intent = new Intent();
intent.setAction("packageName.ActionIdentity");
intent.putExtra("data","send some message to you");
sendBroadCast(intent);

  上面的例子,首先实例化一个 Intent 对象,然后设置它的 Action 信息(应用包名称 + BroadCast 事件的唯一标识,方便 BroadCastReceiver注册时 Intent-Filter的筛选 ),如果要发送一个 有序广播 ,可以调用 sendOrderedBroadCast(Intent,String),除此之外,与发送 标准广播 相同。

  不论是发送标准广播还是有序广播,其 send***BroadCast 方法都可以接受一个 String类型的

名称为 permission 的参数,用于指定目标广播接受者所必须具有的权限。既只有被授予了该权限的应用内注册的 BroadCastReceiver 才能给收到该广播(既在应用的 AndroidManifest.xml 文件中请求了该权限)。

	sendBroadCast(intent,Manifest.permission.ACCESS_NETWORK_STATE);

  上面的例子,只有具有 访问网络状态权限的应用内注册的 BroadCastReceiver 才能够接受到该广播

  同样,在注册 BroadCastReceiver 时同样可以为其声明一个权限属性,同样只有具有指定权限的应用发出的广播才会被该 Receiver 接受

	<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.SEND_SMS">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>

  Receiver 还可以设置一个 android:export 属性,当设为 FALSE 时,便不再接受所在应用之外BroadCast

本地广播(LocalBroadCast)

  上面所说的广播都是全局广播,既广播发出后设备上的任何一个应用都能够接受,本地广播是相对全局广播来说的,当发出一个本地广播时只有与广播发出者所在的应用才能够接受到。

  发送一个本地广播,需要 Android support 包的支持

	Intent intent = new Intent();
intent.setAction("packageName.ActionIdentity");
intent.putExtra("data","send some message to you");
LocalBroadcastManager.sendBroadcast(intent);

  到这里,关于 BroadReceiver 的基础知识就介绍完了。