BroadcastReceiver作为Android四大组件之一,即广播。广播分为发送者和接收者。要想使用广播,首先必须先注册广播接收者,然后接着发送广播。最后在接收者中处理广播。
其中广播接收者需继承BroadcastReceiver并重写onReceive来实现,onReceive就是最终处理广播的方法。
注意:Android中规定了BroadCastReceiver不能处理复杂长时间的逻辑操作,如果在onReceive方法在10s内没法执行完毕,则系统会视之为未响应状态,可能会报ANR错误。可以将这些耗时操作放在Service中开辟子线程去执行。
BroadcastReceiver分以下几个来写:
- 静态注册
- 动态注册
- 有序广播
- 本地广播
- 图解BroadcastReceiver源码处理过程
静态注册广播
静态广播注册:在AndroidManifest.xml中注册BroadcastReceiver。
首先定一个广播接收者StaticReceiver.java
/**
*
* author: chmj
* time : 2017/8/23
* desc : 广播接收者,需要继承BroadcastReceiver,并且重写onReceive方法。其中intent参数就是发送的时候的Intent。
*
*/
public class StaticReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取广播的数据.
String msg = intent.getStringExtra("test");
LogHelper.i("静态广播接收消息....." + msg);
}
}
接着在在AndroidManifest中注册:
注意这里的action,这个属性是这个广播的标志。在我们发送广播的时候会加入广播标志,在接收的时候只有改广播标志对上的才能接收。
在Activity中发送广播。
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 1、通过sendBroadcast将广播的Intent发送出去,Intent可以携带数据.
* 2、setAction表示为intent设置上一个action,即给这个广播添加一个标志,
* 后续只有和这个标志匹配的广播接收者才可以收到。
*/
Intent intent = new Intent();
//广播标志. 在静态注册中即在在AndroidManifest中需拦截这个action。
intent.setAction("com.broadcast.static");
//数据.
intent.putExtra("test","test data 123");
//发送广播
sendBroadcast(intent);
}
});
动态注册广播
动态注册,即在代码中注册,用到IntentFileter这个类包装Receiver然后通过registerReceiver去注册。动态注册可以反注册,静态注册的广播不能取消,一直存在到app退出。一般动态注册在onCreate中注册。在onDestroy中进行反注册.
同样定一个广播接收者DynamicReceiver.java
/**
*
* author: chmj
* time : 2017/8/23
* desc : 广播接收者,需要继承BroadcastReceiver,并且重写onReceive方法。其中intent参数就是发送的时候的Intent。
*
*/
public class DynamicReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取广播的数据.
String msg = intent.getStringExtra("test");
LogHelper.i("动态广播接收消息....." + msg);
}
}
动态注册即在代码中注册,我们一般在onCreate里面注册。通过IntentFileter这个类包装Receiver然后通过registerReceiver去注册。
private DynamicReceiver mDynamicReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_common_broad_cast_context);
//包装Receiver
IntentFilter intentFilter = new IntentFilter();
//添加标志
intentFilter.addAction("com.broadcast.dynamic");
mDynamicReceiver = new DynamicReceiver();
//动态注册广播
registerReceiver(mDynamicReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mDynamicReceiver);
}
注册完,然后发送广播。
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
//广播标志. 在静态注册中即在在AndroidManifest中需拦截这个action。
intent.setAction("com.broadcast.dynamic");
//数据.
intent.putExtra("test","test data 123");
//发送广播
sendBroadcast(intent);
}
});
有序广播
上面那两种广播发送方式都是无序的,有序广播通过sendOrderedBroadcast发送,而接受者Receiver的Action是同一个,只不过他们通过priority属性进行优先级的判定。priority越大优先级越高,优先级最高的会第一个拦截广播并处理,然后才会往下传递.
首先我们定义3个广播接收者:
FirstReceiver
public class FirstReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("msg");
LogHelper.i("This is the First msg from Activity " + msg);
/**
* 接着发送消息,action是一样的,下面的Receiver根据priority优先级来判断由谁来接收.
*
*/
setResultData("FirstReceiver send msg ");
setResultCode(100);
}
}
接收到广播处理之后,要想在传数据给下一个广播接收者使用,就用setResultData,setResultExtras等方法。而下一个广播接收者要想获取上一个广播接收者传过来的信息,就用getResultData,getResultExtras等。
SecondReceiver
public class SecondReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取上一个广播传过来的信息
String msg = getResultData();
//获取code
int code = getResultCode();
/**
* getResultExtras:参数为true的时候如果Bundle是空的,则会创建一个Bundle返回,如果是false,则直接返回Bundle对象.
*/
Bundle bundle1 = getResultExtras(false);
Bundle bundle2 = getResultExtras(true);
LogHelper.i("----idOrderBroadcast----" + isOrderedBroadcast());
LogHelper.i("---bundle1--" + bundle1 + " bundle2 " + bundle2);
LogHelper.i("---msg--" + msg + " code " + code);
Bundle bundle = new Bundle();
bundle.putString("test","444444");
setResultExtras(bundle);
}
}
这里getResultExtras:参数为true的时候如果Bundle是空的,则会创建一个Bundle返回,如果是false,则直接返回Bundle对象.
ThirdReveiver
public class ThirdReveiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(false);
String msg = bundle.getString("test");
LogHelper.i("ThirdReveiver msg " + msg);
}
}
注册三个广播接收者
这里注意priority这个参数,priority值越高越优先,在这边FirstReceiver优先级最高,则从activity发出来的广播,最先被它拦截处理。
发送广播通过sendOrderedBroadcast;
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
//广播标志. 在静态注册中即在在AndroidManifest中需拦截这个action。
intent.setAction("com.broadcast.order");
//数据.
intent.putExtra("test","test data 123");
//发送广播
sendOrderedBroadcast(intent,null);
}
});
本地广播
本地广播,通过LocalBroadcastManager来注册,不需要考虑安全问题,因为它只在应用内部有效。是安全的广播。
同样定一个广播接收者DynamicReceiver
public class DynamicReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取广播的数据.
String msg = intent.getStringExtra("test");
LogHelper.i("动态广播接收消息....." + msg);
}
}
注册的时候需通过LocalBroadcastManager来注册。
private LocalBroadcastManager mLocalBroadcastManager;
private LocalReceiver mLocalReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_common_broad_cast_context);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext);
mLocalReceiver = new LocalReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.broadcast.local");
//本地广播注册.
mLocalBroadcastManager.registerReceiver(mLocalReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocalBroadcastManager.unregisterReceiver(mLocalReceiver);
}
发送广播也是通过LocalBroadcastManager来发送。
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.broadcast.local");
//数据.
intent.putExtra("msg","test data 123");
//发送本地广播需要通过LocalBroadcastManager来发送.
mLocalBroadcastManager.sendBroadcast(intent);
}
});
用三张图来看看源码处理广播的过程。