如何将数据从BroadcastReceiver传递到正在启动的Activity?

时间:2010-04-11 11:36:16

标签: android android-intent bundle broadcastreceiver alarm

我有一个Android应用程序需要在一天中偶尔被唤醒。

要做到这一点,我正在使用AlarmManager来设置PendingIntent并使其触发BroadcastReceiver。然后,此BroadcastReceiver启动一个Activity,将UI带到前台。

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

    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从BroadcastReceiver传递给Activity有什么不同,而不是将bundle从一个Activity传递给一个BroadcastReceiver?我担心我可能会做一些非常明显错误的事情......

5 个答案:

答案 0 :(得分:30)

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

在扩展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的“旧”意图将被重用,并且不会包含额外的值。您必须在onNewIntent()

中的另一个名为YourActivity.的方法中捕获它们
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(意图使用额外内容)。

答案 1 :(得分:5)

  

然后,此BroadcastReceiver启动   将UI带到的活动   前景。

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

你也可以考虑摆脱i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);,看看这种变化是否重要。

结果是你正在做的事情 - 将额外费用放在Intent startActivity() - 应该可以正常工作。实际上,您可以看到here的示例。这表明它对于活动(例如singleTop)或您调用活动的方式(例如,FLAG_ACTIVITY_NEW_TASK)来说是个时髦的东西。

修改

由于我的第一次拍摄不起作用,并且上面给出了“curiouser”评论......

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

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

答案 2 :(得分:2)

而不是getIntent().getExtras().getBoolean(wakeupKey),而不是写getIntent().getBooleanExtra(wakeupKey, defaultValue)更常规。我无法确定这是否与您的问题有关,但是在getExtras()中创建一个我不确定的包,有一些事情可做,所以无论如何它都值得去。

答案 3 :(得分:1)

设置标志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); 

答案 4 :(得分:0)

只需覆盖onNewIntent,就可以在onresume方法中使用Bundle var:

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