【问题标题】:How do I pass data from a BroadcastReceiver through to an Activity being started?如何将数据从 BroadcastReceiver 传递到正在启动的 Activity?
【发布时间】:2010-04-11 11:36:15
【问题描述】:

我有一个 Android 应用程序需要在一天中不时唤醒。

为此,我使用 AlarmManager 来设置 PendingIntent 并让它触发一个 BroadcastReceiver。然后此 BroadcastReceiver 启动一个 Activity 以将 UI 带到前台。

以上所有方法似乎都有效,因为 Activity 可以正确启动;但我希望 BroadcastReceiver 通知 Activity 它是由警报启动的(而不是由用户启动的)。为此,我正在尝试从 BroadcastReceiver 的 onReceive() 方法在意图的附加包中设置一个变量,因此:

    Intent i = new Intent(context, MyActivity.class);
    i.putExtra(wakeupKey, true);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(i);

在我的 Activity 的 onResume() 方法中,然后我寻找这个布尔变量的存在:

protected void onResume() {
    super.onResume();

    String wakeupKey = "blah";      
    if (getIntent()!=null && getIntent().getExtras()!=null)
        Log.d("app", "onResume at " + System.currentTimeMillis() + ":" + getIntent().getExtras().getBoolean(wakeupKey));
    else
        Log.d("app", "onResume at " + System.currentTimeMillis() + ": null");
}

onResume() 中的 getIntent().getExtras() 调用总是返回 null - 我似乎无法在这个包中传递任何额外内容。

如果我使用相同的方法将额外内容绑定到触发 BroadcastReceiver 的 PendingIntent,那么额外内容就会很好地通过。

谁能告诉我将包从广播接收器传递到活动与将包从活动传递到广播接收器有什么不同?我担心我可能会在这里做一些非常明显的错误......

【问题讨论】:

  • 好奇者和好奇者......它刚刚开始工作(在模拟器中),正如我所期望的那样。反复工作了一段时间。我关闭了模拟器,重新启动(没有任何代码更改或重新编译),然后我又回到了旧的行为(活动启动但没有 Bundle 通过)。我仍然可以看到两次运行的日志 - 在前者中,Bundles 正在通过,在后者中没有。

标签: android android-intent bundle broadcastreceiver alarm


【解决方案1】:

只是为了说清楚(因为我花了很多时间弄清楚如何让它工作)

在扩展BroadcastReceiver 的服务类中。将以下代码放入onReceive()

Intent intent2open = new Intent(context, YourActivity.class);
intent2open.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent2open.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
String name = "KEY";
String value = "String you want to pass";
intent2open.putExtra(name, value);
context.startActivity(intent2open);

FLAG_ACTIVITY_SINGLE_TOP 确保应用在已打开的情况下不会重新打开。这意味着首先打开 YourActivity 的“旧”意图被重新使用,它不会包含额外的值。您必须在 YourActivity. 中使用另一个名为 onNewIntent() 的方法来捕获它们

public class YourActivity extends Activity {
    private String memberFieldString;

    @Override
    public void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         // Code doing your thing...
    } // End of onCreate()

    @Override
    protected void onNewIntent(Intent intent) {
    Log.d("YourActivity", "onNewIntent is called!");

    memberFieldString = intent.getStringExtra("KEY");

    super.onNewIntent(intent);
} // End of onNewIntent(Intent intent)

    @Override
    protected void onResume() {
        if (memberFieldString != null) {
            if (opstartsIntent.getStringExtra(KEY) != null) {
               Log.d("YourActivity", "memberFieldString: "+ memberFieldString);
            } else {
               Log.d("YourActivity", "The intent that started YourActivity did not have an extra string value");
            }
        }
    } // End of onResume()

}  // End of YourActivity

请注意两个 if 语句 - onResume() 不知道它是否在 OnCreate()->OnStart() OR onRestart()->onStart() 之后调用
请参阅: http://www.anddev.org/images/android/activity_lifecycle.png

它只是用来测试应用程序是由用户启动(意图没有额外)还是由BroadcastReceiver(意图有额外)。

【讨论】:

  • 但是我也面临同样的问题? ..我的活动一次又一次地开始..还有其他更新吗?
  • 这听起来可能很愚蠢:但是您是否检查过您是否设置了正确的标志并按照说明进行了每一点?我花了很长时间才弄清楚这一点,我意识到并非所有标志都像我期望的那样工作。如果您添加的标志比描述的多,请尝试删除它们。让它发挥作用,然后将它们一一添加,看看会发生什么。
  • 什么是“opstartsIntent”我找不到/编译它。
  • 不会使用intent2open.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent2open.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 将新任务替换为单顶吗?我宁愿让它intent2open .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
【解决方案2】:

这个 BroadcastReceiver 然后启动一个 将 UI 带到 前景。

这可能是您的问题的症结所在。尝试覆盖onNewIntent() 并查看传递给它的Intent 是否有你的额外。如果是这样,那是因为您在清单中设置活动的方式(例如,您使用的是singleTop)以及在这种特定情况下,活动已经存在。

您也可以考虑删除i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);,看看这是否重要。

结果是,您正在做的事情——将额外的放在Intent 中用于startActivity()——应该可以正常工作。事实上,您可以看到here 的示例。这表明活动(例如,singleTop)或您调用活动的方式(例如,FLAG_ACTIVITY_NEW_TASK)有些古怪。

编辑:

由于我的第一张照片没有成功,并且在上面给出了您的“好奇”评论...

这感觉有点像PendingIntent——有了这些,除非你采取措施,否则你将无法更新额外内容。

一时兴起,尝试在清单中的您的活动中添加第二个<intent-filter>,就在一些独特的操作字符串上,并尝试使用它从您的接收器开始您的活动。或者,只需将一些操作字符串扔到您的Intent 中,接收者用于startActivity(),而不会弄乱清单。

【讨论】:

  • 不,onNewIntent() 也没有得到它...... FLAG_ACTIVITY_NEW_TASK 在那里,因为没有它我得到一个 RuntimeException: E/AndroidRuntime(274): java.lang.RuntimeException: Unable to start接收者 com.futureplatforms.twitchr.BirdArrivesAlarmReceiver: android.util.AndroidRuntimeException: 从 Activity 上下文之外调用 startActivity() 需要 FLAG_ACTIVITY_NEW_TASK 标志。这真的是你想要的吗?
  • 我用其他你可以尝试的东西编辑了我之前的答案——在这里评论以防你没有收到关于答案编辑的通知...
  • 好的,再试一次。 onNewIntent() 现在确实得到了它——我将活动启动模式更改为 singleTask,它的工作方式与我希望的完全一样。然后我覆盖了 newIntent 并设置了一个变量,该活动可以在其他地方获取以确定它已被警报唤醒。谢谢!
【解决方案3】:

getIntent().getBooleanExtra(wakeupKey, defaultValue) 代替getIntent().getExtras().getBoolean(wakeupKey) 更为传统。我不能确定这是否与您的问题有关,但是在 getExtras() 中创建一个包有一些事情我不确定,所以无论如何它可能值得一试。

【讨论】:

  • 谢谢吉姆。刚刚尝试进行更改,但该值始终为 false(我只是将其设置为 true)。
【解决方案4】:

设置标志 SingleTop 有效(不要与其他标志混合)

Intent intent = new Intent(ContextManager.getContext(),OrderList.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle bundle = new Bundle();       

bundle.putString("username",username);
bundle.putString("password",password);

intent.putExtras(bundle);
startActivityForResult(intent,0); 

【讨论】:

    【解决方案5】:

    只需像这样覆盖 onNewIntent,Bundle 变量就会在 onresume 方法中可用:

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多