139 votes

PendingIntent n'envoie pas d'extras Intent

Mon MainActicity commence RefreshService avec un Intent qui dispose d'un boolean supplémentaire appelé isNextWeek .

Mon RefreshService fait un Notification qui démarre mon MainActivity lorsque l'utilisateur clique dessus.

cela ressemble à ceci :

    Log.d("Refresh", "RefreshService got: isNextWeek: " + String.valueOf(isNextWeek));

    Intent notificationIntent = new Intent(this, MainActivity.class);
    notificationIntent.putExtra(MainActivity.IS_NEXT_WEEK, isNextWeek);

    Log.d("Refresh", "RefreshService put in Intent: isNextWeek: " + String.valueOf(notificationIntent.getBooleanExtra(MainActivity.IS_NEXT_WEEK,false)));
    pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    builder = new NotificationCompat.Builder(this).setContentTitle("Title").setContentText("ContentText").setSmallIcon(R.drawable.ic_notification).setContentIntent(pendingIntent);
    notification = builder.build();
    // Hide the notification after its selected
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notificationManager.notify(NOTIFICATION_REFRESH, notification);

Comme vous pouvez le constater, la notificationIntent devrait avoir le boolean supplémentaire IS_NEXT_WEEK avec la valeur de isNextWeek qui est placé dans le PendingIntent .

Lorsque je clique sur "maintenant", ceci Notification Je reçois toujours false comme valeur de isNextWeek

C'est ainsi que j'obtiens la valeur dans le champ MainActivity :

    isNextWeek = getIntent().getBooleanExtra(IS_NEXT_WEEK, false);

Journal :

08-04 00:19:32.500  13367-13367/de.MayerhoferSimon.Vertretungsplan D/Refresh: MainActivity sent: isNextWeek: true
08-04 00:19:32.510  13367-13573/de.MayerhoferSimon.Vertretungsplan D/Refresh: RefreshService got: isNextWeek: true
08-04 00:19:32.510  13367-13573/de.MayerhoferSimon.Vertretungsplan D/Refresh: RefreshService put in Intent: isNextWeek: true
08-04 00:19:41.990  13367-13367/de.MayerhoferSimon.Vertretungsplan D/Refresh: MainActivity.onCreate got: isNextWeek: false

Lorsque je démarre directement le MainActivity avec un Intent avec la ìsNextValue` comme ceci :

    Intent i = new Intent(this, MainActivity.class);
    i.putExtra(IS_NEXT_WEEK, isNextWeek);
    finish();
    startActivity(i);

tout fonctionne bien et j'obtiens true quand isNextWeek es true .

Qu'est-ce qui me fait dire qu'il y a toujours un false valeur ?

MISE À JOUR

cela résout le problème : https://stackoverflow.com/a/18049676/2180161

Citation :

Je soupçonne que, puisque la seule chose qui change dans la les extras, le PendingIntent.getActivity(...) f est simplement la réutilisation de l'ancienne intention comme une optimisation.

Dans RefreshService, essayez :

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);

Voir :

http://developer.Android.com/reference/Android/app/PendingIntent.html#FLAG_CANCEL_CURRENT

MISE À JOUR 2

Véase réponse ci-dessous pourquoi il est préférable d'utiliser PendingIntent.FLAG_UPDATE_CURRENT .

2 votes

PendingIntent.FLAG_CANCEL_CURRENT a fonctionné pour moi, merci.

1 votes

M'a permis d'économiser de nombreuses heures de travail. bonne réponse !

0 votes

Vous avez la question et la solution :D génial. Je pense que vous devriez l'ajouter comme réponse à la question. +10s est mieux que +5s ;)

40voto

Iuliia Points 198

L'utilisation de PendingIntent.FLAG_CANCEL_CURRENT n'est pas une bonne solution en raison de l'utilisation inefficace de la mémoire. Utilisez plutôt PendingIntent.FLAG_UPDATE_CURRENT .

Utiliser également Intent.FLAG_ACTIVITY_SINGLE_TOP (l'activité ne sera pas lancée si elle est déjà en cours d'exécution au sommet de la pile de l'historique).

Intent resultIntent = new Intent(this, FragmentPagerSupportActivity.class).
                    addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  
resultIntent.putExtra(FragmentPagerSupportActivity.PAGE_NUMBER_KEY, pageNumber);

PendingIntent resultPendingIntent =
                PendingIntent.getActivity(
                        this,
                        0,
                        resultIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );

Ensuite :

@Override
    protected void onCreate(Bundle savedInstanceState) {
        try {
            super.onCreate(savedInstanceState);

            int startPageNumber;
            if ( savedInstanceState != null)
            {
                startPageNumber = savedInstanceState.getInt(PAGE_NUMBER_KEY);
//so on

Cela devrait fonctionner maintenant.


Si vous n'obtenez toujours pas le comportement escompté, essayez de mettre en œuvre les mesures suivantes void onNewIntent(Intent intent) vous pouvez ainsi accéder à la nouvelle intention qui a été appelée pour l'activité (ce qui n'est pas la même chose que d'appeler getIntent(), qui renverra toujours la première intention qui a lancé votre activité).

@Override
protected void onNewIntent(Intent intent) {
    int startPageNumber;

    if (intent != null) {
        startPageNumber = intent.getExtras().getInt(PAGE_NUMBER_KEY);
    } else {
        startPageNumber = 0;
    }
}

21voto

Vikram Points 17845

Je pense que vous devez mettre à jour le Intent lorsque vous en recevez un nouveau en remplaçant onNewIntent(Intent) dans votre activité. Ajoutez les éléments suivants à votre activité :

@Override
public void onNewIntent(Intent newIntent) {
    this.setIntent(newIntent);

    // Now getIntent() returns the updated Intent
    isNextWeek = getIntent().getBooleanExtra(IS_NEXT_WEEK, false);        
}

Edita:

Cela n'est nécessaire que si votre activité a déjà commencé lorsque l'intention est reçue. Si votre activité est démarrée (et pas seulement reprise) par l'intention, le problème est ailleurs et ma suggestion ne le résoudra peut-être pas.

0 votes

Ceci apparaît également si l'activité est fermée et ensuite ouverte avec la notification.

3voto

hrehman Points 734

Le code suivant devrait fonctionner :-

int icon = R.drawable.icon;
String message = "hello";
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);

Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.putExtra("isNexWeek", true);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, pIntent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);

Dans MainActivity onCreate :

if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("isNextWeek")) {
        boolean isNextWeek = getIntent().getExtras().getBoolean("isNextWeek");
}

0 votes

new Notification(icon, message, when); est obsolète

0 votes

Comment faire sans CLEAR_TOP ?

0voto

RaB Points 849

La raison est donc que le PendingIntent mettra en cache l'intention précédente si les intentions ne diffèrent que par leurs extras. Dans ma situation, aucune combinaison de PendingIntent.FLAG_UPDATE_CURRENT o PendingIntent.FLAG_CANCEL_CURRENT résout ce problème : soit l'ancienne intention est remplacée, soit la nouvelle intention reste identique à l'intention initiale. Vous devez vous assurer qu'Android ne peut pas mettre en cache les Intents derrière le PendingIntent. La solution pour moi est de les faire différer dans leur data attribut.

Ainsi, dans le code de l'affiche originale, il faut s'assurer que l'élément data est unique pour chaque combinaison d'extras que vous attachez.

    Intent notificationIntent = new Intent(this, MainActivity.class);
    notificationIntent.putExtra(MainActivity.IS_NEXT_WEEK, isNextWeek);
    notificationIntent.setData(Uri.parse("myapp://nextWeek/" + (isNextWeek ? "1" : "0"))

Vous pouvez également ajouter un uuid à l'uri des données (cependant, si vous avez beaucoup de notifications, il peut être intéressant de les mettre en cache).

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