Обработка уведомлений Push, когда приложение не выполняется
Когда мое приложение не запущено и получает уведомление о Push, если я нажму на это уведомление, приложение запустится – но тогда он не запрашивает у пользователя настройку Alert-View I, спрашивая, хотят ли они просматривать Содержание уведомления или нет. Он просто запускается и сидит там.
Push Notifications работают отлично, когда приложение запущено – либо в качестве активного приложения, либо в фоновом режиме, но ничего не работает правильно, когда приложение не работает.
Я попытался выполнить launchOptions
NSDictionary в application: didFinishLaunchingWithOptions:
посмотреть, какую нагрузку он приносит, но он появляется как «(null)». Таким образом, он в основном не содержит ничего – что не имеет смысла, не должно ли оно содержать нагрузку уведомления?
- Удаленное уведомление iOS 8
- Android Push Notification (GCM), есть ли ежедневный лимит?
- ActivityManager.getRunningTasks - устаревший андроид
- registerForRemoteNotificationTypes: не поддерживается в iOS 8.0 и более поздних версиях
- Android - используйте внешний профиль в панели уведомлений, например Facebook
У кого-нибудь есть идеи, как заставить 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 я реализовал его, и он работает хорошо! Я оставляю ссылку:
Это процедура:
- Создайте новое расширение службы уведомлений для своего приложения. Откройте проект и нажмите «Файл» – «Создать» и выберите в разделе «iOS» опцию «Расширение службы уведомлений». Введите имя расширения и необходимую информацию. После этого Xcode добавит два файла с языком Objective C: .h и .m.
ПРИМЕЧАНИЕ. Учтите, что вы будете использовать три идентификатора: 1) Идентификатор вашего приложения (у вас уже есть) 2) Идентификатор для вашего расширения (вы создадите) 3) Идентификатор для группы приложений. (вы создадите)
-
Необходимо, чтобы группы приложений могли создавать ресурс, в котором вы можете сохранять и читать информацию для своего приложения и расширения. Нажмите «Показать навигатор проекта». В список целей выберите свой основной проект. Затем нажмите «Возможности» и включите опцию «Группы приложений». Добавьте идентификатор группы приложений для определения общих ресурсов. Вы должны сделать тот же шаг для целевого расширения, которое вы создали (выберите цель расширения – возможности – включите «Группы приложений» – добавьте тот же идентификатор для группы приложений)
-
Вы должны добавить идентификатор для своего расширения на сайт разработчика Apple для определения расширения службы уведомлений, также вам необходимо создать новые предварительные профили (Development, AdHoc и / или Production) и связать их с новыми временными профилями.
-
В обоих идентификаторах (приложение и расширение) вы должны отредактировать их и включить службу «Группы приложений» в обоих из них. Вы должны добавить группу «Идентификатор для приложения» в Службы групп приложений.
ПРИМЕЧАНИЕ. Идентификатор приложения и идентификатора для расширения ДОЛЖЕН ИМЕТЬ ИДЕНТИФИКАТОР ДЛЯ ГРУППЫ APP.
-
Загрузите новый предварительный профиль на Xcode и свяжите его с расширением службы уведомлений. Пожалуйста, убедитесь, что с ними все в порядке.
-
После этого в «Возможности» вашего приложения и расширения откройте раздел «Группы приложений» и обновите их. Три шага – 1) Добавьте права на группы приложений в ваш файл прав, 2) Приложите функцию «Группы приложений» к вашему идентификатору приложения и 3) «Добавить группы приложений» в свой идентификатор приложения – необходимо проверить.
-
Вернитесь в навигатор проекта и выберите папку расширения. Откройте файл .m. Вы увидите метод, называемый requestReceiveNotificationRequest: (UNNotificationRequest *). В этом методе вы создадите различные NSUserDefaults с именем SuiteName, равным идентичному идентификатору для группы приложений следующим образом:
NSUserDefaults * defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @ “идентификатор для группы приложений”];
-
В этот же метод получите тело уведомления и сохраните его в 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"]; }
- Наконец, в App Delegate вашего основного проекта, в вашем методе didFinishLaunchingWithOptions, восстановите Array в ресурсах общего доступа с помощью этого кода:
NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; NSMutableArray *notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy];
- Наслаждайся этим!
Я надеюсь, что с каждым шагом будет ясно. Я собираюсь написать сообщение для реализации этого решения с изображениями на моей странице. Еще один момент, который вы должны учитывать, это не работает с 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 }