android中的四大组件之一,也是一种消息机制,可在app内、app间传递消息。还可以接受系统发送的广播(开机广播、网络状态等)
自定义广播接收器
public class SomeReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if("com.my.action.SOME_ACTION".equals(action)){
//...
}
}
}
onReceive()方法必须在10秒内完成,否则导致ANR。耗时操作最好发送到Service中执行,因为BroadcastReceiver生命周期短Thread容易被回收。
注册
静态注册
在AndroidManifest.xml的<application/>
中:
<receiver android:name=".SomeReceiver"
android:exported="true"
android:permission="string"
android:process="string">
<intent-filter android:priority="int">
<action android:name="com.my.action.SOME_ACTION"/>
</intent-filter>
</receiver>
一个广播可以设置多个action。
几个属性说明下:
属性 说明 android:exported 是否接收外部app发送的广播,如果设置了 intent-filter
则默认为true,否则为falseandroid:permission 如果设置此属性,则发送方必须声明相应权限时发送的广播才能被接收到 android:process 该广播接收器组件运行时的进程。app进程或独立进程 android:priority 优先级设置[-1000, 1000]
动态注册
public class MainActivity extends Activity {
public static final String ACTION_1 = "com.my.action.SOME_ACTION";
private BroadcastReceiver mBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBroadcastReceiver = new SomeReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_1);
registerReceiver(mBroadcastReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBroadcastReceiver);
}
}
注册 / 取消注册 结对使用。此时广播接收在Activity生命周期内。
发送/类型
普通广播(NormalBroadcast)
Intent intent = new Intent();
intent.setAction("com.my.action.SOME_ACTION");
context.sendBroadcast(intent);
被所有广播接收者接收到
有序广播(OrderedBroadcast)
Intent intent = new Intent();
intent.setAction("com.my.action.SOME_ACTION");
context.sendOrderedBroadcast(intent, null);
设置优先级android:priority=”int”,范围[-1000, 1000],值越大优先级别越高;
或 IntentFilter.setPriority() 设置;被接收者依次接收广播;
如:优先级A > B > C,则传递顺序A -> B -> C。
可以被拦截而不往下传递,BroadcastReceiver.abortBroadcast()
此方法意味着广播不再传播出去。
可以修改数据,在intent中改数据或者添加数据,后面的接收器可以接收这些数据;
如果都有两个广播都设置成1000,会出现啥情况?(因为没试过,我也不知道)
关于显式/隐式意图
广播组件一般使用的都是隐式。
显式意图发送广播
发送时指定广播接收器的具体类(类似一对一私聊)
隐式意图发送广播
<intent-filter>
<action android:name="com.my.action.SOME_ACTION"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="*/*"/>
<data android:scheme="string" android:host="string"/>
</intent-filter>
按接收规则声明注册的多个广播接收器皆可接收到广播(类似一对多群发);如发送的action和接收的action一致则接受者都能接收(比很多app都会监听开机广播)。
版本变更
Android 3.1(api 12) 对stoped应用的启动控制
从Android3.1开始,系统包管理器会管理应用是不是stoped状态, 应用stoped状态是指第一次安装还没有被启动或者被人为的在应用管理中强行停止了的状态。 并且所有由系统发出的广播都设置了FLAG_EXCLUDE_STOPPED_PACKAGES'
,这样做防止了后台服务的广播无意的或不必要的启动那些处于stoped状态的应用;
要注意的是应用的stoped状态非指activity的stoped状态,系统会单独的管理新加入的状态,不要混为一谈;
在platform中定义了两个intent的flag:
/** * If set, this intent will not match any components in packages that * are currently stopped. If this is not set, then the default behavior * is to include such applications in the result. */ public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 0x00000010; /** * If set, this intent will always match any components in packages that * are currently stopped. This is the default behavior when * {@link #FLAG_EXCLUDE_STOPPED_PACKAGES} is not set. If both of these * flags are set, this one wins (it allows overriding of exclude for * places where the framework may automatically set the exclude flag). */ public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020;
比如发送广播时,当intent中没有设置这两个falg或者都设置了,则广播都会发送到那些处于stoped状态的应用;如果只设置了
FLAG_EXCLUDE_STOPPED_PACKAGES
则处于stoped状态的应用不会收到广播;
Android5.0(21) deprecated粘滞性广播
Context.sendStickyBroadcast()
此广播使用时需要设置权限
Android (22) android.support.v4中加入的 LocalBroadcastManager
Android8.0 广播限制