广播的动态注册和静态注册以及系统广播的使用!
作者:燕潇洒
导读:前面在说使用广播实现进程间的被动通信的时候,没有考虑到大家是否懂得如何发送广播,在http://blog.csdn.net/yanxiaosa/article/details/59116262这篇博客中,只是稍微说一下广播的简单发送和接收,今天,来给大家说一下,广播的注册(动态和静态)、发送和接收;
Android广播机制概述
Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广
播接收者(广播接收器)。广播作为Android组件间的通信方式,可以使用的场景如下:
1.同一app内部的不同组件之间的消息通信(单个进程);
2.不同app之间的组件之间消息通信;
3.Android系统在特定情况下与App之间的消息通信。
4.同一app内部的同一组件内的消息通信(单个或多个线程之间);
5.同一app具有多个进程的不同组件之间的消息通信;
自定义BroadcastReceiver
自定义广播接收器需要继承基类BroadcastReceivre,并实现抽象方法onReceive(context,
intent)方法。广播接收器接收到相应广播后,会自动回到onReceive(..)方法。默认情况下,广播接
收器也是运行在UI线程,因此,onReceive方法中不能执行太耗时的操作。否则将因此ANR(我在
onReceive方法中sleep10秒并没有出现ANR,但并不说明可以进行耗时操作,具体以官方文档为
主),onReceive方法中都会涉及到与其他组件之间的交互,如发送Notification、启动service等。
下面就是一个简单的广播接收者的例子:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if("SendNotify".equals(intent.getAction())){
Toast.makeText(context, "收到广播", Toast.LENGTH_SHORT).show();
}else if(Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())){//接受系统广播
Toast.makeText(context, "充电器连接了", Toast.LENGTH_SHORT).show();
}
}
}
BroadcastReceiver的注册类型
BroadcastReceiver总体上可以分为两种注册类型:静态注册和动态注册。
静态注册
所谓静态注册就是直接在清单文件(AndroidManifest)中进行注册:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xiao.androidzhujie">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="SendNotify"></action>
</intent-filter>
</receiver>
</application>
</manifest>
上面的标签就是静态注册广播,需要将其写在标签之内,它是与标签同等级的.在标签中需要注意的有:
android:exported ——-此broadcastReceiver能否接收其他App的发出的广播,这个属性默认值有点意思,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。(同样的,activity/service中的此属性默认值一样遵循此规则)同时,需要注意的是,这个值的设定是以”application”或者”程序唯一标识”为界的,而非进程为界(一个应用中可能含有多个进程);
android:name ——是broadcastReceiver类名;
android:permission—-如果设置,那么具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;
- android:process—–broadcastReceiver运行所处的进程。默认为app的进程。可以指定独立的进程(Android四大基本组件都可以通过此属性指定自己的独立进程)
动态注册
动态注册时,无须在清单文件(AndroidManifest)中注册组件。直接在代码中通过调用Context的registerReceiver函数,可以在程序中动态注册BroadcastReceiver。registerReceiver的定义形式如下:
registerReceiver(BroadcastReceiver receiver, IntentFilter filter);
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler);
经常使用的写法示例如下:
public class BroadCastReceiverActivity extends Activity {
/**
* 广播接收者
*/
private MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broad_cast_receiver);
initBroadCast();
}
/**
* 动态注册广播
*/
public void initBroadCast(){
myReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter("SendNotify");
registerReceiver(myReceiver,filter);
}
@Override
protected void onDestroy() {
unregisterReceiver(myReceiver);
super.onDestroy();
}
}
注:当此Activity实例化时,会动态将MyReceiver注册到系统中。当此Activity销毁时,动态注册的MyReceiver将不再接收到相应的广播,需要我们在onDestroy方法中调用unregisterReceiver方法,将不再使用的广播取消注册。
动态注册的案例
以上面的代码为例,我们在这里完善一下,在一个新的activity中,我们声明了一个按钮,然后再activity中初始化这个按钮,给按钮一个点击事件,在点击事件中发送一个广播:
public class BroadCastReceiverActivity extends Activity {
/**
* 发送广播的按钮
*/
private Button btn_send_notify;
/**
* 广播接收者
*/
private MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broad_cast_receiver);
initBroadCast();
btn_send_notify = (Button) findViewById(R.id.btn_send_notify);
btn_send_notify.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//指定广播的action(频道)
Intent intent = new Intent("SendNotify");
//广播附带的消息内容
intent.putExtra("you","我发了一个广播");
sendBroadcast(intent);
}
});
}
/**
* 动态注册广播
*/
public void initBroadCast(){
myReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter("SendNotify");
registerReceiver(myReceiver,filter);
}
@Override
protected void onDestroy() {
unregisterReceiver(myReceiver);
super.onDestroy();
}
}
现在已经发送了广播,那么,谁来接收呢?我们来继承BroadcastReceiver自定义自己的接受者:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//根据action过滤广播内容
if("SendNotify".equals(intent.getAction())){
Toast.makeText(context, "收到广播"+intent.getStringExtra("you"), Toast.LENGTH_SHORT).show();
}
}
}
到此结束,一个动态广播就可以使用了,我们运行看效果:
静态注册
依然以上面的代码为例:我们把动态注册换成静态注册,打开清单文键,在application节点中加上节点:
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="SendNotify"></action>
</intent-filter>
</receiver>
再次运行程序,这里就不再加图片了,因为效果和上面的图片一模一样.
系统广播
为了避免繁琐,我们依旧使用动态注册的代码。android系统为我们提供了很多系统的广播,例如:低电量时的提醒,关机提醒等等,我们在这里使用usb连接手机时发送广播,我们使用静态注册的方式来实现,在上面的静态注册中,我们依旧使用MyReceiver作为接受者,在清单文件中,我们把节点中的name改成系统广播的名称:
<receiver android:name=".reciver.MyReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action>
</intent-filter>
</receiver>
然后在广播接受者中过滤这个系统广播:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if("SendNotify".equals(intent.getAction())){
Toast.makeText(context, "收到广播---->>>>"+intent.getStringExtra("you"), Toast.LENGTH_SHORT).show();
}else if(Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())){//接受系统广播
Toast.makeText(context, "充电器连接了", Toast.LENGTH_SHORT).show();
}
}
}
这里我们并没有去掉上一个广播的过滤,所以我们两个广播都会收到,再次运行,看效果:
我们在插上数据线的时候就会触发这个广播…
广播的基本使用到这里就结束了,我们讲了广播的动态和静态注册,还有系统广播的使用,在这篇http://blog.csdn.net/yanxiaosa/article/details/59116262博文中,我们讲了使用广播实现两个app之间的通信,如果你看完了广播的基本使用,就去看看使用广播实现进程间的通信这篇文章了.
http://blog.csdn.net/yanxiaosa/article/details/59116262