从BroadcastReceiver更新活动

时间:2012-04-18 20:53:24

标签: android android-activity broadcastreceiver

This question提出了一个有趣的问题。

OP有一个显示地图的应用程序,此地图需要使用通过短信接收的位置标记进行更新。个别步骤非常简单:可以通过BroadcastReceiver接收短信,标记可以ItemizedOverlay显示在MapView之上。棘手的部分是让接收部分与应用程序的主要部分进行通信。

  • 如果应用具有有效MapActivity会发生什么情况,然后调用其BroadcastReceiver作为对传入短信的响应?在MapActivity代码在同一进程中执行时,BroadcastReceiver是否被暂停?如果是这样,BroadcastReceiver通过静态引用(由活动的MapActivity方法设置?)访问onCreate是否安全?

  • 相反,应用程序的BroadcastReceiver是在一个单独的进程中执行的,因此需要其他方式与应用程序的活动进行通信?

3 个答案:

答案 0 :(得分:4)

阅读文档,看起来BroadcastReceiver是在不同的进程上执行的,我不是100%肯定(BroadcastReceiver lifecycle

当前正在执行BroadcastReceiver的进程(即当前在其onReceive(Context,Intent)方法中运行代码)被视为前台进程

这就是说,我认为从onReceive访问活动是不安全的,因为它是一个不同的过程,它可能会崩溃。

考虑到Activity还可以充当BroadcastReceiver,您必须控制它在其生命周期中何时主动侦听事件。这样,您可以订阅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应始终保留新标记(通过服务,永远不会在 onReceive 内)并且它应该通知可能有效的MapActivity已添加新标记,如果已添加新标记,则它很活跃。

或者,更简单的是,Activity和BroadcastReceiver侦听相同的SMS Intent。虽然后者持续存在,但第一个更新地图,我只是猜测我会尝试什么。

答案 1 :(得分:1)

BroadcastReceiver应该在同一个进程中运行。 BroadcastReceiver旨在昙花一现。因此,它可以执行而不必担心暂停前台Activity。假设您检查了尚未创建Activity的情况,您可以通过静态引用直接访问Activity。但是,通过Intents进行通信可能更有意义。

答案 2 :(得分:0)

正如其他人所指出的,最佳方法似乎是创建一个对应用程序来说是私有的单独意图。活动不是在清单中声明它,而是在活动时注册它。 This answer解释了如何做到这一点。

public BroadcastReceiver(在清单中声明并处理android.provider.Telephony.SMS_RECEIVED)应该调用此特定于应用程序的意图。