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); } 

这个函数将被多次调用。 我想每个notification单击时启动testActivity。 不幸的是,只有第一个通知启动了testActivity。 点击其余的会导致通知窗口最小化。

额外的信息:函数displayNotification()在一个名为UploadManager的类中。 Context从实例化的activity传递到UploadManager 。 函数displayNotification()在同一个AsyncTask运行的UploadManager中的函数被多次调用。

编辑1:我忘了提及,我作为一个extra传递string响应到Intent intent

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

这会产生很大的差异,因为我需要额外的“响应”来反映通知创build时的string响应。 相反,使用PendingIntent.FLAG_UPDATE_CURRENT ,额外的“响应”反映了最后一次调用displayNotification() String响应。

我知道这是通过阅读FLAG_UPDATE_CURRENT上的文档。 不过,目前我不清楚如何解决这个问题。

不要对PendingIntent.getActivity使用Intent.FLAG_ACTIVITY_NEW_TASK ,请改用FLAG_ONE_SHOT


从评论复制:

然后在Intent上设置一些虚拟操作,否则额外的操作会被丢弃。 例如

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

HomeScreen Widget上,每个Button在使用RemoteViews和几个不同的Intents 。 工作时添加这些:

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

设置行动解决这个给我。 这是我对情况的理解:


我有多个小工具,每个都有一个PendingIntent。 每当有人更新,他们都得到更新。 标志在那里描述了PendingIntents发生的事情是完全一样的。

FLAG_UPDATE_CURRENT描述现在读得好多了:

如果您正在创build的PendingIntent已经存在,那么将所有的旧PendingIntent更新为您正在创build的新的PendingIntent。

完全相同的定义看起来整个PendingIntent除了额外的。 因此,即使你有不同的额外的每个意图(对我来说,我是添加appWidgetId),然后到Android,他们是一样的。

添加.setAction与一些虚拟的唯一string告诉操作系统。 这些是完全不同的,不更新任何东西。 最后,这里是我的实现,这是我想要的,每个Widget都有自己的configurationIntent附:

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

UPDATE


更好的解决scheme,如果你正在使用广播。 唯一的PendingIntents也由唯一的请求代码定义。 这是我的解决scheme:

 //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); 

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

 PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); 

Fwiw, PendingIntent.FLAG_CANCEL_CURRENTPendingIntent.FLAG_UPDATE_CURRENT有更好的运气。

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

如果您确实需要同时激活多个不同的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)。

我有同样的问题,我通过以下步骤进行了修复

1)清除意图的任何标志

 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 

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

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

3)为Pendingintent,插入下面的代码

  PendingIntent Pintent = PendingIntent.getActivity(ctx,0, intent,PendingIntent.FLAG_UPDATE_CURRENT); 

我希望能和你一起工作

我看到答案,但没有解释。 也没有答案处理所有可能的解决scheme,所以我会尽量说清楚。

文档:

如果您确实需要同时激活多个不同的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)。

问题的原因:

您创build2个未决意图的通知。 每个未决意图都与一个意图相关联:

 Intent intent = new Intent(context, testActivity.class); 

然而,这两个意图是平等的,因此当你的第二个通知到达时,它将启动第一个意图。

解:

你必须使每个意图都是唯一的,这样就不会有任何等待的意图。 你如何使意图独特? 而不是你用putExtra()放置的额外的东西。 即使演员不同,意图也可能是平等的。 为了使每个意图唯一,您必须为意向操作,数据或types,类别,类别或请求代码设置一个唯一的值:(其中任何一个都可以)

  • 操作: intent.setAction(...)
  • data: intent.setData(...)
  • 键入: intent.setType(...)
  • class: intent.setClass(...)
  • category: intent.addCategory(...)
  • 请求代码: PendingIntent.getActivity(context, YOUR_UNIQUE_CODE, intent, Intent.FLAG_ONE_SHOT);

注意 :设置一个唯一的请求代码可能会很棘手,因为你需要一个int,而System.currentTimeMillis()返回long,这意味着一些数字将被删除。 因此,我build议要么与类别行动,并设置一个独特的string。

 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK); 

在PendingIntent中是两个int参数,第二个和最后一个。 第二个是“请求代码”,它必须是唯一的数字(例如你的通知的id),否则如果(在你的例子中它等于零,它总是会被覆盖)。

 // Use pending Intent and also use unique id for display notification.... // Get a PendingIntent containing the entire back stack PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT); NotificationManager mNotificationManager = (NotificationManager) sqlitewraper.context.getSystemService(Context.NOTIFICATION_SERVICE); // Issue the notification mNotificationManager.notify(id, builder.build()); 

要发送数据额外正确,你应该发送与挂起的意图通知id像这样:PendingIntent pendingIntent = PendingIntent.getActivity(context, (int)System.currentTimeMillis() ,intent,PendingIntent.FLAG_UPDATE_CURRENT);

我有同样的问题,并使用PendingIntent.html.FLAG_UPDATE_CURRENT来解决它。

我已经检查了源代码。 在ActivityManagerService.java中 ,关键的方法如下。 标志为PendingIntent.FLAG_UPDATE_CURRENT且updateCurrent为true时。 一些额外的将被新的取代,我们将得到一个替代PendingIntent。

  IIntentSender getIntentSenderLocked(int type, String packageName, int callingUid, int userId, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle bOptions) { // ... omitted final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0; final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0; final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0; flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT |PendingIntent.FLAG_UPDATE_CURRENT); PendingIntentRecord.Key key = new PendingIntentRecord.Key( type, packageName, activity, resultWho, requestCode, intents, resolvedTypes, flags, bOptions, userId); WeakReference<PendingIntentRecord> ref; ref = mIntentSenderRecords.get(key); PendingIntentRecord rec = ref != null ? ref.get() : null; if (rec != null) { if (!cancelCurrent) { if (updateCurrent) { if (rec.key.requestIntent != null) { rec.key.requestIntent.replaceExtras(intents != null ? intents[intents.length - 1] : null); } if (intents != null) { intents[intents.length-1] = rec.key.requestIntent; rec.key.allIntents = intents; rec.key.allResolvedTypes = resolvedTypes; } else { rec.key.allIntents = null; rec.key.allResolvedTypes = null; } } return rec; } rec.canceled = true; mIntentSenderRecords.remove(key); } 

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

 LayoutInflater factory = LayoutInflater.from(this); final View textEntryView = factory.inflate(R.layout.appointment, null); AlertDialog.Builder bulider= new AlertDialog.Builder(PatientDetail.this); final AlertDialog alert=bulider.create(); bulider.setTitle("Enter Date/Time"); bulider.setView(textEntryView); bulider.setPositiveButton("Save", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { EditText typeText=(EditText) textEntryView.findViewById(R.id.Editdate); EditText input1 =(EditText) textEntryView.findViewById(R.id.Edittime); getDateAndTime(typeText.getText().toString(),input1.getText().toString()); } }); bulider.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); bulider.show(); }