Обработка уведомлений Push, когда приложение не выполняется

Когда мое приложение не запущено и получает уведомление о Push, если я нажму на это уведомление, приложение запустится – но тогда он не запрашивает у пользователя настройку Alert-View I, спрашивая, хотят ли они просматривать Содержание уведомления или нет. Он просто запускается и сидит там.

Push Notifications работают отлично, когда приложение запущено – либо в качестве активного приложения, либо в фоновом режиме, но ничего не работает правильно, когда приложение не работает.

Я попытался выполнить launchOptions NSDictionary в application: didFinishLaunchingWithOptions: посмотреть, какую нагрузку он приносит, но он появляется как «(null)». Таким образом, он в основном не содержит ничего – что не имеет смысла, не должно ли оно содержать нагрузку уведомления?

У кого-нибудь есть идеи, как заставить Push Notifications работать, когда они приходят, когда приложение не работает?

EDIT: вот код, который я использую в application: didReceiveRemoteNotification чтобы посмотреть, что к чему:

 if (UIApplicationStateBackground) { NSLog(@"==========================="); NSLog(@"App was in BACKGROUND..."); } else if (UIApplicationStateActive == TRUE) { NSLog(@"==========================="); NSLog(@"App was ACTIVE"); } else { [[UIApplication sharedApplication] setApplicationIconBadgeNumber: 99]; UIAlertView *BOOM = [[UIAlertView alloc] initWithTitle:@"BOOM" message:@"app was INACTIVE" delegate:self cancelButtonTitle:@"a-ha!" otherButtonTitles:nil]; [BOOM show]; NSLog(@"App was NOT ACTIVE"); } 

Таким образом, это должно заботиться о всех состояниях приложения, но это не так. Push Notifications работают только при запуске приложения – либо в фоновом режиме, либо на переднем плане …

================================================

UPDATE / EDIT # 2: согласно предложению «@dianz» (ниже), я изменил код моего application: didFinishLaunchingWithOptions чтобы включить следующее:

 UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (localNotif) { NSString *json = [localNotif valueForKey:@"data"]; UIAlertView *bam = [[UIAlertView alloc] initWithTitle:@"appDidFinishWithOptions" message:json delegate:self cancelButtonTitle:@"cool" otherButtonTitles:nil]; [bam show]; } 

Это создает окно AlertView, но, похоже, нет никакой полезной нагрузки: заголовок AlertView появляется («appDidFinishWithOptions»), но json NSString появляется EMPTY … Будет держать настройку …

======================

EDIT # 3 – теперь он работает почти на 100%
Итак, in didFinishLaunchingWithOptions :

 UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (localNotif) { // Grab the pushKey: pushKey = [localNotif valueForKey:@"pushKey"]; // "pushKey" is an NSString declared globally // The "pushKey" in the "valueForKey" statement is part of my custom JSON Push Notification pay-load. // The value of pushKey will always be a String, which will be the name of the // screen I want the App to navigate to. So when a Notification arrives, I go // through an IF statement and say "if pushKey='specials' then push the // specialsViewController on, etc. // Here, I parse the "alert" portion of my JSON Push-Notification: NSDictionary *tempDict = [localNotif valueForKey:@"aps"]; NSString *pushMessage = [tempDict valueForKey:@"alert"]; // Finally, ask user if they wanna see the Push Notification or Cancel it: UIAlertView *bam = [[UIAlertView alloc] initWithTitle:@"(from appDidFinishWithOptions)" message:pushMessage delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"View Info", nil]; [bam show]; } 

Затем я реализую метод alertView: clickedButtonAtIndex чтобы узнать, что пользователь выбрал в AlertView, и действуйте соответственно.

Это, наряду с логикой didReceiveRemoteNotification отлично работает.

ОДНАКО … когда приложение НЕ запускается, и я отправляю ему Push-уведомление, если я НЕ НАЖМИТЕ предупреждение Push Push, как только он придет, и вместо этого подождите, пока он исчезнет (что происходит после того, 4 секунды), а затем я нажимаю на значок приложения, в котором теперь есть BADGE из 1 – приложение запускается, но я не получаю сообщение Push Notification вообще при его запуске. Он просто сидит там.

Думаю, мне нужно понять, что перестановка следующая …

Когда ваше приложение не запускается или не убивается, и вы нажимаете на push-уведомление, эта функция будет запускаться;

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

поэтому вы должны справиться с этим так,

 UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (localNotif) { NSString *json = [localNotif valueForKey:@"data"]; // Parse your string to dictionary } 

Лучше, если вы переопределите didReceiveRemoteNotification Здесь вы идете

 NSDictionary * pushNotificationPayload = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if(pushNotificationPayload) { [self application:application didReceiveRemoteNotification:pushNotificationPayload]; } 

Это снова didReceiveRemoteNotification метод didReceiveRemoteNotification и ваш код push notification будет выполняться так же, как и во время выполнения приложения.

Я попробовал ответить @ dianz, это не сработало для меня, но я получил помощь от ответа.

В моем случае;

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSDictionary *apnsBody = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (apnsBody) { // Do your code with apnsBody } 

Хотя на это был дан ответ, ни один из предоставленных ответов не работал правильно. Вот моя реализация, что я смог работать.

Этот код идет в application:didFinishLaunchingWithOptions:

Swift:

 if let options = launchOptions, notification = options[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject : AnyObject] { // NOTE: (Kyle Begeman) May 19, 2016 - There is an issue with iOS instantiating the UIWindow object. Making this call without // a delay will cause window to be nil, thus preventing us from constructing the application and assigning it to the window. Quark.runAfterDelay(seconds: 0.001, after: { self.application(application, didReceiveRemoteNotification: notification) }) } 

Objective-C:

 if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { [self application:application didReceiveRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]]; } 

Пара отмечает:

  • Возможно, из-за распределения очередей IOS корневой UIApplication.sharedApplication().window при запуске приложения после его уничтожения равен нулю. Добавление 1 миллисекундной задержки устранило эту проблему. Не тестировал это в Objective-C

  • Для того, чтобы избежать конфликтов типа, требуется выполнить [NSObject: AnyObject], но я не экспериментировал с этим; держите это в своем уме при реализации в своем собственном проекте. Objective-C этого не требует.

  • Quark – это просто небольшая библиотека, которую я использую во всех моих проектах, которые содержат полезные и часто используемые расширения и методы. Просто используйте любую форму задержки, которая соответствует потребностям вашего приложения.

Попробуйте перейти к методу didReceiveRemoteNotification и обработать его там. Там вы можете проверить состояния приложения, выполнив условные обозначения для applicationState , например, проверить, является ли это UIApplicationStateActive или другими.

У меня была такая же проблема, но я, наконец, смог обработать Push Notification, когда он неактивен (не работает), используя расширение службы уведомлений. Это решение было рекомендовано Apple Team Support, и только для iOS 10 я реализовал его, и он работает хорошо! Я оставляю ссылку:

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ModifyingNotifications.html

Это процедура:

  1. Создайте новое расширение службы уведомлений для своего приложения. Откройте проект и нажмите «Файл» – «Создать» и выберите в разделе «iOS» опцию «Расширение службы уведомлений». Введите имя расширения и необходимую информацию. После этого Xcode добавит два файла с языком Objective C: .h и .m.

ПРИМЕЧАНИЕ. Учтите, что вы будете использовать три идентификатора: 1) Идентификатор вашего приложения (у вас уже есть) 2) Идентификатор для вашего расширения (вы создадите) 3) Идентификатор для группы приложений. (вы создадите)

  1. Необходимо, чтобы группы приложений могли создавать ресурс, в котором вы можете сохранять и читать информацию для своего приложения и расширения. Нажмите «Показать навигатор проекта». В список целей выберите свой основной проект. Затем нажмите «Возможности» и включите опцию «Группы приложений». Добавьте идентификатор группы приложений для определения общих ресурсов. Вы должны сделать тот же шаг для целевого расширения, которое вы создали (выберите цель расширения – возможности – включите «Группы приложений» – добавьте тот же идентификатор для группы приложений)

  2. Вы должны добавить идентификатор для своего расширения на сайт разработчика Apple для определения расширения службы уведомлений, также вам необходимо создать новые предварительные профили (Development, AdHoc и / или Production) и связать их с новыми временными профилями.

  3. В обоих идентификаторах (приложение и расширение) вы должны отредактировать их и включить службу «Группы приложений» в обоих из них. Вы должны добавить группу «Идентификатор для приложения» в Службы групп приложений.

ПРИМЕЧАНИЕ. Идентификатор приложения и идентификатора для расширения ДОЛЖЕН ИМЕТЬ ИДЕНТИФИКАТОР ДЛЯ ГРУППЫ APP.

  1. Загрузите новый предварительный профиль на Xcode и свяжите его с расширением службы уведомлений. Пожалуйста, убедитесь, что с ними все в порядке.

  2. После этого в «Возможности» вашего приложения и расширения откройте раздел «Группы приложений» и обновите их. Три шага – 1) Добавьте права на группы приложений в ваш файл прав, 2) Приложите функцию «Группы приложений» к вашему идентификатору приложения и 3) «Добавить группы приложений» в свой идентификатор приложения – необходимо проверить.

  3. Вернитесь в навигатор проекта и выберите папку расширения. Откройте файл .m. Вы увидите метод, называемый requestReceiveNotificationRequest: (UNNotificationRequest *). В этом методе вы создадите различные NSUserDefaults с именем SuiteName, равным идентичному идентификатору для группы приложений следующим образом:

    NSUserDefaults * defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @ “идентификатор для группы приложений”];

  4. В этот же метод получите тело уведомления и сохраните его в NSMutableArray, а затем сохраните его в ресурсах общего доступа. Как это:

 - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler{ self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; NSMutableArray *notifications = [NSMutableArray new]; NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy]; if (notifications != nil){ [notifications addObject:self.bestAttemptContent.userInfo]; }else{ notifications = [NSMutableArray new]; [notifications addObject:self.bestAttemptContent.userInfo]; } [defaultsGroup setObject:notifications forKey:@"notifications"]; } 
  1. Наконец, в App Delegate вашего основного проекта, в вашем методе didFinishLaunchingWithOptions, восстановите Array в ресурсах общего доступа с помощью этого кода:
 NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; NSMutableArray *notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy]; 
  1. Наслаждайся этим!

Я надеюсь, что с каждым шагом будет ясно. Я собираюсь написать сообщение для реализации этого решения с изображениями на моей странице. Еще один момент, который вы должны учитывать, это не работает с Silent Push Notification.

попробуй это

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; //register notifications if([application respondsToSelector:@selector(registerUserNotificationSettings:)]) // ios 8 { [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]]; [application registerForRemoteNotifications]; } else // ios 7 { [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge]; } // open app from a notification NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (notification) { //your alert should be here } // Set icon badge number to zero application.applicationIconBadgeNumber = 0; return YES; } 

Swift 3 и xCode 8.3.2 :

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // your code here // Check if app was not running in background and user taps on Push Notification // This will perform your code in didReceiveRemoteNotification where you should handle different application states if let options = launchOptions, let notification = options[UIApplicationLaunchOptionsKey.remoteNotification] as? [NSObject : AnyObject] { self.application(application, didReceiveRemoteNotification: notification) } return true } 
Давайте будем гением компьютера.