使用Intent广播事件
作为一种系统级消息传递的机制,Intent有能力穿越进程边界传递结构化消息。
到目前为止,你已经了解了使用Intent来启动一个新的应用程序组件,但是,它们还可以通过sendBroadcast方法在组件间广播匿名消息。你可以在你的应用程序中实现Broadcast Receiver来监听和响应这些广播的Intent。广播Intent用于通知系统的监听者或应用程序事件,从而扩展了应用程序间的事件驱动编程模型。
广播Intent让你的程序更加开放;通过使用Intent来广播事件,你让你和第三方开发者响应事件而不需要修改你的原始程序。在你的应用程序里,你可以监听广播的Intent来替换或增强本地的(或第三方的)应用程序,或者对系统变化和应用程序事件作出响应。
举个例子,通过监听外来的呼叫广播,你可以改变呼叫者的铃声或音量。
Android广泛地使用广播Intent来广播系统事件,如电池充电变化,网络连接和来电。
广播事件
广播Intent是相当地简单。在你的程序组件里,构建你要广播的Intent,使用sendBroadcast方法发送出去。
设定Intent的动作、数据和种类来使Broadcast Receiver精确地决定它们的兴趣。在这里,Intent动作字符串用来标识要广播的事件,因此,它必须是独一无二的标识事件的字符串。习惯的,动作字符串使用Java包的样子来定义,如下面的片段所示:
public static final String NEW_LIFEFORM_DETECTED =
“com.paad.action.NEW_LIFEFORM”;
如果你想在Intent中包含数据,你可以使用Intent的data属性来指定一个URI。你还可以包含extras来增加额外的本地类型值。考虑就事件驱动模型而言,这些extras包等价于事件处理函数的可选参数。
下面的框架代码给出了一个广播的Intent的基本创建,使用之前定义的动作和一些以extras方法储存的额外的事件信息。
Intent intent = new Intent(NEW_LIFEFORM_DETECTED);
intent.putExtra(“lifeformName”, lifeformType);
intent.putExtra(“longitude”, currentLongitude);
intent.putExtra(“latitude”, currentLatitude);
sendBroadcast(intent);
Broadcast Receiver监听广播
Broadcast Receiver用于监听广播Intent。为了激活一个Broadcast Receiver,需要在代码或在程序manifest中注册。当注册一个Broadcast Receiver时,你必须使用Intent Filter来指定要监听哪个Intent。
为了创建一个新的Broadcast Receiver,需要扩展BroadcastReceiver类,并重写onReceive事件处理函数,如下面的框架代码所示:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//TODO: React to the Intent received.
}
}
当广播的Intent与注册的接收器的Intent Filter匹配时,onReceive方法会执行。onReceive处理函数必须在5秒内完成,否则应用程序无响应的对话框会显示。
在Intent广播的时候,注册有Broadcast Receiver的应用程序不需要正在运行。它们在有匹配的广播Intent时自动启动。这对于资源管理来说,是极好的,因为它允许你创建可以被关闭或杀死的事件驱动应用程序,而此刻又以安全的方式对广播事件做出响应。
典型的,Broadcast Receiver会更新内容、启动服务、更新Activity的UI或使用通知管理器来通知用户。5秒的执行限制确保了主进程不能,或者说不应该在Broadcast Receiver中直接结束。
接下来的例子显示了如何实现一个Broadcast Receiver。在下一个章节,你将学习如何在代码或在manifest中注册它。
public class LifeformDetectedBroadcastReceiver extends BroadcastReceiver {
public static final String BURN =
“com.paad.alien.action.BURN_IT_WITH_FIRE”;
@Override
public void onReceive(Context context, Intent intent) {
// Get the lifeform details from the intent.
Uri data = intent.getData();
String type = intent.getStringExtra(“type”);
double lat = intent.getDoubleExtra(“latitude”, 0);
double lng = intent.getDoubleExtra(“longitude”, 0);
Location loc = new Location(“gps”);
loc.setLatitude(lat);
loc.setLongitude(lng);
if (type.equals(“alien”)) {
Intent startIntent = new Intent(BURN, data);
startIntent.putExtra(“latitude”, lat);
startIntent.putExtra(“longitude”, lng);
context.startActivity(startIntent);
}
}
}
在程序的manifest中注册
为了在程序的manifest中包含一个Broadcast Receiver,通过在application节点增加一个receiver标签,并指定要注册的Broadcast Receiver的类名。receiver节点需要包含一个intent-filter标签来指定要监听的动作字符串,如下面的XML片段所示:
<receiver android:name=”.LifeformDetectedBroadcastReceiver”>
<intent-filter>
<action android:name=”com.paad.action.NEW_LIFEFORM”/>
</intent-filter>
</receiver>
Broadcast Receiver以这种方注册将总是处于活跃状态。
在代码中注册
你可以在代码中控制Broadcast Receiver的注册。这种做法的典型例子就是receiver用来在Activity中更新UI元素。一个好的习惯是当Activity不可见(或不活跃)时,反注册Broadcast Receiver。
下面的代码片段显示了如何使用一个Intent Filter注册Broadcast Receiver:
// Create and register the broadcast receiver.
IntentFilter filter = new IntentFilter(NEW_LIFEFORM_DETECTED);
LifeformDetectedBroadcastReceiver r = new LifeformDetectedBroadcastReceiver();
registerReceiver(r, filter);
为了反注册一个Broadcast Receiver,在程序上下文中使用unregisterReceiver方法,传入一个Broadcast Receiver实例,如下所示:
unregisterReceiver(r);
更多的例子你将在第8章找到,学习创建后台服务和使用Intent广播事件来返回到Activity中。