Як надіслати параметри від натискання сповіщення до дії?


206

Я можу знайти спосіб надсилання параметрів для моєї діяльності з мого сповіщення.

У мене є служба, яка створює сповіщення. Коли користувач натискає сповіщення, я хочу відкрити свою основну діяльність з деякими спеціальними параметрами. Наприклад, ідентифікатор елемента, щоб моя діяльність могла завантажуватись і представляти особливий перегляд деталей елемента. Більш конкретно, я завантажую файл, і коли файл завантажується, я хочу, щоб повідомлення було наміром, що при натисканні воно відкриває мою діяльність у спеціальному режимі. Я намагався використовувати putExtraза своїм наміром, але, схоже, не витягую його, тому думаю, що я роблю це неправильно.

Код від моєї служби, яка створює Повідомлення:

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

Код з моєї діяльності, який намагається отримати додатковий параметр із сповіщення:

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

Екстри завжди є нульовими, і я ніколи нічого не потрапляю до свого журналу.

Btw ... onCreateзапуск виконується лише тоді, коли починається моя діяльність, якщо моя діяльність вже розпочата, я також хочу зібрати додаткові дані та представити свою діяльність відповідно до пункту_id, який я отримую.

Будь-які ідеї?

Відповіді:


241

Погляньте на цей посібник ( створення сповіщення ) та на зразок ApiDemos "StatusBarNotifications" та "NotificationDisplay".

Для управління, якщо діяльність вже запущена, у вас є два способи:

  1. Додайте прапор FLAG_ACTIVITY_SINGLE_TOP до наміру під час запуску діяльності, а потім у класі активності реалізуйте обробник подій onNewIntent (Intent intennt) , таким чином ви зможете отримати доступ до нового наміру, який був викликаний для діяльності (що не те саме, що просто викликати getIntent (), це завжди поверне перший намір, який запустив вашу діяльність.

  2. Те саме, що номер один, але замість того, щоб додавати прапор до наміру, ви повинні додати "singleTop" у своїй діяльності AndroidManifest.xml.

Якщо ви використовуєте додаткові засоби для намірів, перейдіть на дзвінок PendingIntent.getActivity()із прапором PendingIntent.FLAG_UPDATE_CURRENT, інакше ті самі додаткові засоби будуть використані для кожного повідомлення.


95
а також відповісти на запитання користувача про те, що додаткові дані є недійсними: вам потрібно зателефонувати PendingIntent.getActivity()з прапором PendingIntent.FLAG_UPDATE_CURRENT, інакше ті самі додатки будуть повторно використані для кожного повідомлення.
Маттіас

2
u врятував мій день, але чому передача простих даних на кшталт цього настільки складна в андроїд
Незаконний аргумент

8
Якщо у вас є різні сповіщення, обов'язково використовуйте різні ідентифікатори запиту під час дзвінка, PendingIntent.getActivity()окрім установок FLAG_ACTIVITY_SINGLE_TOPна Intentі FLAG_UPDATE_CURRENTна PendingIntent. Див stackoverflow.com/questions/7370324 / ...
schnatterer

101

У мене була подібна проблема, у якій моя програма відображає сповіщення про повідомлення. Коли є декілька сповіщень та натискання кожного сповіщення, він відображає цю деталь сповіщення в діяльності з переглядом повідомлення. Я вирішив проблему отримання тих же додаткових параметрів, що надходять у поле про наміри повідомлення.

Ось код, який це зафіксував. Код для створення наміру сповіщення.

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

Код для перегляду Активність повідомлення.

@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

Можливо, трохи пізно, але: замість цього:

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

Використовуй це:

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

20
Можливо, пізно на ОП, але ніколи не пізно для інших в Інтернеті :)
espinchi

19

Зустрічайте тут же питання. Я вирішую його, використовуючи інший код запиту, використовую той самий ідентифікатор, що і повідомлення, створюючи PendingIntent. але досі не знаю, навіщо це робити.

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

14

Прочитавши деякі списки електронної пошти та інші форуми, я виявив, що хитрість, здається, додає сом унікальних даних до наміру.

подобається це:

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

Я не розумію, для чого це потрібно робити, це має щось спільне з наміром, який не можна визначити лише його додатковими ...


8
Анороїд повторно використовує наміри, дії наміру та код запиту роблять його унікальним, але не додатковими даними. Тому вам потрібно встановити унікальний ідентифікатор запиту або використовувати різні дії з наміром.
Бачі

10

Я спробував все, але нічого не вийшло.

врешті-решт придумали наступне рішення.

1- в маніфесті додати для активності android: launchMode = "singleTop"

2- під час здійснення очікуваного наміру виконайте наступне: використовуйте пакет замість безпосередньо використання intent.putString () або 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); 

3
Це працює для мене. Потрібно використовувати різні значення valueCode та прапор PendingIntent.FLAG_UPDATE_CURRENT.
phuongle

4

AndroidManifest.xml

Включити startMode = "singleTop"

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

SMSReceiver.java

Встановіть прапори для Intent and 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 () - викликає кожен раз, завантажує додаткові.

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

Сподіваюсь, це допомагає, він базувався на інших відповідях тут на stackoverflow, але це саме оновлення, яке працювало для мене.


3

Це просто, це моє рішення за допомогою предметів!

Мій POJO

public class Person implements Serializable{

    private String name;
    private int age;

    //get & set

}

Спосіб повідомлення

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

Нова активність

 private Person person;

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

Щасти!!


3

Після деякого пошуку я отримав рішення від керівництва для розробників 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);

Щоб отримати додаткове значення наміру в класі тестової активності, потрібно написати наступний код:

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

3
Для чого stackBuilder?
AlexioVay

1

У реалізації сповіщення використовуйте такий код:

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

Щоб отримати додаткові значення намірів у ExampleActivity, використовуйте наступний код:

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

ДУЖЕ ВАЖЛИВО: Намір :: putExtra () метод є перевантажений один. Щоб отримати додатковий ключ, вам потрібно використовувати метод Intent :: get [Type] Extra () .

Примітка: NOTIFICATION_ID і NOTIFICATION_CHANNEL_ID - константи, оголошені в ExampleActivity


1

Добрий день, я теж можу сказати, що я спробував усе, що згадується в цих публікаціях та ще декілька з інших місць. Проблема №1 для мене полягала в тому, що новий Намір завжди мав нульовий пакет. Моя проблема полягала в тому, що надто зосереджено увагу на деталях "я включив це. Чи це". Моє рішення полягало в тому, щоб зробити крок назад від деталей і вивчити загальну структуру повідомлення. Коли я це зробив, мені вдалося розмістити ключові частини коду у правильній послідовності. Отже, якщо у вас виникають подібні проблеми, перевірте:

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

2a. Bundle bundle = new Bundle();

// Мені подобається вказувати тип даних набагато краще. наприклад, 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());

За допомогою цієї послідовності я отримую дійсний пакет.


0

Якщо ви використовуєте

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

у вашому файлі AndroidManifest.xml для запуску діяльності ви повинні використовувати наступне у своєму намірі:

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

Важливо - встановити унікальні дані, наприклад, використовуючи унікальний ідентифікатор, наприклад:

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


0

Будь ласка, використовуйте як PendingIntent, показуючи сповіщення, ніж воно буде вирішено.

PendingIntent intennt = PendingIntent.getActivity (це 0, повідомленняIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Додайте PendingIntent.FLAG_UPDATE_CURRENT як останнє поле.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.