Android 4.1: Uygulama için bildirimler devre dışı bırakıldığında nasıl kontrol edilir?


98

Android 4.1, kullanıcıya belirli bir uygulama için bildirimleri devre dışı bırakmak için bir onay kutusu sunar.

Ancak, bir geliştirici olarak, bildirim çağrısının etkili olup olmadığını bilmemizin bir yolu yok.

Geçerli uygulama için bildirimlerin devre dışı bırakılıp bırakılmadığını gerçekten kontrol etmem gerekiyor ancak API'de bunun için herhangi bir ayar bulamıyorum.

Kodda bu ayarı kontrol etmenin bir yolu var mı?


1
Gerçekten bununla ilgilenmemelisin. Bildiriminizin başarılı olduğunu varsayın. Kullanıcı bildirimlerinizi açıkça devre dışı bıraktıysa, muhtemelen bunu yapmak için iyi bir nedeni vardır ve uygulamanız, bildirimin görüntülenip görüntülenmediğine aldırış etmemelidir.
Kevin Coppock

Nedenini ilk yanıtlayanın yorumlarında açıkladım.
Guillaume Perrot

1
İşte yıldıza konudur / izlemek code.google.com/p/android/issues/detail?id=38482 Gerçekten bu .... gerek
brandall

Yanıtlar:


147

% 100 yapamazsınız.

Bu Google I / O 2012 videosunda isteniyor ve yeni bildirimler için Proje sorumlusu yapamayacağınızı beyan ediyor.


Düzenle

2016 güncellemesi: Artık bu Google I / O 2016 videosunda belirtildiği gibi kontrol edebilirsiniz .

NotificationManagerCompat.areNotificationsEnabled()API 19+ üzerinde bildirimlerin engellenip engellenmediğini kontrol etmek için destek kitaplığından kullanın . API 19'un altındaki sürümler doğru döndürür (bildirimler etkinleştirilir).

görüntü açıklamasını buraya girin


2
Videoda bu ayarı okuyamadığımızı gösteren hiçbir şey yok. Açıkça söylemek gerekirse: Sadece onay kutusunun mevcut durumunu değiştirmeden okuyabilmek istiyorum. Korkarım sorumu anlamadınız.
Guillaume Perrot

2
Buna ihtiyacımız var çünkü bir seferde 1 bildirim gösteriyoruz (uygulama içi veya sistem çubuğunda olabilir). Bir sistem bildirimi görüntülenirse, uygulama içi bir başlık göstermeyiz ve bunun tersi de geçerlidir. Bir bildirimin görüntülenip görüntülenmediğini bilemezsek, yaşam döngüsünü artık yönetemeyiz. Sanırım bildirimleri yönetme şeklimizi şimdi tamamen değiştirmemiz gerekiyor ...
Guillaume Perrot

9
Bilginize, soru videoda 48: 05'te (Soru-Cevap sırasında) kısa bir kelime ile sorulur (ve yanıtlanır) ... Hayır. youtube.com/…
devunwired

2
@Stavros_S tam bağlantı ile güncellenmiş yanıtı. NotificationManagerCompat.areNotificationsEnabled () .
Sufian

17
@Stavros_S Kullanmanız gerekiyorNotificationManagerCompat.from(ctx).areNotificationsEnabled()
AlexAndro

39

@Blundell'in cevabı doğru ancak yeni sürümlerde küçük bir değişiklik var.

NotificationManagerCompat.from(context).areNotificationsEnabled()

38

Aslında bunu yapmak oldukça kolaydır:

/**
 * Created by desgraci on 5/7/15.
*/
public class NotificationsUtils {

    private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
    private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

    public static boolean isNotificationEnabled(Context context) {

        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

        ApplicationInfo appInfo = context.getApplicationInfo();

        String pkg = context.getApplicationContext().getPackageName();

        int uid = appInfo.uid;

        Class appOpsClass = null; /* Context.APP_OPS_MANAGER */

        try {

            appOpsClass = Class.forName(AppOpsManager.class.getName());

            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String.class);

            Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
            int value = (int)opPostNotificationValue.get(Integer.class);

            return ((int)checkOpNoThrowMethod.invoke(mAppOps,value, uid, pkg) == AppOpsManager.MODE_ALLOWED);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return false;
    }
}

3
Soru yayınlandığında, Android 4.1 günceldi, bu yalnızca Android 4.4+ içindir ve yansımayı kullanıyor gibi görünüyor ve dokümantasyon, sistem dışı bir uygulama için kullanılmasını önermiyor.
Guillaume Perrot

@Gu GuillaumePerrot aslında, yansıtma konusunda haklısınız, ancak yine, android'in belgeleri ve resmi açıklamaları bunu yapamayacağınızı söylüyor, buna bağlı kalabilirsiniz. Sürüm sorunu için üzgünüm, bu konuda size yardımcı olamam. Eğer istemciniz / çözümünüz bunu gerektiriyorsa, o zaman gerekli sürümü biraz yükseltmeyi düşünebilirsiniz, çünkü bu noktada sizi sınırlayan SDK'dır. Alternatif bir yol bulursan bana haber ver.
desgraci

1
Yeterince adil, ancak bilgiyi alamazsanız doğru olduğunu varsaymalısınız. En azından benim kullanım durumumda daha mantıklı. Veya daha yeniden kullanılabilir hale getirmek için statik işlevde bir parametre olarak varsayılan değere sahip olun.
Guillaume Perrot

1
@Rahul Matte, GlobalContext, bir Context'e referans tutmak için kullandığım bir yardımcı sınıftır, eğer o yapıyı kullanmıyorsanız / kullanmak istemiyorsanız, metod üzerinden bir Context geçirebilirsiniz. Bu yardımcı olur umarım!
desgraci

1
Umarım öyle değildir: p ama google XD'den geliyor, bu yansıma kullandığından, OP_POST_NOTIFICATION kendimi aynı sorunla mücadele ederken bulduktan sonra grep üzerindeki kodu okuyordu.
desgraci

5

Xamarin kullanıyorsanız ve bu cevaba ihtiyacınız varsa şu kodu kullanabilirsiniz:

//return true if this option is not supported.
public class NotificationsUtils 
{
    private const String CHECK_OP_NO_THROW = "checkOpNoThrow";
    private const String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";

    public static bool IsNotificationEnabled(global::Android.Content.Context context) {

        AppOpsManager mAppOps = (AppOpsManager) context.GetSystemService(global::Android.Content.Context.AppOpsService);

        ApplicationInfo appInfo = context.ApplicationInfo;

        String pkg = context.ApplicationContext.PackageName;

        int uid = appInfo.Uid;

        try {

            var appOpsClass = Java.Lang.Class.ForName("android.app.AppOpsManager");
            var checkOpNoThrowMethod = appOpsClass.GetMethod(CHECK_OP_NO_THROW,Java.Lang.Integer.Type,Java.Lang.Integer.Type,new Java.Lang.String().Class);//need to add String.Type

            var opPostNotificationValue = appOpsClass.GetDeclaredField (OP_POST_NOTIFICATION);
            var value = (int)opPostNotificationValue.GetInt(Java.Lang.Integer.Type);
            var mode = (int)checkOpNoThrowMethod.Invoke(mAppOps,value, uid, pkg);
            return (mode == (int)AppOpsManagerMode.Allowed);

        } catch (Exception) 
        {
            System.Diagnostics.Debug.WriteLine  ("Notification services is off or not supported");
        } 
        return true;
    }
}

@AdamPedley AreNotificationsEnabled (), API 24 developer.android.com/reference/android/app/…
Sune Kjærgård

Haklısın, daha önce yanlış okumuş olmalısın. Kimsenin kafasını karıştırmamak için orijinal yorumumu sildim.
Adam

5

Bildirim durumunu sorgulamanın bir yolu yok gibi görünüyor.

Bunu tavsiye ederim:

  • Bildirimlerle uygulamanızı tasarlayın.
  • Kullanıcının, uygulama ayarlarından bildirimleri devre dışı bırakmasına izin verin.
  • Bildirimlerin tıklanıp tıklanmadığını kontrol edin. Kullanıcı bildirimi tıklarsa, bunu tercihlere kaydedin.
  • Uygulamanızda, bildirim ayarı açıksa ve kullanıcı Android 4.1+ (API 16) ise, ancak kullanıcı birkaç gün / hafta boyunca bildirimi tıklamazsa, kullanıcının bildirimleri devre dışı bıraktığını varsayın.

% 100 doğru değil. Ama bu bir fikir veriyor.
Örneğin, kullanıcı 10-15 gün boyunca herhangi bir uygulama bildirimini tıklamazsa, muhtemelen devre dışı bırakmıştır.


1
Bu çok geniş ve soyut bir yaklaşımdır.
IgorGanapolsky

Bu en iyi yaklaşımdır! Bunu uygulamamızda yapıyoruz ve bildirimler devre dışı bırakılırsa kesin olarak söyleyebilirsiniz. HER eylem için PendingIndent ve tercihe kaydedin. Akıllı telefon yeniden başlatıldıysa sıfırlamayı unutmayın.
JacksOnF1re

2

Bildirimlerin etkin olup olmadığını kontrol etmek için bu yöntemi kullanıyorum, yukarıda belirtilen yöntemler bildirimlerin etkin olup olmadığını kontrol etmek için çalışacaktır. Ancak Android 8'den itibaren bildirim oluşturmak için önce bir kanal oluşturmalıyız , bu nedenle Oreo'dan bildirim kanalınızın etkin olup olmadığını kontrol etmeliyiz .

    /**
     * Checking Whether notifications are enabled or not
     * @return true if notifications are enabled otherwise false
     */
    public static final String CHANNEL_ID = "your_channel_id";

    private boolean isNotificationChannelEnabled(){
        if(NotificationManagerCompat.from(this).areNotificationsEnabled()) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                NotificationChannel channel = manager.getNotificationChannel(CHANNEL_ID);
                if (channel == null)
                    return true; //channel is not yet created so return boolean
                // by only checking whether notifications enabled or not
                return channel.getImportance() != NotificationManager.IMPORTANCE_NONE;
            }
            return true;
        }
        return false;
    }

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.