PendingIntent no envía extras de Intent

5 minutos de lectura

avatar de usuario
maysi

Mi MainActicity empieza RefreshService con un Intent que tiene un boolean adicional llamado isNextWeek.

Mi RefreshService hace un Notification que comienza mi MainActivity cuando el usuario hace clic en él.

esto se ve así:

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

Como puedes ver el notificationIntent debería tener el booleanextra IS_NEXT_WEEK con el valor de isNextWeek que se pone en el PendingIntent.

Cuando hago clic ahora esto Notification siempre consigo false como valor de isNextWeek

Esta es la forma en que obtengo el valor en el MainActivity:

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

Tronco:

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

Cuando empiezo directamente el MainActivity con un Intent con el ìsNextValue` así:

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

todo funciona bien y me sale true cuando isNextWeek es true.

¿Qué hago mal que siempre hay un false ¿valor?

ACTUALIZAR

esto resuelve el problema: https://stackoverflow.com/a/18049676/2180161

Cotizar:

Mi sospecha es que, dado que lo único que cambia en el Intent son los extras, el PendingIntent.getActivity(...) El método de fábrica es simplemente reutilizar la intención anterior como una optimización.

En RefreshService, intente:

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

Ver:

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

ACTUALIZAR 2

Vea la respuesta a continuación por qué es mejor usar PendingIntent.FLAG_UPDATE_CURRENT.

  • PendingIntent.FLAG_CANCEL_CURRENT funcionó para mí, gracias

    – Pelanes

    16 de junio de 2014 a las 11:01

  • me ahorró muchas horas de trabajo. ¡respuesta correcta!

    – Tharaka Nirmana

    6 de diciembre de 2014 a las 15:08

  • tienes la pregunta y la solución 😀 genial. Creo que deberías agregarlo como respuesta a la pregunta. +10s es mejor que +5s 😉

    – Muhammed Refaat

    18 de abril de 2017 a las 7:15

  • Haciendo referencia a esta solución: stackoverflow.com/questions/1198558/…

    – Muhammad Noman

    7 de noviembre de 2017 a las 11:43


  • FLAG_UPDATE_CURRENT no fue suficiente en mi caso, ya que mi widget reutilizó el mismo PendingIntent. Terminé usando FLAG_ONE_SHOT para la acción que ocurre raramente y dejé intacto el widget PendingIntent.

    – Eír

    23 de abril de 2020 a las 8:43

avatar de usuario
yuliia ashomok

Usar PendingIntent.FLAG_CANCEL_CURRENT no es una buena solución debido al uso ineficiente de la memoria. En su lugar, use PendingIntent.FLAG_UPDATE_CURRENT.

Usar también Intención.FLAG_ACTIVITY_SINGLE_TOP (la actividad no se iniciará si ya se está ejecutando en la parte superior de la pila de historial).

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

Después:

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

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

Debería funcionar ahora.


Si aún no tiene el comportamiento esperado, intente implementar void onNewIntent(Intent intent) controlador de eventos, de esa manera puede acceder a la nueva intención que se llamó para la actividad (que no es lo mismo que simplemente llamar a getIntent(), esto siempre devolverá la primera intención que lanzó su actividad.

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

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

  • Esto también funciona para PendingIntent.getBroadcast

    – Juan

    7 ene a las 16:25

avatar de usuario
Vikram

Creo que necesitas actualizar el Intent cuando recibe uno nuevo anulando onNewIntent(Intent) en su Actividad. Agregue lo siguiente a su Actividad:

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

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

Editar:

Esto es necesario solo si su actividad ya se inició cuando se recibió la intención. Si su actividad se inicia (y no solo se reanuda) por la intención, entonces el problema está en otra parte y es posible que mi sugerencia no lo solucione.

  • esto aparece también si la actividad se cierra y luego se abre con la notificación.

    – maysi

    4 de agosto de 2013 a las 20:48


El siguiente código debería funcionar: –

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

En MainActivity en Crear:

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

  • new Notification(icon, message, when); es obsoleto

    – maysi

    3 de agosto de 2013 a las 23:13

  • De todos modos, ¿hacerlo sin CLEAR_TOP?

    – ricardoum

    26 de junio de 2015 a las 16:04

Entonces, la razón real es que PendingIntent almacenará en caché la intención anterior si las intenciones solo difieren en sus extras. En mi situación no hay combinación de PendingIntent.FLAG_UPDATE_CURRENT o PendingIntent.FLAG_CANCEL_CURRENT resuelve esto ya que se reemplazará la intención anterior o la nueva permanecerá igual que la inicial. Debe asegurarse de que Android no pueda almacenar en caché los Intents detrás del PendingIntent. La solución para mí es hacer que difieran en su data atributo.

por lo tanto, en el código original de los carteles, debe asegurarse de que el data El atributo es único para cada combinación de extras que está adjuntando.

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

Alternativamente, probablemente también podría agregar un uuid al uri de datos (sin embargo, si tiene muchas notificaciones, sería bueno almacenarlas en caché

¿Ha sido útil esta solución?