Determina su iPhone se l'utente ha abilitato le notifiche push


Risposte:


300

Chiama enabledRemoteNotificationsTypese controlla la maschera.

Per esempio:

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone) 
   // blah blah blah

iOS8 e versioni successive:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]

19
iOS 5: verifica il tipo di notifiche push utilizzate dall'app indipendentemente dal tempo in cui l'app si trova nel centro di notifica del telefono o meno. Ho disabilitato le notifiche push per la mia app e ho ancora ricevuto i tipi == 6. Dopo aver disabilitato lo stile audio e di avviso, ho ricevuto i tipi == UIRemoteNotificationTypeNone.
quantumpotato,

4
Come sottolineato da quantumpotato, questa risposta non gestisce più tutti i casi e non è una soluzione completa.
DBD,

5
Cosa sta succedendo con Apple? Mi piacerebbe sentire la loro risposta su questo problema. Come possiamo sviluppare grandi app senza conoscere tali informazioni di base ??
Oded Regev,

15
@ZacBowling: la soluzione per iOS 8e successive è errata perché controlla solo se l'utente si è registrato per la notifica remota. Secondo la documentazione:This method reflects only the successful completion of the remote registration process that begins when you call the registerForRemoteNotifications method. This method does not reflect whether remote notifications are actually available due to connectivity issues. The value returned by this method takes into account the user’s preferences for receiving remote notifications.
Apan,

5
Quindi secondo me dovresti anche controllare[[UIApplication sharedApplication] currentUserNotificationSettings];
Apan,

99

problema di quantumpotato:

Dove typesviene dato da

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

si può usare

if (types & UIRemoteNotificationTypeAlert)

invece di

if (types == UIRemoteNotificationTypeNone) 

ti consentirà di verificare solo se le notifiche sono abilitate (e non preoccuparti di suoni, badge, centro notifiche, ecc.). La prima riga di codice ( types & UIRemoteNotificationTypeAlert) verrà restituita YESse "Stile avviso" è impostato su "Banner" o "Avvisi" e NOse "Stile avviso" è impostato su "Nessuno", indipendentemente da altre impostazioni.


questo non affronta il problema di quantumpotato. Non si preoccupa solo di avvisi, ma sottolinea che non è possibile discernere tramite enabledRemoteNotifications se l'utente ha attivato o disattivato l'impostazione del Centro notifiche.
Joey,

8
La mia risposta potrebbe non rispondere direttamente "come determinare se l'app si trova nel Centro notifiche", ma offre un modo per verificare se l'utente riceverà o meno notifiche per la tua app , che ritengo sia una risposta nello spirito della domanda . Non credo sia possibile controllare il primo.
Tim Camber,

2
Il trucco di "if (types & UIRemoteNotificationTypeAlert)" è molto buono.
nembleton,

Assicurati di capire perché il trucco funziona! Gli operatori bit a bit sono molto utili e le maschere a bit sono comuni in Cocoa. Dai
Tim Camber,

2
In Swift2 / XCode7 l'operazione bit a bit ha esito negativo con errore L'operatore binario '&' non può essere applicato a due operandi 'UIUserNotificationType' . Puoi usare invece contienegrantedSettings.types.contains(notificationType)
Philipp Otto del

54

Nell'ultima versione di iOS questo metodo è ora obsoleto. Per supportare sia iOS 7 che iOS 8 utilizzare:

UIApplication *application = [UIApplication sharedApplication];

BOOL enabled;

// Try to use the newer isRegisteredForRemoteNotifications otherwise use the enabledRemoteNotificationTypes.
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
    enabled = [application isRegisteredForRemoteNotifications];
}
else
{
    UIRemoteNotificationType types = [application enabledRemoteNotificationTypes];
    enabled = types & UIRemoteNotificationTypeAlert;
}

2
Che dire delle notifiche locali? iOS 8 ora richiede all'utente di consentirli. Ma poi come verificare in seguito che questi erano consentiti o no?
Frédéric Adda,

@FredA. Controllare UserNotifications. Non ho una risposta completa ora, sfortunatamente.
Mazyod,


3
in Swift non posso fare enabled = types & UIRemoteNotificationTypeAlert. Errore: i tipi non sono bool
grandagile

53

Codice aggiornato per swift4.0, iOS11

import UserNotifications

UNUserNotificationCenter.current().getNotificationSettings { (settings) in
   print("Notification settings: \(settings)")
   guard settings.authorizationStatus == .authorized else { return }

   //Not authorised 
   UIApplication.shared.registerForRemoteNotifications()
}

Codice per swift3.0, iOS10

    let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
    if isRegisteredForRemoteNotifications {
        // User is registered for notification
    } else {
        // Show alert user is not registered for notification
    }

Da iOS9, swift 2.0 UIRemoteNotificationType è obsoleto, utilizzare il codice seguente

let notificationType = UIApplication.shared.currentUserNotificationSettings!.types
if notificationType == UIUserNotificationType.none {
        // Push notifications are disabled in setting by user.
    }else{
  // Push notifications are enabled in setting by user.

}

controlla semplicemente se le notifiche push sono abilitate

    if notificationType == UIUserNotificationType.badge {
        // the application may badge its icon upon a notification being received
    }
    if notificationType == UIUserNotificationType.sound {
        // the application may play a sound upon a notification being received

    }
    if notificationType == UIUserNotificationType.alert {
        // the application may display an alert upon a notification being received
    }

33

Di seguito troverai un esempio completo che copre sia iOS8 che iOS7 (e versioni precedenti). Prima di iOS8 non è possibile distinguere tra "notifiche remote disabilitate" e " Visualizza solo nella schermata di blocco abilitata".

BOOL remoteNotificationsEnabled = false, noneEnabled,alertsEnabled, badgesEnabled, soundsEnabled;

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    // iOS8+
    remoteNotificationsEnabled = [UIApplication sharedApplication].isRegisteredForRemoteNotifications;

    UIUserNotificationSettings *userNotificationSettings = [UIApplication sharedApplication].currentUserNotificationSettings;

    noneEnabled = userNotificationSettings.types == UIUserNotificationTypeNone;
    alertsEnabled = userNotificationSettings.types & UIUserNotificationTypeAlert;
    badgesEnabled = userNotificationSettings.types & UIUserNotificationTypeBadge;
    soundsEnabled = userNotificationSettings.types & UIUserNotificationTypeSound;

} else {
    // iOS7 and below
    UIRemoteNotificationType enabledRemoteNotificationTypes = [UIApplication sharedApplication].enabledRemoteNotificationTypes;

    noneEnabled = enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone;
    alertsEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeAlert;
    badgesEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeBadge;
    soundsEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeSound;
}

if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    NSLog(@"Remote notifications enabled: %@", remoteNotificationsEnabled ? @"YES" : @"NO");
}

NSLog(@"Notification type status:");
NSLog(@"  None: %@", noneEnabled ? @"enabled" : @"disabled");
NSLog(@"  Alerts: %@", alertsEnabled ? @"enabled" : @"disabled");
NSLog(@"  Badges: %@", badgesEnabled ? @"enabled" : @"disabled");
NSLog(@"  Sounds: %@", soundsEnabled ? @"enabled" : @"disabled");

6
userNotificationSettings.types & UIUserNotificationTypeNone sarà sempre falso, poiché UIUserNotificationTypeNone è una maschera di bit vuota, è l'assenza degli altri bit. per Nessuno vuoi solo controllare l'uguaglianza.
dberwick,

25

Swift 3+

    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
            // settings.authorizationStatus == .authorized
        })
    } else {
        return UIApplication.shared.currentUserNotificationSettings?.types.contains(UIUserNotificationType.alert) ?? false
    }

Versione osservabile RxSwift per iOS10 +:

import UserNotifications
extension UNUserNotificationCenter {
    static var isAuthorized: Observable<Bool> {
        return Observable.create { observer in
            DispatchQueue.main.async {
                current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
                    if settings.authorizationStatus == .authorized {
                        observer.onNext(true)
                        observer.onCompleted()
                    } else {
                        current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in
                            observer.onNext(granted)
                            observer.onCompleted()
                        }
                    }
                })
            }
            return Disposables.create()
        }
    }
}

1
mi salvi la giornata. :)
Chetan Dobariya,

1
Grazie stavo cercando questo per un'ora.
Chanchal Warde,

4
getNotificationSettings(...)è asincrono, quindi il ritorno all'interno sarà ignorato
shelll

17

Nel tentativo di supportare sia iOS8 che inferiore, non ho avuto molta fortuna usando isRegisteredForRemoteNotificationscome suggerito Kevin. Invece ho usato currentUserNotificationSettings, che ha funzionato benissimo nei miei test.

+ (BOOL)notificationServicesEnabled {
    BOOL isEnabled = NO;

    if ([[UIApplication sharedApplication] respondsToSelector:@selector(currentUserNotificationSettings)]){
        UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];

        if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
            isEnabled = NO;
        } else {
            isEnabled = YES;
        }
    } else {
        UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
        if (types & UIRemoteNotificationTypeAlert) {
            isEnabled = YES;
        } else{
            isEnabled = NO;
        }
    }

    return isEnabled;
}

Questo non si applica quando l'applicazione è appena installata. Il metodo restituirà sempre NO e l'autorizzazione pop-up per le notifiche push non verrà mai visualizzata. Pertanto, sulle impostazioni del dispositivo, l'app non verrà visualizzata se si desidera modificare le impostazioni di notifica per tale app (consenti / non consentire). Qualcuno ha idea di come aggirare questo problema?
tyegah123,

Le impostazioni di notifica persistono anche quando un'app viene eliminata. Quindi, se la tua app è completamente nuova, questo metodo funzionerà. Se la tua app è stata eliminata ma reinstallata, le autorizzazioni sono ancora nel sistema e Apple non ti darà l'opportunità di richiedere nuovamente le autorizzazioni.
Shaheen Ghiassy,

Vedo un codice ridondante: isEnabled = NO;nei tuoi ifcasi non è necessario in quanto è stato inizializzato comeNO
Jasper

15

Purtroppo nessuna di queste soluzioni ha fornito davvero risolve il problema perché alla fine le API mancano seriamente quando si tratta di fornire le informazioni pertinenti. Puoi fare alcune ipotesi, tuttavia l'utilizzo currentUserNotificationSettings(iOS8 +) non è sufficiente nella sua forma attuale per rispondere davvero alla domanda. Anche se molte delle soluzioni qui sembrano suggerire che o quello oisRegisteredForRemoteNotifications sia più una risposta definitiva, in realtà non lo è.

Considera questo:

con isRegisteredForRemoteNotifications stati della documentazione:

Restituisce SÌ se l'applicazione è attualmente registrata per le notifiche remote, tenendo conto di tutte le impostazioni di sistema ...

Tuttavia, se si lancia semplicemente un NSLogdelegato nell'app per osservare il comportamento, è chiaro che questo non si comporta nel modo in cui prevediamo che funzionerà. In realtà riguarda direttamente le notifiche remote che sono state attivate per questa app / dispositivo. Una volta attivato per la prima volta, questo ritornerà sempre YES. Anche la disattivazione nelle impostazioni (notifiche) comporterà comunque questo ritorno YESperché, a partire da iOS8, un'app può registrarsi per le notifiche remote e persino inviare a un dispositivo senza che l'utente abbia le notifiche abilitate, semplicemente non possono fare avvisi, Badge e suoni senza che l'utente lo accenda. Le notifiche silenziose sono un buon esempio di qualcosa che potresti continuare a fare anche con le notifiche disattivate.

Per quanto currentUserNotificationSettingsindica una delle quattro cose:

Gli avvisi sono attivi I badge sono attivi Il suono è attivo Nessuno è attivo.

Ciò non fornisce assolutamente alcuna indicazione sugli altri fattori o sul pulsante di notifica stesso.

Un utente può infatti disattivare badge, suoni e avvisi, ma può comunque essere mostrato nella schermata di blocco o nel centro notifiche. Questo utente dovrebbe comunque ricevere notifiche push ed essere in grado di vederle sia nella schermata di blocco che nel centro notifiche. Hanno l'attivazione della notifica. MA currentUserNotificationSettingstornerà: UIUserNotificationTypeNonein quel caso. Questo non è veramente indicativo delle impostazioni effettive degli utenti.

Alcune ipotesi si possono fare:

  • se lo isRegisteredForRemoteNotificationsèNO tal possibile ritenere che questo dispositivo non sia mai stato registrato correttamente per le notifiche remote.
  • dopo la prima volta che si registra per le notifiche remote application:didRegisterUserNotificationSettings:viene effettuato un callback contenente le impostazioni di notifica dell'utente in quanto questa è la prima volta che un utente è stato registrato, le impostazioni dovrebbero indicare ciò che l'utente ha selezionato in termini di richiesta di autorizzazione. Se le impostazioni equivalgono a qualcosa di diverso da: UIUserNotificationTypeNonequindi è stata concessa l'autorizzazione push, altrimenti è stata rifiutata. La ragione di ciò è che dal momento in cui inizi il processo di registrazione remota l'utente ha solo la possibilità di accettare o rifiutare, con le impostazioni iniziali di un'accettazione che sono le impostazioni che hai impostato durante il processo di registrazione.

8

Per completare la risposta, potrebbe funzionare in questo modo ...

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
switch (types) {
   case UIRemoteNotificationTypeAlert:
   case UIRemoteNotificationTypeBadge:
       // For enabled code
       break;
   case UIRemoteNotificationTypeSound:
   case UIRemoteNotificationTypeNone:
   default:
       // For disabled code
       break;
}

modifica: questo non è giusto. dal momento che queste sono cose bit-saggio, non funzionerà con un interruttore, quindi ho finito con questo:

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
UIRemoteNotificationType typesset = (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge);
if((types & typesset) == typesset)
{
    CeldaSwitch.chkSwitch.on = true;
}
else
{
    CeldaSwitch.chkSwitch.on = false;
}

Ho considerato (per la mia situazione) le notifiche sonore non abilitate (poiché ho bisogno del testo per considerarle abilitate per la mia funzionalità dell'app)
pojomx

5

Per iOS7 e precedenti dovresti effettivamente utilizzare enabledRemoteNotificationTypese verificare se è uguale (o non uguale a seconda di ciò che desideri) a UIRemoteNotificationTypeNone.

Tuttavia per iOS 8 è non è sempre sufficiente controllare soltanto con isRegisteredForRemoteNotificationsil maggior numero di stato sopra. Dovresti anche controllare se è application.currentUserNotificationSettings.typesuguale (o non è uguale a seconda di ciò che vuoi) UIUserNotificationTypeNone!

isRegisteredForRemoteNotificationspotrebbe restituire true anche se currentUserNotificationSettings.typesrestituisce UIUserNotificationTypeNone.


5

iOS8 + (OBIETTIVO C)

#import <UserNotifications/UserNotifications.h>


[[UNUserNotificationCenter currentNotificationCenter]getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {

    switch (settings.authorizationStatus) {
          case UNAuthorizationStatusNotDetermined:{

            break;
        }
        case UNAuthorizationStatusDenied:{

            break;
        }
        case UNAuthorizationStatusAuthorized:{

            break;
        }
        default:
            break;
    }
}];

4
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
    // blah blah blah
{
    NSLog(@"Notification Enabled");
}
else
{
    NSLog(@"Notification not enabled");
}

Qui otteniamo UIRemoteNotificationType da UIApplication. Rappresenta lo stato della notifica push di questa app nell'impostazione, quindi puoi controllarne facilmente il tipo


3
per favore spiega cosa fa questo codice, scrivere codice non risponde semplicemente alla domanda.
Batty,

4

Cerco di supportare iOS 10 e versioni successive utilizzando la soluzione fornita da @Shaheen Ghiassy ma trovo un problema di privazione enabledRemoteNotificationTypes. Quindi, la soluzione che trovo usando isRegisteredForRemoteNotificationsinvece di quella enabledRemoteNotificationTypesdeprecata in iOS 8. Di seguito è la mia soluzione aggiornata che ha funzionato perfettamente per me:

- (BOOL)notificationServicesEnabled {
    BOOL isEnabled = NO;
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(currentUserNotificationSettings)]){
        UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];

        if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
            isEnabled = NO;
        } else {
            isEnabled = YES;
        }
    } else {

        if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]) {
            isEnabled = YES;
        } else{
            isEnabled = NO;
        }
    }
    return isEnabled;
}

E possiamo chiamare questa funzione facilmente e accedendo al suo Boolvalore e possiamo convertirla nel valore di stringa in questo modo:

NSString *str = [self notificationServicesEnabled] ? @"YES" : @"NO";

Spero che possa aiutare anche gli altri :) Buona programmazione.


3

Sebbene la risposta di Zac fosse perfettamente corretta fino a iOS 7, è cambiata da quando iOS 8 è arrivato. Perché enabledRemoteNotificationTypes è stato deprecato da iOS 8 in poi. Per iOS 8 e versioni successive, è necessario utilizzare isRegisteredForRemoteNotifications .

  • per iOS 7 e precedenti -> Usa enabledRemoteNotificationTypes
  • per iOS 8 e versioni successive -> Usa isRegisteredForRemoteNotifications.

2

Questa soluzione Swifty ha funzionato bene per me ( iOS8 + ),

Metodo :

func isNotificationEnabled(completion:@escaping (_ enabled:Bool)->()){
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
            let status =  (settings.authorizationStatus == .authorized)
            completion(status)
        })
    } else {
        if let status = UIApplication.shared.currentUserNotificationSettings?.types{
            let status = status.rawValue != UIUserNotificationType(rawValue: 0).rawValue
            completion(status)
        }else{
            completion(false)
        }
    }
}

Utilizzo :

isNotificationEnabled { (isEnabled) in
            if isEnabled{
                print("Push notification enabled")
            }else{
                print("Push notification not enabled")
            }
        }

arbitro


0

ri:

questo è corretto

if (types & UIRemoteNotificationTypeAlert)

ma anche seguire è corretto! (come UIRemoteNotificationTypeNone è 0)

if (types == UIRemoteNotificationTypeNone) 

vedi quanto segue

NSLog(@"log:%d",0 & 0); ///false
NSLog(@"log:%d",1 & 1); ///true
NSLog(@"log:%d",1<<1 & 1<<1); ///true
NSLog(@"log:%d",1<<2 & 1<<2); ///true
NSLog(@"log:%d",(0 & 0) && YES); ///false
NSLog(@"log:%d",(1 & 1) && YES); ///true
NSLog(@"log:%d",(1<<1 & 1<<1) && YES); ///true
NSLog(@"log:%d",(1<<2 & 1<<2) && YES); ///true

0

Ecco come farlo in Xamarin.ios.

public class NotificationUtils
{
    public static bool AreNotificationsEnabled ()
    {
        var settings = UIApplication.SharedApplication.CurrentUserNotificationSettings;
        var types = settings.Types;
        return types != UIUserNotificationType.None;
    }
}

Se si supporta iOS 10+, utilizzare solo il metodo UNUserNotificationCenter.


0

In Xamarin, la soluzione sopra descritta non funziona per me. Questo è quello che uso invece:

public static bool IsRemoteNotificationsEnabled() {
    return UIApplication.SharedApplication.CurrentUserNotificationSettings.Types != UIUserNotificationType.None;
}

Sta ricevendo un aggiornamento live anche dopo aver modificato lo stato delle notifiche in Impostazioni.


-1

Codice copia e incolla semplice e completo creato dalla soluzione di @ ZacBowling ( https://stackoverflow.com/a/1535427/2298002 )

questo porterà anche l'utente alle impostazioni della tua app e consentirà loro di abilitarlo immediatamente

Ho anche aggiunto una soluzione per verificare se i servizi di localizzazione sono abilitati (e portano anche alle impostazioni)

// check if notification service is enabled
+ (void)checkNotificationServicesEnabled
{
    if (![[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
    {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Notification Services Disabled!"
                                                            message:@"Yo don't mess around bro! Enabling your Notifications allows you to receive important updates"
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];

        alertView.tag = 300;

        [alertView show];

        return;
    }
}

// check if location service is enabled (ref: https://stackoverflow.com/a/35982887/2298002)
+ (void)checkLocationServicesEnabled
{
    //Checking authorization status
    if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)
    {

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Location Services Disabled!"
                                                            message:@"You need to enable your GPS location right now!!"
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];

        //TODO if user has not given permission to device
        if (![CLLocationManager locationServicesEnabled])
        {
            alertView.tag = 100;
        }
        //TODO if user has not given permission to particular app
        else
        {
            alertView.tag = 200;
        }

        [alertView show];

        return;
    }
}

// handle bringing user to settings for each
+ (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

    if(buttonIndex == 0)// Cancel button pressed
    {
        //TODO for cancel
    }
    else if(buttonIndex == 1)// Settings button pressed.
    {
        if (alertView.tag == 100)
        {
            //This will open ios devices location settings
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=LOCATION_SERVICES"]];
        }
        else if (alertView.tag == 200)
        {
            //This will open particular app location settings
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
        }
        else if (alertView.tag == 300)
        {
            //This will open particular app location settings
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
        }
    }
}

GLHF!

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.