por qué no se llama didRegisterForRemoteNotificationsWithDeviceToken

89

Estoy creando una aplicación en la que quiero implementar el servicio de notificaciones push de Apple. Estoy siguiendo las instrucciones paso a paso que se dan en este tutorial .

Pero aún así, los métodos no se llaman. No sé qué está causando el problema. ¿Alguien puede ayudarme?

    - (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
fuente
no hay necesidad de agregar ningún otro código, solo
verifíquelo

Respuestas:

74

Tuve el mismo problema: la llamada registerForRemoteNotificationTypes:no se invocó application:didRegisterForRemoteNotificationsWithDeviceToken:niapplication:didFailToRegisterForRemoteNotificationsWithError:

Finalmente resolví este problema con la ayuda de la nota técnica TN2265 de Apple .

Esto es lo que hice:

En primer lugar, verifiqué dos veces que de hecho me estoy registrando correctamente para las notificaciones push , incluida la verificación de mi perfil de aprovisionamiento para la clave "aps-environment" y la firma de código del archivo .app en sí. Lo tenía todo configurado correctamente.

Luego tuve que depurar los mensajes de estado de notificaciones push en la consola (necesita instalar el perfil de aprovisionamiento PersistentConnectionLogging.mobileconfig en su dispositivo y reiniciarlo. Consulte TN2265 en "Observación de mensajes de estado push"). Noté que el proceso apns inicia un temporizador y calcula una fecha de disparo mínima, lo que me hizo sospechar que el mensaje de confirmación de registro de notificación push, que normalmente se presenta en este punto, está suprimido por APNS, como se indica en TN2265:

Restablecimiento de la alerta de permisos de notificaciones push en iOS

La primera vez que una aplicación habilitada para push se registra para recibir notificaciones push, iOS le pregunta al usuario si desea recibir notificaciones para esa aplicación. Una vez que el usuario ha respondido a esta alerta, no se vuelve a presentar a menos que el dispositivo se restaure o la aplicación se haya desinstalado durante al menos un día.

Si desea simular una primera ejecución de su aplicación, puede dejar la aplicación desinstalada durante un día. Puede lograr lo último sin esperar un día realmente adelantando el reloj del sistema un día o más, apagando el dispositivo por completo y luego volviendo a encenderlo.

Entonces, eliminé la aplicación del dispositivo, luego cambié manualmente la fecha del iPhone en Configuración, reinicié el dispositivo y reinstalé la aplicación.

La próxima vez que mi código llamó registerForRemoteNotificationTypes, recibió devoluciones de llamada como se esperaba.

Esto me resolvió el problema. Espero eso ayude.

100 gramos
fuente
1
El punto clave para mí fue que estaba usando un certificado de desarrollo anterior en otra máquina. La transferencia del certificado más reciente desde la computadora portátil de desarrollo principal solucionó este problema.
Markus Rautopuro
3
Después de habilitar las notificaciones Push es necesario generar nuevamente los perfiles de aprovisionamiento.
Tony
3
¡Hola! Aunque esta es una publicación antigua, descubrí que a veces se solucionará cuando apagues y enciendas todas las configuraciones de notificación de la aplicación. Porque la última vez que recuerdo se llamó a didRegisterForRemoteNotificationsWithDeviceToken y de repente no lo fue. Espero eso ayude.
otakuProgrammer
1
Solo logré que esto funcione agregando otro paso de restablecimiento: 1. Eliminar aplicación 2. Restablecer dispositivo 3. Reenviar el reloj 1+ días 4. Restablecer dispositivo OTRA VEZ 5. Ahora instálelo y debería
mostrar la
También es importante asegurarse de no tener varias copias "válidas" del mismo perfil de aprovisionamiento de desarrollo, ya sea en Xcode o en el propio dispositivo. Quizás creó un nuevo certificado APN y volvió a crear su perfil de aprovisionamiento después de que expiró el certificado anterior. El antiguo perfil de desarrollo sigue siendo válido como perfil de desarrollo, pero no será suficiente para habilitar APN. Verá un error típico sobre "ningún derecho aps válido bla, bla".
jaredsinclair
66

En iOS 8, algunos métodos están en desuso. Siga los pasos a continuación para la compatibilidad con iOS 8

1. Registrar notificación

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. Agregue 2 métodos nuevos

- (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: se requieren dos métodos nuevos en iOS 8 además de didRegisterForRemoteNotificationsWithDeviceTokeny didReceiveRemoteNotification.. De lo contrario, no se invocará el método delegado.

Ver: Notificación remota iOS 8

Comunidad
fuente
1
¿Deberían ir esos dos nuevos métodos en Appdelegate.m?
Ethan Parker
- (nula) aplicación: (UIApplication *) aplicación didRegisterUserNotificationSettings: (UIUserNotificationSettings *) notificationSettings {// registrarse para recibir notificaciones [aplicación registerForRemoteNotifications]; } Agregar lo siguiente es peligroso, se bloqueó mi teléfono y no puedo ni siquiera restablecerlo de fábrica en este momento.
John
Esta es probablemente la respuesta que está buscando si termina aquí. Curiosamente, hoy se llamó al delegado sin que yo agregara uno de estos métodos. Ahora parece que los necesito a ambos.
Será
mi aplicación se bloquea con esta línea[application registerForRemoteNotifications];
smithyy
26

En iOS 8 , además de solicitar el acceso a las notificaciones push de manera diferente, también debe registrarse de manera diferente.

Solicitar acceso:

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

Manejar dispositivo registrado:

// 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
fuente
Extramadamente útil. No pude entender por qué fallaron mis notificaciones.
GoldenJoe
4
¿Cómo puedo obtener el token en iOS 8?
Yossi
@Yossi se almacena en la variable "token" enapplication:didRegisterForRemoteNotificationsWithDeviceToken:
Kyle Clegg
mi aplicación se bloquea con esta línea [aplicación registerForRemoteNotifications];
smithyy
13

Tenga en cuenta que las notificaciones remotas no son compatibles con el simulador. Por lo tanto, si ejecuta su aplicación en el simulador, didRegisterForRemoteNotificationsWithDeviceTokenno se llamará.

Eric
fuente
@hochl: Actualicé mi respuesta para que responda más específicamente a la pregunta.
Eric
1
Tenga en cuenta que tampoco se llamará a didFailToRegisterForRemoteNotificationsWithError. De hecho, no se llama a ninguna notificación si desactiva las notificaciones automáticas para su aplicación en Configuración (ya sea en el dispositivo o en el simulador). Apple no parece considerar esto como un error stackoverflow.com/questions/9199935/…
Zack Morris
12

Asegúrese de llamar en su código (actualice de acuerdo con los tipos de notificación admitidos)

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

y el perfil de aprovisionamiento está habilitado para APNS. Es posible que deba volver a descargar el perfil de aprovisionamiento después de habilitar APNS. Si tiene problemas y obtiene errores, entonces tal vez debería crear un Entitlements.plist y agregar la clave "aps-environment" con el valor "desarrollo" o "producción" según el tipo de compilación (normalmente este par clave-valor es contenidos en el perfil de aprovisionamiento, pero a veces Xcode se mete con ellos).

Lorenzo Bevilacqua
fuente
Nota: "y el perfil de aprovisionamiento está habilitado para APNS". Haga clic en la parte superior del árbol del proyecto> Capacidades> Las notificaciones automáticas deben estar activadas.
trevorgrayson
6

Si los perfiles de aprovisionamiento se utilizan antes para habilitar y configurar el servicio de notificaciones push de Apple, deberá volver a descargar los perfiles de aprovisionamiento.

Elimine los perfiles de aprovisionamiento de Xcode Organizer y del iPhone / iPad. IrSettings -> General -> Profiles -> [Your provisioning] -> Remove .

Instale los nuevos perfiles de aprovisionamiento descargados. Luego limpie y ejecute el proyecto desde XCode. Ahora didRegisterForRemoteNotificationsWithDeviceTokendebería llamarse.

Borislav Gizdov
fuente
Funciona para mi. simplemente eligió la certificación y el aprovisionamiento que tenían APN registrados para la aplicación.
lee
Eliminé todo el perfil de aprovisionamiento de iphone (ios9) y luego, después de que se reciba el Token del dispositivo. Dedique cuatro horas a solucionarlo (aunque aprendo mucho). Gracias
Shobhakar Tiwari
3

Cometí un error y pasé por alto un detalle de implementación que me llevó aquí. Traté de ponerme elegante y pedirle al usuario notificaciones automáticas más adelante en el proceso de incorporación de la aplicación, así que tenía mi registerForRemoteNotificationTypes, didRegisterForRemoteNotificationsWithDeviceTokeny didFailToRegisterForRemoteNotificationsWithErrortodo en una UIView personalizada.

FIX: el didRegisterForRemoteNotificationsWithDeviceTokeny didFailToRegisterForRemoteNotificationsWithErrordebe estar en el UIApplicationDelegate( YourAppDelegate.m) para ser activado.

parece obvio ahora, je.

GraehamF
fuente
Sí, los métodos deben estar incluidos AppDelegate. No puedo creer que desperdicié mis últimas horas con esta simple respuesta
incluso Cheng
3

Asegúrese de que su conexión a Internet esté encendida. Me tomó horas recibir notificaciones de trabajo debido a la conexión a Internet.

Rendel
fuente
3

Si ha agregado push a un ID de aplicación existente, asegúrese de volver a generar sus perfiles de aprovisionamiento. Si no lo hace, el perfil no sabrá sobre su habilitación de inserción en el ID de la aplicación.

Michael Peterson
fuente
3

Prueba esto, funciona para mí

Primer paso

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

En el método anterior, agregue el código siguiente

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

Segundo paso

Agregue la función de código siguiente

 #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

Obtendrá el token del dispositivo en la siguiente función

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

para obtener una respuesta detallada, consulte este

Espero que esto sea de ayuda para alguien.

Jaywant Khedkar
fuente
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
fuente
2

Requisito mínimo para obtener el token del dispositivo:

no es necesario configurar la identificación de la aplicación, el aprovisionamiento o el certificado, etc., por lo que no se establece la firma de código para obtener el método de delegado didRegisterForRemoteNotificationsWithDeviceToken llamado.

Acabo de crear un nuevo proyecto de iOS en Xcode 7 para vista única con la configuración predeterminada y le di un ID de paquete aleatorio como com.mycompany.pushtest que no está configurado en el portal de desarrollo de Apple.

Con el siguiente código, obtengo el token de mi dispositivo en el método didRegisterForRemoteNotificationsWithDeviceToken en mi iPad con acceso a Internet a WIFI. Mi dispositivo está conectado y solo estoy ejecutando la aplicación directamente desde xcode y viendo los valores en la consola 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
fuente
1

Tengo un punto en esto Recientemente yo también enfrenté este problema. He hecho todo de acuerdo con la documentación, pero el método delegado no llamaba. Finalmente vi una publicación que decía ese problema con la red. Luego cambié la red y funciona bien. Así que tenga cuidado con la red también porque pocas redes pueden bloquear el APNS.

SURESH SANKE
fuente
1

Después de perder las 3 horas más molestas, estos son los pasos para solucionar el problema:

  1. Eliminar la aplicación

  2. Restablecer el dispositivo

  3. Corre de nuevo

Simplemente funcionó

ozd
fuente
0

Esto me pasó a mí, porque restablecí y borré todos los datos del teléfono (quería usar un teléfono de desarrollo). Esto impidió que APN se conectara después de configurar el teléfono nuevamente.

Probé todo tipo de cosas, pero lo único que lo solucionó fue configurar el teléfono para que funcione con un operador con una nueva tarjeta SIM.

Este enlace ofrece más pistas sobre lo que podría haber estado sucediendo: https://developer.apple.com/library/ios/technotes/tn2265/_index.html

Dice que APN intenta conectarse preferentemente a través de operadores / torres en lugar de wifi. Quizás el problema también era que algo estaba pasando con el enrutador bloqueando el puerto 5223 en la red wifi, pero lo dudo porque funcionó bien el día anterior antes de que ocurriera el reinicio global.

Phyllis Sutherland
fuente
0

Para mí, lo que resolvió fue ir a la configuración de compilación y, en la sección de firma de código, seleccionar manualmente la identidad de firma de código y el perfil de aprovisionamiento. Aparentemente, la configuración automática no estaba recogiendo la correcta y, por lo tanto, la aplicación no estaba debidamente autorizada.

Diego Rebosio
fuente
0

si cierra el mensaje push de la aplicación,

appdidRegisterForRemoteNotificationsWithDeviceToken nunca se llamará

libai
fuente
0

Además, no olvide verificar el estado del sistema en Apple https://developer.apple.com/system-status/ .

Probé todas las soluciones publicadas anteriormente, pero al final la falla se debió a que el servicio APNS no funcionaba. Al día siguiente todo volvió a funcionar como se esperaba.

Además, tiene un error tipográfico en su método de devolución de llamada:

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

Como Rupesh señaló, el nombre correcto del método es:

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

¡Probablemente por eso nunca recibió el token en su caso!

Brett
fuente
En realidad, el nombre del método es incorrecto, debería ser - (nulo) aplicación: (UIApplication *) aplicación didRegisterForRemoteNotificationsWithDeviceToken: (NSData *) deviceToken Hay un espacio entre los parámetros
Rupesh
Gracias, hemos actualizado la respuesta para incluir tu comentario. Estoy bastante seguro de que esta es la solución al problema de los OP, ¡pero es posible que nunca lo descubramos!
Brett
0

Debe llamar al método registerForNotifications desde 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
fuente
0

Tuve un problema diferente en el que mis devoluciones de llamada de notificación push estaban siendo secuestradas por bibliotecas de terceros, que había incluido, a saber, Firebase. Estas bibliotecas combinan métodos de devolución de llamada de notificación push para obtener las devoluciones de llamada.

Espero que esto ayude a alguien.

jarora
fuente