Wie sende ich Parameter von einem Benachrichtigungsklick an eine Aktivität?


206

Ich kann anhand meiner Benachrichtigung einen Weg finden, Parameter an meine Aktivität zu senden.

Ich habe einen Dienst, der eine Benachrichtigung erstellt. Wenn der Benutzer auf die Benachrichtigung klickt, möchte ich meine Hauptaktivität mit einigen speziellen Parametern öffnen. ZB eine Artikel-ID, damit meine Aktivität eine spezielle Artikeldetailansicht laden und anzeigen kann. Genauer gesagt, ich lade eine Datei herunter, und wenn die Datei heruntergeladen wird, soll die Benachrichtigung die Absicht haben, dass beim Klicken meine Aktivität in einem speziellen Modus geöffnet wird. Ich habe versucht, putExtrameine Absicht zu nutzen , kann sie aber nicht extrahieren, also denke ich, dass ich es falsch mache.

Code von meinem Dienst, der die Benachrichtigung erstellt:

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

Code aus meiner Aktivität, der versucht, den zusätzlichen Parameter aus der Benachrichtigung abzurufen:

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

Die Extras sind immer null und ich bekomme nie etwas in mein Log.

Übrigens ... das onCreatewird nur ausgeführt, wenn meine Aktivität beginnt. Wenn meine Aktivität bereits gestartet ist, möchte ich auch die Extras sammeln und meine Aktivität gemäß der item_id präsentieren, die ich erhalte.

Irgendwelche Ideen?

Antworten:


241

Schauen Sie sich dieses Handbuch an ( Erstellen einer Benachrichtigung ) und sehen Sie sich ApiDemos "StatusBarNotifications" und "NotificationDisplay" an.

Um zu verwalten, ob die Aktivität bereits ausgeführt wird, haben Sie zwei Möglichkeiten:

  1. Fügen Sie dem Intent beim Starten der Aktivität das Flag FLAG_ACTIVITY_SINGLE_TOP hinzu , und implementieren Sie dann in der Aktivitätsklasse den Ereignishandler onNewIntent (Intent Intent) . Auf diese Weise können Sie auf die neue Absicht zugreifen, die für die Aktivität aufgerufen wurde (was nicht mit dem Aufrufen von getIntent identisch ist) (), dies gibt immer die erste Absicht zurück, die Ihre Aktivität gestartet hat.

  2. Wie Nummer eins, aber anstatt der Absicht ein Flag hinzuzufügen, müssen Sie "singleTop" in Ihre Aktivität AndroidManifest.xml einfügen.

Wenn Sie Absichts-Extras verwenden, denken Sie daran, PendingIntent.getActivity()mit der Flagge anzurufen PendingIntent.FLAG_UPDATE_CURRENT. Andernfalls werden dieselben Extras für jede Benachrichtigung wiederverwendet.


95
und um die Frage des Benutzers zu beantworten, ob Extras null sind: Sie müssen PendingIntent.getActivity()mit der Flagge anrufen PendingIntent.FLAG_UPDATE_CURRENT, andernfalls werden dieselben Extras für jede Benachrichtigung wiederverwendet.
Matthias

onNewIntent()war der Schlüssel :)
cprcrack

2
Du hast meinen Tag gerettet, aber warum ist das Übertragen einfacher Daten wie dieser in Android so kompliziert
Illegales Argument

8
Wenn Sie unterschiedliche Benachrichtigungen haben sollten, stellen Sie sicher, dass Sie beim Anrufen PendingIntent.getActivity()zusätzlich zu den Einstellungen FLAG_ACTIVITY_SINGLE_TOPfür Intentund FLAG_UPDATE_CURRENTfür unterschiedliche Anforderungs-IDs verwenden PendingIntent. Siehe stackoverflow.com/questions/7370324/…
Schnatterer

Danke @schnatterer: Es hat nur bei mir funktioniert, als ich eindeutige Absichts-IDs gemäß der Antwort hinzugefügt habe, auf die Sie verlinkt haben.
Mark Whitaker

101

Ich hatte das ähnliche Problem, dass meine Anwendung Nachrichtenbenachrichtigungen anzeigt. Wenn mehrere Benachrichtigungen vorhanden sind und auf jede Benachrichtigung geklickt wird, werden diese Benachrichtigungsdetails in einer Ansichtsnachrichtenaktivität angezeigt. Ich habe das Problem gelöst, dass dieselben zusätzlichen Parameter in der Absicht der Ansichtsnachricht empfangen werden.

Hier ist der Code, der dies behoben hat. Code zum Erstellen der Benachrichtigungsabsicht.

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

Code zum Anzeigen der Nachrichtenaktivität.

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


}

29

Vielleicht etwas spät, aber: stattdessen:

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

Benutze das:

Bundle extras = getIntent().getExtras();
if(extras !=null) {
    String value = extras.getString("keyName");
}

20
Vielleicht zu spät für die OP, aber es ist nie zu spät für die anderen im Internet :)
Espinchi

19

Treffen Sie hier auf dasselbe Problem. Ich löse es, indem ich einen anderen Anforderungscode verwende, dieselbe ID als Benachrichtigung verwende, während ich PendingIntent erstelle. aber ich weiß immer noch nicht, warum das getan werden soll.

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

1
das hat bei mir funktioniert. Es muss etwas mit konsistenten Anforderungscodes zu tun haben. Ich kann in dieser Dokumentation leider nicht viel darüber finden. Wenn jemand eine Erklärung hat, bitte posten oder kommentieren. developer.android.com/reference/android/app/PendingIntent.html
Nlinscott

Funktioniert bei mir. Ich hätte auch gerne eine Erklärung!
koherent

Bedeutet, dass beide IDs gleich oder unterschiedlich sein sollten?
Dhrupal

14

Nachdem ich einige E-Mail-Listen und andere Foren gelesen hatte, stellte ich fest, dass der Trick der Absicht einige eindeutige Daten hinzuzufügen scheint.

so was:

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

Ich verstehe nicht, warum dies getan werden muss. Es hat etwas mit der Absicht zu tun, kann nicht nur durch seine Extras identifiziert werden ...


8
Anroid verwendet Absichten wieder, die Absichtsaktion und der Anforderungscode machen sie eindeutig, aber nicht die zusätzlichen Daten. Sie müssen also eine eindeutige Anforderungs-ID festlegen oder andere Absichtsaktionen verwenden.
Bachi

@Bachi alles was ich brauche ist das zu ändernrequestID
Mehdi Khademloo

Funktioniert gut :) (obwohl es ein Hack ist).
Dimitar Vukman

10

Ich habe alles versucht, aber nichts hat funktioniert.

kam schließlich mit folgender Lösung.

1- im Manifest für die Aktivität Android hinzufügen: launchMode = "singleTop"

2- Verwenden Sie das Bundle, während Sie ausstehende Absichten ausführen, und verwenden Sie das Bundle, anstatt direkt intent.putString () oder intent.putInt () zu verwenden.

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

3
Für mich geht das. Es muss ein anderer requestCode-Wert und ein anderes PendingIntent.FLAG_UPDATE_CURRENT-Flag verwendet werden.
Phuongle

Nur diese Lösung hat funktioniert. Flags für notificationIntent sind optional.
ZimaXXX

Dies funktionierte wie ein Zauber für mich, die Zufallszahl und das Bündel haben den Job gemacht :)
Abhilash

4

AndroidManifest.xml

Include launchMode = "singleTop"

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

SMSReceiver.java

Setzen Sie die Flags für Intent und 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 () - wird jedes Mal aufgerufen, lade die Extras.

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

Ich hoffe, es hilft, es basiert auf anderen Antworten hier auf Stackoverflow, aber dies ist die aktuellste, die für mich funktioniert hat.


3

Es ist einfach, das ist meine Lösung mit Objekten!

Mein POJO

public class Person implements Serializable{

    private String name;
    private int age;

    //get & set

}

Methodenbenachrichtigung

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

Neue Aktivität

 private Person person;

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

Viel Glück!!


3

Nach einiger Suche bekam ich eine Lösung aus dem Android Developer Guide

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

Um einen zusätzlichen Wert für die Absicht in der Testaktivitätsklasse zu erhalten, müssen Sie folgenden Code schreiben:

 Intent intent = getIntent();
 String extra = intent.getStringExtra("extra") ;

3
Wofür ist stackBuilder?
AlexioVay

1

Verwenden Sie in Ihrer Benachrichtigungsimplementierung einen Code wie den folgenden:

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

Verwenden Sie den folgenden Code, um zusätzliche Werte für Intent in der ExampleActivity abzurufen:

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

SEHR WICHTIGER HINWEIS : Die Intent :: putExtra () -Methode ist überladen . Um den zusätzlichen Schlüssel zu erhalten, müssen Sie die Methode Intent :: get [Type] Extra () verwenden.

Hinweis: NOTIFICATION_ID und NOTIFICATION_CHANNEL_ID sind in ExampleActivity deklarierte Konstanten


1

G'day, ich kann auch sagen, dass ich alles versucht habe, was in diesen Posts erwähnt wurde, und ein paar mehr von woanders. Das größte Problem für mich war, dass der neue Intent immer ein Null-Bundle hatte. Mein Problem bestand darin, mich zu sehr auf die Details von "Habe ich dies oder das aufgenommen?" Zu konzentrieren. Meine Lösung bestand darin, einen Schritt vom Detail zurückzutreten und die Gesamtstruktur der Benachrichtigung zu betrachten. Als ich das tat, gelang es mir, die wichtigsten Teile des Codes in der richtigen Reihenfolge zu platzieren. Wenn Sie ähnliche Probleme haben, suchen Sie nach:

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

2a. Bundle bundle = new Bundle();

// Ich mag es, den Datentyp viel besser anzugeben. zB 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());

Mit dieser Sequenz bekomme ich ein gültiges Bundle.


0

Wenn du benutzt

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

In Ihrer AndroidManifest.xml-Datei, damit die Aktivität gestartet werden kann, müssen Sie in Ihrer Absicht Folgendes verwenden:

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

Wichtig ist, eindeutige Daten festzulegen, z. B. mit einer eindeutigen ID wie:

notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));

0

für die Nutzung von Diensten PendingIntent.FLAG_UPDATE_CURRENT

für mich arbeiten.


0

Bitte verwenden Sie als PendingIntent, während Sie eine Benachrichtigung anzeigen, da diese dann behoben wird.

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

Fügen Sie PendingIntent.FLAG_UPDATE_CURRENT als letztes Feld hinzu.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.