Android四大组件,除了activity外,用的最多的估计就是BroadcaseReceiver.
广播分为两种广播类型:
- 标准广播(无序)
- 有序广播
无序广播就是指所有的广播接收者都可以接收到所需要的信息,有序广播则不然,有序广播可根据优先级进行接收,中间可能会被拦截。
大家都知道,广播为Android四大组件之一,想要使用他必须要注册。
广播注册形式分为两种: - 静态注册(清单文件中注册)
- 动态注册(代码中注册)
下面就通过一个实例在展示每种广播形式。
监听手机网络变化
/**
*动态注册广播监听网络变化
*1.注册广播
*2.创建netWorkChangeReceiver类继承BroadCastReceiver,实现onReceiver()方法
*
*/
public class MainActivity extends Activity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
//动态注册
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//解除广播
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes",
Toast.LENGTH_SHORT).show();
//得到网络连接管理器
ConnectivityManager connectionManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
//通过管理器得到网络实例
NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
//判断是否连接
if (networkInfo != null && networkInfo.isAvailable()) {
Toast.makeText(context, "network is available",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "network is unavailable",
Toast.LENGTH_SHORT).show();
}
}
}
}
代码中注释比较清楚了。就不进行说明了。
记得别忘记了添加权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
有的人可能会说了,如果这个类不存在了,就接收不到广播了,如果需要打开应用就接收到广播的话,就需要静态注册了。
实现开机启动功能
<receiver android:name=".BootCompleteReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
在清单文件的Application标签下进行注册。action是必不可少的。
创建BootCompleteReceiver类
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}
需要注意的是,不要在onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收
器中是不允许开启线程的,当onReceive()方法运行了较长时间而没有结束时,程序就会报错。
刚才一直说的接收广播,下面来看看发送自定义广播:
在发送广播之前,我们还是需要先定义一个广播接收器来准备接收此广播才行,不然发
出去也是白发。因此新建一个MyBroadcastReceiver 继承自BroadcastReceiver,代码如下所示:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceiver",
Toast.LENGTH_SHORT).show();
}
}
在清单文件中注册
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="com.example.broadcasttest. MY_BROADCAST"/>
</intent-filter>
</receiver>
接下来就是发送广播了:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//action和清单文件中的action对应
Intent intent = new Intent("com.example.broadcasttest.
MY_BROADCAST");
//发送广播
sendBroadcast(intent);
}
}
发送本地广播:
为了能够简单地解决广播的安全性问题,Android 引入了一套本地广播机制,使用这个
机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用
程序发出的广播,这样所有的安全性问题就都不存在了。
本地广播的用法并不复杂,主要就是使用了一个LocalBroadcastManager 来对广播进行
管理,并提供了发送广播和注册广播接收器的方法。下面我们就通过具体的实例来尝试一下
它的用法,修改MainActivity 中的代码,如下所示:
public class MainActivity extends Activity {
private IntentFilter intentFilter;
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
localBroadcastManager = LocalBroadcastManager.getInstance(this);
// 获取实例
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.
LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent); // 发送本地广播
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
// 注册本地广播监听器
}
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received local broadcast",
Toast.LENGTH_SHORT).show();
}
}
}
最后我们再来盘点一下使用本地广播的几点优势吧。
1. 可以明确地知道正在发送的广播不会离开我们的程序,因此不需要担心机密数据泄
漏的问题。
2. 其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐
患。
3. 发送本地广播比起发送系统全局广播将会更加高效。
强制下线功能
强制下线功能需要先关闭掉所有的活动,然后回到登录界面。先创建一个ActivityCollector 类用于管理所有的活动,代码如下所示:
/**
*记录所有的activity
*/
public class ActivityCollector {
//创建一个集合记录打开的activity
public static List<Activity> activities = new ArrayList<Activity>();
//每次调用这个方法添加activity
public static void addActivity(Activity activity) {
activities.add(activity);
}
//关闭指定activity
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
//关闭所有activity
public static void finishAll() {
for (Activity activity : activities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}
然后创建BaseActivity 类作为所有活动的父类,代码如下所示:
/**
*创建activity的基类
*/
public class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//每次调用这个方法添加activity
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}
登录界面我就不列出来了。主要是看广播。创建LoginActivity类继承BaseActivity类
强制下线广播代码
//发送强制下线广播,场景自己订
Intent intent = new Intent("com.example.broadcastbestpractice.
FORCE_OFFLINE ");
sendBroadcast(intent);
,接下来我们就需要创建一个广播接收器了,新建ForceOfflineReceiver
继承自BroadcastReceiver,代码如下所示:
/**
*自定义广播类
*/
public class ForceOfflineReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
//接收到广播后创建dialog
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle("Warning");
dialogBuilder.setMessage("You are forced to be offline. Please try
to login again.");
//不能手动取消dialog
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);
//在非activity中使用intent,需要开辟新任务桟
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); // 重新启动LoginActivity
}
});
AlertDialog alertDialog = dialogBuilder.create();
// 需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTE
M_ALERT);
alertDialog.show();
}
}
在清单文件中:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<receiver android:name=".ForceOfflineReceiver" >
<intent-filter>
<action android:name="com.example.broadcastbestpractice.
FORCE_OFFLINE" />
</intent-filter>
</receiver>
这里有几点内容需要注意,首先由于我们在ForceOfflineReceiver 里弹出了一个系统级别
的对话框,因此必须要声明android.permission.SYSTEM_ALERT_WINDOW 权限。然后对
LoginActivity 进行注册,并把它设置为主活动,因为肯定不能让用户启动程序就直接进入
MainActivity 吧。最后再对ForceOfflineReceiver 进行注册,并指定它接收com.example.
broadcastbestpractice.FORCE_OFFLINE 这条广播。
基本上就是这样。
申明:本文中代码采用郭神的第一行代码中内容。便于自己理解。