PresidentingIntentは最初の通知では正しく機能しますが、残りの通知では正しく機能しません


87
  protected void displayNotification(String response) {
    Intent intent = new Intent(context, testActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);

    Notification notification = new Notification(R.drawable.icon, "Upload Started", System.currentTimeMillis());
    notification.setLatestEventInfo(context, "Upload", response, pendingIntent);

    nManager.notify((int)System.currentTimeMillis(), notification);
}

この関数は複数回呼び出されます。notificationクリックすると、それぞれがtestActivityを起動したいと思います。残念ながら、最初の通知のみがtestActivityを起動します。残りをクリックすると、通知ウィンドウが最小化されます。

追加情報:関数displayNotification()UploadManager。というクラスにあります。 インスタンス化ContextするUploadManagerからに渡されactivityます。関数displayNotification()は、UploadManagerでも、で実行されている関数から複数回呼び出されますAsyncTask

編集1:文字列応答をIntent intentとしてに渡していることを忘れましたextra

  protected void displayNotification(String response) {
    Intent intent = new Intent(context, testActivity.class);
    intent.putExtra("response", response);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

通知が作成されたときの文字列応答を反映するために追加の「応答」が必要になるため、これは大きな違いになります。代わりに、を使用するPendingIntent.FLAG_UPDATE_CURRENTと、追加の「応答」は、への最後の呼び出しでの文字列応答を反映しdisplayNotification()ます。

のドキュメントを読んだことで、これがなぜなのかわかりFLAG_UPDATE_CURRENTます。ただし、現時点では回避方法がわかりません。

回答:


125

Intent.FLAG_ACTIVITY_NEW_TASKStartedIntent.getActivityには使用せず、代わりにFLAG_ONE_SHOTを使用してください


コメントからコピー:

次に、インテントにダミーアクションを設定します。そうしないと、エキストラが削除されます。例えば

intent.setAction(Long.toString(System.currentTimeMillis()))

このフラグは、同じ理由で実際には機能しませんでした。私のエクストラが正しく機能していないと思います(編集1を確認してください)。

32
次に、インテントにダミーアクションを設定します。そうしないと、余分なものが削除されます。たとえば、intent.setAction( "foo")
ognian 2010

20
優秀な。それはうまくいった。mbauerが提案したFLAG_UPDATE_CURRENTの使用と組み合わせて、setAction(Long.toString(System.currentTimeMillis()))を設定しました。FLAG_ONE_SHOTを使用すると、通知をクリックできるのは1回だけでした(これは理にかなっています)。どうもありがとう。

5
「次に、インテントにダミーアクションを設定します。そうしないと、余分なものが削除されます」-これはどこかに文書化されていますか?
mr_and_Mrs_D 2013年

setActionメカニズムは私のために働いた。文書化されている限り、確かではありませんが、Androidのソースはandroid.googlesource.comで入手できます;-)
Norman H

62

ウィジェットでそれぞれに苦労しRemoteViews、いくつかの異なるものIntentsでした。これらを追加すると機能しました:ButtonHomeScreen

1.1。 intent.setAction(Long.toString(System.currentTimeMillis()));

2.2。 PendingIntent.FLAG_UPDATE_CURRENT

        PackageManager pm = context.getPackageManager();

        Intent intent = new Intent(context, MyOwnActivity.class);
        intent.putExtra("foo_bar_extra_key", "foo_bar_extra_value");
        intent.setAction(Long.toString(System.currentTimeMillis()));
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.widget_layout);
        views.setOnClickPendingIntent(my_button_r_id_received_in_parameter, pendingIntent);

+1クールありがとう。intent.setAction()を追加することで機能する理由はありますか?
AjOnFire 2013年

setActionは機能しますが、実際にインテントアクションを他の何かに設定する必要がある場合はどうなりますか?フレームワークがとてもバグがあるのはなぜですか?
b.lit 2014

2
Android SDKが開発者にとって非常に直感的であることが大好きです...(:♥️ところで、理由の説明については、以下の@ObjectiveTruthの回答を読んでくださいsetAction
Aviel Gross 2014

1
setActionメソッドがないと、デバッグ中にインテントエクストラが機能しますが、デバッグしない場合、インテントエクストラは常に最初の呼び出しで渡された最初のエクストラと同じになります。デバッグ中は、アプリから移動するときにonCreateが常に呼び出されていましたが、デバッグしていない間は、onCreateは呼び出されず、onStartのみが呼び出されていました。setActionメソッドを呼び出すと問題が解決しました。これは、extras値のみが変更された場合に、インテントが「異なる」わけではないことに関係していると思います。
maxJ 2015

@clu私はすでにを使用しているのでsetAction、あなたができることはですaddCategory。アクション、データ、タイプ、クラス、およびカテゴリが等しいかどうかを確認するためにPendingIntent使用Intent.filterEqualsします。 developer.android.com/reference/android/content/...
iamreptar

43

セットアクション私のためにこれを解決しました。これが状況についての私の理解です:


それぞれにPendingIntentがアタッチされた複数のウィジェットがあります。1つが更新されるたびに、それらはすべて更新されました。フラグは、まったく同じPendingIntentsで何が起こるかを説明するためにあります。

FLAG_UPDATE_CURRENTの説明がはるかに読みやすくなりました。

作成しているのと同じPendingIntentがすでに存在する場合は、古いものをすべて、作成している新しいPendingIntentに更新します。

まったく同じの定義は、エクストラを除いて、PendingIntent全体を見ています。したがって、インテントごとに異なるエクストラがある場合でも(私にとっては、appWidgetIdを追加していました)、Androidでも同じです。

ダミーの一意の文字列を使用して.setActionを追加すると、OSに通知されます。これらは完全に異なり、何も更新しません。最後に、これが私が望むように機能する私の実装であり、各ウィジェットには独自の構成インテントが添付されています。

Intent configureIntent = new Intent(context, ActivityPreferences.class);

configureIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

configureIntent.setAction("dummy_unique_action_identifyer" + appWidgetId);

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, configureIntent,
    PendingIntent.FLAG_UPDATE_CURRENT);

更新


放送を扱っている場合のさらに良い解決策。一意のPendingIntentsは、一意のリクエストコードによっても定義されます。これが私の解決策です:

//Weee, magic number, just want it to be positive nextInt(int r) means between 0 and r
int dummyuniqueInt = new Random().nextInt(543254); 
PendingIntent pendingClearScreenIntent = PendingIntent.getBroadcast(context, 
    dummyuniqueInt, clearScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);

1
素敵なクリーンソリューション
Varun Garg

1
保留中のインテントに対して一意のIDとPendingIntent.FLAG_ONE_SHOTを持ち、インテントのsetActionが機能した私にとっては。
kaustuv 2016

インテント変更のために追加の変更を考慮していないのは少し奇妙ですが、本当のようです:/
zeroDivider 2018

20

答えは見えますが、説明はありません。また、すべての可能な解決策に対応している回答はないので、それを明確にしようと思います。

ドキュメンテーション:

複数の異なるPendingIntentオブジェクトを同時にアクティブにする必要がある場合(両方が同時に表示される2つの通知として使用する場合など)、それらを異なるものに関連付けるには、それらについて異なるものがあることを確認する必要があります。保留中のインテント。これは、Intent.filterEqualsによって考慮されるIntent属性のいずれか、またはgetActivity(Context、int、Intent、int)、getActivities(Context、int、Intent []、int)、getBroadcast(Context、int)に提供されるさまざまな要求コード整数である可能性があります。 、Intent、int)、またはgetService(Context、int、Intent、int)。

問題の原因:

2つの保留中のインテントを持つ2つの通知を作成します。保留中の各インテントは、インテントに関連付けられています。

Intent intent = new Intent(context, testActivity.class);

ただし、これら2つのインテントは等しいため、2番目の通知が到着すると、最初のインテントが起動されます。

解決:

保留中のインテントが等しくならないように、各インテントを一意にする必要があります。インテントをどのようにユニークにしますか?あなたが付けたエキストラではありませんputExtra()。エクストラが異なっていても、意図は同じかもしれません。各インテントを一意にするには、インテントアクション、データ、タイプ、クラス、カテゴリ、またはリクエストコードに一意の値を設定する必要があります:(これらはいずれも機能します)

  • アクション: intent.setAction(...)
  • データ: intent.setData(...)
  • タイプ: intent.setType(...)
  • クラス: intent.setClass(...)
  • カテゴリー: intent.addCategory(...)
  • リクエストコード: PendingIntent.getActivity(context, YOUR_UNIQUE_CODE, intent, Intent.FLAG_ONE_SHOT);

:intが必要であるため、一意のリクエストコードを設定するのは難しい場合がありますが、System.currentTimeMillis()longを返します。これは、一部の桁が削除されることを意味します。したがって、カテゴリまたはアクションを使用して、一意の文字列を設定することをお勧めします。


これは、通知ごとに一意のID(キャンセル可能にするためにとにかく必要)とアクションごとのカスタムカテゴリ(同じ通知に同じタイプの複数のアクションを持つことはありません)を使用して、最終的に私にとってうまくいったものです。
MandisaW 2018

はい、インテントごとに固有のカテゴリも使用しています。うまく機能します。
steliosf 2018

同じ問題が発生しました。2つの通知が同時にトリガーされました。2番目の通知をクリックしても、何も起こりませんでした。このsetAction(Long.toString(System.currentTimeMillis()));を設定した後 。その魅力のように機能します。素敵な説明@MScottに感謝
Ananthaバブー

13

同じ問題が発生し、フラグを次のように変更することで修正できました。

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

問題を解決したものを投稿するために時間を割いていただき、ありがとうございます。インテントにエクストラを渡していることを忘れました。これにより、問題が少し複雑になります。私の編集1.チェック

9

ドキュメントに記載されているように、一意のリクエストコードを使用します。

複数の異なるPendingIntentオブジェクトを同時にアクティブにする必要がある場合(両方が同時に表示される2つの通知として使用する場合など)、それらを異なるものに関連付けるには、それらについて異なるものがあることを確認する必要があります。保留中のインテント。これは、Intent.filterEqualsによって考慮されるIntent属性のいずれか、またはgetActivity(Context、int、Intent、int)、getActivities(Context、int、Intent []、int)、getBroadcast(Context、int)に提供されるさまざまな要求コード整数である可能性があります。 、Intent、int)、またはgetService(Context、int、Intent、int)。


1
これが唯一の真実で正しい答えです。それを探していたので、同じものを投稿したかったのです。:-)
Sevastyan Savanyuk 2017

7

Fwiw、私はよりも幸運がPendingIntent.FLAG_CANCEL_CURRENTありましたPendingIntent.FLAG_UPDATE_CURRENT


私はこれに完全に同意します。古いものをキャンセルしてから新しいものを作成することができれば、インテントを無駄な余分なもので埋める必要はありません。何も変わらなければ役に立たないこともあるのは事実ですが、今の問題は「メモリを節約するか、時間を節約するか」です。
zeroDivider 2018

4

私は同じ問題を抱えていました、そして私は以下のステップでそれを修正しました

1)意図のフラグをクリアします

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

2)以下のコードでintent.setActionを挿入します

 intent.setAction(Long.toString(System.currentTimeMillis()));

3)Pendingintentの場合、以下のコードを挿入します

   PendingIntent Pintent = PendingIntent.getActivity(ctx,0, intent,PendingIntent.FLAG_UPDATE_CURRENT);

私はあなたと一緒に働きたいです


1
誰もがこの答えが反対票を投じられた理由を説明することに関心があります。これは私のために働いた。これが正当な答えかどうかはわかりませんが、この解決策は完璧な解決策です。少なくとも私にとっては。
Sandeep R 2016

私のためにも働いた!ありがとう!
アンドレス

2
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);

PresidentingIntentには、2番目と最後の2つのintパラメーターがあります。2つ目は「リクエストコード」であり、一意の番号(たとえば、通知のID)である必要があります。そうでない場合(例のようにゼロに等しい場合は、常に上書きされます)。


0
// Use pending Intent and  also use unique id for display notification....
// Get a PendingIntent containing the entire back stack
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotificationManager = (NotificationManager)  sqlitewraper.context.getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(id, builder.build());

0

送信データに余分正しくあなたは意図保留して送信する必要があり、このような通知ID:PendingIntent pendingIntent = PendingIntent.getActivity(文脈、(int型)のSystem.currentTimeMillis() 、意図、PendingIntent.FLAG_UPDATE_CURRENT)。


0

同じ問題があり、PendingIntent.html.FLAG_UPDATE_CURRENTを使用して修正します。

ソースコードを確認しました。でActivityManagerService.java次のように、鍵方式です。フラグがPendingIntent.FLAG_UPDATE_CURRENTで、updateCurrentがtrueの場合。一部のエクストラは新しいものに置き換えられ、置き換えられたPendingIntentを取得します。

    IIntentSender getIntentSenderLocked(int type, String packageName,
            int callingUid, int userId, IBinder token, String resultWho,
            int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
            Bundle bOptions) {

// ... omitted

        final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
        final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
        final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
        flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
                |PendingIntent.FLAG_UPDATE_CURRENT);

        PendingIntentRecord.Key key = new PendingIntentRecord.Key(
                type, packageName, activity, resultWho,
                requestCode, intents, resolvedTypes, flags, bOptions, userId);
        WeakReference<PendingIntentRecord> ref;
        ref = mIntentSenderRecords.get(key);
        PendingIntentRecord rec = ref != null ? ref.get() : null;
        if (rec != null) {
            if (!cancelCurrent) {
                if (updateCurrent) {
                    if (rec.key.requestIntent != null) {
                        rec.key.requestIntent.replaceExtras(intents != null ?
                                intents[intents.length - 1] : null);
                    }
                    if (intents != null) {
                        intents[intents.length-1] = rec.key.requestIntent;
                        rec.key.allIntents = intents;
                        rec.key.allResolvedTypes = resolvedTypes;
                    } else {
                        rec.key.allIntents = null;
                        rec.key.allResolvedTypes = null;
                    }
                }
                return rec;
            }
            rec.canceled = true;
            mIntentSenderRecords.remove(key);
        }


-5

同じ問題が発生し、フラグを次のように変更することで修正できました。

LayoutInflater factory = LayoutInflater.from(this);            
      final View textEntryView = factory.inflate(R.layout.appointment, null);
      AlertDialog.Builder bulider= new AlertDialog.Builder(PatientDetail.this);
      final AlertDialog alert=bulider.create();


        bulider.setTitle("Enter Date/Time");
        bulider.setView(textEntryView);
        bulider.setPositiveButton("Save", new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                      EditText typeText=(EditText) textEntryView.findViewById(R.id.Editdate);
                      EditText input1 =(EditText) textEntryView.findViewById(R.id.Edittime);
                      getDateAndTime(typeText.getText().toString(),input1.getText().toString());
                }
            });
        bulider.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });

        bulider.show();

    }

4
それは尋ねられた質問とは何の関係もありません。
Paul Turchenko

それがこの質問にどのように関連しているかを明確にする必要があります。
ノーマンH
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.