İşlem tıklandıktan sonra bildirim nasıl kapatılır?


143

API seviye 16 (Jelly Bean) olduğundan, bir bildirime eylem ekleme

builder.addAction(iconId, title, intent);

Ancak bir bildirime bir eylem eklediğimde ve işleme basıldığında bildirim reddedilmeyecek. Bildirimin kendisi tıklandığında, ile reddedilebilir

notification.flags = Notification.FLAG_AUTO_CANCEL;

veya

builder.setAutoCancel(true);

Ancak açıkçası, bunun bildirimle ilgili eylemlerle hiçbir ilgisi yoktur.

İpucu var mı? Yoksa bu henüz API'nin bir parçası değil mi? Hiçbir şey bulamadım.

Yanıtlar:


155

Bildirim yöneticisinde bildirim çağırdığınızda, ona bir kimlik verdiniz - bu daha sonra erişmek için kullanabileceğiniz benzersiz bir kimliktir (bu bildirim yöneticisinden:

notify(int id, Notification notification)

İptal etmek için şunu arayabilirsiniz:

cancel(int id)

aynı kimliğe sahip. Yani, temel olarak, kimliği izlemeniz veya kimliği PendingIntent içindeki Niyet'e eklediğiniz bir Pakete koymanız gerekiyor mu?


25
Teşekkürler, bu benim sorunumu çözdü. Ancak, hala biraz fazla karmaşık olduğunu düşünüyorum. Bir eyleme basıldığında bildirimi otomatik olarak kapatmak için bir API sağlamak yerine, bunu gerçekleştirmek için niyet ve bildirim kimliği geçirme ile çalışmanız gerekir.
endowzoner

2
Bunun karmaşık olduğunu düşünüyorsanız, bir bildirimi güncellemeye (bu kimliğin kaydını kaybetmeyin) veya görüntülenip görüntülenmediğini kontrol etmeyin (API bunu izlemez, yapmanız gerekir): P
Travis

2
@Daksh: Temel olarak, eyleminize basıldığında başlayan niyetinize bildirim etiketi ve kimliği eklersiniz. Bu ek bilgilerle, başlangıç ​​etkinliğinde bir bildirim işlemi yoluyla başlatılıp başlatılmadığını kontrol edebilirsiniz.
endowzoner

5
OnCreate () 'den kod örneği: Bundle extras = getIntent (). GetExtras (); if (extras! = null) {String tag = extras.getString (NotificationReceiver.INTENT_EXTRA_NOTIFICATION_TAG); int id = extras.getInt (NotificationReceiver.INTENT_EXTRA_NOTIFICATION_ID); (NotificationReceiver.NOTIFICATION_ID == id && NotificationReceiver.NOTIFICATION_TAG.equals (tag)) {// etkinlik bildirim işlemi yoluyla başlatıldıysa, dismiss // bildirim NotificationManager yöneticisi = (NotificationManager) getSystemService (Service.NOTIFICATION_SERVICE); manager.cancel (etiket, kimlik); }}
endowzoner

1
Yeni API'da bildirim (Dize etiketi, int id, Bildirim bildirimi) ve buna göre iptal (Dize etiketi, int id) var
Malachiasz

64

Lollipop'un Heads Up Display bildirimini kullanırken bu bir sorun olarak bulundu. Tasarım yönergelerine bakın . İşte uygulamak için tam (ish) kodu.

Şimdiye kadar, 'Kapat' düğmesine sahip olmak daha az önemliydi, ama şimdi yüzünüzde daha fazla.

uyarı bildirimi

Bildirimi Oluşturma

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'nin bir arka yığına odaklanmasını önlemek için gereken özellikler)

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

bir uygulamadan birden fazla bildirim var ve bildirim devam eden bildirime ayarlanır. Pertiküler bildirimde addaksiyon yapıldığında bildirimi silmek istiyorum
Prasad

3
Bunun yerine bildirimi kapatmak için bir BroadcastReceiver kullanmak daha etkili olmaz mıydı? İşte uygulamayı gösteren iyi bir örnek, ancak daha da azaltılabilir: stackoverflow.com/a/19745745/793150
alice.harrison

1
Belirlenen ekstralar dışında özüm ile yönlendirilen çözümler çalışır. OnCreate'e yönlendirilmezler. Bunun bir yolu statik değişkenler kullanmaktır. Kimse neden ekstraların iletilmediğini biliyor mu?
Baschi

Neden getDismissIntent yalnızca NotificationActivity'ye yerleştirildiğinde çalışır? PendingIntent oluşturma kodu bildirim oluşturucu sınıfına yerleştirilirse, işten çıkarma Niyeti çalışmaz. Bu konuda sadece 2 saat geçirdim ve Beklemede Niyetin neden Faaliyette oluşturulması GEREKİR? Herkes bunun neden böyle olduğunu açıklayabilir mi?
Ray Li

getDismissIntent (), NotificationActivity ile iletişim kurmak için kullanılacak doğru Niyeti oluşturan statik bir "yardımcı" işlevdir. Bu nedenle, bunlar genellikle Faaliyet ile birlikte gelir. Ancak, NOTIFICATION_ID ve bağlamı doğru şekilde ayarlamaya dikkat ettiğiniz sürece, bu statik işlevin neden bildirim oluşturucu sınıfına yerleştirilemediğini anlamıyorum.
Mike

17

Genişletilmiş düğmelerde eylem düğmelerini kullandığınızda, ekstra kod yazmanız gerektiğini ve daha kısıtlı olduğunuzu gördüm.

Kullanıcı bir eylem düğmesini tıkladığında bildiriminizi manuel olarak iptal etmeniz gerekir. Bildirim yalnızca varsayılan işlem için otomatik olarak iptal edilir.

Ayrıca düğmeden bir yayın alıcısı başlatırsanız, bildirim çekmecesi kapanmaz.

Bu sorunları ele almak için yeni bir NotificationActivity oluşturdum. Kullanıcı arayüzü olmayan bu aracı etkinlik bildirimi iptal eder ve gerçekten bildirimden başlamak istediğim etkinliği başlatır.

İlgili bir gönderide örnek kod yayınladım Android Bildirim İşlemleri'ni tıklamak Bildirim çekmecesini kapatmıyor .


2
Çok kötü onlar hala API içine pişmiş değil ... Bu şekilde yapmak oldukça hackish. Ancak yine de tek yol, özellikle de hedef URL üzerinde herhangi bir kontrolünüz yoksa, örneğin bir URL görüntülemek gibi.
Bogdan Zurac

Bilgi için teşekkürler, haklısın. Ancak aracılık faaliyeti yerine intentervice kullanırım
Tim

7

Her zaman olabilir dan (içinde, örneğin eylem tarafından çağrılan ediliyor olursa olsun bağlı faaliyet size tedarik ).cancel()NotificationonCreate()PendingIntentaddAction()


2
Ancak, çağrılan etkinlikteki bildirime nasıl erişebilirim?
endowzoner

@FleshWound: aradığınızda kullandığınız cancel()kimliğini alır . Nesneye ihtiyacınız yok . Notificationnotify()Notification
CommonsWare

SetGroup ayarlanmışsa ve bir Grup özeti bildirimi varsa @CommonsWare cancel (id) çalışmayı durdurdu. Bu durumda, iptal bir nedenden dolayı hiçbir şey yapmaz. Grup özeti olmadan iptal olsa da iyi çalışır
Kushan

beklemede olan amacım ACTION_VIEWve tür ise image/jpeg(bir görüntüyü başka bir uygulamayla paylaşmak için) o zaman bu iptalin nasıl tetiklenmesi gerekir? IMO Android otomatik olarak iptal etmeli, Android'in neden sadece onunla ilgilenmediğine şaşkınım?!
Birisi

@SomeoneSomewhere: "o zaman bu iptal nasıl tetiklenir?" - olamaz. Bir üçüncü taraf uygulamasına işaret durdurma şey olsa da NotificationPendingIntentbunun gibi sorunları çalıştırmak böylece, işte bu işe nasıl tasarlandığına gerçekten değil ve. "IMO Android otomatik olarak iptal edilmelidir" - Bunun için bir bayrak teklifini görebiliyordum, ama her zaman böyle bir şey olmamalı. Öyle olsaydı, müzik çalar bildirimindeki bir parçayı atlamak bildirimi kapatırdı.
CommonsWare

7

Bence bir BroadcastReceiver bir Bildirimi iptal etmenin daha temiz bir yoludur:

AndroidManifest.xml'de:

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

Java Dosyasında:

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
Yaptığım şey bu, ancak onReceive yönteminden bildirim kimliğini (bu örnekte 0) nasıl alırsınız? Niyette değil, çünkü ona eklenmedi. Fazladan eklemeyi denedim ama gerçek bildirim kimliği, oluşturma etkinliğinde fazladan eklediğim gibi değil ...: - /
Marco Zanetti

Etkinlikler yerine Yayın hizmetlerini kullanma yaklaşımını gerçekten çok seviyorum, bu çok daha hafif bir yaklaşım.
Christophe Moine

Ancak, gösterilen bildirimlerin herhangi birini reddetmek için, <intent.setAction (Integer.toString (reportId));> öğelerini kullanmak zorunda kaldım.
Christophe Moine

1
@MarcoZanetti, beklemede olan hedefe ve bildirimi gönderirken bildirim yöntemine ilettiğiniz bir bildirim kimliği oluşturmanız gerekir. Bunu yaparsanız, kullanıcı iptal etmek için eylemi tıklattığında yayın alıcısını çağırır ve ardından ekstralardan bildirim kimliğini alabilirsiniz.
Ray Hunter

@ChristopheMoine üzerinden id koymak intent.putExtra()ve almakBroadcastReceiver
Vadim Kotov

5

Yeni API'larda TAG'ı unutma:

notify(String tag, int id, Notification notification)

ve buna göre

cancel(String tag, int id) 

onun yerine:

cancel(int id)

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


Haklıydın! cancel()fonksiyonun 2 uygulaması olmasına rağmen ; biri TAG ve diğeri olmadan. Ancak, bir TAG. İşte canceldokümanlar işlevi public void cancel(@Nullable String tag, int id). En son Android Q'da kontrol edildi
sud007

1

Sadece bu satırı yazınız:

 builder.setAutoCancel(true);

Ve tam kod:

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

AutoCancel'in Android 9'u hedeflerken hiçbir etkisi yok gibi görünüyor (Android 8.1'i hedeflerken iyi çalıştı)
Alix

Burada ayrım eylemin ile
Birisi bir yerde

0

Bildirimi kaldırmak için amacınız tetiklendikten sonra aşağıdaki kodu çalıştırmanız gerekir.

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

Not: bildirim Kimliği, bildiriminizi çalıştırmak için geçirilen kimlikle aynı kimliktir


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.