简介

Android 中的广播主要可以分为两种类型,标准广播和有序广播。

标准广播:完全异步执行,效率会比较高,无法被截断。

有序广播:同步执行,广播接收器有先后顺序,可以截断。

接收系统广播


Android 内置了很多系统级别的广播,可以通过监听这些广播来得到各种系统的状态信息

动态注册


动态注册:新建继承自 BroadcastReceiver的一个类,并重写父类的 onReceive()方法。 当有广播到来时, onReceive()方法就会得到执行。


示例


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();
}
}
}

说明:在onCreate方法中创建了一个IntentFilter实例。广播接收器想要监听什么广播,就在这里添加相应的action 就行了,示例中添加的是值为android.net.conn.CONNECTIVITY_CHANGE 的 action。接下来创建了NetworkChangeReceiver 的实例,调用 registerReceiver()


方法进行注册,将 NetworkChangeReceiver 的实例和 IntentFilter 的实例都传了进去,这样NetworkChangeReceiver 就会收到所有值为 android.net.conn.CONNECTIVITY_CHANGE的广播,也就实现了监听网络变化的功能。动态注册的广播接收器一定都要取消注册才行,示例中是在 onDestroy()方法中通过调用 unregisterReceiver()方法来实现的。


静态注册


实现开机启动示例如下,新建BootCompleteReceiver(不再使用内部类方式,因为需要在配置文件中注册)


public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}

AndroidManifest.xml文件


<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
……
<receiver android:name=".BootCompleteReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>

说明:<application>标签内出现了一个新的标签<receiver>,所有静态注册的广播接收器都是在这里进行注册的。通过 android:name来指定具体注册哪一个广播接收器, 然后在<intent-filter>标签里加入想要接收的广播。Android系统启动完成后会发出一条值为 android.intent.action.BOOT_COMPLETED的广播,因此这里添加了相应的 action。监听系统开机广播需要声明权限,示例中<uses-permission>标签又加入了一条 android.permission.RECEIVE_BOOT_COMPLETED 权限。


访问 http://developer.android.com/reference/android/Manifest.permission.html 可以查看 Android系统所有可声明的权限。


注意:不要在 onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的, 当 onReceive()方法运行了较长时间而没有结束时, 程序就会报错。


发送自定义广播


首先定义一个广播接收器来准备接收此广播


public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceiver",
Toast.LENGTH_SHORT).show();
}
}

配置文件中注册


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest"
android:versionCode="1"
android:versionName="1.0" >
……
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
……
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="com.example.broadcasttest. MY_BROADCAST"/>
</intent-filter>
</receiver>
</application>
</manifest>

主Activity,点击按钮发送广播


public class MainActivity extends Activity {
……
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.
MY_BROADCAST");
sendBroadcast(intent);
}
});
……
}
……
}

广播是一种可以跨进程的通信方式,因此在我们应用程序内发出的广播,其他的应用程序应该也是可以收到的。


public class MainActivity extends Activity {
……
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.
MY_BROADCAST");
sendOrderedBroadcast(intent, null);
}
});
……
}
……
}

发送有序广播只需要

将 sendBroadcast() 方法改成 sendOrderedBroadcast() 方法。 sendOrderedBroadcast() 方法接收两个参数,第一个参数仍然是 Intent,第二个参数是一个与权限相关的字符串,这里传入 null。


有序广播中,优先级比较高的广播接收器就可以先收到广播,并可以选择继续传递或者丢弃。配置文件优先级和选择丢弃代码如下:


<receiver android:name=".MyBroadcastReceiver">
<intent-filter android:priority="100" >
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>



public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceive",
Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}

本地广播


本地广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播。


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();
}
}
}

本地广播是无法通过静态注册的方式来接收的。