perché didRegisterForRemoteNotificationsWithDeviceToken non viene chiamato


89

Sto realizzando un'applicazione in cui voglio implementare il servizio di notifica push di Apple. Sto seguendo le istruzioni passo passo fornite in questo tutorial .

Tuttavia, i metodi non vengono chiamati. Non so cosa stia causando il problema. Qualcuno può aiutarmi?

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

non c'è bisogno di aggiungere qualsiasi altro codice basta controllare che collegano stackoverflow.com/a/39849892/3269536
JENISH

Risposte:


74

Ho avuto lo stesso problema: la chiamata registerForRemoteNotificationTypes:non è stata invocata néapplication:didRegisterForRemoteNotificationsWithDeviceToken:application:didFailToRegisterForRemoteNotificationsWithError:

Alla fine ho risolto questo problema con l'aiuto della nota tecnica di Apple TN2265 .

Questo è quello che ho fatto:

Prima di tutto, ho ricontrollato che mi sto effettivamente registrando correttamente per le notifiche push , inclusa la verifica del mio profilo di provisioning per la chiave "aps-environment" e la firma del codice del file .app stesso. Avevo impostato tutto correttamente.

Ho quindi dovuto eseguire il debug dei messaggi di stato delle notifiche push nella console (è necessario installare il profilo di provisioning PersistentConnectionLogging.mobileconfig sul dispositivo e riavviarlo. Vedere TN2265 in "Osservazione dei messaggi di stato push"). Ho notato che il processo di apns avvia un timer e calcola una data minima di attivazione, il che mi ha fatto sospettare che il messaggio di conferma della registrazione della notifica push, che normalmente viene presentato a questo punto, sia soppresso da APNS, come indicato in TN2265:

Reimpostazione dell'avviso sulle autorizzazioni per le notifiche push su iOS

La prima volta che un'app abilitata per il push si registra per le notifiche push, iOS chiede all'utente se desidera ricevere notifiche per quell'app. Una volta che l'utente ha risposto a questo avviso, questo non viene presentato di nuovo a meno che il dispositivo non venga ripristinato o l'app non sia stata disinstallata da almeno un giorno.

Se desideri simulare la prima esecuzione della tua app, puoi lasciare l'app disinstallata per un giorno. È possibile ottenere quest'ultimo senza attendere effettivamente un giorno impostando l'orologio di sistema in avanti di un giorno o più, spegnendo completamente il dispositivo, quindi riaccendendolo.

Quindi, ho rimosso l'app dal dispositivo, quindi ho modificato manualmente la data dell'iPhone in Impostazioni, riavviato il dispositivo e reinstallato l'app.

La prossima volta che il mio codice ha chiamato registerForRemoteNotificationTypes, ha ricevuto le richiamate come previsto.

Questo ha risolto il problema per me. Spero che sia d'aiuto.


1
Il punto chiave per me era che stavo usando un vecchio certificato di sviluppo su un'altra macchina. Il trasferimento del certificato più recente dal laptop di sviluppo principale ha risolto questo problema.
Markus Rautopuro

3
Dopo aver abilitato le notifiche Push è necessario generare nuovamente i profili di provisioning.
Tony

3
Ciao! sebbene questo sia un vecchio post, ho scoperto che a volte verrà risolto quando spegni e accendi tutte le impostazioni di notifica dell'app. Perché l'ultima volta che ricordo è stato chiamato didRegisterForRemoteNotificationsWithDeviceToken, poi improvvisamente non lo era. Spero che sia d'aiuto.
otakuProgrammer

1
L'ho fatto funzionare solo aggiungendo un altro passaggio di ripristino: 1. Elimina app 2. Ripristina dispositivo 3. Inoltra orologio 1+ giorni 4. Ripristina di nuovo il dispositivo 5. Ora installa e dovrebbe richiedere l'avviso di notifica push
etayluz

È anche importante assicurarsi di non disporre di più copie "valide" dello stesso profilo di provisioning di sviluppo, né in Xcode né sul dispositivo stesso. Forse hai creato un nuovo certificato APN e ricreato il tuo profilo di provisioning dopo la scadenza del certificato precedente. Il vecchio profilo di sviluppo è ancora valido come profilo di sviluppo, ma non sarà sufficiente per abilitare gli APN. Vedrai un tipico errore di "no aps-entitlement blah blah valido".
jaredsinclair

66

In iOS 8, alcuni metodi sono deprecati. Segui i passaggi seguenti per la compatibilità con iOS 8

1. Notifica del registro

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. Aggiungere nuovi 2 metodi

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

Nota: in iOS 8 sono richiesti due nuovi metodi sopra oltre a didRegisterForRemoteNotificationsWithDeviceTokenedidReceiveRemoteNotification metodo delegato ..Otherwise non viene invocato.

Vedi: Notifica remota iOS 8


1
Questi due nuovi metodi dovrebbero essere inseriti in Appdelegate.m?
Ethan Parker

- (void) application: (UIApplication *) application didRegisterUserNotificationSettings: (UIUserNotificationSettings *) notificationSettings {// registrati per ricevere notifiche [application registerForRemoteNotifications]; } L'aggiunta di quanto segue è pericoloso, il mio telefono si è bloccato e non riesco nemmeno a ripristinarlo in fabbrica a questo punto.
John

Questa è probabilmente la risposta che stai cercando se finisci qui. Stranamente, oggi il delegato è stato chiamato prima senza che io aggiungessi uno di questi metodi. Ora sembra che mi servano entrambi.
Will

la mia app si arresta in modo [application registerForRemoteNotifications];
anomalo

26

In iOS 8 , oltre a richiedere l'accesso alle notifiche push in modo diverso, è anche necessario registrarsi in modo diverso.

Richiesta di accesso:

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

Gestire il dispositivo registrato:

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

Estremamente utile. Non sono riuscito a capire perché le mie notifiche si sono interrotte.
GoldenJoe

4
Come posso ottenere il token in iOS 8?
Yossi

@Yossi è memorizzato nella variabile "token" inapplication:didRegisterForRemoteNotificationsWithDeviceToken:
Kyle Clegg

la mia app si arresta in modo anomalo con questa riga [application registerForRemoteNotifications];
fucina

13

Tieni presente che le notifiche remote non sono supportate nel simulatore. Pertanto, se esegui la tua app nel simulatore, didRegisterForRemoteNotificationsWithDeviceTokennon verrà chiamata.


@hochl: ho aggiornato la mia risposta in modo che risponda in modo più specifico alla domanda.
Eric,

1
Nota che didFailToRegisterForRemoteNotificationsWithError non verrà nemmeno chiamato. In effetti, nessuna notifica viene chiamata se disabiliti le notifiche push per la tua app in Impostazioni (sia sul dispositivo che sul simulatore). Apple non sembra considerare questo come un errore stackoverflow.com/questions/9199935/…
Zack Morris,

12

Assicurati di chiamare il codice (aggiorna in base ai tipi di notifica supportati)

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

e il profilo di provisioning è abilitato per APNS. Potrebbe essere necessario scaricare nuovamente il profilo di provisioning dopo aver abilitato APNS. Se hai problemi e ricevi errori, forse dovresti creare un Entitlements.plist e aggiungere la chiave "aps-environment" con valore "development" o "production" a seconda del tipo di build (normalmente questa coppia chiave-valore è contenuti nel profilo di provisioning, ma a volte Xcode si confonde con loro).


Nota: "e il profilo di provisioning è abilitato per APNS". Fare clic sulla parte superiore della struttura ad albero del progetto> Funzionalità> Notifiche push dovrebbe essere impostato su ON.
trevorgrayson

6

Se i profili di provisioning vengono utilizzati prima per abilitare e configurare il servizio di notifiche push di Apple, sarà necessario scaricare nuovamente i profili di provisioning.

Elimina i profili di provisioning da Xcode Organizer e da iPhone / iPad. Vai a Settings -> General -> Profiles -> [Your provisioning] -> Remove.

Installa i nuovi profili di provisioning scaricati. Quindi pulire ed eseguire il progetto da XCode. Ora didRegisterForRemoteNotificationsWithDeviceTokendovrebbe essere chiamato.


Per me funziona. ha semplicemente scelto la certificazione e il provisioning che avevano registrato gli APN per l'app.
lee

Ho cancellato tutto il profilo di provisioning da iphone (ios9) e poi, dopo che il token del dispositivo ha ricevuto, ho impiegato quattro ore per risolvere il problema (anche se ho imparato molto). Grazie
Shobhakar Tiwari

3

Ho commesso un errore e ho trascurato un dettaglio di implementazione che mi ha portato qui. Ho provato a essere fantasioso e ho chiesto all'utente di ricevere notifiche push in un secondo momento nel processo di onboarding dell'applicazione, quindi ho avuto il mio registerForRemoteNotificationTypes, didRegisterForRemoteNotificationsWithDeviceTokene didFailToRegisterForRemoteNotificationsWithErrortutto in una UIView personalizzata.

FIX: il didRegisterForRemoteNotificationsWithDeviceTokene didFailToRegisterForRemoteNotificationsWithErrordeve essere in UIApplicationDelegate( YourAppDelegate.m) per essere attivato.

sembra ovvio ora, eh.


Sì, i metodi devono essere inseriti AppDelegate. Non posso credere di aver sprecato le mie ultime ore con questa semplice risposta
Anche Cheng il

3

Assicurati che la tua connessione Internet sia attiva. Mi ci sono volute ore per ricevere notifiche di lavoro a causa della connessione a Internet.


3

Se hai aggiunto il push a un ID app esistente, assicurati di rigenerare i tuoi profili di provisioning. Se non lo fai, il profilo non saprà della tua abilitazione del push sull'App ID.


3

Prova questo funziona per me,

Primo passo

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

Nel metodo sopra aggiungi il codice sottostante

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

Secondo passo

Aggiungi sotto il codice Funzione

 #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

Otterrai il token del dispositivo nella funzione sottostante

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

per una risposta dettagliata, fare riferimento a questo

Spero che questo sia aiuto per qualcuno.


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

Requisito minimo per ottenere il token del dispositivo:

non è necessario configurare l'ID dell'app, il provisioning o il certificato, ecc., Quindi nessuna firma del codice impostata per ottenere il metodo delegato didRegisterForRemoteNotificationsWithDeviceToken chiamato.

Ho appena creato un nuovo progetto iOS in Xcode 7 per visualizzazione singola con impostazioni predefinite e ho fornito un ID bundle casuale come com.mycompany.pushtest che non è configurato nel portale di sviluppo Apple.

Con il codice seguente, ottengo il token del mio dispositivo nel metodo didRegisterForRemoteNotificationsWithDeviceToken sul mio iPad con accesso Internet al WIFI. Il mio dispositivo è collegato e sto solo eseguendo l'app direttamente da xcode e visualizzando i valori nella console di 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

Ho un punto su questo.Recentemente anch'io devo affrontare questo problema.Ho fatto tutto secondo la documentazione ma il metodo delegato non chiamava.Finalmente ho visto un post che diceva quel problema con la rete.Quindi ho cambiato rete e funziona bene. Quindi attenzione alla rete anche perché poche reti possono bloccare l'APNS.


1

Dopo aver sprecato le 3 ore più fastidiose, ecco i passaggi per risolvere il problema:

  1. Elimina l'app

  2. Resetta il dispositivo

  3. Esegui di nuovo

Ha funzionato e basta


0

Questo è successo a me, perché ho ripristinato e cancellato tutti i dati sul telefono (volevo un telefono sviluppatore da utilizzare). Ciò ha impedito all'APN di connettersi dopo aver configurato nuovamente il telefono.

Ho provato di tutto, ma l'unica cosa che ha risolto il problema è stato impostare il telefono in modo che funzionasse con un operatore con una nuova scheda SIM.

Questo collegamento offre ulteriori suggerimenti su cosa potrebbe essere successo: https://developer.apple.com/library/ios/technotes/tn2265/_index.html

Dice che APN cerca di connettersi preferenzialmente tramite carrier / tower anziché wifi. Forse il problema era anche qualcosa che stava succedendo con il router che bloccava la porta 5223 sulla rete wifi, ma ne dubito perché funzionava bene il giorno precedente prima che si verificasse il ripristino globale.


0

Per me ciò che ha risolto è stato andare nelle impostazioni di build e nella sezione della firma del codice, selezionando manualmente l'identità della firma del codice e il profilo di provisioning. Apparentemente l'impostazione automatica non stava riprendendo quella corretta e quindi l'app non era correttamente autorizzata.


0

se chiudi il messaggio push dell'app,

appdidRegisterForRemoteNotificationsWithDeviceToken non verrà mai chiamato


0

Inoltre, non dimenticare di controllare lo stato del sistema su Apple https://developer.apple.com/system-status/ .

Avevo provato tutte le soluzioni pubblicate sopra ma alla fine la colpa era perché il servizio APNS era inattivo! Il giorno successivo tutto funzionava di nuovo come previsto.

Inoltre, hai un errore di battitura nel tuo metodo di callback:

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

Come ha sottolineato Rupesh, il nome corretto del metodo è:

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

Probabilmente è per questo che non hai mai ricevuto il token nel tuo caso!


In realtà il nome del metodo non è corretto, dovrebbe essere - (void) application: (UIApplication *) application didRegisterForRemoteNotificationsWithDeviceToken: (NSData *) deviceToken C'è uno spazio tra i parametri
Rupesh

Grazie, ho aggiornato la risposta per includere il tuo commento. Abbastanza sicuro che questa sia la soluzione al problema degli OP, ma potremmo non scoprirlo mai!
Brett

0

È necessario chiamare il metodo registerForNotifications da 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

Ho avuto un problema diverso in cui i callback delle mie notifiche push venivano dirottati dalle librerie di terze parti, che avevo incluso, ovvero Firebase. Queste librerie cambiano i metodi di callback delle notifiche push per ottenere i callback.

Spero che questo aiuti qualcuno.

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.