个人对广播使用得不多,在目前接触的项目开发中暂时没有使用到广播作为组件间交流工具,仅仅是在做应用复活的时候,接触过利用系统广播拉活的机制(现在已经不那么灵验了)。不过广播接收者作为Android四大组件之一,其重要性自然不言而喻 ,也是各类面试的常客,还是得好好总结一番。
定义
广播是一种广泛应用的在应用程序之间传输信息的机制,Android中我们要发送的广播内容是一个Intent,这个Intent中可以携带我们要传送的数据。
使用场景
A、同一个app不同组件之间的消息通信(可以同进程或者不同进程)。
B、不同的app之间的组件之间进行通信。
种类与使用方式
- 普通广播(Normal Broadcast)
- 系统广播(System Broadcast)
- 有序广播(Ordered Broadcast)
- 粘性广播(Sticky Boradcast),在Android 5.0即API 21已经被废弃
- 本地广播(Local Broadcast)
1. 普通广播
普通广播就是我们最常使用的一种广播,使用方法如下:
* 发送:我们在代码中通过创建Intent,设置action,再通过Context调用sendBroadcast(Intent)方法发送。
* 接收:
* 自定义一个广播接收者类继承自BroadcastReceiver,重写里面的onReceive(…)方法。
* 通过静态或者动态方式注册广播接收者:
* 静态:
在AndroidManifest.xml文件中的application标签内注册
java
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="123"/>
</intent-filter>
</receiver>
* 动态:
“` java
@Override
protected void onResume() {
super.onResume();
mReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter(“123”);
registerReceiver(mReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
```
要注意的是通过动态注册时,一定要记得注销。Activity的声明周期是成对出现的,因此在onResume方法中注册,在onPause方法中注销。因为当Activity由于内存不足被回收时,只能保证onPause方法被调用,在onPause方法中进行注销从而能避免内存泄漏。
2. 系统广播
系统广播是Android系统内置的广播。当手机状态发生改变时,系统会发出相应的预设的广播。具体有哪些系统广播请随时搜索,不同版本谷歌会增删一些广播。要注意的是不要总是期望能接收到系统广播,一些国产ROM出于安全考虑可能会屏蔽掉某些系统广播。
3. 有序广播
有序广播与普通广播类似,差别只在于发送时调用的是sendOrderedBroadcast(Intent)
方法。有序广播发出去后,会根据广播接收者的优先级,按序传递,优先级高的广播接收者先接收到广播,可以对广播进行修改后再传递给优先级较低的广播接收者。也可以通过abortBroadcast()
方法将广播拦截,这样优先级较低的广播接收者将无法再接收到这条广播。
至于广播接收者的优先级,可以通过IntentFilter的setPriority(int)方法设置。
4. 粘性广播
在Android 5.0 / Api 21中已被废弃
5. 本地广播
为了解决其他应用通过注册与当前应用一致的IntentFilter来接收一些敏感的广播的安全问题,可以使用本地广播。顾名思义,本地广播是只发往同个应用内的广播,其他应用无法收到。发送本地广播需要使用LocalBroadcastManager来进行,使用方法如下:
public class MainActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
private BroadcastReceiver mReceiver;
private LocalBroadcastManager mLbm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view) {
Intent intent = new Intent("123");
mLbm.sendBroadcast(intent);
sendBroadcast(intent);
Log.i(TAG, "发送广播了");
}
@Override
protected void onResume() {
super.onResume();
if (mReceiver == null) {
mReceiver = new MyBroadcastReceiver();
}
if (mLbm == null) {
IntentFilter intentFilter = new IntentFilter("123");
mLbm = LocalBroadcastManager.getInstance(this);
mLbm.registerReceiver(mReceiver, intentFilter);
}
}
@Override
protected void onPause() {
super.onPause();
if (mLbm != null && mReceiver != null) {
mLbm.unregisterReceiver(mReceiver);
}
}
}
除了通过这种方法来保证广播的安全性之外,我们还可以在发送普通广播的时候,利用Intent指定接收的应用的包名,避免发送给其他应用,如下:
intent.setPackage(String packageName);
上面两种方式能保证我们发送的广播只被自身应用接收到。而要使应用内自定义的广播接收者不接受其他应用的广播,只需要在注册广播接收者的时候指定exported
属性为false
就可以了:
<receiver android:name=".MyBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="123"/>
</intent-filter>
</receiver>
exported属性如果没有设置,默认有intent-filter时为true,否则为false