Jak wysłać parametry z kliknięcia powiadomienia do działania?

206

Mogę znaleźć sposób na przesłanie parametrów do mojej aktywności z mojego powiadomienia.

Mam usługę, która tworzy powiadomienie. Gdy użytkownik kliknie powiadomienie, chcę otworzyć moją główną aktywność z pewnymi specjalnymi parametrami. Np. Identyfikator przedmiotu, więc moja aktywność może załadować i przedstawić specjalny widok szczegółów przedmiotu. Mówiąc dokładniej, pobieram plik, a gdy plik jest pobierany, chcę, aby powiadomienie miało taki zamiar, że po kliknięciu otwiera moją aktywność w trybie specjalnym. Próbowałem użyć putExtrazgodnie z moją intencją, ale nie mogę tego wydobyć, więc myślę, że robię to źle.

Kod z mojej usługi, który tworzy powiadomienie:

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

Kod z mojej aktywności, która próbuje pobrać dodatkowy parametr z powiadomienia:

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

Dodatki są zawsze zerowe i nigdy nie dostaję niczego do mojego dziennika.

Przy okazji ... onCreate jest uruchamiane tylko wtedy, gdy moja aktywność się rozpoczyna, jeśli moja aktywność już się rozpoczęła Chcę również zebrać dodatki i przedstawić moją aktywność zgodnie z otrzymanym item_id.

Jakieś pomysły?

Vidar Vestnes
źródło

Odpowiedzi:

241

Przejrzyj ten przewodnik ( tworzenie powiadomienia ) oraz z przykładami ApiDemos „StatusBarNotifications” i „NotificationDisplay”.

Do zarządzania, jeśli działanie jest już uruchomione, masz dwa sposoby:

  1. Dodaj flagę FLAG_ACTIVITY_SINGLE_TOP do obiektu Intent podczas uruchamiania działania, a następnie w klasie aktywności zaimplementuj moduł obsługi zdarzeń wNewIntent (Intent intent) , w ten sposób możesz uzyskać dostęp do nowego zamiaru, który został wywołany dla działania (co nie jest tym samym, co wywołanie getIntent (), to zawsze zwróci pierwszą intencję, która rozpoczęła Twoją aktywność.

  2. Taki sam jak numer jeden, ale zamiast dodawać flagę do zamiaru, musisz dodać „singleTop” w swojej aktywności AndroidManifest.xml.

Jeśli korzystasz z zamierzonych dodatków, pamiętaj, aby zadzwonić PendingIntent.getActivity()z flagą PendingIntent.FLAG_UPDATE_CURRENT, w przeciwnym razie te same dodatki będą ponownie wykorzystywane przy każdym powiadomieniu.

Lucas S.
źródło
95
i aby odpowiedzieć na pytanie użytkownika, czy dodatki są nieważne: musisz zadzwonić PendingIntent.getActivity()z flagą PendingIntent.FLAG_UPDATE_CURRENT, w przeciwnym razie te same dodatki będą ponownie wykorzystane przy każdym powiadomieniu.
Matthias,
2
uratowałeś mi dzień, ale dlaczego przesyłanie takich prostych danych jest tak skomplikowane w Androidzie
nielegalny argument
8
Jeśli powinieneś mieć różne powiadomienia, upewnij się, że używasz różnych identyfikatorów żądań podczas dzwonienia PendingIntent.getActivity()oprócz ustawień FLAG_ACTIVITY_SINGLE_TOPna Intenti FLAG_UPDATE_CURRENTna PendingIntent. Zobacz stackoverflow.com/questions/7370324/…
schnatterer
101

Miałem podobny problem, że moja aplikacja wyświetla powiadomienia o wiadomościach. Gdy jest wiele powiadomień i kliknięcie każdego powiadomienia powoduje wyświetlenie tego szczegółu powiadomienia w aktywności wyświetlania wiadomości. Rozwiązałem problem z tymi samymi dodatkowymi parametrami, które są odbierane w celu wyświetlenia wiadomości.

Oto kod, który to naprawił. Kod do utworzenia zamiaru powiadomienia.

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

Kod do wyświetlenia Wiadomość Aktywność.

@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
źródło
29

Może trochę późno, ale: zamiast tego:

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

Użyj tego:

Bundle extras = getIntent().getExtras();
if(extras !=null) {
    String value = extras.getString("keyName");
}
pinaise
źródło
20
Być może jest późno na OP, ale dla innych w Internecie nigdy nie jest późno :)
espinchi,
19

Spotkaj się z tym samym problemem tutaj. Rozwiązuję go za pomocą innego kodu żądania, używam tego samego identyfikatora jako powiadomienia podczas tworzenia PendingIntent. ale wciąż nie wiem, dlaczego należy to zrobić.

PendingIntent contentIntent = PendingIntent.getActivity(context, **id**, notificationIntent, 0);
notif.contentIntent = contentIntent;
nm.notify(**id**, notif);
jamchen
źródło
14

Po przeczytaniu niektórych list e-mail i innych forów odkryłem, że sztuczka wydaje się dodawać jakieś unikalne dane do intencji.

lubię to:

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

Nie rozumiem, dlaczego trzeba to zrobić, ma to coś wspólnego z intencją, że nie można go zidentyfikować tylko dzięki dodatkom ...

Vidar Vestnes
źródło
8
Anroid ponownie wykorzystuje zamiary, celowe działanie i kod żądania sprawiają, że jest unikalny, ale nie dodatkowe dane. Musisz więc ustawić unikalny identyfikator żądania lub zastosować inne zamierzone działania.
Bachi
10

Próbowałem wszystkiego, ale nic nie działało.

w końcu wymyślił następujące rozwiązanie.

1- w manifeście dodaj dla działania android: launchMode = "singleTop"

2- wykonując zamierzoną czynność wykonaj następujące czynności, użyj pakunku zamiast bezpośrednio za pomocą intent.putString () lub 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
źródło
3
Mi to pasuje. Musi użyć innej wartości requestCode i flagi PendingIntent.FLAG_UPDATE_CURRENT.
phuongle
4

AndroidManifest.xml

Uwzględnij launchMode = „singleTop”

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

SMSReceiver.java

Ustaw flagi dla Intent i 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 () - jest wywoływany za każdym razem, ładuje dodatki.

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

Mam nadzieję, że to pomaga, opierało się na innych odpowiedziach na temat przepełnienia stosu, ale jest to najbardziej zaktualizowana, która działała dla mnie.

Miguel Jesus
źródło
3

To proste, to moje rozwiązanie z wykorzystaniem przedmiotów!

Moje POJO

public class Person implements Serializable{

    private String name;
    private int age;

    //get & set

}

Powiadomienie o metodzie

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

Nowe zajęcie

 private Person person;

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

Powodzenia!!

David Hackro
źródło
3

Po przeprowadzeniu wyszukiwania dostałem rozwiązanie z Android Developer's 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);

Aby uzyskać dodatkową wartość w klasie Test Activity, musisz napisać następujący kod:

 Intent intent = getIntent();
 String extra = intent.getStringExtra("extra") ;
mohit
źródło
3
Do czego służy stackBuilder?
AlexioVay
1

W implementacji powiadomień użyj takiego kodu:

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

Aby uzyskać dodatkowe wartości Intent w Przykładowej czynności, użyj następującego kodu:

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

BARDZO WAŻNE: Intent :: putExtra () metoda jest przeciążony jeden. Aby uzyskać dodatkowy klucz, musisz użyć metody Intent :: get [Type] Extra () .

Uwaga: NOTIFICATION_ID i NOTIFICATION_CHANNEL_ID są stałymi zadeklarowanymi w Przykładzie

Carlos Espinoza
źródło
1

Dzień dobry, ja też mogę powiedzieć, że próbowałem wszystkiego wymienionego w tych postach i kilku innych z innych źródeł. Problem nr 1 polegał na tym, że nowy Intent zawsze miał pakiet zerowy. Mój problem polegał na zbyt dużym skupieniu się na szczegółach „czy to. Czy to. Lub.”. Moim rozwiązaniem było wycofanie się od szczegółów i przyjrzenie się ogólnej strukturze powiadomienia. Kiedy to zrobiłem, udało mi się umieścić kluczowe części kodu we właściwej kolejności. Jeśli masz podobne problemy, sprawdź:

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

2a. Bundle bundle = new Bundle();

// Lubię znacznie lepiej określać typ danych. np. 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());

W tej sekwencji otrzymuję prawidłowy pakiet.

Peter Suter
źródło
0

Jeśli użyjesz

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

w pliku AndroidManifest.xml w celu uruchomienia działania należy użyć następujących elementów:

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

Ważne jest, aby ustawić unikalne dane, np. Używając unikalnego identyfikatora, takiego jak:

notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
Złodziejaszek
źródło
0

do użytku Usług PendingIntent.FLAG_UPDATE_CURRENT

dla mnie praca.

Ali Bagheri
źródło
0

Użyj jako PendingIntent podczas wyświetlania powiadomienia, niż zostanie to rozwiązane.

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

Dodaj PendingIntent.FLAG_UPDATE_CURRENT jako ostatnie pole.

M.Noman
źródło