Android 如何将数据从 BroadcastReceiver 传递到正在启动的 Activity?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2616859/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I pass data from a BroadcastReceiver through to an Activity being started?
提问by Tom Hume
I've got an Android application which needs to be woken up sporadically throughout the day.
我有一个 Android 应用程序,它需要全天偶尔被唤醒。
To do this, I'm using the AlarmManager to set up a PendingIntent and have this trigger a BroadcastReceiver. This BroadcastReceiver then starts an Activity to bring the UI to the foreground.
为此,我使用 AlarmManager 来设置 PendingIntent 并触发 BroadcastReceiver。然后这个 BroadcastReceiver 启动一个 Activity 将 UI 带到前台。
All of the above seems to work, in that the Activity launches itself correctly; but I'd like the BroadcastReceiver to notify the Activity that it was started by the alarm (as opposed to being started by the user). To do this I'm trying, from the onReceive() method of the BroadcastReceiver to set a variable in the extras bundle of the intent, thus:
以上所有似乎都有效,因为 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);
In the onResume() method of my Activity, I then look for the existence of this boolean variable:
在我的 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");
}
The getIntent().getExtras() call in onResume() always returns null - I don't seem to be able to pass any extras through at all in this bundle.
onResume() 中的 getIntent().getExtras() 调用总是返回 null - 我似乎无法在这个包中传递任何额外内容。
If I use the same method to bind extras to the PendingIntent which triggers the BroadcastReceiver however, the extras come through just fine.
但是,如果我使用相同的方法将附加内容绑定到触发 BroadcastReceiver 的 PendingIntent,附加内容就可以正常通过。
Can anyone tell me what's different about passing a bundle from a BroadcastReceiver to an Activity, as opposed to passing the bundle from an Activity to a BroadcastReceiver? I fear I may be doing something very very obvious wrong here...
谁能告诉我将包从 BroadcastReceiver 传递到 Activity 与将包从 Activity 传递到 BroadcastReceiver 有什么不同?我担心我可能会在这里做一些非常非常明显的错误......
回答by Norfeldt
Just to make it clear (because I used a lot of time figuring out how to make it work)
只是为了说清楚(因为我花了很多时间来弄清楚如何使它工作)
In the service class that extends BroadcastReceiver
. Put in the following code in onReceive()
在扩展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);
The FLAG_ACTIVITY_SINGLE_TOP
makes sure the apps doesn't re-open if already open. This means that the "old" intent that opened YourActivity in the first place is re-used and it will NOT contain the extra values. You have to catch them in another method called onNewIntent()
in YourActivity.
在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
Please note the two if statements - the onResume()
does not know if it's called after OnCreate()->OnStart() OR onRestart()->onStart()
Please see:http://www.anddev.org/images/android/activity_lifecycle.png
请注意两个 if 语句 -onResume()
不知道它是否在之后调用OnCreate()->OnStart() OR onRestart()->onStart()
请参阅:http : //www.anddev.org/images/android/activity_lifecycle.png
It's just used to test if the app is launched by the user (intent with no extras) OR by the BroadcastReceiver
(intent with extras).
它仅用于测试应用程序是由用户(没有额外的意图)还是由BroadcastReceiver
(有额外的意图)启动。
回答by CommonsWare
This BroadcastReceiver then starts an Activity to bring the UI to the foreground.
然后这个 BroadcastReceiver 启动一个 Activity 将 UI 带到前台。
This may be the crux of your problem here. Try overriding onNewIntent()
and seeing if the Intent
passed to it has your extra. If so, that's because of the way you set up the activity in the manifest (e.g., you're using singleTop
) and the fact that, in this specific case, the activity already existed.
这可能是您问题的症结所在。尝试覆盖onNewIntent()
并查看Intent
传递给它的是否有额外的。如果是这样,那是因为您在清单中设置活动的方式(例如,您正在使用singleTop
)以及在这种特定情况下,活动已经存在的事实。
You might also consider getting rid of i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
and see if that changes matters.
你也可以考虑摆脱,i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
看看改变是否重要。
The upshot is that what you're doing -- putting the extra in the Intent
for startActivity()
-- should work just fine. In fact, you can see examples of that here. This suggests it's something funky about the activity (e.g., singleTop
) or the way you're invoking the activity (e.g., FLAG_ACTIVITY_NEW_TASK
).
结果是你正在做的事情——把额外的钱放在Intent
for里startActivity()
——应该可以正常工作。事实上,您可以在此处查看相关示例。这表明活动(例如,singleTop
)或您调用活动的方式(例如,)有些奇怪FLAG_ACTIVITY_NEW_TASK
。
EDIT:
编辑:
Since my first shots didn't work, and given your "curiouser" comment above...
由于我的第一次拍摄没有成功,并且上面给出了您的“好奇”评论......
This feels a bit like a PendingIntent
-- with those, unless you take steps, you will not be able to update extras.
这感觉有点像PendingIntent
- 有了这些,除非您采取措施,否则您将无法更新附加功能。
On a whim, try adding a second <intent-filter>
to your activity in the manifest, just on some unique action string, and try starting your activity from your receiver using that. Or, just toss some action string into your Intent
that the receiver is using for startActivity()
, without messing with the manifest.
一时兴起,尝试<intent-filter>
在清单中为您的活动添加一秒钟,只是在一些独特的操作字符串上,并尝试使用它从您的接收器开始您的活动。或者,只需将一些操作字符串放入您Intent
的接收者正在使用的 for 中startActivity()
,而不会弄乱清单。
回答by Jim Blackler
Instead of getIntent().getExtras().getBoolean(wakeupKey)
it is more conventional to write getIntent().getBooleanExtra(wakeupKey, defaultValue)
. I can't be sure if this is related to your problem, but there is some stuff to do with creating a bundle inside getExtras() that I'm not sure about, so it might be worth a go anyway.
而不是getIntent().getExtras().getBoolean(wakeupKey)
更传统的写getIntent().getBooleanExtra(wakeupKey, defaultValue)
. 我不能确定这是否与您的问题有关,但是我不确定在 getExtras() 内创建包有一些事情要做,所以无论如何它可能值得一试。
回答by Phillip Phan
Set flag SingleTop works (don't mix with other flags)
设置标志 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);
回答by RClemens
Just override the onNewIntent like this and the Bundle var will be available in the onresume method:
只需像这样覆盖 onNewIntent 并且 Bundle var 将在 onresume 方法中可用:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}