Повідомлення передає старі наміри


134

я створюю сповіщення всередині BroadcastReceiver за допомогою цього коду:

String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(ns);
        int icon = R.drawable.ic_stat_notification;
        CharSequence tickerText = "New Notification";
        long when = System.currentTimeMillis();

        Notification notification = new Notification(icon, tickerText, when);
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        long[] vibrate = {0,100,200,200,200,200};
        notification.vibrate = vibrate;
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        CharSequence contentTitle = "Title";
        CharSequence contentText = "Text";
        Intent notificationIntent = new Intent(context, NotificationActivity.class);
        notificationIntent.putExtra(Global.INTENT_EXTRA_FOO_ID, foo_id);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

        notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

        int mynotification_id = 1;

        mNotificationManager.notify(mynotification_id, notification);

Коли я натискаю на сповіщення, воно відкриває NotificationActivity і всередині Activity я можу отримати foo_id з пакету намірів (наприклад, 1)

Однак якщо запускається інше сповіщення, і я натискаю на нього ще раз, активність все одно отримує "старе" значення (1) від пакету намірів. Я намагався очистити пакет з clear (), але отримую той же ефект. Я думаю, що що-небудь не так з моїм кодом ..


скажіть, будь ласка, як ви отримуєте дані від очікуваного наміру
user49557

зрозуміти, що це відправка старих статей, полегшило мої триагінг.
Уцав Гупта

Відповіді:


268

Ви надсилаєте той самий код запиту, який ви очікуєте. Змініть це:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

До:

PendingIntent contentIntent = PendingIntent.getActivity(context, UNIQUE_INT_PER_CALL, notificationIntent, 0);

наміри не створюються, якщо ви надсилаєте ті самі парами. Вони повторно використовуються.


1
значить, UNIQUE_INT_PER_CALL - це ціле число, яке я повинен надати? чи це десь оголошена статична змінна?
BrianM

23
android gotcha # 147 - тож, Intentщо має різні додатки (через putExtra), вважаються однаковими та повторно використовуються, тому що я не надав унікальний ідентифікатор деякому очікуваному виклику наміру - жахливий api
Wal

знаєте що, я був такий недбалий. Думаю, як міг залишитися 0 в одному блоці (в моєму випадку) :(
Exigente05

3
Це було неймовірно корисно для мене, лише порада для інших. Цілком ймовірно, що ви будуєте своє сповіщення тим самим методом, і тому ви можете просто встановити ідентифікатор для нового очікуваного наміру таким же, як той, який ви збираєтеся використовувати для сповіщень унікальний ідентифікатор!
James McNee

1
@IncrediApp, це те ж саме з PendingIntent.getBroadcast (); ?
Шрути

139

Крім того, ви можете використовувати наступний код для створення PendingIntent:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Від документа для PendingIntent.FLAG_UPDATE_CURRENT:

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


Дякую ... чудово працює для цього прапора, який додають "PendingIntent.FLAG_UPDATE_CURRENT" :)
Najib Ahmed Puthawala

1
Працював для мене, використовуючи очікуваний намір перевести стан із встановлення тривоги на приймач широкомовної програми.
Вільям Т. Маллард

Я просто хотів би, щоб я знав про те, що насправді робили ці прапори, перш ніж надсилати сповіщення своїм користувачам (!) Радий, що це вирішує мої клопоти ...
Джеймс Ендрю

42

Ви передаєте той самий ідентифікатор. У такій ситуації зробіть унікальний ідентифікатор, подібний до цього часу:

int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);

І покладіть так:

PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),iUniqueId, intentForNotification, 0);

3
чому б не використати новий Random (). nextInt ()
exloong

@hderanga, що робить додавання "& 0xfffffff" до інтернату вище?
AJW

3
@AJW System.currentTimeMillis()повертає довгий час, тоді як requestIdпараметр take PendingIntent.getActivity()приймає int. 0xffffffff- це бітмаска. Хоча в цьому є трохи більше, просте пояснення полягає в тому, що виконання "long & 0xffffffff" дає найнижчі 32-бітові з довгих і відкидає найвищі 32-бітові, залишаючи вам по суті 32-бітову цілу. Це краще, ніж просто запросити на int, тому що він не приглушить бітовий знак (якщо ви передасте довге, що більше, ніж int до int, бітовий знак переповниться, і ви потенційно зможете отримати негативне значення )
Йордан Бондо

8

Для тих, хто шукає найкращий підхід після тривалого часу, вам потрібно передати PendingIntent.FLAG_UPDATE_CURRENT як останній аргумент, як показано нижче

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

вам навіть не потрібно вводити новий унікальний ідентифікатор.

Це потрібно робити наступного разу, не вперше


1
Це не працює, я потрапив сюди, бо ось що я робив.
Брілл Паппін

Це потрібно робити наступні рази не в перший раз, це спрацює.
Ніжний

0

Ваш код запиту - 0 для всіх повідомлень. Змінити наступний рядок:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

З:

PendingIntent contentIntent = PendingIntent.getActivity(context, new Random().nextInt(), notificationIntent, 0);

1
Чи є якась користь від використання "нового Random (). NextInt ()", а не "System.currentTimeMillis ()"?
AJW

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

@AJW в моєму випадку було Я створив 2 різні сповіщення в точно такі ж мілісекунди, тому одне з них отримало помилкові додатки.
художник

0

Просто хотів додати ще один варіант

 PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.