95 votes

PendingIntent fonctionne correctement pour la première notification mais incorrectement pour le reste

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

Cette fonction sera appelée plusieurs fois. Je voudrais que pour chaque notification pour lancer testActivity lorsqu'on clique dessus. Malheureusement, seule la première notification lance testActivity. En cliquant sur les autres, la fenêtre de notification est réduite.

Informations supplémentaires : Fonction displayNotification() est dans une classe appelée UploadManager . Context est passé dans UploadManager del activity qui s'instancie. Fonction displayNotification() est appelée plusieurs fois à partir d'une fonction, également dans UploadManager, qui s'exécute dans un fichier AsyncTask .

Edit 1 : J'ai oublié de mentionner que je passe la réponse String dans Intent intent comme un extra .

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

Cela fait une grande différence car j'ai besoin de la "réponse" supplémentaire pour refléter ce qu'était la réponse de String lorsque la notification a été créée. Au lieu d'utiliser PendingIntent.FLAG_UPDATE_CURRENT le "response" supplémentaire reflète la réponse de String lors du dernier appel à displayNotification() .

Je sais pourquoi c'est le cas en lisant la documentation sur FLAG_UPDATE_CURRENT . Toutefois, je ne sais pas comment contourner ce problème pour le moment.

139voto

ognian Points 6906

N'utilisez pas Intent.FLAG_ACTIVITY_NEW_TASK pour PendingIntent.getActivity, utilisez FLAG_ONE_SHOT au lieu de


Copié des commentaires :

Ensuite, définissez une action fictive sur l'intention, sinon les extras sont abandonnés. Par exemple

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

67voto

ViliusK Points 1257

Je me débattais avec RemoteViews et plusieurs Intents pour chaque Button sur HomeScreen Widget. Cela a fonctionné quand on les a ajoutés :

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

50voto

ObjectiveTruth Points 21

Set Action a résolu le problème pour moi. Voici comment je comprends la situation :


J'ai plusieurs widgets auxquels est attaché un PendingIntent. Chaque fois que l'un d'entre eux est mis à jour, tous sont mis à jour. Les drapeaux sont là pour décrire ce qui se passe avec des PendingIntents qui sont exactement les mêmes.

La description de FLAG_UPDATE_CURRENT se lit beaucoup mieux maintenant :

Si le même PendingIntent que vous créez existe déjà, mettez à jour tous les anciens PendingIntent en fonction du nouveau PendingIntent que vous créez.

La définition d'exactement le même regarde l'ensemble du PendingIntent SAUF les extras. Ainsi, même si vous avez des suppléments différents pour chaque intention (pour moi, j'ai ajouté l'appWidgetId), pour Android, ce sont les mêmes.

L'ajout de .setAction avec une chaîne unique factice indique au système d'exploitation. Ceux-ci sont complètement différents et ne mettent rien à jour. Au final, voici mon implémentation qui fonctionne comme je le voulais, où chaque Widget a sa propre configuration d'intention attachée :

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


Une solution encore meilleure si vous travaillez avec des émissions. Les PendingIntents uniques sont également définis par des codes de demande uniques. Voici ma solution :

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

23voto

mole363 Points 438

Je vois des réponses mais pas d'explications. De plus, aucune des réponses n'aborde toutes les solutions possibles, je vais donc essayer de le préciser.

Documentation :

Si vous avez vraiment besoin de plusieurs objets PendingIntent distincts actifs en même temps (par exemple, pour utiliser deux notifications qui s'affichent en même temps), vous devrez vous assurer qu'il y a quelque chose de différent à leur sujet pour les associer à différents PendingIntents. Il peut s'agir de l'un des attributs Intent pris en compte par Intent.filterEquals, ou de différents codes de requête entiers fournis à getActivity(Context, int, Intent, int), getActivities(Context, int, Intent[], int), getBroadcast(Context, int, Intent, int), ou getService(Context, int, Intent, int).

Cause du problème :

Vous créez 2 notifications avec 2 intentions en attente. Chaque intention en attente est associée à une intention :

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

Cependant, ces 2 intentions sont égales, donc lorsque votre 2ème notification arrivera, elle lancera la première intention.

Solución:

Vous devez rendre chaque intention unique, de sorte qu'aucune intention en suspens ne soit jamais égale. Comment rendre les intentions uniques ? Pas par les extras que vous mettez avec putExtra() . Même si les extras sont différents, les intentions peuvent être identiques. Pour que chaque intention soit unique, vous devez définir une valeur unique pour l'action, les données, le type, la classe, la catégorie ou le code de demande de l'intention : (tous ces éléments fonctionnent)

  • action : intent.setAction(...)
  • données : intent.setData(...)
  • type : intent.setType(...)
  • classe : intent.setClass(...)
  • catégorie : intent.addCategory(...)
  • code de demande : PendingIntent.getActivity(context, YOUR_UNIQUE_CODE, intent, Intent.FLAG_ONE_SHOT);

Note : La définition d'un code de demande unique peut être délicate car vous avez besoin d'un int, alors que System.currentTimeMillis() renvoie une valeur longue, ce qui signifie que certains chiffres seront supprimés. C'est pourquoi je vous recommande d'opter pour la méthode catégorie ou le action et en fixant une chaîne unique.

13voto

mbauer14 Points 404

J'ai eu le même problème, et j'ai pu le résoudre en changeant le drapeau en :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X