PendingIntent는 첫 번째 알림에 대해서는 올바르게 작동하지만 나머지 알림에는 올바르지 않습니다.


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에서도 함수에서 함수 가 여러 번 호출 됩니다.UploadManageractivitydisplayNotification()AsyncTask

편집 1 : 내가로 문자열 응답을 전달하고 있음을 언급하는 것을 잊었다 Intent intentint로서 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);

알림이 생성되었을 때 String 응답이 무엇인지 반영하기 위해 추가 "응답"이 필요하기 때문에 이것은 큰 차이를 만듭니다. 대신을 사용 PendingIntent.FLAG_UPDATE_CURRENT하여 추가 "응답"은에 대한 마지막 호출에서 문자열 응답이 무엇인지 반영합니다 displayNotification().

나는 이것이에 대한 문서를 읽은 이유를 알고 FLAG_UPDATE_CURRENT있습니다. 그러나 현재로서는 어떻게 해결해야할지 모르겠습니다.

답변:


125

사용하지 마십시오 Intent.FLAG_ACTIVITY_NEW_TASKPendingIntent.getActivity, 사용에 대한 FLAG_ONE_SHOT 대신


댓글에서 복사 :

그런 다음 의도에 더미 동작을 설정하십시오. 그렇지 않으면 추가 항목이 삭제됩니다. 예를 들면

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

이 플래그는 실제로 동일한 이유로 작동하지 않았습니다. 내 추가 기능이 제대로 작동하지 않는다고 생각합니다 (내 편집 1 확인).

32
그런 다음 의도에 더미 동작을 설정하십시오. 그렇지 않으면 추가 항목이 삭제됩니다. 예 : intent.setAction ( "foo")
ognian

20
우수한. 작동했습니다. mbauer가 제안한 FLAG_UPDATE_CURRENT 사용과 함께 setAction (Long.toString (System.currentTimeMillis ())). FLAG_ONE_SHOT을 사용하면 알림을 한 번만 클릭 할 수있었습니다 (이치에 맞습니다). 고마워요.

5
"그런 다음 의도에 대해 더미 작업을 설정하십시오. 그렇지 않으면 추가 항목이 삭제됩니다."-이 문서가 어딘가에 있습니까?
Mr_and_Mrs_D nov.

setAction 메커니즘이 저에게 효과적이었습니다. 문서화 된 한 확실하지 않지만 Android의 소스는 android.googlesource.com 에서 사용할 수 있습니다 . ;-)
Norman H

62

고민 한 RemoteViews여러 가지 Intents각각 ButtonHomeScreen위젯. 다음을 추가하면 작동했습니다.

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

+1 쿨 감사합니다. intent.setAction ()을 추가하면 왜 작동하는지 알 수 있습니까?
AjOnFire

setAction은 작동하지만 실제로 의도 작업을 다른 것으로 설정해야하는 경우 어떻게됩니까? 프레임 워크가 왜 그렇게 버그가 있습니까?
LyteSpeed

2
난 그냥 안드로이드 SDK는 (... 개발자들에게 매우 직관적 얼마나 사랑 : ♥ ️ BTW 이유에 대한 설명은 아래 @ObjectiveTruth 대답 읽기setAction
Aviel 총

1
이상한 동작이 발생했습니다. setAction 메서드가 없으면 디버깅하는 동안 인 텐트 추가 호출이 작동하지만 디버깅하지 않을 때 인 텐트 추가는 항상 첫 번째 호출에서 전달 된 초기 추가와 동일합니다. 디버깅하는 동안 onCreate는 항상 앱에서 탐색 할 때 호출되지만 디버깅하지 않는 동안에는 onCreate가 호출되지 않고 onStart 만 호출된다는 것을 알았습니다. setAction 메서드를 호출하면 문제가 해결되었습니다. 엑스트라 값만 변경된 경우 의도가 '다른'것이 아닌 것과 관련이 있다고 생각합니다.
MaxJ 2015 년

@clu 이미 사용 setAction하고 있으므로 할 수있는 것은 addCategory입니다. 작업, 데이터, 유형, 클래스 및 범주가 같은지 확인하는 PendingIntent데 사용 Intent.filterEquals합니다. developer.android.com/reference/android/content/...
iamreptar

43

Set Action이 문제를 해결했습니다. 상황에 대한 나의 이해는 다음과 같습니다.


PendingIntent가 각각 연결된 여러 위젯이 있습니다. 하나가 업데이트 될 때마다 모두 업데이트되었습니다. 플래그는 정확히 동일한 PendingIntents에서 발생하는 일을 설명하기 위해 있습니다.

FLAG_UPDATE_CURRENT 설명은 이제 훨씬 더 잘 읽 힙니다.

동일한 PendingIntent가 이미 존재하는 경우 기존의 모든 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);

최신 정보


방송으로 작업하는 경우 더 나은 솔루션입니다. Unique 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
Nice Clean Solution
Varun Garg

1
저에게는 보류 인 텐트에 대한 고유 ID와 PendingIntent.FLAG_ONE_SHOT가 있고 인 텐트에 대한 setAction이 작동했습니다.
Kaustuv

의도 변경을 위해 추가 변경 사항을 고려하지 않는 것이 조금 이상하지만 사실 인 것 같습니다 : /
zeroDivider

20

답변은 보이지만 설명은 없습니다. 또한 가능한 모든 해결책을 다룰 수있는 답변이 없으므로 명확하게 설명하겠습니다.

선적 서류 비치:

동시에 활성화 된 여러 개의 개별 PendingIntent 개체가 필요한 경우 (예 : 동시에 표시되는 두 개의 알림으로 사용) 서로 다른 개체와 연결하기 위해 다른 개체가 있는지 확인해야합니다. 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);

그러나이 두 인 텐트는 동일하므로 두 번째 알림이 도착하면 첫 번째 인 텐트가 시작됩니다.

해결책:

보류중인 인 텐트가 동일하지 않도록 각 인 텐트를 고유하게 만들어야합니다. 의도를 고유하게 만드는 방법은 무엇입니까? 당신이 넣은 엑스트라가 아닙니다 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

예, 각 의도에 대해 고유 한 카테고리를 사용하고 있습니다. 잘 작동합니다.
steliosf

같은 문제가 있습니다. 두 개의 알림이 동시에 트리거되었습니다. 두 번째 알림을 클릭해도 아무 일도 일어나지 않았습니다. 이 설정 후 setAction (Long.toString (System.currentTimeMillis ())); . 매력처럼 작동합니다. 좋은 설명 @MScott 주셔서 감사합니다
인 Anantha 바부

13

나는 같은 문제가 있었고 플래그를 다음과 같이 변경하여 해결할 수있었습니다.

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

시간을내어 문제를 해결 한 내용을 게시 해 주셔서 감사합니다. Intent에 여분을 전달하고 있다는 것을 언급하는 것을 잊었습니다. 이것은 문제를 좀 더 복잡하게 만듭니다. 내 편집 1을 확인하십시오.

9

문서에 따르면 고유 한 요청 코드를 사용하십시오.

동시에 활성화 된 여러 개의 개별 PendingIntent 개체가 필요한 경우 (예 : 동시에 표시되는 두 개의 알림으로 사용) 서로 다른 개체와 연결하기 위해 다른 개체가 있는지 확인해야합니다. PendingIntents. 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

7

FWIW, 내가 더 잘 행운이 있었다 PendingIntent.FLAG_CANCEL_CURRENT보다 PendingIntent.FLAG_UPDATE_CURRENT.


나는 이것에 전적으로 동의합니다. 이전 항목을 취소 한 다음 새 항목을 만들 수 있다면 인 텐트에 쓸모없는 추가 항목을 채울 필요가 없습니다. 아무것도 변하지 않으면 쓸모가 없을 수도 있지만 이제 문제는 "메모리를 절약하거나 시간을 절약하는 것"입니다.
zeroDivider

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

나를 위해 일했습니다! 감사!
Andres

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

PendingIntent에는 두 개의 int 매개 변수, 두 번째 매개 변수와 마지막 매개 변수가 있습니다. 두 번째는 "요청 코드"이며 고유 번호 (예 : 알림의 ID) 여야합니다. 그렇지 않으면 (예에서와 같이 0과 같으면 항상 덮어 쓰게됩니다).


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 (context, (int) System.currentTimeMillis () , intent, 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 2013-08-21

이 질문과 어떤 관련이 있는지 명확히해야합니다.
Norman H
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.