9

I've got an Android application which needs to be woken up sporadically throughout the day.

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.

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:

    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:

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.

If I use the same method to bind extras to the PendingIntent which triggers the BroadcastReceiver however, the extras come through just fine.

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...

4

5 に答える 5

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

2 つの if ステートメントに注意してください。onResume()後で呼び出されたかどうかはわかりませんOnCreate()->OnStart() OR onRestart()->onStart()

これは、アプリがユーザーによって起動されたか (追加機能なしの意図)、またはBroadcastReceiver(追加機能を備えた意図) によって起動されたかをテストするためにのみ使用されます。

于 2011-07-28T10:41:18.420 に答える
5

This BroadcastReceiver then starts an Activity to bring the UI to the foreground.

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.

You might also consider getting rid of i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); and see if that changes matters.

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).

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.

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.

于 2010-04-11T11:48:41.983 に答える
2

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.

于 2010-04-11T11:45:19.837 に答える
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); 
于 2011-02-23T06:25:14.487 に答える
0

このようにonNewIntentをオーバーライドするだけで、バンドル変数がonresumeメソッドで使用できるようになります。

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}
于 2012-12-31T13:23:59.237 に答える