来自通知的意图没有额外内容

Posted

技术标签:

【中文标题】来自通知的意图没有额外内容【英文标题】:Intent from notification does not have extras 【发布时间】:2012-07-18 01:38:22 【问题描述】:

这似乎是一个常见问题,我已经找到了所有相关问题: Activity isn't picking up new intent,Why extra data (integer) is not sent in android notification intent?,Notification passes old Intent Extras,Can't put extras for an intent in notification,android pending intent notification problem;但仍然无法弄清楚。

问题是一样的。我设置了一个带有 PendingIntent 的通知,其中包含一些额外的信息,但我没有在另一边得到它。

这是生成通知的代码:

Notification notification = new Notification(R.drawable.icon, getResources().getString(R.string.notification_ticker), System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONLY_ALERT_ONCE;

Intent start_test = new Intent(this, MyActivity.class);
start_test.putExtra("start_test", true);
start_test.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

PendingIntent pi = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), start_test, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, getResources().getString(R.string.notification_title), getResources().getString(R.string.notification_content, expired), pi);
nm.notify(NOTIFICATION_ID, notification);

另一方面:

boolean start_test=getIntent().getBooleanExtra("start_test", false);

捆绑包实际上不存在(getExtras() 返回 null)。

我为PendingIntent.getActivityFLAG_UPDATE_CURRENTFLAG_CANCEL_CURRENTFLAG_ONE_SHOT)尝试了不同的标志,但都没有帮助。

如代码所示,我使用 getCurrentMillis 来确保 requestID 发生变化......

还发现在 MyActivity 中,onCreateonNewIntent 没有被调用。只有onResume 是。即使设置了FLAG_ACTIVITY_NEW_TASK...?

我错过了一些非常简单的东西吗?

【问题讨论】:

如果您只想添加一个额外内容,请忘记使用Bundle。只需使用new_intent.putExtra("start_test", true),然后在另一端使用getIntent.getBooleanExtra("start_test", false) 是的,我也尝试过,它没有改变任何东西......仍然没有在另一边得到它 发生这种情况时,您的应用程序是否正在运行(或在后台)? MyActivity 是否在活动堆栈的顶部? @DavidWasser,是的,MyActivity 仍在后台运行(尚未调用 onDestroy)。不确定它是否在活动堆栈的顶部或不在该任务中。 new_intent.putExtra("start_test", true) 然后在另一端使用 getIntent.getBooleanExtra("start_test", false) 不起作用 【参考方案1】:

为通知 Intent 设置 FLAG_ACTIVITY_NEW_TASK 将导致以下情况:

如果 Activity已经在任务中运行,则会启动一个新任务并将 Intent 传递给onCreate()中的 Activity

但是,如果活动已在任务中运行,则该任务将被带到前台。就这样。 Intent 将不会被传递,onNewIntent() 也不会被调用。

如果您希望 Intent 实际交付,您需要指定:

start_test.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 
                    Intent.FLAG_ACTIVITY_SINGLE_TOP);

不管activity的launchMode是不是singleTop没有区别,你还是必须在Intent中指定Intent.FLAG_ACTIVITY_SINGLE_TOP

注意:如果 Activity 已经在某个任务中运行,并且该 Activity位于该任务中的 Activity 堆栈顶部,则该任务将被带到前景。就这样。 Intent 将不会交付。实现这一点的唯一方法是将Intent.FLAG_ACTIVITY_CLEAR_TOP 添加到其他 2 个标志,但这可能不是您想要发生的(取决于您的具体情况)。

在http://code.google.com/p/android/issues/detail?id=17137查看我在 Google 代码上的(仍然)未决问题

【讨论】:

非常感谢您的详细解释。还必须将 PendingIntent.getActivity 中的标志设置为 FLAG_CANCEL_CURRENT 否则 onNewIntent 将被调用多次。不完全确定为什么,但它现在似乎按预期工作。 因为它总是接受传递给它的第一个意图,而不是来自通知的意图。所以你需要覆盖 - @Override protected void onNewIntent(Intent intent) super.onNewIntent(intent); setIntent(intent); 这样你的意图就会被接收到。【参考方案2】:

我刚刚将PendingIntent.FLAG_UPDATE_CURRENT 标志添加到我的待处理意图中,它开始为我工作(跳过了意图的所有标志)。

示例代码:

PendingIntent pendIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

【讨论】:

谢谢,成功了! :) 无需再添加任何内容。 这应该是公认的答案,因为它更容易实现 接受的答案在 api 16 上对我不起作用 - 但是,这在 16 - 23 上完美 这是正确的答案。附加说明,如果活动已经打开,则不会再次触发 onStart,因此需要在 onResume 中检查意图 经过至少 2-3 小时的搜索,这救了我。非常感谢【参考方案3】:

    如果不需要,则避免将清单中的活动设置为单个任务。如果可以,请省略此行或将其更改为 singleTop:

      android:launchMode="singleTask”
    

    如果您必须有一个任务,那么在待处理的意图中将标志设置为: 意图。FLAG_ACTIVITY_NEW_TASK |意图。FLAG_ACTIVITY_CLEAR_TASK 还有 PendingIntent。FLAG_CANCEL_CURRENT

    resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_CLEAR_TASK);
    pIntent = PendingIntent.getActivity(context, 0, resultIntent,    PendingIntent.FLAG_CANCEL_CURRENT );
    

    如果您有一个任务 - 通过 setIntent(intent);

    在 onNewIntent() 中重置您的活动中的额外内容
    protected void onNewIntent(Intent intent) 
           setIntent(intent);
           ... 
     
    

【讨论】:

在我的情况下,它与 FLAG_UPDATE_CURRENT 待定意图效果很好【参考方案4】:

您可以按照以下方式发送附加信息

PendingIntent contentIntent ;
Intent intent = new Intent(this,TestActivity.class);
intent.putExtra("extra","Test");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

stackBuilder.addParentStack(ArticleDetailedActivity.class);

contentIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

要在测试活动类中获取 Intent 额外值,您需要编写以下代码:

Intent intent = getIntent();
 String extra = intent.getStringExtra("extra") ;

【讨论】:

【参考方案5】:

更简单的方法:真正的问题是,指向同一个目标的 Intent 被替换了。我刚刚通过创建一个新服务“NotificationDismissalService”解决了这个问题。访问该服务的唯一意图是 setDeleteIntent 项。因为它是一项独特的服务,所以参数不会被替换。 NotificationDismissalService 的主体(它实际上是每个唯一意图类型的一个这样的解雇服务)是“onStartCommand”的一个简单实现,它将意图发送到首选服务(读取/写入正确的参数)。因为这是服务的实际发送,中间没有挂起的意图,所以它工作得很好。

【讨论】:

【参考方案6】:

我用过类似的东西

Intent myIntent = new Intent(context, DoSomething.class);
 PendingIntent pendingIntent = PendingIntent.getActivity(
        context, 
        0, 
        myIntent, 
        Intent.FLAG_ACTIVITY_NEW_TASK);

查看完整示例 here

【讨论】:

【参考方案7】:

当应用未运行或处于后台并且用户点击托盘中的通知时,您可以获得额外的 Intent 并检查键:

@Override
protected void onCreate(Bundle savedInstanceState)
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.d("RC","MainActivity.onCreate() called");

    if (getIntent().getExtras() != null)
        Bundle extra = getIntent().getExtras();
        Log.d("RC", "MainActivity.onCreate() : keys count = " + extra.keySet().size());

        for ( String key : extra.keySet()) 
            Log.d("RC","MainActivity.onCreate() : key = " + key + " = " + extra.getString(key));
        

    

这将显示:

D/RC: MainActivity.onCreate() called
D/RC: MainActivity.onCreate() : keys count = 8
D/RC: MainActivity.onCreate() : key = google.delivered_priority = high
D/RC: MainActivity.onCreate() : key = google.sent_time = null
D/RC: MainActivity.onCreate() : key = google.ttl = null
D/RC: MainActivity.onCreate() : key = google.original_priority = high
D/RC: MainActivity.onCreate() : key = from = 631131412302
D/RC: MainActivity.onCreate() : key = google.message_id = 0:1627370460932539%952b1da9952b1da9
D/RC: MainActivity.onCreate() : key = gcm.n.analytics_data = null
D/RC: MainActivity.onCreate() : key = collapse_key = com.reflectcode.demo.cloudmessaging

【讨论】:

以上是关于来自通知的意图没有额外内容的主要内容,如果未能解决你的问题,请参考以下文章

除了第一个意图外,所有意图都收到了不正确的额外内容

使用额外的捆绑包创建通知意图不起作用

如何从 RemoteViewsService 中的意图访问额外内容?

广播接收器没有收到额外的

通过谷歌推送通知接收来自额外密钥的旧值

即使重新创建活动,也不会清除待处理的意图额外内容