Android 4.1: Wie überprüfe ich, ob Benachrichtigungen für die Anwendung deaktiviert sind?


98

Android 4.1 bietet dem Benutzer ein Kontrollkästchen zum Deaktivieren von Benachrichtigungen für eine bestimmte Anwendung.

Als Entwickler können wir jedoch nicht feststellen, ob ein Benachrichtigungsaufruf effektiv war oder nicht.

Ich muss wirklich überprüfen, ob die Benachrichtigungen für die aktuelle Anwendung deaktiviert sind, aber ich kann keine Einstellung dafür in der API finden.

Gibt es jemals eine Möglichkeit, diese Einstellung im Code zu überprüfen?


1
Sie sollten sich wirklich nicht darum kümmern. Nehmen Sie einfach an, dass Ihre Benachrichtigung erfolgreich war. Wenn der Benutzer Ihre Benachrichtigungen explizit deaktiviert hat, hatte er wahrscheinlich gute Gründe dafür, und Ihre Anwendung sollte sich nicht darum kümmern, ob die Benachrichtigung angezeigt wurde oder nicht.
Kevin Coppock

Ich habe den Grund in den Kommentaren der ersten Antwort erklärt.
Guillaume Perrot

1
Hier ist das Problem zu star / track code.google.com/p/android/issues/detail?id=38482 Ich brauche das wirklich ...
Brandall

Antworten:


147

Sie können nicht 100% können nicht.

In diesem Google I / O 2012-Video wird danach gefragt, und der Projektleiter für die neuen Benachrichtigungen erklärt, dass dies nicht möglich ist.


Bearbeiten

Update 2016: Jetzt können Sie es überprüfen, wie in diesem Google I / O 2016-Video erwähnt .

Verwenden Sie NotificationManagerCompat.areNotificationsEnabled()in der Support-Bibliothek, um zu überprüfen, ob Benachrichtigungen auf API 19+ blockiert sind. Die Versionen unter API 19 geben true zurück (Benachrichtigungen sind aktiviert).

Geben Sie hier die Bildbeschreibung ein


2
Das Video enthält nichts, was zeigt, dass wir diese Einstellung nicht lesen können. Nur um klar zu sein: Ich möchte nur den aktuellen Status des Kontrollkästchens lesen können, ohne ihn zu ändern. Ich fürchte, Sie haben meine Frage nicht verstanden.
Guillaume Perrot

2
Wir brauchen dies, weil wir jeweils 1 Benachrichtigung anzeigen (die in der App oder in der Systemleiste erfolgen kann). Wenn eine Systembenachrichtigung angezeigt wird, wird kein In-App-Banner angezeigt und umgekehrt. Wenn wir nicht wissen können, ob eine Benachrichtigung angezeigt wird oder nicht, können wir ihren Lebenszyklus nicht mehr verwalten. Ich denke, wir müssen die Art und Weise, wie wir Benachrichtigungen verwalten, jetzt komplett ändern ...
Guillaume Perrot

9
Zu Ihrer Information, die Frage wird um 48:05 Uhr im Video (während der Fragen und Antworten) mit einem kurzen Wort gestellt (und beantwortet) ... Nein. youtube.com/…
Devunwired

2
@Stavros_S aktualisierte Antwort mit dem vollständigen Link. NotificationManagerCompat.areNotificationsEnabled () .
Sufian

16
@Stavros_S Sie müssen verwendenNotificationManagerCompat.from(ctx).areNotificationsEnabled()
AlexAndro

38

Eigentlich ist das ziemlich einfach:

/**
 * 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
Zum Zeitpunkt der Veröffentlichung der Frage war Android 4.1 aktuell. Dies gilt nur für Android 4.4+ und scheint Reflexion zu verwenden. Die Dokumentation empfiehlt nicht, es für eine Nicht-System-App zu verwenden.
Guillaume Perrot

@ GuillaumePerrot Eigentlich haben Sie Recht mit Reflexion, aber auch hier sagen die Dokumentation und die offiziellen Aussagen von Android, dass Sie es nicht können, Sie können sich auch daran halten. Entschuldigung für das Versionsproblem, ich kann Ihnen dabei nicht helfen. Wenn Ihr Client / Ihre Lösung dies erfordert, sollten Sie die erforderliche Version ein wenig erhöhen, da das SDK Sie an diesem Punkt einschränkt. Lassen Sie mich wissen, wenn Sie einen alternativen Weg finden.
Desgraci

1
Fair genug, aber Sie sollten davon ausgehen, dass return true ist, wenn Sie die Informationen nicht erhalten können. Zumindest in meinem Anwendungsfall macht es mehr Sinn. Oder haben Sie einen Standardwert als Parameter in der statischen Funktion, um sie wiederverwendbarer zu machen.
Guillaume Perrot

1
@Rahul Matte, GlobalContext ist nur eine Dienstprogrammklasse, mit der ich einen Verweis auf einen Kontext behalte. Sie können einen Kontext durch die Methode übergeben, wenn Sie diese Struktur nicht verwenden oder bereit sind, sie zu verwenden. Hoffe das hilft!
Desgraci

1
Ich hoffe, dass sie nicht: p, sondern von Google XD stammen, da dies Reflexion verwendet, las die OP_POST_NOTIFICATION den Code auf dem Grep durch, nachdem ich festgestellt hatte, dass ich mit demselben Problem zu kämpfen hatte.
desgraci

37

Die Antwort von @blundell ist korrekt, aber in neueren Versionen gibt es eine geringfügige Änderung.

NotificationManagerCompat.from(context).areNotificationsEnabled()

5

Wenn Sie Xamarin verwenden und diese Antwort benötigen, können Sie diesen Code verwenden:

//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 () wurde in API 24 hinzugefügt. Developer.android.com/reference/android/app/…
Sune Kjærgård

Sie haben Recht, müssen es vorher falsch verstanden haben. Ich habe meinen ursprünglichen Kommentar gelöscht, um niemanden zu verwirren.
Adam Pedley

5

Es scheint, dass es keine Möglichkeit gibt, den Benachrichtigungsstatus abzufragen.

Ich empfehle dies:

  • Entwerfen Sie Ihre Anwendung mit Benachrichtigungen.
  • Lassen Sie den Benutzer Benachrichtigungen in den Anwendungseinstellungen deaktivieren.
  • Überprüfen Sie, ob auf Benachrichtigungen geklickt wird. Wenn der Benutzer auf Benachrichtigung klickt, speichern Sie diese in den Einstellungen.
  • Wenn in Ihrer App die Benachrichtigungseinstellung aktiviert ist und der Benutzer Android 4.1+ (API 16) ist, der Benutzer jedoch einige Tage / Wochen lang nicht auf Benachrichtigung klickt, wird davon ausgegangen, dass der Benutzer Benachrichtigungen deaktiviert hat.

Nicht 100% korrekt. Dies gibt aber eine Meinung.
Wenn der Benutzer beispielsweise 10 bis 15 Tage lang nicht auf eine App-Benachrichtigung klickt, hat er diese wahrscheinlich deaktiviert


1
Dies ist ein sehr breiter und abstrakter Ansatz.
IgorGanapolsky

Dies ist der beste Ansatz! Wir tun dies in unserer Anwendung und Sie können genau sagen, ob die Benachrichtigungen deaktiviert sind. PendingIndent für JEDE Aktion und in den Einstellungen speichern. Vergessen Sie nicht, zurückzusetzen, wenn das Smartphone neu gestartet wurde.
JacksOnF1re

1

Ich verwende diese Methode, um zu überprüfen, ob die Benachrichtigungen aktiviert sind oder nicht. Die oben genannten Methoden funktionieren, um zu überprüfen, ob Benachrichtigungen aktiviert sind oder nicht. Ab Android 8 müssen wir jedoch zum Erstellen von Benachrichtigungen zuerst einen Kanal erstellen. Ab Oreo müssen wir also überprüfen, ob Ihr Benachrichtigungskanal aktiviert ist oder nicht .

    /**
     * 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;
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.