¿Cómo enviar parámetros desde un clic de notificación a una actividad?

206

Puedo encontrar una manera de enviar parámetros a mi actividad desde mi notificación.

Tengo un servicio que crea una notificación. Cuando el usuario hace clic en la notificación, quiero abrir mi actividad principal con algunos parámetros especiales. Por ejemplo, una identificación de elemento, por lo que mi actividad puede cargar y presentar una vista de detalle de elemento especial. Más específicamente, estoy descargando un archivo, y cuando se descarga el archivo, quiero que la notificación tenga la intención de que, al hacer clic, abra mi actividad en un modo especial. He intentado usarlo putExtraen mi intento, pero parece que no puedo extraerlo, así que creo que lo estoy haciendo mal.

Código de mi servicio que crea la Notificación:

        // construct the Notification object.
     final Notification notif = new Notification(R.drawable.icon, tickerText, System.currentTimeMillis());


    final RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.custom_notification_layout);
    contentView.setImageViewResource(R.id.image, R.drawable.icon);
    contentView.setTextViewText(R.id.text, tickerText);
    contentView.setProgressBar(R.id.progress,100,0, false);
    notif.contentView = contentView;        

    Intent notificationIntent = new Intent(context, Main.class);
    notificationIntent.putExtra("item_id", "1001"); // <-- HERE I PUT THE EXTRA VALUE
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
    notif.contentIntent = contentIntent;

    nm.notify(id, notif);

Código de mi actividad que intenta obtener el parámetro adicional de la notificación:

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);


    Bundle extras = getIntent().getExtras();
    if(extras != null){
        Log.i( "dd","Extra:" + extras.getString("item_id") );
    }

Los extras siempre son nulos y nunca pongo nada en mi registro.

Por cierto ... el onCreate solo se ejecuta cuando comienza mi actividad, si mi actividad ya ha comenzado, también quiero recopilar los extras y presentar mi actividad de acuerdo con el item_id que recibo.

¿Algunas ideas?

Vidar Vestnes
fuente

Respuestas:

241

Echa un vistazo a esta guía ( crear una notificación ) y a ejemplos de ApiDemos "StatusBarNotifications" y "NotificationDisplay".

Para administrar si la actividad ya se está ejecutando, tiene dos formas:

  1. Agregue el indicador FLAG_ACTIVITY_SINGLE_TOP al Intento al iniciar la actividad, y luego en la clase de actividad implemente el controlador de eventos onNewIntent (Intent intent) , de esa manera puede acceder al nuevo intento 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.

  2. Igual que el número uno, pero en lugar de agregar una bandera a la intención, debe agregar "singleTop" en su actividad AndroidManifest.xml.

Si usa extras intencionales, recuerde llamar PendingIntent.getActivity()con la bandera PendingIntent.FLAG_UPDATE_CURRENT, de lo contrario, se reutilizarán los mismos extras para cada notificación.

Lucas S.
fuente
95
y para responder a la pregunta del usuario acerca de que los extras son nulos: debe llamar PendingIntent.getActivity()con la bandera PendingIntent.FLAG_UPDATE_CURRENT, de lo contrario, se reutilizarán los mismos extras para cada notificación.
Matthias
2
me salvaste el día, pero ¿por qué es tan complicado transferir datos simples como este en Android?
Argumento ilegal
8
Si debe tener notificaciones diferentes, asegúrese de usar diferentes ID de solicitud al llamar PendingIntent.getActivity()además de configurarlo FLAG_ACTIVITY_SINGLE_TOPen Intenty FLAG_UPDATE_CURRENTen el PendingIntent. Ver stackoverflow.com/questions/7370324/…
schnatterer el
101

Tuve el mismo problema, mi aplicación muestra notificaciones de mensajes. Cuando hay varias notificaciones y al hacer clic en cada notificación, muestra los detalles de la notificación en una actividad de visualización de mensajes. Resolví el problema de que se están recibiendo los mismos parámetros adicionales en la intención del mensaje de vista.

Aquí está el código que solucionó esto. Código para crear la intención de notificación.

 Intent notificationIntent = new Intent(getApplicationContext(), viewmessage.class);
    notificationIntent.putExtra("NotificationMessage", notificationMessage);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingNotificationIntent = PendingIntent.getActivity(getApplicationContext(),notificationIndex,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notification.setLatestEventInfo(getApplicationContext(), notificationTitle, notificationMessage, pendingNotificationIntent);

Código para ver la actividad del mensaje.

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

    onNewIntent(getIntent());
}

@Override
public void onNewIntent(Intent intent){
    Bundle extras = intent.getExtras();
    if(extras != null){
        if(extras.containsKey("NotificationMessage"))
        {
            setContentView(R.layout.viewmain);
            // extract the extra-data in the Notification
            String msg = extras.getString("NotificationMessage");
            txtView = (TextView) findViewById(R.id.txtMessage);
            txtView.setText(msg);
        }
    }


}
Muhammad Yousaf Sulahria
fuente
29

Tal vez un poco tarde, pero: en lugar de esto:

public void onNewIntent(Intent intent){
    Bundle extras = intent.getExtras();
    Log.i( "dbg","onNewIntent");

    if(extras != null){
        Log.i( "dbg", "Extra6 bool: "+ extras.containsKey("net.dbg.android.fjol"));
        Log.i( "dbg", "Extra6 val : "+ extras.getString("net.dbg.android.fjol"));

    }
    mTabsController.setActiveTab(TabsController.TAB_DOWNLOADS);
}

Utilizar este:

Bundle extras = getIntent().getExtras();
if(extras !=null) {
    String value = extras.getString("keyName");
}
pinaise
fuente
20
Tal vez tarde para el OP, pero nunca es tarde para los demás en Internet :)
espinchi
19

Encuentra el mismo problema aquí. Lo resuelvo usando un código de solicitud diferente, uso la misma identificación que la notificación, mientras creo PendingIntent. pero aún no sé por qué debería hacerse esto.

PendingIntent contentIntent = PendingIntent.getActivity(context, **id**, notificationIntent, 0);
notif.contentIntent = contentIntent;
nm.notify(**id**, notif);
jamchen
fuente
14

Después de leer algunas listas de correo electrónico y otros foros, descubrí que el truco parece agregar algunos datos únicos a la intención.

Me gusta esto:

   Intent notificationIntent = new Intent(Main.this, Main.class);
   notificationIntent.putExtra("sport_id", "sport"+id);
   notificationIntent.putExtra("game_url", "gameURL"+id);

   notificationIntent.setData((Uri.parse("foobar://"+SystemClock.elapsedRealtime()))); 

No entiendo por qué esto debe hacerse, tiene algo que ver con la intención, no se puede identificar solo por sus extras ...

Vidar Vestnes
fuente
8
Anroid reutiliza los intentos, la acción del intento y el código de solicitud lo hacen único, pero no los datos adicionales. Por lo tanto, debe establecer una identificación de solicitud única o utilizar diferentes acciones de intención.
Bachi
10

Intenté todo pero nada funcionó.

finalmente se le ocurrió la siguiente solución.

1- en manifiesto agregar para la actividad android: launchMode = "singleTop"

2- mientras realiza una intención pendiente, haga lo siguiente, use el paquete en lugar de usar directamente intent.putString () o intent.putInt ()

                    Intent notificationIntent = new Intent(getApplicationContext(), CourseActivity.class);

                    Bundle bundle = new Bundle();
                    bundle.putString(Constants.EXAM_ID,String.valueOf(lectureDownloadStatus.getExamId()));
                    bundle.putInt(Constants.COURSE_ID,(int)lectureDownloadStatus.getCourseId());
                    bundle.putString(Constants.IMAGE_URL,lectureDownloadStatus.getImageUrl());

                    notificationIntent.putExtras(bundle);

                    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                            Intent.FLAG_ACTIVITY_SINGLE_TOP);
                    PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),
                            new Random().nextInt(), notificationIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT); 
Dheeraj Sachan
fuente
3
Esto funciona para mi. Debe usar un valor requestCode diferente y un indicador PendingIntent.FLAG_UPDATE_CURRENT.
phuongle
4

AndroidManifest.xml

Incluir launchMode = "singleTop"

<activity android:name=".MessagesDetailsActivity"
        android:launchMode="singleTop"
        android:excludeFromRecents="true"
        />

SMSReceiver.java

Establezca las banderas para Intent y PendingIntent

Intent intent = new Intent(context, MessagesDetailsActivity.class);
    intent.putExtra("smsMsg", smsObject.getMsg());
    intent.putExtra("smsAddress", smsObject.getAddress());
    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

    PendingIntent contentIntent = PendingIntent.getActivity(context, notification_id, intent, PendingIntent.FLAG_UPDATE_CURRENT);

MessageDetailsActivity.java

onResume (): se llama cada vez que se cargan los extras.

Intent intent = getIntent();
    String extraAddress = intent.getStringExtra("smsAddress");
    String extraBody = intent.getStringExtra("smsMsg");

Espero que ayude, se basó en otras respuestas aquí en stackoverflow, pero esta es la más actualizada que funcionó para mí.

Miguel Jesus
fuente
3

¡Es fácil, esta es mi solución usando objetos!

Mi POJO

public class Person implements Serializable{

    private String name;
    private int age;

    //get & set

}

Notificación de método

  Person person = new Person();
  person.setName("david hackro");
  person.setAge(10);

    Intent notificationIntent = new Intent(this, Person.class);
    notificationIntent.putExtra("person",person);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.notification_icon)
                .setAutoCancel(true)
                .setColor(getResources().getColor(R.color.ColorTipografiaAdeudos))
                .setPriority(2)
                .setLargeIcon(bm)
                .setTicker(fotomulta.getTitle())
                .setContentText(fotomulta.getMessage())
                .setContentIntent(PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT))
                .setWhen(System.currentTimeMillis())
                .setContentTitle(fotomulta.getTicketText())
                .setDefaults(Notification.DEFAULT_ALL);

Nueva actividad

 private Person person;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notification_push);
    person = (Person) getIntent().getSerializableExtra("person");
}

¡¡Buena suerte!!

David Hackro
fuente
3

Después de hacer una búsqueda, obtuve una solución de la guía para desarrolladores de Android

PendingIntent contentIntent ;
Intent intent = new Intent(this,TestActivity.class);
intent.putExtra("extra","Test");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

stackBuilder.addParentStack(ArticleDetailedActivity.class);

contentIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

Para obtener un valor adicional de intención en la clase de actividad de prueba, debe escribir el siguiente código:

 Intent intent = getIntent();
 String extra = intent.getStringExtra("extra") ;
mohit
fuente
3
Lo que es stackBuilderpara?
AlexioVay
1

En su implementación de notificación, use un código como este:

NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
...
Intent intent = new Intent(this, ExampleActivity.class);
intent.putExtra("EXTRA_KEY", "value");

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
nBuilder.setContentIntent(pendingIntent);
...

Para obtener valores adicionales de intención en ExampleActivity, use el siguiente código:

...
Intent intent = getIntent();
if(intent!=null) {
    String extraKey = intent.getStringExtra("EXTRA_KEY");
}
...

NOTA MUY IMPORTANTE: el método Intent :: putExtra () es sobrecargado. Para obtener la clave adicional, debe usar Intent :: get [Type] Extra () método .

Nota: NOTIFICATION_ID y NOTIFICATION_CHANNEL_ID son constantes declaradas en ExampleActivity

Carlos Espinoza
fuente
1

G'day, yo también puedo decir que probé todo lo mencionado en estas publicaciones y algunas más de otros lugares. El problema número 1 para mí fue que la nueva intención siempre tenía un paquete nulo. Mi problema fue centrarme demasiado en los detalles de "he incluido .esto o eso". Mi solución fue dar un paso atrás de los detalles y observar la estructura general de la notificación. Cuando hice eso, logré colocar las partes clave del código en la secuencia correcta. Entonces, si tiene problemas similares, busque:

1. Intent notificationIntent = new Intent(MainActivity.this, NotificationActivity.class);

2a. Bundle bundle = new Bundle();

// Me gusta especificar el tipo de datos mucho mejor. ej. bundle.putInt

2b. notificationIntent.putExtras(bundle);
3. PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, WIZARD_NOTIFICATION_ID, notificationIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
4. NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
5.          NotificationCompat.Builder nBuilder =
                    new NotificationCompat.Builder(this)
                            .setSmallIcon(R.drawable.ic_notify)
                            .setContentTitle(title)
                            .setContentText(content)
                            .setContentIntent(contentIntent)
                            .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
                            .setAutoCancel(false)//false is standard. true == automatically removes the notification when the user taps it.
                            .setColor(getResources().getColor(R.color.colorPrimary))
                            .setCategory(Notification.CATEGORY_REMINDER)
                            .setPriority(Notification.PRIORITY_HIGH)
                            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
            notificationManager.notify(WIZARD_NOTIFICATION_ID, nBuilder.build());

Con esta secuencia obtengo un paquete válido.

Peter Suter
fuente
0

Si utiliza

android:taskAffinity="myApp.widget.notify.activity"
android:excludeFromRecents="true"

en su archivo AndroidManifest.xml para que se inicie la Actividad, debe usar lo siguiente en su intención:

Intent notificationClick = new Intent(context, NotifyActivity.class);
    Bundle bdl = new Bundle();
    bdl.putSerializable(NotifyActivity.Bundle_myItem, myItem);
    notificationClick.putExtras(bdl);
    notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
    notificationClick.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);  // schließt tasks der app und startet einen seperaten neuen

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(NotifyActivity.class);
    stackBuilder.addNextIntent(notificationClick);

    PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(notificationPendingIntent);

Importante es establecer datos únicos, por ejemplo, usando una identificación única como:

notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
Gorrón
fuente
0

para uso de servicios PendingIntent.FLAG_UPDATE_CURRENT

para mi trabajo

Ali Bagheri
fuente
0

Úselo como PendingIntent mientras muestra la notificación de lo que se resolverá.

PendingIntent intent = PendingIntent.getActivity (this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Agregue PendingIntent.FLAG_UPDATE_CURRENT como último campo.

M.Noman
fuente