广播是一种可以跨进程通信的方式。
1、分两种:
有序广播(同步执行的广播,同一时刻只会有一个广播接收器能收到这条广播信息,可被拦截)和标准广播(异步执行的广播)。
2、接受系统广播
Android内置了很多系统级别的广播,可在程序中通过监听这些广播得到各种系统的状态信息。有两种方式:
1)动态注册广播
原理类似与收听收音机,首先你要打开收音机,然后调频到相应频道来接受广播,最后可把接受到的信息自由处理,比如插耳机听或者直接听。
动态注册广播的原理:先创建一个广播接收器(即开机),然后注册要监听的广播类型(即调频到哪个频道),最后使用广播接收器接受信息并处理。动态注册的广播接收器一定要取消注册:在onDestroy()中调用unregisterReceiver(networkChangeReceiver);
//调频
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
NetworkChangeReceiver netRec = new NetworkChangeReceiver();
//使用广播接收器接受广播
registerReceiver(netRec, intentFilter);
//创建一个广播接收器
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
}
}
优点:可自由控制注册与注销。
缺点:必须在程序启动后才能接受广播,因为注册的逻辑在Activity中。
2)静态注册广播接收器
原理:创建一个广播接收器,在清单文件中注册该广播。
<receiver android:name=".BootCompleteReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
优点:不用启动程序就能接受广播。
注意事项:广播接收器的onReceive()中不要添加过多的逻辑或者进行任何耗时的操作,因为广播接收器中是不允许开线程的,当onReceive()运行了较长时间而没有结束时,程序就会报错。因此广播接收器更多是扮演一种打开程序其他组件的角色。
3、发送自定义广播
1)发送标准广播
接受自定义广播的原理与接受系统广播的原理相同。只是在调频时需调频到自己的广播频道,即intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");中的内容需改成自定义的广播,如:com.example.broadcasttest. MY_BROADCAST。
系统广播由系统发出,而自定义广播须由自己发出:
Intent intent = new Intent("com.example.broadcasttest. MY_BROADCAST");
sendBroadcast(intent);
2)发送有序广播
Intent intent = new Intent("com.example.broadcasttest. MY_BROADCAST");
sendOrderedBroadcast(intent, null);//第二个参数是与权限相关的字符串
设定广播接收器的先手顺序:在注册时设定。
<receiver android:name=".MyBroadcastReceiver">
<intent-filter android:priority="100" >
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
priority设置优先级,优先级比较高的广播接收器可先收到广播。那如何阻止广播继续传递呢?在广播接收器中调用abortBroadcast();即可。
4、使用本地广播
需求:前面发送的广播都属于系统全局广播,即发出的广播可被其他任何程序接收到,并且也可接收到来自其他任何程序的广播。为了简单解决广播安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序内部进行传递,并且广播接收器也只能接受来自本应用程序发出的广播。
原理:使用LocalBroadcastManager来对广播进行管理,并提供了发送广播和注册广播接收器的方法。
// 获取实例
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent); // 发送本地广播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
// 注册本地广播监听器
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received local broadcast",
Toast.LENGTH_SHORT).show();
}
}
本地广播是无法通过静态注册的方式来接受的。
5、广播实现强制下线
原理:发送一个广播,然后接受到广播后将所有activity都结束(所以需要静态注册广播),打开登陆activity。
贴下广播收到消息后的下线处理:
public void onReceive(final Context context, Intent intent) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle("Warning");
dialogBuilder.setMessage("You are forced to be offline. Please try to login again.");
dialogBuilder.setCancelable(false);
dialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCollector.finishAll(); // 销毁所有活动
Intent intent = new Intent(context, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); // 重新启动LoginActivity
}
});
AlertDialog alertDialog = dialogBuilder.create();
// 需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); alertDialog.show();
}
注意事项:
1)由于强制弹出了一个系统级别的对话框,所以需要加权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />如果不加权限:
2)如果没有这个标识:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);将不会跳转到LoginActivity界面。
3)如果没有alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)将会报错:因为Broadcast并没有界面,而AlertDialog需要一个token来放置在其上。此处我们可选择放置在系统上。