Визначте на iPhone, чи користувач увімкнув push-сповіщення


Відповіді:


300

Зателефонуйте enabledRemoteNotificationsTypesі перевірте маску.

Наприклад:

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

iOS8 і вище:

[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]

19
iOS 5: Цей параметр перевіряє, який тип push-сповіщень використовує додаток незалежно від погоди, перебуваючи у центрі сповіщень вашого телефону чи ні. Я відключив натискання сповіщень для свого додатка і все ще отримав типи == 6. Після відключення звуку та стилю оповіщення я отримав типи == UIRemoteNotificationTypeNone.
квантовий картоплин

4
Як зазначалося в квантовій картотеці, ця відповідь вже не розглядає всі випадки і не є повноцінним рішенням.
ДБД

5
Що відбувається з Apple? Я хотів би почути їх відповідь на це питання. Як ми можемо розробляти чудові програми, не знаючи такої основної інформації ??
Одед Регев

15
@ZacBowling - рішення для iOS 8та вище є неправильним, оскільки він перевіряє, чи зареєстрований користувач для віддаленого сповіщення. Відповідно до документації: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
Тож, на мою думку, ви також повинні перевірити[[UIApplication sharedApplication] currentUserNotificationSettings];
Apan

99

Випуск квантової картоплі:

Де typesдано

UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

можна використовувати

if (types & UIRemoteNotificationTypeAlert)

замість

if (types == UIRemoteNotificationTypeNone) 

дозволить вам перевіряти лише чи ввімкнено сповіщення (і не хвилюйтеся щодо звуків, значків, центру сповіщень тощо). Перший рядок коду ( types & UIRemoteNotificationTypeAlert) повернеться, YESякщо для "Стилю сповіщення" встановлено значення "Банери" або "Попередження", а NOякщо "Стиль сповіщення" встановлено на "Ніхто", незалежно від інших параметрів.


це не стосується питання квантової картоплі. Він не стосується лише сповіщень, але вказує, що ви не можете розпізнати через enableRemoteNotifications, чи ввімкнено або вимкнено налаштування Центру сповіщень.
Джої

8
Моя відповідь може не відповідати безпосередньо "як визначити, чи додаток знаходиться в Центрі сповіщень", але він пропонує спосіб перевірити, чи отримає користувач сповіщення про ваш додаток , чи я вважаю це відповіддю в дусі питання . Я не думаю, що це можливо перевірити.
Тім Камбер

2
Трюк "if (type & UIRemoteNotificationTypeAlert)" дуже хороший.
Немблтон

Переконайтеся, що ви зрозуміли, чому трюк працює! Бітові оператори дуже корисні, а бітові маски поширені в какао. Перевірте stackoverflow.com/a/3427633/1148702
Тім Камбер

2
У Swift2 / XCode7 побітова операція не вдається з помилкою. Бінарний оператор "&" не може бути застосований до двох операндів "UIUserNotificationType" . Ви можете використовувати замість міститьgrantedSettings.types.contains(notificationType)
Philipp Otto,

54

В останній версії iOS цей метод тепер застарілий. Для підтримки iOS 7 та iOS 8 використовуйте:

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
Що з місцевими сповіщеннями? Тепер iOS 8 вимагає від користувача їх дозволу. Але як потім перевірити, чи це дозволено чи ні?
Frédéric Adda

@FredA. Перевірка UserNotifications. На жаль, зараз не маю повної відповіді.
Мазюд


3
у Swift я не можу зробити увімкнено = type & UIRemoteNotificationTypeAlert. Помилка: типи не є bool
grandagile

53

Оновлений код для 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()
}

Код для swift3.0, iOS10

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

З iOS9 швидкий 2.0 UIRemoteNotificationType застарілий, використовуйте наступний код

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.

}

просто перевірте, чи активовано Push-сповіщення

    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

Нижче ви знайдете повний приклад, який охоплює як iOS8, так і iOS7 (та нижчі версії). Зауважте, що до iOS8 ви не можете розрізняти "віддалене сповіщення вимкнено" та "лише Перегляд на екрані блокування ".

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 завжди буде помилковим, оскільки UIUserNotificationTypeNone - порожня бітова маска, це відсутність інших бітів. для None ви просто хочете перевірити рівність.
dberwick

25

Швидкий 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
    }

Версія, що спостерігається RxSwift для 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
ти врятуєш мій день. :)
Четанська Добріанія

1
Дякую, я шукав це протягом години.
Чанчал Уорд

4
getNotificationSettings(...)є асинхронним, тому повернення всередину буде ігноровано
shelll

17

Намагаючись підтримати iOS8 і новіші версії, мені не пощастило використовувати, isRegisteredForRemoteNotificationsяк запропонував Кевін. Натомість я використав currentUserNotificationSettings, що спрацювало чудово у моєму тестуванні.

+ (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;
}

Це не застосовується, коли додаток щойно встановлено. Метод завжди повертатиме НІ, і спливаючий дозвіл на push-повідомлення ніколи не з’явиться. Таким чином, у налаштуваннях пристрою додаток не з’явиться, якщо ви хочете змінити налаштування сповіщень для цього додатка (дозволити / заборонити). Хтось має ідею, як обійти цю проблему?
tyegah123

Налаштування сповіщень зберігаються навіть при видаленні програми. Тож якщо ви додаток абсолютно новий, то цей метод спрацює. Якщо ваш додаток було видалено, але потім перевстановлено, дозволи все ще є в системі, і Apple не надасть вам можливості повторно запитувати дозволи.
Shaheen Ghiassy

Я бачу якийсь зайвий код: isEnabled = NO;у ваших ifвипадках він не потрібен, оскільки він був ініціалізований якNO
Джаспер

15

На жаль, жодне з цих рішень не реально вирішило проблему, оскільки наприкінці дня API не вдається серйозно брати участь у наданні відповідної інформації. Ви можете зробити кілька здогадок, однак, використовуючи currentUserNotificationSettings(iOS8 +), просто не достатньо в його теперішній формі, щоб дійсно відповісти на питання. Хоча, здається, багато рішень тут говорять про те, що це чи isRegisteredForRemoteNotificationsбільше, ніж остаточний відповідь, це насправді не так.

Врахуйте це:

з isRegisteredForRemoteNotificationsдокументацією зазначено:

Повертає ТАК, якщо програма наразі зареєстрована для віддалених сповіщень з урахуванням будь-яких системних налаштувань ...

Однак якщо ви просто киньте NSLogделегату програми, щоб спостерігати за поведінкою, зрозуміло, що це не так, як ми очікуємо, що це буде працювати. Це стосується безпосередньо віддалених сповіщень, активованих для цього додатка / пристрою. Після активації вперше це завжди повернеться YES. Навіть якщо вимкнути їх у налаштуваннях (сповіщеннях), це все одно призведе до цього повернення. YESЦе тому, що, як в iOS8, додаток може реєструватися для віддалених сповіщень і навіть надсилати на пристрій без увімкнення користувачем сповіщень, вони просто не можуть робити сповіщення, Значки та звук без включення користувача. Безшумні сповіщення - хороший приклад того, що ви можете продовжувати робити навіть із вимкнутими сповіщеннями.

Наскільки currentUserNotificationSettingsце вказує на одну з чотирьох речей:

Повідомлення увімкнено Значки ввімкнено Звук увімкнено Ніхто не увімкнено.

Це не дає абсолютно жодних вказівок щодо інших факторів чи самого перемикача сповіщень.

Користувач може насправді вимкнути значки, звук та сповіщення, але все-таки відображати його на блокувальному екрані чи в центрі сповіщень. Цей користувач все одно повинен отримувати push-сповіщення та мати можливість бачити їх як на заблокованому екрані, так і в центрі сповіщень. У них увімкнено перемикач сповіщень. АЛЕ currentUserNotificationSettingsповернеться: UIUserNotificationTypeNoneу такому випадку. Це справді не вказує на фактичні настройки користувачів.

Кілька здогадок можна зробити:

  • якщо isRegisteredForRemoteNotificationsце NOтоді, ви можете припустити, що цей пристрій ніколи не був успішно зареєстрований для віддалених сповіщень.
  • після першого разу реєстрації для віддалених сповіщень робиться зворотний виклик application:didRegisterUserNotificationSettings:, що містить налаштування сповіщень користувача в цей час, оскільки це перший раз, коли користувач був зареєстрований, налаштування повинні вказувати, що обрав користувач з точки зору запиту на дозвіл. Якщо налаштування прирівнюються до чогось іншого, ніж: UIUserNotificationTypeNoneтоді було надано дозвіл на натискання, інакше його було відхилено. Причиною цього є те, що з моменту початку процесу віддаленої реєстрації користувач має лише можливість приймати або відхиляти, при цьому початкові параметри прийняття - це налаштування, які ви встановлюєте під час реєстрації.

8

Для завершення відповіді це могло б спрацювати приблизно так ...

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

редагувати: Це неправильно. оскільки це трохи розумні речі, він не буде працювати з комутатором, тому я закінчив використовувати це:

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

Я вважав (для моєї ситуації) звукові сповіщення не ввімкненими (оскільки мені потрібен текст, щоб вважати їх увімкнутими для моєї програми)
pojomx

5

Для iOS7 і перед цим ви дійсно повинні використовувати enabledRemoteNotificationTypesі перевірити, чи він дорівнює (чи не дорівнює, залежно від того, що ви хочете) UIRemoteNotificationTypeNone.

Однак для iOS8 не завжди достатньо лише перевірити isRegisteredForRemoteNotificationsстільки станів, котрі вище. Ви також повинні перевірити, чи application.currentUserNotificationSettings.typesдорівнює (чи не дорівнює, залежно від того, що ви хочете) UIUserNotificationTypeNone!

isRegisteredForRemoteNotificationsможе повернути правду, навіть незважаючи на те, що currentUserNotificationSettings.typesповертається UIUserNotificationTypeNone.


5

iOS8 + (ОБ'ЄКТИВ 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");
}

Тут ми отримуємо UIRemoteNotificationType від UIApplication. Він відображає стан push-повідомлення цього додатка в налаштуваннях, ніж ви можете легко перевірити його тип


3
поясніть, будь ласка, що робить цей код, написання коду не відповідає просто на питання.
Батті

4

Я намагаюся підтримувати iOS 10 і вище, використовуючи рішення, надані від @Shaheen Ghiassy, ​​але знаходжу проблему позбавлення enabledRemoteNotificationTypes. Отже, рішення, яке я знаходжу, використовуючи isRegisteredForRemoteNotificationsзамість цього enabledRemoteNotificationTypesзастаріле в iOS 8. Нижче наведено моє оновлене рішення, яке ідеально працювало для мене:

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

І ми можемо легко викликати цю функцію і отримувати доступ до її Boolзначення і можемо перетворити її у значення рядка таким чином:

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

Сподіваюся, це допоможе і іншим :) Щасливе кодування.


3

Хоча відповідь Зака ​​була абсолютно правильною до iOS 7, вона змінилася з моменту появи iOS 8. Оскільки enableRemoteNotificationTypes було вимкнено з iOS 8 і далі. Для iOS 8 та новіших версій потрібно використовувати isRegisteredForRemoteNotifications .

  • для iOS 7 і раніше -> Використовуйте увімкнені Визначення сповіщень
  • для iOS 8 та новіших версій -> Використовуйте isRegisteredForRemoteNotifications.

2

Це рішення Swifty працювало для мене добре ( iOS8 + ),

Спосіб :

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)
        }
    }
}

Використання :

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

Реф


0

re:

це вірно

if (types & UIRemoteNotificationTypeAlert)

але наступне також правильно! (оскільки UIRemoteNotificationTypeNone дорівнює 0)

if (types == UIRemoteNotificationTypeNone) 

див. наступне

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

Ось як це зробити в Xamarin.ios.

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

Якщо ви підтримуєте iOS 10+, перейдіть лише методом UNUserNotificationCenter.


0

У «Xamarin» все вище рішення не працює для мене. Це те, що я використовую натомість:

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

Він отримує оновлення в реальному часі також після того, як ви змінили статус сповіщення в Налаштуваннях.


-1

Повна проста копія та вставлення коду, створеного за допомогою рішення @ ZacBowling ( https://stackoverflow.com/a/1535427/2298002 )

це також приведе користувача до налаштувань вашої програми та дозволить їм негайно ввімкнути

Я також додав у рішення для перевірки того, чи ввімкнено послуги локації (і приводить до налаштувань)

// 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!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.