我有一个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?我担心我可能会做一些非常明显错误的事情......
答案 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);
}