pourquoi didRegisterForRemoteNotificationsWithDeviceToken n'est pas appelé

89

Je crée une application dans laquelle je souhaite implémenter le service de notification push Apple. Je suis les instructions étape par étape données dans ce tutoriel .

Mais encore, les méthodes ne sont pas appelées. Je ne sais pas ce qui cause le problème. Quelqu'un peut-il m'aider?

    - (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);    
    }
Muzammil
la source
il n'est pas nécessaire d'ajouter un autre code, vérifiez simplement le lien stackoverflow.com/a/39849892/3269536
jenish

Réponses:

74

J'ai eu le même problème: appeler registerForRemoteNotificationTypes:invoqué ni application:didRegisterForRemoteNotificationsWithDeviceToken:niapplication:didFailToRegisterForRemoteNotificationsWithError:

J'ai finalement résolu ce problème à l'aide de la note technique d'Apple TN2265 .

C'est ce que j'ai fait:

Tout d'abord, j'ai revérifié que je m'inscrivais bien aux notifications push , y compris la vérification de mon profil d'approvisionnement pour la clé "aps-environnement" et la signature du fichier .app lui-même. J'ai tout configuré correctement.

J'ai ensuite dû déboguer les messages d'état de notification push dans la console (vous devez installer le profil de provisionnement PersistentConnectionLogging.mobileconfig sur votre appareil et le redémarrer. Voir TN2265 sous «Observation des messages d'état push»). J'ai remarqué que le processus apns démarre une minuterie et calcule une date d'incendie minimale, ce qui m'a fait suspecter que le message de confirmation d'enregistrement Push-Notification, qui est normalement présenté à ce stade, est supprimé par APNS, comme indiqué dans TN2265:

Réinitialisation de l'alerte d'autorisations de notifications push sur iOS

La première fois qu'une application activée par push s'enregistre pour les notifications push, iOS demande à l'utilisateur s'il souhaite recevoir des notifications pour cette application. Une fois que l'utilisateur a répondu à cette alerte, elle n'est plus présentée à moins que l'appareil ne soit restauré ou que l'application n'ait été désinstallée pendant au moins un jour.

Si vous souhaitez simuler une première exécution de votre application, vous pouvez laisser l'application désinstallée pendant une journée. Vous pouvez réaliser ce dernier sans attendre réellement un jour en réglant l'horloge système d'un jour ou plus en avant, en éteignant complètement l'appareil, puis en le rallumant.

J'ai donc supprimé l'application de l'appareil, puis modifié manuellement la date de l'iPhone dans les paramètres, redémarré l'appareil et réinstallé l'application.

La prochaine fois que mon code a appelé registerForRemoteNotificationTypes, il a reçu des rappels comme prévu.

Cela a résolu le problème pour moi. J'espère que cela aide.

100 grammes
la source
1
Le point clé pour moi était que j'utilisais un ancien certificat de développement sur une autre machine. Le transfert du certificat le plus récent depuis l'ordinateur portable de développement principal a résolu ce problème.
Markus Rautopuro
3
Après l'activation, les notifications Push sont nécessaires pour générer à nouveau les profils d'approvisionnement.
Tony le
3
Salut! bien qu'il s'agisse d'un ancien message, j'ai découvert que parfois, il sera corrigé lorsque vous désactivez et activez tous les paramètres de notification de l'application. Parce que la dernière fois que je me souviens, didRegisterForRemoteNotificationsWithDeviceToken a été appelé, puis soudainement il ne l'était pas. J'espère que cela aide.
otakuProgrammer
1
Je n'ai réussi à le faire qu'en ajoutant une autre étape de réinitialisation: 1. Supprimer l'application 2. Réinitialiser le périphérique 3.
Faire avancer l'
Il est également important de vous assurer que vous ne disposez pas de plusieurs copies «valides» du même profil d'approvisionnement de développement, que ce soit dans Xcode ou sur l'appareil lui-même. Peut-être avez-vous créé un nouveau certificat APN et recréé votre profil d'approvisionnement après l'expiration du certificat précédent. L'ancien profil de développement est toujours valide en tant que profil de développement, mais il ne sera pas suffisant pour activer les APN. Vous verrez une erreur typique concernant "aucun droit aps-bla bla valide".
jaredsinclair
66

Dans iOS 8, certaines méthodes sont obsolètes. Suivez les étapes ci-dessous pour la compatibilité iOS 8

1. Enregistrer la notification

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. Ajouter 2 nouvelles méthodes

- (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"]){
    }
}

Remarque: ci-dessus, deux nouvelles méthodes sont requises dans iOS 8 en plus de didRegisterForRemoteNotificationsWithDeviceTokenet didReceiveRemoteNotification.. Sinon, la méthode de délégation ne sera pas appelée.

Voir: Notification à distance iOS 8

Communauté
la source
1
Ces deux nouvelles méthodes devraient-elles aller dans Appdelegate.m?
Ethan Parker
- (void) application: (UIApplication *) application didRegisterUserNotificationSettings: (UIUserNotificationSettings *) notificationSettings {// s'inscrire pour recevoir des notifications [application registerForRemoteNotifications]; } L'ajout de ce qui suit est dangereux, mon téléphone a planté et je ne peux même pas le réinitialiser aux paramètres d'usine à ce stade.
John
C'est probablement la réponse que vous recherchez si vous vous retrouvez ici. Curieusement, le délégué a été appelé plus tôt dans la journée sans que j'ajoute une de ces méthodes. Maintenant, il semble que j'ai besoin des deux.
Sera
mon application plante avec cette ligne[application registerForRemoteNotifications];
smithyy
26

Dans iOS 8 , en plus de demander l'accès aux notifications push différemment, vous devez également vous enregistrer différemment.

Demande d'accès:

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

Gérer l'appareil enregistré:

// 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
}
Kyle Clegg
la source
Extrêmement utile. Je ne pouvais pas comprendre pourquoi mes notifications étaient interrompues
GoldenJoe
4
Comment puis-je obtenir le jeton dans iOS 8?
Yossi
@Yossi il est stocké dans la variable "token" dansapplication:didRegisterForRemoteNotificationsWithDeviceToken:
Kyle Clegg
mon application plante avec cette ligne [application registerForRemoteNotifications];
smithyy
13

Gardez à l'esprit que les notifications à distance ne sont pas prises en charge dans le simulateur. Par conséquent, si vous exécutez votre application dans le simulateur, didRegisterForRemoteNotificationsWithDeviceTokenelle ne sera pas appelée.

Eric
la source
@hochl: J'ai mis à jour ma réponse pour qu'elle réponde plus spécifiquement à la question.
Eric
1
Notez que didFailToRegisterForRemoteNotificationsWithError ne sera pas appelé non plus. En fait, aucune notification n'est appelée si vous désactivez les notifications push pour votre application dans les paramètres (que ce soit sur l'appareil ou le simulateur). Apple ne semble pas considérer cela comme une erreur stackoverflow.com/questions/9199935/…
Zack Morris
12

Assurez-vous d'appeler votre code (mise à jour selon les types de notification pris en charge)

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

et le profil de provisionnement est activé APNS. Vous devrez peut-être retélécharger le profil d'approvisionnement après avoir activé APNS. Si vous rencontrez des problèmes et que vous obtenez des erreurs, vous devriez peut-être créer un Entitlements.plist et ajouter la clé "aps-environment" avec la valeur "development" ou "production" selon le type de build (normalement, cette paire clé-valeur est contenus dans le profil de provisionnement, mais parfois Xcode les gâche).

Lorenzo Bevilacqua
la source
Remarque: «et le profil d'approvisionnement est APNS activé». Cliquez en haut de votre arborescence de projet> Capacités> Les notifications push doivent être activées.
trevorgrayson
6

Si les profils d'approvisionnement sont utilisés auparavant pour activer et configurer le service de notification push Apple, vous devrez retélécharger les profils d'approvisionnement.

Supprimez les profils d'approvisionnement de Xcode Organizer et de l'iPhone / iPad. Allez à Settings -> General -> Profiles -> [Your provisioning] -> Remove.

Installez les nouveaux profils d'approvisionnement téléchargés. Ensuite, nettoyez et exécutez le projet à partir de XCode. Maintenant didRegisterForRemoteNotificationsWithDeviceTokendevrait être appelé.

Borislav Gizdov
la source
Ça marche pour moi. il suffit de choisir la certification et l'approvisionnement qui avaient des APN enregistrés pour l'application.
lee
J'ai supprimé tous les profils d'approvisionnement de l'iphone (ios9), puis après la réception du jeton de périphérique, passez quatre heures pour résoudre ce problème (bien que j'apprenne beaucoup). Merci
Shobhakar Tiwari
3

J'ai fait une erreur et négligé un détail de mise en œuvre qui m'amène ici. J'ai essayé d'avoir de la fantaisie et de demander à l'utilisateur des notifications push plus tard dans le processus d'intégration de l'application, donc j'avais mon registerForRemoteNotificationTypes, didRegisterForRemoteNotificationsWithDeviceTokenet le didFailToRegisterForRemoteNotificationsWithErrortout dans un UIView personnalisé.

CORRECTIF: les didRegisterForRemoteNotificationsWithDeviceTokenet didFailToRegisterForRemoteNotificationsWithErrordoivent être dans le UIApplicationDelegate( YourAppDelegate.m) pour être déclenchés.

semble évident maintenant, heh.

GraehamF
la source
Oui, les méthodes doivent être en place AppDelegate. Je ne peux pas croire que j'ai gaspillé mes dernières heures sur cette réponse simple
Même Cheng
3

Assurez-vous que votre connexion Internet est activée. Cela m'a pris des heures pour recevoir des notifications de travail en raison de la connexion Internet.

Rendel
la source
3

Si vous avez ajouté push à un ID d'application existant, assurez-vous de régénérer vos profils d'approvisionnement. Si vous ne le faites pas, le profil ne saura pas que vous avez activé le push sur l'ID d'application.

Michael Peterson
la source
3

Essayez ça, ça marche pour moi,

Premier pas

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

Dans la méthode ci-dessus, ajoutez le code ci-dessous

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

Deuxième étape

Ajouter ci-dessous la fonction de code

 #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

Vous obtiendrez un jeton d'appareil dans la fonction ci-dessous

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

pour une réponse détaillée, veuillez consulter ceci

J'espère que c'est de l'aide pour quelqu'un.

Jaywant Khedkar
la source
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]);
}
Sachin Kumaram
la source
2

Exigence minimale pour obtenir un jeton de périphérique:

pas besoin de configurer l'ID d'application, l'approvisionnement ou le certificat, etc., donc aucun jeu de signature de code pour obtenir la méthode déléguée didRegisterForRemoteNotificationsWithDeviceToken appelée.

Je viens de créer un nouveau projet iOS dans Xcode 7 pour une vue unique avec les paramètres par défaut et j'ai donné un identifiant de bundle aléatoire comme com.mycompany.pushtest qui n'est pas configuré dans le portail de développement Apple.

Avec le code suivant, je reçois le jeton de mon appareil dans la méthode didRegisterForRemoteNotificationsWithDeviceToken sur mon iPad avec accès Internet au WIFI. Mon appareil est connecté et je lance simplement l'application directement à partir de xcode et affiche les valeurs dans la console de 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);
}
Zeeawan
la source
1

J'ai un point à ce sujet.Récemment, je suis aussi confronté à ce problème.J'ai tout fait selon la documentation mais la méthode de délégation n'appelait pas.Enfin, j'ai vu un message disant ce problème avec le réseau.Ensuite, j'ai changé de réseau et cela fonctionne bien. Faites donc attention au réseau également car peu de réseaux peuvent bloquer l'APNS.

SURESH SANKE
la source
1

Après avoir perdu les 3h les plus ennuyeuses, voici les étapes pour résoudre le problème:

  1. Supprimer l'appli

  2. Réinitialiser l'appareil

  3. Courez à nouveau

Ça a juste marché

ozd
la source
0

Cela m'est arrivé, car j'ai réinitialisé et supprimé toutes les données du téléphone (je voulais qu'un téléphone de développement utilise). Cela a empêché APN de se connecter après avoir configuré à nouveau le téléphone.

J'ai essayé toutes sortes de choses, mais la seule chose qui a résolu le problème a été de configurer le téléphone pour qu'il fonctionne avec un opérateur sous une nouvelle carte SIM.

Ce lien offre plus d'indices sur ce qui aurait pu se passer: https://developer.apple.com/library/ios/technotes/tn2265/_index.html

Il dit qu'APN essaie de se connecter de préférence via un opérateur / des tours par opposition au wifi. Peut-être que le problème était également lié au blocage du port 5223 du routeur sur le réseau wifi, mais j'en doute car cela fonctionnait bien la veille avant la réinitialisation globale.

Phyllis Sutherland
la source
0

Pour moi, ce qui a résolu cela a été d'aller dans les paramètres de construction et sous la section de signature de code, en sélectionnant manuellement l'identité de signature de code et le profil d'approvisionnement. Apparemment, le réglage automatique ne sélectionnait pas le bon et donc l'application n'était pas correctement autorisée.

Diego Rebosio
la source
0

si arrêter le message push de l'application,

appdidRegisterForRemoteNotificationsWithDeviceToken ne sera jamais appelé

libai
la source
0

N'oubliez pas non plus de vérifier l'état du système sur Apple https://developer.apple.com/system-status/ .

J'avais essayé toutes les solutions affichées ci-dessus mais à la fin la faute était que le service APNS était en panne! Le lendemain, tout fonctionnait à nouveau comme prévu.

En outre, vous avez une faute de frappe dans votre méthode de rappel:

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

Comme Rupesh l'a souligné, le nom correct de la méthode est:

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

C'est probablement pourquoi vous n'avez jamais reçu le jeton dans votre cas!

Brett
la source
En fait, le nom de la méthode est incorrect, il devrait être - (void) application: (UIApplication *) application didRegisterForRemoteNotificationsWithDeviceToken: (NSData *) deviceToken Il y a un espace entre les paramètres
Rupesh
Merci d'avoir mis à jour la réponse pour inclure votre commentaire. À peu près sûr que c'est la solution au problème des OP, mais nous ne le saurons peut-être jamais!
Brett
0

Vous devez appeler la méthode registerForNotifications à partir de 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
            }
        }
    }
}
Ved Rauniyar
la source
0

J'ai eu un problème différent dans lequel mes rappels de notification push étaient détournés par les bibliothèques tierces, que j'avais incluses, à savoir Firebase. Ces bibliothèques utilisent des méthodes de rappel de notification push pour obtenir les rappels.

J'espère que cela aide quelqu'un.

Jarora
la source