首页 文章

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

提问于
浏览
9

我有一个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 - 我似乎无法在此bundle中传递任何额外的东西 .

如果我使用相同的方法将额外的东西绑定到触发BroadcastReceiver的PendingIntent,那么额外的东西就可以了 .

任何人都可以告诉我将一个bundle从BroadcastReceiver传递给Activity有什么不同,而不是将bundle从一个Activity传递给一个BroadcastReceiver?我担心我可能会做一些非常明显错误的事情......

5 回答

  • 5

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

    在扩展 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的"old" intent会被重用,并且不会包含额外的值 . 您必须在 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() 之后调用它
    Please see: http://www.anddev.org/images/android/activity_lifecycle.png

    它仅用于测试应用程序是由用户启动(意图没有额外的)还是 BroadcastReceiver (意图有额外的) .

  • 30

    然后,此BroadcastReceiver启动一个Activity,将UI带到前台 .

    这可能是你问题的症结所在 . 尝试重写 onNewIntent() 并查看传递给它的 Intent 是否有你的额外费用 . 如果是这样,那么's because of the way you set up the activity in the manifest (e.g., you'正在使用 singleTop )以及在这种特定情况下活动已经存在的事实 .

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

    结果就是你正在做的事情 - 把额外的东西放在 Intent 中 - 应该可以正常工作 . 事实上,你可以看到here的例子 . 这表明它对于活动(例如, singleTop )或您调用活动的方式(例如, FLAG_ACTIVITY_NEW_TASK )来说是一种时髦的东西 .

    EDIT:

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

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

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

  • 1

    而不是 getIntent().getExtras().getBoolean(wakeupKey) ,更常规的是写 getIntent().getBooleanExtra(wakeupKey, defaultValue) . 我可以'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'我不确定,所以无论如何它可能值得去 .

  • 0

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

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

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

相关问题