通知は古いインテントエクストラを渡します


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が開き、アクティビティ内でIntent-Bundle(例:1)からfoo_idを取得できます。

ただし、別の通知がトリガーされてもう一度クリックすると、アクティビティは引き続きIntent-Bundleから「古い」値(1)を受け取ります。clear()でバンドルをクリアしようとしましたが、同じ効果が得られます。私のコードではsthが間違っていると思います。


保留中のインテントからデータをどのように取得するのか教えてください
user49557 '11

古いエキストラを送信していることを理解することで、トリアージが簡単になりました。
Utsav Gupta

回答:


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 2011

23
android gotcha#147- 異なるエクストラIntentを持つ(を介して)は同じと見なされ、保留中のインテントコールに一意のIDを提供しなかったため再利用されます-恐ろしいapiputExtra
wal

あなたは何を知っている、私はとても不注意だった。どうやってそれが1つのブロック(私の場合)で0のままでいられるかを考えています:(
Exigente05

3
これは私にとって非常に役に立ちました。他の人へのヒントにすぎません。同じ方法で通知を作成している可能性が高いため、新しい保留中のインテントのIDを、目的のインテントと同じに設定できます通知の一意のIDに使用してください!
James McNee 2017年

1
@ IncrediApp、PendingIntent.getBroadcast();と同じですか。?
Shruti 2017

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
ペンディングインテントを使用して、アラームの設定から放送受信機に状態を転送するために私のために働きました。
ウィリアムT.マラード2015年

ユーザーに通知を送信する前に、これらのフラグが実際に何をしたかを知りたいだけです(!)これで私の悩みは解決しました...
James Andrew

42

同じIDを渡しています。このような状況では、次のような時間から一意のIDを作成します。

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

そして、それを次のように置きます:

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

3
。なぜ新しいランダム()nextInt()は使用しないで
exloong

@hderanga上記のintに「&0xfffffff」を追加するとどうなりますか?
AJW

3
@AJW System.currentTimeMillis()はlongを返しますが、requestIdパラメータはPendingIntent.getActivity()int を取ります。0xffffffffビットマスクです。それにはもう少しありますが、簡単に説明すると、「long&0xffffffff」を実行すると、最下位の32ビットがlongから取得され、最上位の32ビットが破棄され、基本的に32ビットのintが残ります。これは、単にintにキャストするよりも優れています。これは、符号ビットをマックアップしないためです(intよりも大きいlongをintにキャストすると、符号ビットがオーバーフローし、負の値になる可能性があります。 )
ジョーダンボンド

8

久しぶりに最善の方法を探している人は、以下に示すように、最後の引数としてPendingIntent.FLAG_UPDATE_CURRENTを渡す必要があります。

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

新しい一意のIDを提供する必要すらありません。

初めてではなく、次回以降にこれを行う必要があります


1
それはうまくいきません、私がやっていたのでここに行きました。
ブリルパピン

あなたはこれを初めてではなく次回に行う必要があります、それはうまくいきます。
ジェントル

0

すべての通知のリクエストコードは0です。次の行を変更します。

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

と:

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

1
「System.currentTimeMillis()」ではなく「new Random()。nextInt()」を使用するメリットはありますか?
AJW

randomを使用すると、偶然同じ整数値を簡単に再生成できるため、渡された古いインテントのバグを見つけるのが非常に困難になります。
サム

@AJW私の場合はありました。まったく同じミリ秒で2つの異なる通知を作成したので、そのうちの1つが間違ったエキストラを受け取りました。
アートマン2018

0

別のオプションを追加したかっただけ

 PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.