Je réalise une application dans laquelle je souhaite implémenter Apple Service de notification push. Je suis les instructions pas à pas données dans ce didacticiel .
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);
}
J'ai eu le même problème: appeler registerForRemoteNotificationTypes:
n'a invoqué ni application:didRegisterForRemoteNotificationsWithDeviceToken:
ni application: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 vérifié deux fois que je m'étais bien en m'inscrivant correctement pour les notifications Push , notamment en vérifiant mon profil d'approvisionnement pour la clé "aps-environment" et la codification du fichier .app lui-même. Je l'avais tout mis en place correctement.
J'ai ensuite dû déboguer les messages d'état de notifications Push dans la console (vous devez installer le profil d'approvisionnement PersistentConnectionLogging.mobileconfig sur votre appareil et le redémarrer. Voir TN2265 sous "Observer les messages d'état Push"). J'ai remarqué que le processus apns démarre une minuterie et calcule une date de mise à feu minimale, ce qui m'a amené à penser que le message de confirmation d'enregistrement Push-Notification, qui est normalement présenté à ce stade, est supprimé par APNS, comme indiqué dans le TN2265:
Réinitialisation de l'alerte d'autorisations de notifications push sur iOS
La première fois qu'une application compatible Push 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, il n'est plus présenté, sauf si le périphérique est restauré ou l'application désinstallée depuis au moins un jour.
Si vous souhaitez simuler une première exécution de votre application, vous pouvez la laisser désinstallée pendant un jour. Vous pouvez atteindre ce dernier sans attendre un jour en réglant l'horloge système d'un jour ou plus, 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 appelé registerForRemoteNotificationTypes
, il a reçu les rappels attendus.
Cela a résolu le problème pour moi. J'espère que ça aide.
Dans iOS 8, certaines méthodes sont obsolètes. Suivez les étapes ci-dessous pour la compatibilité iOS 8
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)];
}
- (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: deux nouvelles méthodes sont requises dans iOS 8 en plus de didRegisterForRemoteNotificationsWithDeviceToken
et didReceiveRemoteNotification
.. Sinon, la méthode déléguée ne sera pas appelée.
Dans iOS 8, en plus de demander un accès par notification 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 le périphérique 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
}
Assurez-vous d'appeler votre code (mise à jour en fonction des types de notification pris en charge)
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
et le profil d'approvisionnement est activé par APNS. Vous devrez peut-être télécharger à nouveau le profil de provisioning après avoir utilisé APNS. Si vous rencontrez des problèmes et que vous obtenez des erreurs, vous devriez peut-être créer un fichier Entitlements.plist et ajouter la clé "environnement-aps" avec la valeur "développement" ou "production" en fonction du type de construction (normalement, cette paire clé-valeur est contenu dans le profil de provisioning, mais parfois Xcode gache avec eux).
N'oubliez pas 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, didRegisterForRemoteNotificationsWithDeviceToken
ne sera pas appelé.
Si les profils de provisionnement sont utilisés avant d'activer et de configurer le service de notification Push Apple), vous devrez retélécharger à nouveau les profils de provisionnement.
Supprimez les profils d'approvisionnement de Xcode Organizer et de l'iPhone/iPad. Aller à Settings -> General -> Profiles -> [Your provisioning] -> Remove
.
Installez les nouveaux profils d'approvisionnement téléchargés. Puis nettoyez et exécutez le projet à partir de XCode. Maintenant, didRegisterForRemoteNotificationsWithDeviceToken
devrait être appelé.
Si vous avez ajouté Push à un ID d'application existant, veillez à générer à nouveau vos profils de provisioning. Sinon, le profil ne saura pas que vous avez activé Push sur l'ID de l'application.
J'ai commis une erreur et oublié un détail de mise en œuvre qui m'amène ici. J'ai essayé de me mettre en fantaisie et de demander des notifications Push à l'utilisateur plus tard dans le processus d'intégration de l'application. J'ai donc eu mon registerForRemoteNotificationTypes
, didRegisterForRemoteNotificationsWithDeviceToken
et didFailToRegisterForRemoteNotificationsWithError
dans une vue UIV personnalisée.
CORRECTIF: les didRegisterForRemoteNotificationsWithDeviceToken
et didFailToRegisterForRemoteNotificationsWithError
doivent être dans le UIApplicationDelegate
(YourAppDelegate.m
) à déclencher.
semble évident maintenant, heh.
Assurez-vous que votre connexion Internet est activée. Cela m'a pris des heures pour obtenir des notifications de travail en raison de la connexion Internet.
Essayez ça, ça marche pour moi,
Première étape
- (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 le code Fonction
#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 en détail, veuillez vous reporter This
J'espère que c'est une aide pour quelqu'un.
-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions{ //Overridepointforcustomizationafterapplicationlaunch.
//Addtheviewcontroller’sviewtothewindowanddisplay. [windowaddSubview:viewController.view]; [windowmakeKeyAndVisible];
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]);
}
Exigence minimale pour obtenir un jeton de périphérique:
Pas besoin de configurer l'id de l'application, le provisioning ou le certificat, etc. donc pas de signature de code pour obtenir la méthode de délégation didRegisterForRemoteNotificationsWithDeviceToken appelé.
Je viens de créer un nouveau projet iOS dans Xcode 7 pour une vue unique avec des paramètres par défaut et un identifiant de lot aléatoire, comme com.mycompany.pushtest, qui n'est pas configuré dans Apple dev portal .
Avec le code suivant, je reçois mon jeton de périphérique dans la méthode didRegisterForRemoteNotificationsWithDeviceToken sur mon iPad avec un accès Internet au WIFI. Mon appareil est connecté et je lance 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);
}
si fermé Appuyez sur le message de l'application,
appdidRegisterForRemoteNotificationsWithDeviceToken ne sera jamais appelé
Après avoir perdu les 3h les plus ennuyeux, voici les étapes à suivre pour résoudre le problème:
Supprimer l'application
Réinitialiser l'appareil
Courir à nouveau
Ça a juste fonctionné
Récemment, je suis également confronté à ce problème.J'ai tout fait conformément à la documentation, mais la méthode de délégation n'appelait pas.Enfin, j'ai vu un message dire ce problème avec le réseau.Ensuite, j'ai changé de réseau et tout fonctionne correctement. Veillez donc également au réseau car peu de réseaux peuvent bloquer l’APNS.
De plus, n'oubliez pas de vérifier l'état du système à l'adresse Apple https://developer.Apple.com/system-status/ .
J'avais essayé toutes les solutions indiquées ci-dessus, mais en fin de compte, la faute était due au fait 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 le suivant:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
C'est probablement pourquoi vous n'avez jamais reçu le jeton dans votre cas!
Cela m'est arrivé car j'ai réinitialisé et supprimé toutes les données du téléphone (je voulais utiliser un téléphone dev). Cela empêchait APN de se connecter après la configuration du téléphone.
J'ai essayé toutes sortes de choses, mais la seule solution à ce problème était de permettre au téléphone de fonctionner avec un opérateur sous une nouvelle carte SIM.
Ce lien offre plus d'indications sur ce qui aurait pu se passer: https://developer.Apple.com/library/ios/technotes/tn2265/_index.html
Il dit que APN essaie de se connecter préférentiellement via l'opérateur/les tours au lieu du wifi. Peut-être que le problème tenait également au fait que le routeur bloquait le port 5223 sur le réseau wifi, mais j'en doute, car il fonctionnait bien la veille de la réinitialisation globale.
J'ai eu un problème différent dans lequel mes rappels de notification Push ont été détournés par les bibliothèques tierces, que j'avais incluses, à savoir Firebase. Ces bibliothèques basculent les méthodes de rappel de notification Push pour obtenir les rappels.
J'espère que ça aide quelqu'un.
Pour moi, ce qui a résolu le problème 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 n'était pas correct et l'application n'était donc pas correctement autorisée.
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
}
}
}
}