Android 4.1: come controllare che le notifiche siano disabilitate per l'applicazione?


98

Android 4.1 offre all'utente una casella di controllo per disabilitare le notifiche per un'applicazione specifica.

Tuttavia, come sviluppatore non abbiamo modo di sapere se una chiamata per la notifica è stata efficace o meno.

Ho davvero bisogno di controllare se le notifiche sono disabilitate per l'applicazione corrente ma non riesco a trovare alcuna impostazione per questo nell'API.

C'è mai un modo per controllare questa impostazione nel codice?


1
Non dovresti davvero preoccuparti di questo. Supponi solo che la tua notifica sia andata a buon fine. Se l'utente ha disabilitato esplicitamente le tue notifiche, probabilmente aveva una buona ragione per farlo e alla tua applicazione non dovrebbe importare se la notifica è stata visualizzata o meno.
Kevin Coppock

Ho spiegato il motivo nei commenti della prima risposta.
Guillaume Perrot

1
Ecco il problema per contrassegnare / monitorare code.google.com/p/android/issues/detail?id=38482 Ne ho davvero bisogno ...
brandall

Risposte:


147

Non puoi farlo al 100%.

Viene chiesto in questo video di Google I / O 2012 e il responsabile del progetto per le nuove notifiche dichiara che non è possibile.


modificare

Aggiornamento 2016: ora puoi controllarlo, come detto in questo video di Google I / O 2016 .

Utilizzare NotificationManagerCompat.areNotificationsEnabled(), dalla libreria di supporto, per verificare se le notifiche sono bloccate su API 19+. Le versioni sotto l'API 19 restituiranno true (le notifiche sono abilitate).

inserisci qui la descrizione dell'immagine


2
Non c'è niente nel video che mostra che non possiamo leggere questa impostazione. Giusto per essere chiari: voglio solo essere in grado di leggere lo stato corrente della casella di controllo, senza alterarlo. Temo che tu non abbia capito la mia domanda.
Guillaume Perrot

2
Ne abbiamo bisogno perché mostriamo 1 notifica alla volta (che può essere in-app o nella barra di sistema). Se viene visualizzata una notifica di sistema, non viene visualizzato un banner nell'app e viceversa. Se non possiamo sapere se una notifica viene visualizzata o meno, non possiamo più gestirne il ciclo di vita. Immagino che ora dobbiamo cambiare completamente il modo in cui gestiamo le notifiche ...
Guillaume Perrot

9
Cordiali saluti, la domanda viene posta (e risposta) alle 48:05 nel video (durante il Q&A) con una breve parola ... No. youtube.com/…
Devunwired

2
@Stavros_S ha aggiornato la risposta con il link completo. NotificationManagerCompat.areNotificationsEnabled () .
Sufian

16
@Stavros_S Devi usareNotificationManagerCompat.from(ctx).areNotificationsEnabled()
AlexAndro

38

In realtà questo è abbastanza facile da fare:

/**
 * 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
Al momento in cui è stata pubblicata la domanda, Android 4.1 era aggiornato, questo è solo per Android 4.4+ e sembra utilizzare la riflessione e la documentazione non consiglia di utilizzarlo per un'app non di sistema.
Guillaume Perrot

@GuillaumePerrot in realtà hai ragione sulla riflessione, ma ancora una volta, la documentazione e le dichiarazioni ufficiali di Android dicono che non puoi farlo, puoi anche attenersi a quello. Mi dispiace per il problema della versione, non posso aiutarti in questo. Se il tuo client / soluzione lo richiede, beh, potresti prendere in considerazione l'idea di aumentare un po 'la versione richiesta poiché è l'SDK che ti limita a quel punto. Fammi sapere se trovi un modo alternativo.
desgraci

1
Abbastanza giusto, ma dovresti presumere che restituisca true se non puoi ottenere le informazioni. Almeno nel mio caso d'uso ha più senso. Oppure avere il valore predefinito come parametro nella funzione statica per renderlo più riutilizzabile.
Guillaume Perrot

1
@Rahul Matte, GlobalContext è solo una classe di utilità che utilizzo per mantenere un riferimento a un contesto, puoi passare un contesto attraverso il metodo se non stai usando / o sei disposto a usare quella struttura. Spero che questo ti aiuti!
desgraci

1
Spero di no: p ma provenendo da google XD, poiché utilizza la riflessione, l'OP_POST_NOTIFICATION stava leggendo il codice su grep dopo essermi trovato alle prese con lo stesso problema.
desgraci

37

La risposta di @blundell è corretta ma c'è una piccola modifica nelle versioni più recenti.

NotificationManagerCompat.from(context).areNotificationsEnabled()

5

Se stai usando Xamarin e hai bisogno di questa risposta puoi usare questo codice:

//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 () è stato aggiunto in API 24 developer.android.com/reference/android/app/…
Sune Kjærgård

Hai ragione, devi averlo letto male in precedenza. Ho cancellato il mio commento originale, in modo da non confondere nessuno.
Adam Pedley

5

Sembra che non sia possibile interrogare lo stato di notifica.

Raccomando questo:

  • Progetta la tua applicazione con le notifiche.
  • Consenti all'utente di disabilitare le notifiche dalle impostazioni dell'applicazione.
  • Controlla se si fa clic sulle notifiche. Se l'utente fa clic sulla notifica, salvalo nelle preferenze.
  • Nella tua app, se l'impostazione di notifica è attiva e se l'utente è Android 4.1+ (API 16), ma se l'utente non fa clic sulla notifica per alcuni giorni / settimane, presumi che l'utente abbia disattivato le notifiche.

Non corretto al 100%. Ma questo dà un'opinione.
Ad esempio, se l'utente non fa clic su alcuna notifica dell'app per 10-15 giorni, probabilmente l'ha disabilitata


1
Questo è un approccio molto ampio e astratto.
IgorGanapolsky

Questo è l'approccio migliore! Lo stiamo facendo nella nostra applicazione e puoi dire con precisione se le notifiche sono disabilitate. PendingIndent per OGNI azione e salva nelle preferenze. Non dimenticare di ripristinare se lo smartphone è stato riavviato.
JacksOnF1re

1

Uso questo metodo per verificare se le notifiche sono abilitate o meno, i metodi sopra menzionati funzioneranno per verificare se le notifiche sono abilitate o meno. Ma da Android 8 in poi per la creazione delle notifiche dobbiamo prima creare un canale , quindi da Oreo, dobbiamo verificare se il tuo canale di notifica è abilitato o meno .

    /**
     * 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;
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.