web-dev-qa-db-ja.com

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

_  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()は、AsyncTaskで実行されているUploadManagerの関数から複数回呼び出されます。

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

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

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

これが_FLAG_UPDATE_CURRENT_のドキュメントを読んでいる理由を知っています。ただし、現時点では回避方法がわかりません。

84
user350617

PendingIntent.getActivityにIntent.FLAG_ACTIVITY_NEW_TASKを使用しないで、代わりに FLAG_ONE_SHOT を使用してください


コメントからコピー:

次に、Intentにダミーアクションを設定します。設定しない場合、余分なものは削除されます。例えば

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

RemoteViewsウィジェットの各IntentsButtonといくつかの異なるHomeScreenに苦労していました。これらを追加したときに機能しました:

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

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

セットアクションこれは私のために解決しました。状況についての私の理解は次のとおりです。


それぞれにPendingIntentがアタッチされた複数のウィジェットがあります。更新されるたびに、すべて更新されます。フラグは、まったく同じ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);
40
ObjectiveTruth

回答は表示されますが、説明は表示されません。また、すべての可能な解決策に対処する回答はないため、それを明確にしようとします。

ドキュメント:

複数の個別のPendingIntentオブジェクトを同時にアクティブにする必要がある場合(両方が同時に表示される2つの通知として使用する場合など)、それらを異なるものに関連付けるには、何か異なるものがあることを確認する必要がありますPendingIntents。これは、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);

System.currentTimeMillis()がlongを返すため、intが必要なため、一意の要求コードを設定するのは難しい場合があります。つまり、いくつかの数字が削除されます。したがって、categoryまたはactionを使用して、一意の文字列を設定することをお勧めします。

13
MScott

私も同じ問題を抱えていましたが、フラグを次のように変更することで修正できました。

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

文書によると、一意のリクエストコードを使用します:

複数の個別のPendingIntentオブジェクトを同時にアクティブにする必要がある場合(両方が同時に表示される2つの通知として使用する場合など)、それらを異なるものに関連付けるには、何か異なるものがあることを確認する必要がありますPendingIntents。これは、Intent.filterEqualsで考慮されるIntent属性のいずれか、またはgetActivity(Context、int、Intent、int)、getActivities(Context、int、Intent []、int)、getBroadcast(Context、int 、Intent、int)、またはgetService(Context、int、Intent、int)。

9
Tomasz

ちなみに、私はPendingIntent.FLAG_CANCEL_CURRENTよりもPendingIntent.FLAG_UPDATE_CURRENT

7
Jon Shemitz

私は同じ問題を抱えていたので、以下の手順で修正しました

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

私はあなたと働きたい

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

PendingIntentには、2番目と最後の2つのintパラメーターがあります。 2つ目は「リクエストコード」であり、一意の番号(たとえば、通知のID)でなければなりません。

1
Dmytro Ubogyi
// 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
MIkka Marmik

私は同じ問題を抱えており、 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);
        }
0
qin hao

データを正しく送信するには、保留中のインテントで次のような通知IDを送信する必要があります。PendingIntent pendingIntent = PendingIntent.getActivity(context、(int)System.currentTimeMillis()、intent、PendingIntent.FLAG_UPDATE_CURRENT);

0
Amal Kronz