чому didRegisterForRemoteNotificationsWithDeviceToken не викликається


88

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

Але все-таки методи не називаються. Я не знаю, що спричиняє проблему. Хто-небудь може мені допомогти?

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
        //NSString * token = [[NSString alloc] initWithData:deviceTokenencoding:NSUTF8StringEncoding];
        NSString *str = [NSString stringWithFormat:@"Device Token=%@",deviceToken];
        NSLog(@"Device Token:%@",str);

        //NSLog(@"Device token is called");
        //const void *devTokenBytes = [deviceToken bytes];
        //NSLog(@"Device Token");
    }

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
        NSString *str = [NSString stringWithFormat: @"Error: %@", err];
        NSLog(@"Error:%@",str);    
    }

немає необхідності додавати будь-який інший код , просто перевірити його посилання stackoverflow.com/a/39849892/3269536
Женіш

Відповіді:


73

У мене була та сама проблема: дзвінок registerForRemoteNotificationTypes:не викликався ні, application:didRegisterForRemoteNotificationsWithDeviceToken:ніapplication:didFailToRegisterForRemoteNotificationsWithError:

Врешті-решт я вирішив це питання за допомогою технічної записки Apple TN2265 .

Це те, що я зробив:

По-перше, я ще раз перевірив, чи справді я правильно реєструюсь для push-сповіщень , включаючи перевірку свого профілю підготовки для ключа "aps-environment" та кодового підписання самого файлу .app. Я все це правильно налаштував.

Потім мені довелося налагоджувати повідомлення про стан push-сповіщень у консолі (вам потрібно встановити на вашому пристрої профіль забезпечення PersistentConnectionLogging.mobileconfig і перезавантажити його. Див. TN2265 у розділі "Спостереження повідомлень про статус push"). Я помітив, що процес apns запускає таймер і обчислює мінімальну дату спрацьовування, що змусило мене запідозрити, що повідомлення про підтвердження реєстрації Push-Notification, яке зазвичай представлене в цей момент, пригнічується APNS, як зазначено в TN2265:

Скидання сповіщення про дозволи push-сповіщень на iOS

Перший раз, коли додаток із підтримкою push-реєстрації реєструється для push-сповіщень, iOS запитує користувача, чи бажає він отримувати сповіщення для цієї програми. Після того, як користувач відповів на це сповіщення, воно більше не відображається, якщо пристрій не відновлено або програму не видалено принаймні протягом доби.

Якщо ви хочете змоделювати перший запуск програми, ви можете залишити програму невстановленою на день. Ви можете досягти останнього, фактично не чекаючи доби, встановивши системний годинник вперед на день або більше, повністю вимкнувши пристрій, а потім знову ввімкнувши пристрій.

Отже, я видалив програму з пристрою, а потім вручну змінив дату iPhone у Налаштуваннях, перезавантажив пристрій та заново встановив програму.

Наступного разу, коли мій код зателефонував registerForRemoteNotificationTypes, він отримав зворотні дзвінки, як очікувалося.

Це вирішило проблему для мене. Сподіваюся, це допоможе.


1
Ключовим моментом для мене було те, що я використовував старіший сертифікат розробки на іншій машині. Ця проблема вирішена при передачі найновішого сертифіката з основного ноутбука розробки.
Маркус Раутопуро

3
Після увімкнення push-повідомлень необхідно знову генерувати профілі підготовки.
Тоні

3
Привіт! хоча це стара публікація, я дізнався, що іноді це буде виправлено, коли ви вимкнете та ввімкнете всі налаштування сповіщень програми. Оскільки минулого разу, як я пам’ятаю, викликали didRegisterForRemoteNotificationsWithDeviceToken, тоді раптом цього не було. Сподіваюся, це допоможе.
otakuProgrammer

1
Я змусив це працювати, лише додавши ще один крок скидання: 1. Видалити програму 2. Скинути пристрій 3. Переадресувати годинник на 1+ днів 4.
Знову

Важливо також переконатися, що у вас немає кількох "дійсних" копій одного і того ж профілю надання розробки, ні в Xcode, ні на самому пристрої. Можливо, ви створили новий сертифікат APN і відтворили свій профіль підготовки після закінчення терміну дії попереднього сертифіката. Старий профіль розробки все ще є дійсним як профіль розробки, але цього буде недостатньо, щоб увімкнути APN. Ви побачите типову помилку про те, що "немає дійсних aps-прав бла-бла".
jaredsinclair

66

У iOS 8 деякі методи застаріли. Виконайте наведені нижче дії щодо сумісності iOS 8

1. Зареєструвати повідомлення

if([[UIDevice currentDevice] systemVersion].floatValue >= 8.0)
{
    UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];    
}
else
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound|UIRemoteNotificationTypeBadge)];
}

2. Додайте нові 2 методи

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    //register to receive notifications
    [application registerForRemoteNotifications];
}

//For interactive notification only
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
    else if ([identifier isEqualToString:@"answerAction"]){
    }
}

Примітка: вище два нові методи потрібні в iOS 8 на додаток до didRegisterForRemoteNotificationsWithDeviceTokenі .. В didReceiveRemoteNotificationіншому випадку метод делегування не буде викликаний.

Див .: Віддалене сповіщення iOS 8


1
Чи слід ці два нові методи використовувати в Appdelegate.m?
Ітан Паркер,

- (недійсне) додаток: (UIApplication *) додаток didRegisterUserNotificationSettings: (UIUserNotificationSettings *) notificationSettings {// реєструватися для отримання сповіщень [application registerForRemoteNotifications]; } Додавання наведеного нижче є небезпечним, це призвело до аварії на моєму телефоні, і я не можу навіть скинути його до заводських налаштувань.
Джон

Це, мабуть, відповідь, яку ви шукаєте, якщо опиняєтесь тут. Як не дивно, делегата зателефонували раніше сьогодні, не додавши жодного з цих методів. Зараз здається, що вони потрібні мені обом.
Буде

мій додаток аварійно розбивається на цій лінії[application registerForRemoteNotifications];
smithyy

26

У iOS 8 , крім того, що по-іншому запитують доступ до push-сповіщень, вам також потрібно зареєструватися по-різному.

Запросити доступ:

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    // iOS 8
    UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
    // iOS 7 or iOS 6
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}

Обробляти зареєстрований пристрій:

// New in iOS 8
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [application registerForRemoteNotifications];
}

// iOS 7 or iOS 6
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    // Send token to server
}

Надзвичайно корисний. Я не міг зрозуміти, чому мої сповіщення зламалися.
GoldenJoe

4
Як я можу отримати маркер в iOS 8?
Йоссі

@Yossi він зберігається у змінній "token" уapplication:didRegisterForRemoteNotificationsWithDeviceToken:
Кайл Клег

мій додаток аварійно завершує роботу з цим рядком [application registerForRemoteNotifications];
smithyy

13

Майте на увазі, що віддалені сповіщення не підтримуються в симуляторі. Тому, якщо ви запустите програму в симуляторі, didRegisterForRemoteNotificationsWithDeviceTokenвона не буде викликана.


@hochl: Я оновив свою відповідь, щоб вона конкретніше відповідала на питання.
Ерік,

1
Зверніть увагу, що didFailToRegisterForRemoteNotificationsWithError також не буде викликаний. Фактично, жодне сповіщення не викликається, якщо ви вимкнете push-сповіщення для свого додатка в Налаштуваннях (на пристрої чи симуляторі). Apple, схоже, не вважає це помилкою stackoverflow.com/questions/9199935/…
Зак Морріс

12

Переконайтесь, що ви ввели свій код (оновіть відповідно до підтримуваних видів сповіщень)

[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];

і для профілю підготовки ввімкнено APNS. Можливо, вам доведеться повторно завантажити профіль підготовки після ввімкнення APNS. Якщо у вас виникають проблеми, і ви отримуєте помилки, можливо, вам слід створити Entitlements.plist і додати ключ "aps-environment" зі значенням "розвиток" або "виробництво" залежно від виду збірки (зазвичай ця пара ключ-значення є містяться у профілі надання, але іноді Xcode плутається з ними).


Примітка: "і в профілі підготовки ввімкнено APNS." Клацніть у верхній частині дерева дерев проектів> Можливості> Push-сповіщення потрібно встановити на УВІМК.
trevorgrayson

6

Якщо профілі підготовки раніше використовувались для Увімкнення та налаштування служби Apple Push Notification, вам доведеться знову завантажити профілі підготовки.

Видаліть профілі забезпечення з Xcode Organizer та з iPhone / iPad. Перейти до Settings -> General -> Profiles -> [Your provisioning] -> Remove.

Встановіть нові завантажені профілі підготовки. Потім очистіть і запустіть проект із XCode. Тепер didRegisterForRemoteNotificationsWithDeviceTokenслід зателефонувати.


Це працює для мене. просто вибрав сертифікацію та надання, які мали зареєструвати APN-адреси для програми.
lee

Я видалив весь профіль підготовки з iphone (ios9), а потім після отримання маркера пристрою. Витратьте чотири години, щоб це виправити (хоча я багато чому навчусь). Дякую
Шобхакар Тіварі

3

Я помилився і пропустив деталь реалізації, яка привела мене сюди. Я спробував вигадати і попросити у користувача Push-сповіщення пізніше в процесі вбудовування програми, тому я мав свій registerForRemoteNotificationTypes, didRegisterForRemoteNotificationsWithDeviceTokenі didFailToRegisterForRemoteNotificationsWithErrorвсе це в користувацькому UIView.

ВИПРАВЛЕННЯ: didRegisterForRemoteNotificationsWithDeviceTokenі didFailToRegisterForRemoteNotificationsWithErrorпотрібно бути в UIApplicationDelegate( YourAppDelegate.m) для спрацьовування.

здається очевидним зараз, хе.


Так, методи повинні бути в AppDelegate. Не можу повірити, що я витратив свої останні години на цю просту відповідь
Навіть Ченга

3

Переконайтеся, що з’єднання з Інтернетом увімкнено. Це займало години, щоб отримувати робочі сповіщення через з’єднання з Інтернетом.


3

Якщо ви додали push до існуючого ідентифікатора програми, переконайтеся, що ви повторно створили свої профілі підготовки. Якщо ви цього не зробите, профіль не знатиме про те, що ви дозволили натиснути на ідентифікатор програми.


3

Спробуйте це працює для мене,

Перший крок

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

У наведеному вище методі додайте нижче код

 UIApplication *application = [UIApplication sharedApplication];
 if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
                                                                                     |UIUserNotificationTypeSound
                                                                                     |UIUserNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
 } 
 else {
      UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
     }

Другий крок

Додайте нижче код Функція

 #ifdef __IPHONE_8_0
   - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
   {
  //register to receive notifications
  [application registerForRemoteNotifications];
  }

 - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
  {
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
   else if ([identifier isEqualToString:@"answerAction"]){
   }
}
 #endif

Ви отримаєте маркер пристрою у нижченаведеній функції

 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 

для детальної відповіді, будь ласка, зверніться до цього

Сподіваюся, це допоможе комусь.


2
-​(BOOL)application:(UIApplication​*)application​ didFinishLaunchingWithOptions:(NSDictionary​*)launchOptions​{​​​​ ​​​​ ​​​​//​Override​point​for​customization​after​application​launch.
​​​​//​Add​the​view​controller’s​view​to​the​window​and​display. ​​​​[window​addSubview:viewController.view]; ​​​​[window​makeKeyAndVisible];
NSLog(@”Registering for push notifications...”);
 [[UIApplication sharedApplication]
registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound)]; 
​​​​returnYES;
}


- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
}
NSString *str = [NSString stringWithFormat:@”Device Token=%@”,deviceToken];
NSLog(@”%@”, str);


- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSString *str = [NSString stringWithFormat: @”Error: %@”, err]; NSLog(@”%@”, str);
}


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
}
for (id key in userInfo) { NSLog(@”key: %@, value: %@”, key, [userInfo objectForKey:key]);
}

2

Мінімальна вимога для отримання маркера пристрою:

Не потрібно налаштовувати ідентифікатор програми, забезпечення чи сертифікат тощо, отже, не встановлено підпис коду для отримання методу делегування didRegisterForRemoteNotificationsWithDeviceToken .

Я щойно створив новий проект iOS у Xcode 7 для одного перегляду з налаштуваннями за замовчуванням і дав випадковий ідентифікатор набору, як com.mycompany.pushtest, який не налаштовано на порталі Apple Dev.

За допомогою наступного коду я отримую маркер свого пристрою в методі didRegisterForRemoteNotificationsWithDeviceToken на своєму iPad із доступом до Інтернету до WIFI. Мій пристрій підключено, і я просто запускаю програму безпосередньо з xcode і переглядаю значення в консолі xcode.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   

{  
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])  
    {  
        UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound);  
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes categories:nil];  
        [application registerUserNotificationSettings:settings];  
        [application registerForRemoteNotifications];  
    }  
    else  
    {  
        // Register for Push Notifications, if running iOS version < 8  
        [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];  
    }  
    return YES;  
}  


- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Error: %@", error.description);
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken);
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    NSLog(@"NotificationSettings: %@", notificationSettings);
}

1

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


1

Витративши найприкріші 3 години, ось кроки, щоб вирішити проблему:

  1. Видаліть програму

  2. Скиньте налаштування пристрою

  3. Біжи знову

Це просто спрацювало


0

Це трапилося зі мною, тому що я скинув і видалив всі дані на телефоні (хотів, щоб використовував телефон розробника). Це заважало APN взагалі підключатися після повторного налаштування телефону.

Я пробував всілякі речі, але єдине, що це виправляло, - це налаштування телефону на роботу з носієм під новою SIM-карткою.

Це посилання пропонує більше підказок щодо того, що могло відбуватися: https://developer.apple.com/library/ios/technotes/tn2265/_index.html

Там сказано, що APN намагається підключитись переважно через оператор / вежі, на відміну від Wi-Fi. Можливо, проблема також була в тому, що щось відбувалося з маршрутизатором, що блокував порт 5223 у мережі Wi-Fi, але я сумніваюся в цьому, оскільки він працював нормально попереднього дня до глобального скидання.


0

Для мене, що вирішено, це перехід до налаштувань збірки та в розділі підписання коду, вручну вибираючи ідентифікатор підпису коду та профіль надання. Очевидно, автоматичне налаштування не підібрало правильне, а тому програма не була належним чином авторизована.


0

якщо вимкнути push-повідомлення програми,

appdidRegisterForRemoteNotificationsWithDeviceToken ніколи не буде викликаний


0

Також не забудьте перевірити стан системи на Apple https://developer.apple.com/system-status/ .

Я спробував усі рішення, розміщені вище, але врешті-решт, помилка в тому, що служба APNS не працює! Наступного дня все знову працювало, як очікувалося.

Крім того, у вас є метод друку в методі зворотного дзвінка:

- (void)application:(UIApplication *)appdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

Як зазначив Рупеш, правильна назва методу:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

Ось, мабуть, тому ви так і не отримали маркер у вашому випадку!


Насправді ім'я методу неправильне, воно повинно бути - (недійсне) додаток: (UIApplication *) додаток didRegisterForRemoteNotificationsWithDeviceToken: (NSData *) deviceToken Між параметрами є пробіл
Рупеш

Дякуємо, оновили відповідь, включивши ваш коментар. Цілком впевнений, що це рішення проблеми ОП, але ми можемо ніколи не дізнатися про це!
Бретт

0

Вам потрібно викликати метод registerForNotifications з didFinishLaunchingWithOptions.

 func registerForNotifications(){

        if #available(iOS 10.0, *) {

            let center = UNUserNotificationCenter.current()
            center.delegate = self
            center.requestAuthorization(options:[.alert,.sound,.badge]) { (granted, error) in
                if granted{
                    UIApplication.shared.registerForRemoteNotifications()
                }else{

                    print("Notification permission denied.")

                }
            }

        } else {

            // For iOS 9 and Below
            let type: UIUserNotificationType = [.alert,.sound,.badge];
            let setting = UIUserNotificationSettings(types: type, categories: nil);
            UIApplication.shared.registerUserNotificationSettings(setting);
            UIApplication.shared.registerForRemoteNotifications()
        }
    }

 func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        let token = String(format: "%@", deviceToken as CVarArg).trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "")
        print(token)

    }


extension AppDelegate : UNUserNotificationCenterDelegate{

    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter,  willPresent notification: UNNotification, withCompletionHandler   completionHandler: @escaping (_ options:   UNNotificationPresentationOptions) -> Void) {
        print("Handle push from foreground”)

        let info = ((notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
        if let type = info.value(forKey: "type") as? Int{
            if type == 0 {  

         // notification received ,Handle your notification here

            }
        }
    }

    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        print("Handle push from background or closed")

        let info = ((response.notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
        if let type = info.value(forKey: "type") as? Int{
            if type == 0 {   

            // notification received ,Handle your notification here
            }
        }
    }
}

0

У мене була інша проблема, коли мої зворотні дзвінки з push-сповіщення захоплювались сторонніми бібліотеками, які я включив, а саме Firebase. Ці бібліотеки для отримання зворотних викликів розмовляють методи зворотного виклику сповіщень.

Сподіваюся, це комусь допомагає.

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