Android中每个应用程序都可以对自己感兴趣的广播进行注册,这样程序就只会接收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能时来自于其他应用程序的。Android提供一套完整的API,允许应用程序自由地发送和接收广播。发送广播即Intent,接收广播的方法则需引入——广播接收器(Broadcast Receiver)
标准广播(Normal broadcasts)是一种完全异步执行的广播,在广播发出后,所有广播接收器机会都会在同时接收到这条广播消息,因此它们间没有任何先后顺序可言。这种广播效率较高,但无法被截断。
有序广播(Ordered broadcasts)同步执行的广播,广播发出后,同一时刻只会有一个广播接收器能够接收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,且前面的广播接收器可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了。
动态注册监听网络变化
广播接收器可自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收器就能够收到该广播,并在内部处理相应的逻辑
注册广播的方式有两种:在代码中注册(动态注册),在AndroidManifest.xml中注册(静态注册)
测试代码:监听是否有网络
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
//网络发生变化时系统发出的是一条值为android.net.conn.CONNECTIVITY_CHANGE的广播,
//即想监听什么广播就在此添加相应action
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//创建NetworkChangeReceiver实例
networkChangeReceiver = new NetworkChangeReceiver();
//注册实例
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//动态注册的广播接收器需取消注册
unregisterReceiver(networkChangeReceiver);
}
/**
* 继承自BroadcastReceiver,并重写了onReceive()。当网络状态发生变化时,onReceive()方法便会执行
*/
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.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();
}
}
}
}
需在AndroidManifest.xml中添加:
但是这样只有在程序启动后才能接收广播。若要在程序未启动就能接收广播,需要使用静态注册
创建Broadcast Receiver
Exported表示是否允许这个广播接收器接收本程序以外的广播,Enabled表示是否启用这个广播接收器
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}
可以发现AndroidManifest.xml文件中已自动注册:
添加权限:
修改
此时可以接收开机广播。
注:不要在onReceive()方法中添加过多的逻辑或进行任何的耗时操作,因为广播接收器不允许开启线程,当onReceive()方法进行较长时间没有结束时,程序会报错。因此,广播接收器更多的是扮演一种打开程序其他组件的角色,如创建一条状态栏通知,或启动一个服务等。
新建广播接收器MyBroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();
}
}
修改AndroidManifest.xml:
修改activity_main.xml:
修改MainActivity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.lyp1020k.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);
}
});
}
新建BroadcastTest2,新建AnotherBroadcastReceiver:
public class AnotherBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in AnotherBroadcastReceiver", Toast.LENGTH_SHORT).show();
}
}
修改AndroidManifest.xml文件:
回到BroadcastTest在MainActivity中将sendBroadcast(intent)改为sendOrderedBroadcast(intent,null);(第二个参数是一个与权限相关的字符串)
设定广播接收器的先后顺序:在BroadcastTest中AndroidManifest.xml文件中修改receiver
修改MyBroadcastReceiver可选择是否允许广播继续传递:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
abortBroadcast()表示将这条广播截断,后面的广播接收器无法接收到这条广播