작업을 클릭 한 후 알림을 해제하는 방법


143

API 레벨 16 (Jelly Bean)부터 다음을 사용하여 알림에 조치를 추가 할 수 있습니다.

builder.addAction(iconId, title, intent);

그러나 알림에 작업을 추가하고 작업을 누르면 알림이 닫히지 않습니다. 알림 자체를 클릭하면 다음과 같이 알림을 해제 할 수 있습니다.

notification.flags = Notification.FLAG_AUTO_CANCEL;

또는

builder.setAutoCancel(true);

그러나 분명히 이것은 알림과 관련된 작업과 관련이 없습니다.

힌트가 있습니까? 아니면 아직 API의 일부가 아닙니까? 나는 아무것도 찾지 못했습니다.

답변:


155

통지 관리자에서 notify를 호출 할 때 ID를 제공했습니다. 이는 나중에 액세스 할 때 사용할 수있는 고유 ID입니다 (이는 통지 관리자에서 제공됨).

notify(int id, Notification notification)

취소하려면 다음으로 전화하십시오.

cancel(int id)

같은 ID로. 따라서 기본적으로 ID를 추적하거나 PendingIntent 내부의 Intent에 추가 한 번들에 ID를 넣어야합니까?


25
고마워, 내 문제를 해결했다. 그러나 여전히 약간 복잡하다고 생각합니다. 조치를 눌렀을 때 알림을 자동으로 닫는 API를 제공하는 대신 의도와 알림 ID를 전달하여 동일한 작업을 수행해야합니다.
endowzoner

2
이것이 복잡하다고 생각되면 알림을 업데이트하거나 (ID를 추적하지 마십시오) 표시 여부를 확인하지 마십시오 (api가 추적하지 않는 경우). P
Travis

2
@Daksh : 기본적으로 작업을 누를 때 시작되는 알림 태그와 ID를 의도에 추가합니다. 추가 정보를 사용하여 시작 활동이 알림 조치를 통해 시작되었는지 여부를 체크인 할 수 있습니다.
endowzoner

5
onCreate ()의 코드 샘플 : 번들 엑스트라 = getIntent (). getExtras (); if (extras! = null) {문자열 태그 = extras.getString (NotificationReceiver.INTENT_EXTRA_NOTIFICATION_TAG); int id = extras.getInt (NotificationReceiver.INTENT_EXTRA_NOTIFICATION_ID); if (NotificationReceiver.NOTIFICATION_ID == id && NotificationReceiver.NOTIFICATION_TAG.equals (tag)) {// 활동이 알림 작업을 통해 시작된 경우, // 알림 NotificationManager 관리자 = (NotificationManager) getSystemService (Service.NOTIFICATION_SERVICE); manager.cancel (태그, 아이디); }}
endowzoner

1
새로운 API에서는 notify (String tag, int id, Notification notification) 및 이에 상응하는 cancel (String tag, int id)이 있습니다
Malachiasz

64

Lollipop의 HUD (Heads Up Display) 알림을 사용할 때 이것이 문제인 것으로 나타났습니다. 설계 지침을 참조하십시오 . 구현할 완전한 (ish) 코드는 다음과 같습니다.

지금까지 '닫기'버튼을 사용하는 것이 덜 중요했지만 지금은 더 중요합니다.

알림 통지

알림 작성

int notificationId = new Random().nextInt(); // just use a counter in some util class...
PendingIntent dismissIntent = NotificationActivity.getDismissIntent(notificationId, context);

NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setPriority(NotificationCompat.PRIORITY_MAX) //HIGH, MAX, FULL_SCREEN and setDefaults(Notification.DEFAULT_ALL) will make it a Heads Up Display Style
        .setDefaults(Notification.DEFAULT_ALL) // also requires VIBRATE permission
        .setSmallIcon(R.drawable.ic_action_refresh) // Required!
        .setContentTitle("Message from test")
        .setContentText("message")
        .setAutoCancel(true)
        .addAction(R.drawable.ic_action_cancel, "Dismiss", dismissIntent)
        .addAction(R.drawable.ic_action_boom, "Action!", someOtherPendingIntent);

// Gets an instance of the NotificationManager service
NotificationManager notifyMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

// Builds the notification and issues it.
notifyMgr.notify(notificationId, builder.build());

NotificationActivity

public class NotificationActivity extends Activity {

    public static final String NOTIFICATION_ID = "NOTIFICATION_ID";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        manager.cancel(getIntent().getIntExtra(NOTIFICATION_ID, -1));
        finish(); // since finish() is called in onCreate(), onDestroy() will be called immediately
    }

    public static PendingIntent getDismissIntent(int notificationId, Context context) {
        Intent intent = new Intent(context, NotificationActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.putExtra(NOTIFICATION_ID, notificationId);
        PendingIntent dismissIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        return dismissIntent;
    }

}

AndroidManifest.xml (SystemUI가 백 스택에 집중하지 못하도록하는 데 필요한 속성)

<activity
    android:name=".NotificationActivity"
    android:taskAffinity=""
    android:excludeFromRecents="true">
</activity>

하나의 응용 프로그램에서 여러 알림이 있고 알림이 진행중인 알림으로 설정되어 있습니다. perticular 알림에 addaction이 수행 될 때 알림을 지우고 싶습니다
Prasad

3
대신 BroadcastReceiver를 사용하여 알림을 닫는 것이 더 효과적이지 않습니까? 여기 쇼 그 좋은 예는 구현이지만, 더욱 줄일 수 있습니다 stackoverflow.com/a/19745745/793150을
alice.harrison

1
추가 세트가 의도와 함께 전달되는 것을 제외하고 솔루션이 작동합니다. onCreate로 전달되지 않습니다. 한 가지 방법은 정적 변수를 사용하는 것입니다. 누구도 왜 인 텐트 엑스트라가 전달되지 않는지 알고 있습니까?
Baschi

getDismissIntent가 NotificationActivity에 배치 된 경우에만 작동하는 이유는 무엇입니까? PendingIntent 작성 코드가 알림 빌더 클래스에 배치되면 해제 의도가 작동하지 않습니다. 방금이 문제에 2 시간을 보냈으며 활동에서 보류 의도가 왜 생성되어야하는지 알 수 없습니다. 아무도 이것이 왜 그런지 설명 할 수 있습니까?
Ray Li

getDismissIntent ()는 NotificationActivity와 통신하는 데 사용할 올바른 의도를 작성하는 정적 "도우미"함수입니다. 이와 같이 이들은 일반적으로 활동과 번들로 제공됩니다. 그러나 NOTIFICATION_ID 및 컨텍스트를 올바르게 설정하기 만하면이 정적 함수를 알림 빌더 클래스에 배치 할 수없는 이유를 알 수 없습니다.
Mike

17

확장 알림에서 작업 버튼을 사용할 때 추가 코드를 작성해야하며 더 제한적이라는 것을 알았습니다.

사용자가 작업 버튼을 클릭하면 알림을 수동으로 취소해야합니다. 알림은 기본 작업에 대해서만 자동으로 취소됩니다.

또한 버튼에서 브로드 캐스트 수신기를 시작하면 알림 드로어가 닫히지 않습니다.

이러한 문제를 해결하기 위해 새로운 NotificationActivity를 만들었습니다. UI가없는이 중개 활동은 알림을 취소 한 다음 실제로 알림에서 시작하려는 활동을 시작합니다.

관련 게시물에 샘플 코드를 게시했습니다. Android 알림 작업을 클릭해도 알림 서랍이 닫히지 않습니다 .


2
너무 안타깝게도 API로이 기능을 구워 내지 못했습니다. 이렇게하는 것은 꽤 어려운 일입니다. 그러나 URL을 보는 것과 같이 도착 의도를 제어 할 수없는 경우에는 여전히 유일한 방법입니다.
Bogdan Zurac

정보 주셔서 감사합니다, 당신은 맞습니다. 그러나 나는 중개 활동보다는 인 텐트 서비스를 사용하려고합니다
Tim

7

당신은 항상 할 수 에서 (에, 예를 들면 작용에 의해 호출되고 무엇이든 받는 사람 연결 활동의 당신이 제공 ).cancel()NotificationonCreate()PendingIntentaddAction()


2
그러나 호출 된 활동에서 알림에 액세스하려면 어떻게해야합니까?
endowzoner

@FleshWound : 를 호출했을 때 사용한 cancel()ID Notification를 사용합니다 notify(). Notification객체 가 필요하지 않습니다 .
CommonsWare

setGroup이 설정되고 그룹 요약 알림이있는 경우 @CommonsWare cancel (id) 작동이 중지되었습니다. 이 경우 취소는 어떤 이유로 든 아무 것도하지 않습니다. 그룹 요약 없이는, cancel이 잘 작동합니다
Kushan

보류중인 의도가 ACTION_VIEW있고 유형이 image/jpeg(다른 응용 프로그램과 이미지를 공유하는 경우) 취소가 어떻게 트리거되어야합니까? IMO 안드로이드는 자동 취소해야합니다. 왜 안드로이드가 그것을 돌보지 않는지 궁금합니다!
누군가 어딘가에

@SomeoneSomewhere : "그러면 어떻게 취소가 트리거됩니까?" -못해 Notification관련 앱에서 타사 앱을 가리키는 것을 막을 수는 PendingIntent없지만 실제로 작동하도록 설계된 방식은 아니므로 이와 같은 문제가 발생합니다. "IMO Android가 자동 취소해야 함"-조치에 해당 플래그를 제공하는 것을 볼 수 있지만 항상 그런 것은 아닙니다. 음악 플레이어 알림에서 트랙을 건너 뛰면 알림이 닫힙니다.
CommonsWare

7

제 생각에는 a를 사용하는 BroadcastReceiver것이 알림을 취소하는 더 확실한 방법입니다.

AndroidManifest.xml에서 :

<receiver 
    android:name=.NotificationCancelReceiver" >
    <intent-filter android:priority="999" >
         <action android:name="com.example.cancel" />
    </intent-filter>
</receiver>

자바 파일에서 :

Intent cancel = new Intent("com.example.cancel");
PendingIntent cancelP = PendingIntent.getBroadcast(context, 0, cancel, PendingIntent.FLAG_CANCEL_CURRENT);

NotificationCompat.Action actions[] = new NotificationCompat.Action[1];

NotificationCancelReceiver

public class NotificationCancelReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //Cancel your ongoing Notification
    };
}

1
그것이 내가하는 일이지만 onReceive 메소드에서 알림 ID (이 예제에서는 0)를 어떻게 얻습니까? 추가되지 않았기 때문에 의도에 없습니다. 나는 그것을 추가로 추가하려고 시도했지만 실제 알림 ID는 내가 활동을 생성하는 데 추가로 추가하지 않은 것처럼 보입니다 ... :-/
Marco Zanetti

액티비티 대신 브로드 캐스트 서비스를 사용하는이 방법이 정말 마음에 듭니다.
Christophe Moine

그러나 표시된 알림을 해제하려면 <intent.setAction (Integer.toString (notificationId)) ;;을 사용해야했습니다.
Christophe Moine

1
@MarcoZanetti 알림을 보낼 때 보류중인 의도와 알림 방법에 전달하는 알림 ID를 생성해야합니다. 그렇게하면 사용자가 작업을 클릭하여 취소 할 때 브로드 캐스트 리시버를 호출 한 다음 엑스트라에서 알림 ID를 얻을 수 있습니다.
레이 헌터

@ChristopheMoine 당신은 ID를 통해 intent.putExtra()그것을 넣을 수 있습니다BroadcastReceiver
Vadim Kotov

5

새로운 API에서는 TAG를 잊지 마십시오.

notify(String tag, int id, Notification notification)

그리고 이에 상응하여

cancel(String tag, int id) 

대신에:

cancel(int id)

https://developer.android.com/reference/android/app/NotificationManager


당신이 옳았! cancel()함수에는 두 가지 구현이 있지만 ; 하나는 태그가 있고 다른 하나는 태그가 없습니다. 그러나 우리는을 제공해야합니다 TAG. 다음은 canceldocs의 기능입니다 public void cancel(@Nullable String tag, int id). Android Q에서 마지막으로 확인
sud007

1

이 줄을 넣으십시오.

 builder.setAutoCancel(true);

전체 코드는 다음과 같습니다.

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    builder.setSmallIcon(android.R.drawable.ic_dialog_alert);
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.co.in/"));
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    builder.setContentIntent(pendingIntent);
    builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.misti_ic));
    builder.setContentTitle("Notifications Title");
    builder.setContentText("Your notification content here.");
    builder.setSubText("Tap to view the website.");
    Toast.makeText(getApplicationContext(), "The notification has been created!!", Toast.LENGTH_LONG).show();

    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    builder.setAutoCancel(true);
    // Will display the notification in the notification bar
    notificationManager.notify(1, builder.build());

자동 취소는 Android 9를 타겟팅 할 때 아무런 영향을 미치지 않는 것 같습니다 (Android 8.1을 대상으로 할 때 정상적으로 작동 함)
Alix

여기에 구별은 행동의 것입니다
누군가 어딘가에

0

알림을 제거하려면 인 텐트가 시작된 후 다음 코드를 실행해야합니다.

NotificationManagerCompat.from(this).cancel(null, notificationId);

NB : notificationId는 알림을 실행하기 위해 전달 된 것과 동일한 ID입니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.