porque didRegisterForRemoteNotificationsWithDeviceToken não é chamado

89

Estou fazendo um aplicativo em que desejo implementar o serviço de notificação por push da apple. Estou seguindo as instruções passo a passo fornecidas neste tutorial .

Mesmo assim, os métodos não são chamados. Não sei o que está causando o problema. Alguém pode me ajudar?

    - (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
fonte
não há necessidade de adicionar nenhum outro código, basta verificar no link stackoverflow.com/a/39849892/3269536
jenish

Respostas:

74

Eu tive o mesmo problema: chamar registerForRemoteNotificationTypes:não invocado application:didRegisterForRemoteNotificationsWithDeviceToken:nemapplication:didFailToRegisterForRemoteNotificationsWithError:

Acabei resolvendo esse problema com a ajuda da nota técnica TN2265 da Apple .

Isso é o que eu fiz:

Em primeiro lugar, verifiquei duas vezes se estou realmente me registrando corretamente para notificações push , incluindo a verificação do meu perfil de provisionamento para a chave "aps-environment" e a assinatura de código do próprio arquivo .app. Eu tinha tudo configurado corretamente.

Em seguida, tive que depurar as mensagens de status de notificação por push no console (você precisa instalar o perfil de provisionamento PersistentConnectionLogging.mobileconfig em seu dispositivo e reiniciá-lo. Consulte TN2265 em "Observando mensagens de status por push"). Percebi que o processo apns inicia um cronômetro e calcula uma data mínima de disparo, o que me fez suspeitar que a mensagem de confirmação de registro do Push-Notification, que normalmente é apresentada neste ponto, foi suprimida pelo APNS, conforme indicado em TN2265:

Redefinindo o alerta de permissões de notificações push no iOS

Na primeira vez que um aplicativo habilitado para push se registra para notificações push, o iOS pergunta ao usuário se deseja receber notificações para esse aplicativo. Depois que o usuário responde a este alerta, ele não é apresentado novamente, a menos que o dispositivo seja restaurado ou o aplicativo tenha sido desinstalado por pelo menos um dia.

Se você deseja simular a primeira execução de seu aplicativo, pode deixá-lo desinstalado por um dia. Você pode conseguir o último sem realmente esperar um dia, ajustando o relógio do sistema um dia ou mais, desligando o dispositivo completamente e, em seguida, ligando-o novamente.

Então, removi o aplicativo do dispositivo, alterei manualmente a data do iPhone em Ajustes, reiniciei o dispositivo e reinstalei o aplicativo.

Na próxima vez que meu código foi chamado registerForRemoteNotificationTypes, ele recebeu retornos de chamada conforme o esperado.

Isso resolveu o problema para mim. Espero que ajude.

100 gramas
fonte
1
O ponto principal para mim era que eu estava usando um certificado de desenvolvimento mais antigo em outra máquina. Transferir o certificado mais recente do laptop de desenvolvimento principal corrigiu esse problema.
Markus Rautopuro
3
Após habilitar as notificações push é necessário gerar novamente os perfis de provisionamento.
Tony
3
Oi! embora esta seja uma postagem antiga, descobri que às vezes ela será corrigida quando você desligar e ligar todas as configurações de notificação do aplicativo. Porque da última vez que me lembro, didRegisterForRemoteNotificationsWithDeviceToken foi chamado e, de repente, não foi. Espero que ajude.
otakuProgrammer
1
Só fiz isso funcionar adicionando outra etapa de redefinição: 1. Excluir aplicativo 2. Redefinir dispositivo 3. Avançar relógio 1+ dias 4. Redefinir dispositivo NOVAMENTE 5. Agora instale e ele deve
exibir o
Também é importante certificar-se de que você não tenha várias cópias "válidas" do mesmo perfil de provisionamento de desenvolvimento, seja no Xcode ou no próprio dispositivo. Talvez você tenha criado um novo certificado APN e recriado seu perfil de provisionamento depois que o certificado anterior expirou. O perfil de desenvolvimento antigo ainda é válido como um perfil de desenvolvimento, mas não será suficiente para habilitar APNs. Você verá um erro típico sobre "nenhum aps-entitlement válido, blá, blá".
jaredsinclair
66

No iOS 8, alguns métodos estão obsoletos. Siga as etapas abaixo para compatibilidade com iOS 8

1. Registrar notificação

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. Adicione novos 2 métodos

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

Observação: dois novos métodos acima são necessários no iOS 8, além de didRegisterForRemoteNotificationsWithDeviceTokene didReceiveRemoteNotification.. Caso contrário, o método delegado não será invocado.

Veja: Notificação Remota iOS 8

Comunidade
fonte
1
Esses dois novos métodos devem ir para Appdelegate.m?
Ethan Parker
- (void) application: (UIApplication *) application didRegisterUserNotificationSettings: (UIUserNotificationSettings *) notificationSettings {// registrar para receber notificações [application registerForRemoteNotifications]; } Adicionar o seguinte é perigoso, pois meu telefone travou e não consigo nem mesmo redefini-lo de fábrica neste momento.
João,
Esta é provavelmente a resposta que você está procurando se acabar aqui. Estranhamente, o delegado foi chamado hoje cedo sem que eu adicionasse um desses métodos. Agora parece que preciso dos dois.
Será
meu aplicativo trava com esta linha[application registerForRemoteNotifications];
smithyy
26

No iOS 8 , além de solicitar acesso à notificação push de forma diferente, você também precisa se registrar de forma diferente.

Solicitar acesso:

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

Manipular 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
fonte
Extremamente útil. Não consegui descobrir por que minhas notificações falharam.
GoldenJoe,
4
Como posso obter o token no iOS 8?
Yossi de
@Yossi está armazenado na variável "token" emapplication:didRegisterForRemoteNotificationsWithDeviceToken:
Kyle Clegg
meu aplicativo trava com esta linha [application registerForRemoteNotifications];
smithyy
13

Lembre-se de que notificações remotas não são suportadas no simulador. Portanto, se você executar seu aplicativo no simulador, didRegisterForRemoteNotificationsWithDeviceTokennão será chamado.

Eric
fonte
@hochl: Eu atualizei minha resposta para que ela responda mais especificamente à pergunta.
Eric
1
Observe que didFailToRegisterForRemoteNotificationsWithError também não será chamado. Na verdade, nenhuma notificação é chamada se você desabilitar notificações push para seu aplicativo em Configurações (seja no dispositivo ou no simulador). A Apple não parece considerar isso um erro stackoverflow.com/questions/9199935/…
Zack Morris
12

Certifique-se de chamar seu código (atualize de acordo com os tipos de notificação suportados)

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

e o perfil de provisionamento está habilitado para APNS. Pode ser necessário baixar novamente o perfil de provisionamento após habilitar o APNS. Se você tiver problemas e receber erros, então talvez você deva criar um Entitlements.plist e adicionar a chave "aps-environment" com o valor "development" ou "production" dependendo do tipo de construção (normalmente este par de chave-valor é contido no perfil de provisionamento, mas às vezes o Xcode bagunça com eles).

Lorenzo Bevilacqua
fonte
Nota: "e o perfil de provisionamento está habilitado para APNS." Clique na parte superior da sua Árvore do projeto> Recursos> Notificações push devem ser definidas como ATIVADAS.
trevorgrayson
6

Se os perfis de provisionamento forem usados ​​antes para habilitar e configurar o serviço Apple Push Notification, você precisará baixar novamente os perfis de provisionamento.

Exclua perfis de provisionamento do Xcode Organizer e do iPhone / iPad. Vá para Settings -> General -> Profiles -> [Your provisioning] -> Remove.

Instale os novos perfis de provisionamento baixados. Em seguida, limpe e execute o projeto a partir do XCode. Agora didRegisterForRemoteNotificationsWithDeviceTokendeve ser chamado.

Borislav Gizdov
fonte
Funciona para mim. apenas escolheu a certificação e o provisionamento que tinha APNs registrados para o aplicativo.
Lee
Excluí todos os perfis de provisionamento do iphone (ios9) e, depois que o token do dispositivo está recebendo. Gaste quatro horas para consertar isso (embora eu aprenda muito). Obrigado
Shobhakar Tiwari
3

Cometi um erro e esqueci um detalhe de implementação que me trouxe até aqui. Tentei começar a fantasia e pedir ao usuário para Push Notifications mais tarde no processo de integração de aplicativos, então eu tive a minha registerForRemoteNotificationTypes, didRegisterForRemoteNotificationsWithDeviceTokene didFailToRegisterForRemoteNotificationsWithErrortudo em um UIView personalizado.

CORREÇÃO: o didRegisterForRemoteNotificationsWithDeviceTokene didFailToRegisterForRemoteNotificationsWithErrorprecisa estar no UIApplicationDelegate( YourAppDelegate.m) para ser disparado.

parece óbvio agora, heh.

GraehamF
fonte
Sim, os métodos precisam estar incluídos AppDelegate. Não posso acreditar que perdi minhas últimas horas com esta resposta simples
Even Cheng
3

Certifique-se de que sua conexão com a Internet esteja ligada. Levei horas para receber notificações de trabalho por causa da conexão com a Internet.

Rendel
fonte
3

Se você adicionou push a um ID de aplicativo existente, certifique-se de gerar novamente seus perfis de provisionamento. Se você não fizer isso, o perfil não saberá sobre sua habilitação de push no ID do aplicativo.

Michael Peterson
fonte
3

Experimente trabalhar para mim,

Primeiro passo

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

No método acima, adicione o código abaixo

 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 passo

Adicionar função de código abaixo

 #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

Você receberá o token do dispositivo na função abaixo

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

para obter uma resposta detalhada, consulte Este

Espero que isso ajude alguém.

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

Requisito mínimo para obter o token do dispositivo:

Não há necessidade de configurar o id do aplicativo, provisionamento ou certificado etc., portanto, nenhuma assinatura de código definida para obter o método delegado didRegisterForRemoteNotificationsWithDeviceToken chamado.

Acabei de criar um novo projeto iOS no Xcode 7 para visualização única com configurações padrão e dei um id de pacote aleatório como com.mycompany.pushtest que não está configurado no portal de desenvolvimento da apple.

Com o código a seguir, estou obtendo meu token de dispositivo no método didRegisterForRemoteNotificationsWithDeviceToken em meu iPad com acesso à Internet para WIFI. Meu dispositivo está conectado e estou apenas executando o aplicativo diretamente do xcode e visualizando os valores no console do 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
fonte
1

Eu tenho um ponto sobre isso.Recentemente eu também enfrento esse problema.Fiz tudo de acordo com a documentação, mas o método delegado não estava chamando.Finalmente vi um post dizendo esse problema com a rede. Então eu mudei de rede e funciona bem. Portanto, tome cuidado com a rede também porque poucas redes podem bloquear o APNS.

SURESH SANKE
fonte
1

Depois de desperdiçar as 3h mais irritantes, aqui estão as etapas para corrigir o problema:

  1. Exclua o aplicativo

  2. Reinicie o dispositivo

  3. Corra novamente

Simplesmente funcionou

ozd
fonte
0

Isso aconteceu comigo, porque eu reiniciei e apaguei todos os dados do telefone (queria um telefone de desenvolvimento para usar). Isso impediu o APN de se conectar depois de configurar o telefone novamente.

Tentei todos os tipos de coisas, mas a única coisa que consertou foi configurar o telefone para funcionar com uma operadora com um novo cartão SIM.

Este link oferece mais dicas sobre o que pode estar acontecendo: https://developer.apple.com/library/ios/technotes/tn2265/_index.html

Ele diz que o APN tenta se conectar preferencialmente via operadora / torres ao invés de wi-fi. Talvez o problema também estivesse acontecendo com o roteador bloqueando a porta 5223 na rede wi-fi, mas eu duvido porque funcionou bem no dia anterior, antes da redefinição global ocorrer.

Phyllis Sutherland
fonte
0

Para mim, o que resolveu foi ir para as configurações de compilação e na seção de assinatura de código, selecionando manualmente a identidade de assinatura de código e o perfil de provisionamento. Aparentemente, a configuração automática não selecionava a correta e, portanto, o aplicativo não estava devidamente autorizado.

Diego Rebosio
fonte
0

se desligar a mensagem push do aplicativo,

appdidRegisterForRemoteNotificationsWithDeviceToken nunca será chamado

libai
fonte
0

Além disso, não se esqueça de verificar o status do sistema em Apple https://developer.apple.com/system-status/ .

Eu tentei todas as soluções postadas acima, mas no final a falha foi porque o serviço APNS estava fora do ar! No dia seguinte, tudo estava funcionando como esperado.

Além disso, você tem um erro de digitação em seu método de retorno de chamada:

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

Como Rupesh apontou, o nome do método correto é:

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

Provavelmente é por isso que você nunca recebeu o token em seu caso!

Brett
fonte
Na verdade, o nome do método está incorreto, deveria ser - (vazio) aplicativo: (UIApplication *) aplicativo didRegisterForRemoteNotificationsWithDeviceToken: (NSData *) deviceToken Há um espaço entre os parâmetros
Rupesh
Obrigado, atualizei a resposta para incluir seu comentário. Certeza que esta é a solução para o problema dos OPs, mas talvez nunca descubramos!
Brett de
0

Você precisa chamar o método registerForNotifications 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
fonte
0

Tive um problema diferente em que meus retornos de chamada de notificação por push estavam sendo sequestrados pelas bibliotecas de terceiros, que incluí, ou seja, Firebase. Essas bibliotecas usam métodos de retorno de chamada de notificação push para obter os retornos de chamada.

Espero que isso ajude alguém.

Jarora
fonte