it-swarm.com.de

PendingIntent funktioniert für die erste Benachrichtigung korrekt, für den Rest jedoch falsch

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

Diese Funktion wird mehrmals aufgerufen. Ich möchte, dass jede notification testActivity startet, wenn sie angeklickt wird. Leider startet nur die erste Benachrichtigung testActivity. Wenn Sie auf den Rest klicken, wird das Benachrichtigungsfenster minimiert.

Zusätzliche Informationen: Die Funktion displayNotification() gehört zur Klasse UploadManager. Context wird von der UploadManager, die instanziiert wird, an activity übergeben. Die Funktion displayNotification() wird mehrmals von einer Funktion aufgerufen, auch in UploadManager, die in einer AsyncTask ausgeführt wird.

Edit 1: Ich habe vergessen zu erwähnen, dass ich String-Antwort als extra an Intent intent übergeben habe.

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

Das macht einen großen Unterschied, weil ich die zusätzliche "Antwort" benötige, um zu zeigen, wie die Antwort von String war, als die Benachrichtigung erstellt wurde. Bei Verwendung von PendingIntent.FLAG_UPDATE_CURRENT gibt die zusätzliche "Antwort" an, welche String-Antwort beim letzten Aufruf von displayNotification() war.

Ich weiß, warum dies aus dem Lesen der Dokumentation zu FLAG_UPDATE_CURRENT hervorgeht. Ich bin jedoch nicht sicher, wie ich es umgehen kann.

78
user350617

Verwenden Sie Intent.FLAG_ACTIVITY_NEW_TASK nicht für PendingIntent.getActivity, sondern stattdessen FLAG_ONE_SHOT


Aus Kommentaren kopiert:

Legen Sie dann eine Dummy-Aktion für den Intent fest, andernfalls werden Extras weggelassen. Zum Beispiel

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

Wir hatten Probleme mit RemoteViews und mehreren unterschiedlichen Intents für jedes Button im HomeScreen Widget. Funktioniert, wenn hinzugefügt:

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

Set Action Das wurde für mich gelöst. Hier ist mein Verständnis der Situation:


Ich habe mehrere Widgets, an die jeweils ein PendingIntent angehängt ist. Wann immer man aktualisiert wurde, wurden alle aktualisiert. Die Flags beschreiben, was genau mit PendingIntents geschieht. 

FLAG_UPDATE_CURRENT Beschreibung liest sich jetzt viel besser: 

Wenn dasselbe PendingIntent bereits vorhanden ist, aktualisieren Sie alle alten auf das neue PendingIntent, das Sie erstellen.

Die Definition von genau dem gleichen bezieht sich auf das gesamte PendingIntent EXCEPT der Extras. Selbst wenn Sie unterschiedliche Absichten haben (für mich habe ich die appWidgetId hinzugefügt), dann auf Android, sie sind die gleichen.

Durch das Hinzufügen von .setAction mit einigen Dummy-Zeichenfolgen wird das Betriebssystem informiert. Diese sind völlig verschieden und aktualisieren nichts. Am Ende ist hier meine Implementierung, die funktioniert wie ich wollte, wobei jedem Widget eine eigene Konfiguration zugeordnet ist:

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

AKTUALISIEREN


Noch bessere Lösung für den Fall, dass Sie mit Broadcasts arbeiten. Eindeutige PendingIntents werden auch durch eindeutige Anforderungscodes definiert. Hier ist meine Lösung:

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

Ich hatte das gleiche Problem und konnte dieses Problem beheben, indem die Flagge folgendermaßen geändert wurde:

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

Ich sehe Antworten, aber keine Erklärungen. Auch keine der Antworten befasst sich mit allen möglichen Lösungen, also versuche ich das klar zu stellen.

Dokumentation:

Wenn Sie wirklich mehrere verschiedene PendingIntent-Objekte gleichzeitig aktiv sein müssen (z. B. als zwei Benachrichtigungen gleichzeitig verwendet werden sollen), müssen Sie sicherstellen, dass sie sich auf etwas anderes beziehen, um sie mit anderen zu verknüpfen PendingIntents. Dies können beliebige Intent-Attribute sein, die von Intent.filterEquals berücksichtigt werden, oder verschiedene Anforderungscode-Ganzzahlen, die an getActivity (Context, int, Intent, int), getActivities (Context, int, Intent [], int), getBroadcast (Context, int) übergeben werden , Intent, Int) oder getService (Kontext, Int, Intent, Int).

Ursache des Problems:

Sie erstellen 2 Benachrichtigungen mit 2 ausstehenden Absichten. Jeder anstehende Absicht ist eine Absicht zugeordnet:

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

Diese beiden Absichten sind jedoch gleich. Wenn Ihre zweite Benachrichtigung eintrifft, wird die erste Absicht gestartet.

Lösung:

Sie müssen jede Absicht einzigartig machen, damit keine anstehenden Absichten jemals gleich sind. Wie machen Sie die Absichten einzigartig? Nicht bei den Extras, die Sie mit putExtra() setzen. Selbst wenn die Extras unterschiedlich sind, sind die Absichten möglicherweise gleich. Um jede Absicht eindeutig zu machen, müssen Sie der Absichtsaktion, den Daten, dem Typ, der Klasse, der Kategorie oder dem Anforderungscode einen eindeutigen Wert zuweisen. (Jede dieser Optionen funktioniert).

  • aktion: intent.setAction(...)
  • daten: intent.setData(...)
  • typ: intent.setType(...)
  • klasse: intent.setClass(...)
  • kategorie: intent.addCategory(...)
  • anforderungscode: PendingIntent.getActivity(context, YOUR_UNIQUE_CODE, intent, Intent.FLAG_ONE_SHOT);

Hinweis : Das Festlegen eines eindeutigen Anforderungscodes kann schwierig sein, da Sie ein int benötigen, während System.currentTimeMillis() long zurückgibt, was bedeutet, dass einige Ziffern entfernt werden. Daher würde ich empfehlen, entweder mit der category oder der action zu gehen und einen eindeutigen String zu setzen.

12
MScott

Als Dokumentation verwenden Sie einen eindeutigen Anforderungscode:

Wenn Sie wirklich mehrere verschiedene PendingIntent-Objekte benötigen, die unter .__ aktiv sind. zur gleichen Zeit (z. B. als zwei Benachrichtigungen, die gleichzeitig angezeigt werden), müssen Sie sicherstellen, dass etwas vorhanden ist das ist anders, wenn man sie mit anderen .__ verbindet. PendingIntents. Dies kann eines der von .__ betrachteten Intent-Attribute sein. Intent.filterEquals oder verschiedene Anforderungscode-Ganzzahlen, die an .__ übergeben werden. getActivity (Kontext, int, Intent, int), getActivities (Kontext, int, Intent [], int), getBroadcast (Kontext, int, Intent, int) oder getService (Kontext, int, Intent, int).

8
Tomasz

Fwiw, ich hatte mit PendingIntent.FLAG_CANCEL_CURRENT mehr Glück als mit PendingIntent.FLAG_UPDATE_CURRENT.

7
Jon Shemitz

Ich hatte das gleiche Problem und habe es mit den folgenden Schritten behoben

1) Löschen Sie ein beliebiges Flag für Absicht 

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

2) Fügen Sie mit dem folgenden Code eine intent.setAction ein 

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

3) Bei Pendingintent geben Sie den folgenden Code ein 

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

Ich hoffe mit dir zu arbeiten

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

In PendingIntent befinden sich zwei int-Parameter, der zweite und der letzte. Der zweite ist "Request-Code" und muss eine eindeutige Nummer sein (z. B. die ID Ihrer Benachrichtigung). Andernfalls (wenn er in Ihrem Beispiel gleich Null ist, wird er immer überschrieben).

1
Dmytro Ubogyi
// 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());
0
MIkka Marmik

Ich habe das gleiche Problem und verwende das PendingIntent.html.FLAG_UPDATE_CURRENT , um das Problem zu beheben.

Ich habe den Quellcode überprüft. In ActivityManagerService.Java lautet die Schlüsselmethode wie folgt. Wenn das Flag PendingIntent.FLAG_UPDATE_CURRENT ist und updateCurrent wahr ist. Einige Extras werden durch neue ersetzt und wir erhalten ein ersetzendes 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);
        }

0
qin hao

um Daten korrekt zu senden, senden Sie die Benachrichtigungs-ID mit anstehender Absicht wie folgt: PendingIntent pendingIntent = PendingIntent.getActivity (Kontext, (int) System.currentTimeMillis () , intent, PendingIntent.FLAG_UPDATE_CURRENT);

0
Amal Kronz