这个问题提出了一个有趣的问题。
OP有一个显示地图的应用程序,需要用通过短信接收的位置标记更新此地图。各个步骤相当简单:SMS消息可以由BroadcastReceiver
接收,标记可以通过MapView
顶部的ItemizedOverlay
显示。棘手的部分是让接收部分与应用程序的主要部分进行通信。
-
如果应用具有活动
MapActivity
,然后调用其BroadcastReceiver
作为对传入短信的响应,会发生什么情况?在同一进程中执行BroadcastReceiver
代码时,MapActivity
是否挂起?如果是这样,BroadcastReceiver
通过静态引用(由活动的onCreate
方法设置)访问MapActivity
是否安全? -
相反,应用的
BroadcastReceiver
是否在单独的进程中执行,因此需要其他方式与应用的活动进行通信?
阅读文档,看起来 BroadcastReceiver 是在不同的进程中执行的,但我不是 100% 确定(BroadcastReceiver 生命周期)
当前正在执行 BroadcastReceiver 的进程(即当前在其 onReceive(Context, Intent) 方法中运行代码)被视为前台进程
也就是说,我认为从onReceive访问活动是不安全的,因为这是一个不同的过程,它可能会崩溃。
考虑到活动也可以充当广播接收器,您必须控制在其生命周期中何时主动侦听事件。这样,您就可以订阅onResume(从ZXing项目中提取的代码)
public void onResume(){
activity.registerReceiver(powerStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
[...]
}
public void onPause() {
[...]
activity.unregisterReceiver(powerStatusReceiver);
}
您将 BroadcastReceiver 定义为公共类中的私有类
final class InactivityTimer {
[onResume, onPause, rest of the stuff ...]
private final class PowerStatusReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent){
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
// 0 indicates that we're on battery
// In Android 2.0+, use BatteryManager.EXTRA_PLUGGED
int batteryPlugged = intent.getIntExtra("plugged", -1);
if (batteryPlugged > 0) {
InactivityTimer.this.cancel();
}
}
}
}
}
因此,BroadcastReceiver 应始终保留新标记(通过服务,而不是在 onTReceive 内部),并且它应该通知潜在活动的 MapActivity 添加了新标记,如果它处于活动状态,它将侦听。
或者,更简单的是,活动和广播接收器侦听相同的 SMS 意图。虽然后者坚持它,但第一个更新地图,我只是猜测我会尝试什么。
BroadcastReceiver
应在同一进程中运行。 BroadcastReceiver
被设计为短暂的。因此,它可以执行,而无需真正担心挂起前台Activity
。假设您检查了尚未创建Activity
的情况,则可能会通过静态引用直接访问Activity
。但是,通过 Intents 进行通信可能更有意义。
正如其他人指出的那样,最好的方法似乎是创建一个对应用程序私有的单独意图。活动不是在清单中声明它,而是在它处于活动状态时注册它。这个答案解释了如何做到这一点。
然后,公共BroadcastReceiver
(在清单中声明并处理android.provider.Telephony.SMS_RECEIVED
)应调用此特定于应用程序的意图。