【问题标题】:Updating an Activity from a BroadcastReceiver从 BroadcastReceiver 更新 Activity
【发布时间】:2012-04-18 20:53:24
【问题描述】:

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

OP 有一个显示地图的应用程序,此地图需要使用通过 SMS 消息接收的位置标记进行更新。各个步骤相当简单:短信可以通过BroadcastReceiver 接收,标记可以通过ItemizedOverlayMapView 上显示。棘手的部分是让接收部分与应用程序的主要部分进行通信。

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

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

【问题讨论】:

    标签: android android-activity broadcastreceiver


    【解决方案1】:

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

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

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

    考虑到 Activity 也可以充当广播接收器,但您必须控制它在其生命周期中何时主动侦听事件。这样就可以订阅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。虽然后者保持它,但第一个更新地图,我只是在猜测我会尝试什么。

    【讨论】:

      【解决方案2】:

      BroadcastReceiver 应该在同一个进程中运行。 BroadcastReceiver 被设计为短暂的。因此,它可以执行而无需真正担心暂停前台Activity。假设您检查了尚未创建 Activity 的情况,您可能会通过静态引用直接访问 Activity。但是,通过 Intent 进行通信可能更有意义。

      【讨论】:

        【解决方案3】:

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

        公共BroadcastReceiver(在清单中声明并处理android.provider.Telephony.SMS_RECEIVED)然后应该调用这个特定于应用程序的意图。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-06-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多