PendingIntent对第一个通知正常工作,但对其余通知不正确

86 notifications android android-pendingintent

  protected void displayNotification(String response) {
    Intent intent = new Intent(context, testActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);

    Notification notification = new Notification(R.drawable.icon, "Upload Started", System.currentTimeMillis());
    notification.setLatestEventInfo(context, "Upload", response, pendingIntent);

    nManager.notify((int)System.currentTimeMillis(), notification);
}
Run Code Online (Sandbox Code Playgroud)

该函数将被多次调用.我希望每个人notification在点击时启动testActivity.不幸的是,只有第一个通知启动testActivity.单击其余部分会导致通知窗口最小化.

额外信息:函数displayNotification()在一个叫做的类中UploadManager. 从实例化Context传递进来.函数在函数中多次调用,也在UploadManager中运行.UploadManageractivitydisplayNotification()AsyncTask

编辑1:我忘了提到我正在将String响应传递Intent intentextra.

  protected void displayNotification(String response) {
    Intent intent = new Intent(context, testActivity.class);
    intent.putExtra("response", response);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Run Code Online (Sandbox Code Playgroud)

这有很大的不同,因为我需要额外的"响应"来反映创建通知时的字符串响应.相反,使用PendingIntent.FLAG_UPDATE_CURRENT,额外的"响应"反映了最后一次调用时String响应displayNotification().

我知道为什么这是通过阅读文档FLAG_UPDATE_CURRENT.但是,我不知道如何解决这个问题.

ogn*_*ian 120

不要Intent.FLAG_ACTIVITY_NEW_TASK用于PendingIntent.getActivity,而是使用FLAG_ONE_SHOT


复制评论:

然后在Intent上设置一些虚拟动作,否则会删除额外的动作.例如

intent.setAction(Long.toString(System.currentTimeMillis()))
Run Code Online (Sandbox Code Playgroud)

  • 然后在Intent上设置一些虚拟动作,否则会删除额外的动作.例如,intent.setAction("foo") (32认同)
  • 优秀.那很有效.我将setAction(Long.toString(System.currentTimeMillis()))与使用mbauer建议的FLAG_UPDATE_CURRENT结合使用.使用FLAG_ONE_SHOT只允许我点击一次通知(这是有道理的).非常感谢ognian. (20认同)
  • "然后在Intent上设置一些虚拟动作,否则会删除额外内容" - 这是在某处记录的吗? (4认同)

Vil*_*usK 61

与挣扎RemoteViews和几个不同的Intents每个ButtonHomeScreen的Widget.添加这些时的工作:

1. intent.setAction(Long.toString(System.currentTimeMillis()));

2. PendingIntent.FLAG_UPDATE_CURRENT

        PackageManager pm = context.getPackageManager();

        Intent intent = new Intent(context, MyOwnActivity.class);
        intent.putExtra("foo_bar_extra_key", "foo_bar_extra_value");
        intent.setAction(Long.toString(System.currentTimeMillis()));
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.widget_layout);
        views.setOnClickPendingIntent(my_button_r_id_received_in_parameter, pendingIntent);
Run Code Online (Sandbox Code Playgroud)

  • 我只是喜欢Android SDK对开发人员如此直观...(:♥️BTW阅读下面的@ObjectiveTruth答案以获取setAction原因的解释 (2认同)

Obj*_*uth 40

设置动作解决了这个问题.以下是我对情况的理解:


我有多个小部件,每个小部件都附有PendingIntent.每当有人更新,他们都会得到更新.Flags用于描述与PendingIntents完全相同的情况.

FLAG_UPDATE_CURRENT描述现在读得更好:

如果您正在制作的PendingIntent相同,则将所有旧的PendingIntent更新为您正在制作的新PendingIntent.

完全相同的定义着眼于整个PendingIntent EXCEPT附加内容.因此,即使你对每个意图都有不同的额外内容(对我来说,我是在添加appWidgetId)然后到android,它们也是一样的.

使用一些虚拟唯一字符串添加.setAction会告诉操作系统.这些完全不同,不会更新任何内容.最后这里是我的实现,它按我的意愿工作,其中每个Widget都有自己的配置Intent附加:

Intent configureIntent = new Intent(context, ActivityPreferences.class);

configureIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

configureIntent.setAction("dummy_unique_action_identifyer" + appWidgetId);

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, configureIntent,
    PendingIntent.FLAG_UPDATE_CURRENT);
Run Code Online (Sandbox Code Playgroud)

UPDATE


如果您正在使用广播,这是更好的解决方案.Unique PendingIntents也由唯一的请求代码定义.这是我的解决方案:

//Weee, magic number, just want it to be positive nextInt(int r) means between 0 and r
int dummyuniqueInt = new Random().nextInt(543254); 
PendingIntent pendingClearScreenIntent = PendingIntent.getBroadcast(context, 
    dummyuniqueInt, clearScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Run Code Online (Sandbox Code Playgroud)

  • 不错的清洁解决方案 (2认同)

ste*_*osf 16

我看到答案但没有解释.此外,没有一个答案能解决所有可能的解决方案,所以我会尽力说清楚.

文档:

如果您确实需要多个不同的PendingIntent对象同时处于活动状态(例如用作同时显示的两个通知),那么您需要确保有一些不同的东西将它们与不同的关联起来PendingIntents.这可能是Intent.filterEquals考虑的任何Intent属性,或者提供给getActivity(Context,int,Intent,int),getActivities(Context,int,Intent [],int),getBroadcast(Context,int)的不同请求代码整数. ,Intent,int)或getService(Context,int,Intent,int).

问题原因:

您创建2个通知,其中包含2个待处理意图.每个待处理的意图都与意图相关联:

Intent intent = new Intent(context, testActivity.class);
Run Code Online (Sandbox Code Playgroud)

但是,这两个意图是相同的,因此当您的第二个通知到达时,它将启动第一个意图.

解:

你必须使每个意图都是唯一的,这样任何未决的意图都不会相等.你如何使意图独特?不是你附加的额外内容putExtra().即使额外的不同,意图可能仍然相等.要使每个intent都是唯一的,您必须为intent操作或数据,类型,类或类别或请求代码设置唯一值:(任何这些都可以工作)

  • 行动: intent.setAction(...)
  • 数据: intent.setData(...)
  • 类型: intent.setType(...)
  • 类: intent.setClass(...)
  • 类别: intent.addCategory(...)
  • 请求代码: PendingIntent.getActivity(context, YOUR_UNIQUE_CODE, intent, Intent.FLAG_ONE_SHOT);

注意:设置唯一的请求代码可能会很棘手,因为您需要一个int,而System.currentTimeMillis()返回long,这意味着将删除一些数字.因此,我建议您使用类别操作并设置唯一字符串.


mba*_*r14 13

我有同样的问题,并能够通过将标志更改为:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Run Code Online (Sandbox Code Playgroud)


Tom*_*asz 9

正如文档所说使用唯一的请求代码:

如果您确实需要多个不同的PendingIntent对象同时处于活动状态(例如用作同时显示的两个通知),那么您需要确保有一些不同的东西将它们与不同的关联起来PendingIntents.这可能是Intent.filterEquals考虑的任何Intent属性,或者提供给getActivity(Context,int,Intent,int),getActivities(Context,int,Intent [],int),getBroadcast(Context,int)的不同请求代码整数. ,Intent,int)或getService(Context,int,Intent,int).


Jon*_*itz 7

FWIW,我有更好的运气PendingIntent.FLAG_CANCEL_CURRENTPendingIntent.FLAG_UPDATE_CURRENT.


Wal*_*lil 5

我遇到了同样的问题,我通过以下步骤修复了它

1) 清除任何意图标记

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
Run Code Online (Sandbox Code Playgroud)

2)通过下面的代码插入intent.setAction

 intent.setAction(Long.toString(System.currentTimeMillis()));
Run Code Online (Sandbox Code Playgroud)

3) 对于 Pendingintent ,插入以下代码

   PendingIntent Pintent = PendingIntent.getActivity(ctx,0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
Run Code Online (Sandbox Code Playgroud)

我希望和你一起工作