处理推送通知时,应用程序无法运行(Handling Push Notifications when

2019-06-17 21:03发布

当我的应用程序没有运行并接收推送通知,如果我点击该通知,应用启动-但是它不提示与报警,查看我建立用户,询问他们是否要查看通知的内容或没有。 它只是推出,并坐在那里。

该应用程序运行时,推送通知就很好地工作-无论是作为活跃APP或者在后台-但没有正常工作时,应用程序没有运行。

我试图登录时的launchOptions的NSDictionary在application: didFinishLaunchingWithOptions:看什么加载其自备-但它作为“(空)”登场。 因此,它基本上不包含任何内容 - 这是没有意义的事业不应该是包含通知的负荷?

任何人有任何想法如何使推送通知的工作,当他们到达而应用程序没有运行?

编辑:这里是我使用的代码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");
}

所以,这是应该采取应用程序的所有国家的照顾 - 但它不是。 推送通知只工作应用程序运行时 - 无论是在后台或前台...

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

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出现空...将继续的调整?

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

编辑#3 -它的工作现在几乎 100%
所以,在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逻辑完美的作品。

无论其......当应用程序没有运行,我发送推送通知,如果我不上的推送通知警报,一旦它到达点击,而是等待它淡出(这之后会发生类似的3- 4秒), 然后我点击程序图标-现在有1就可以了徽章-应用程序启动,但我没有得到推送通知警报在所有时候推出。 它只是坐在那里。

我想我需要计算下次排列...

Answer 1:

当你的应用程序没有运行,或者死亡,你点击在推送通知这个功能将触发;

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

所以你应该处理它这个样子,

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


Answer 2:

更好的是,如果你重写didReceiveRemoteNotification在这里你去

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

这将再次触发didReceiveRemoteNotification方法和你的push notification ,因为它在应用程序运行时运行的代码将执行相同。



Answer 3:

我试图@ dianz的回答,这不是我的工作,但我得到了答案帮助。

在我的情况;

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

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


Answer 4:

虽然这已经回答了,没有提供答案的实际工作正常。 下面是我的实现,我能得到工作。

此代码放在application:didFinishLaunchingWithOptions:

迅速:

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的不需要这个。

  • 夸克仅仅是我在所有项目中包含有帮助和常用的扩展和方法使用一个有趣的小库。 简单地使用适合您的应用需求的任何形式的延迟。



Answer 5:

我有同样的问题,但我终于可以用通知服务扩展处理推送通知时无效(不运行)。 建议由苹果团队支持该解决方案,它是唯一的iOS 10,我实现它,它工作得很好! 我离开的链接:

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

这是该过程:

  1. 创建为您的应用新的Notification服务扩展。 打开您的项目,然后按文件 - 新建 - 目标并选择在iOS部分,选择“通知服务扩展”。 把推广和所需的信息的名称。 在此之后,Xcode中添加将两个文件使用Objective C语言:h和.m文件。

注意:假设您将使用三个标识符:1)标识符为您的应用程序(你已经有了)2)标识为您的扩展(您将创建)3)标识符的应用程序组。 (您将创建)

  1. 必须启用应用程序组创建一个资源,你可以保存和读取您的应用程序和扩展信息。 点击“查看项目浏览器”。 到目标的列表中选择你的主要项目。 然后,点击“功能”和名为“应用程序组”选项切换。 请添加标识为App组查明资源共享。 你应该做的,你创建扩展的目标相同的步骤(扩展的选择目标 - 能力 - 在“应用程序组”开机 - 添加应用程序组相同的标识符)

  2. 您应该添加标识符为您的扩展到苹果开发者网站标识通知服务扩展,另外,应做出新的临时配置文件(发展的AdHoc和/或生产),并将其与新的临时配置文件相关联。

  3. 在这两个标识符(App和扩展),你应该对其进行编辑,并能够在他们两个“应用程序组”服务。 您应该添加标识符为App组进入App群体提供服务。

注:标识符App和标识符扩展应该有APP集团相同的标识符。

  1. 下载文件的Xcode新的临时配置文件,并将它们与通知服务扩展关联。 请确保你一切都确定了它们。

  2. 在此之后,您的应用和推广的“能力”,打开“应用程序组”部分,更新它们。 这三个步骤 - 1)添加应用程序组权利,以您的权利文件,2)应用程序的应用程序组功能,以您的应用程序ID和3)应用群组添加到您的应用程序ID - 应该进行检查。

  3. 回来项目导航并选择扩展的文件夹。 打开.m文件。 你会看到一个名为didReceiveNotificationRequest方法:(UNNotificationRequest *)的要求。 这个方法,你将创建SuiteName正好等于标识符喜欢这个程序组NSUserDefaults的不同:

    * NSUserDefaults的defaultsGroup = [[ALLOC NSUserDefaults的] 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. 最后,到主项目的应用代表,在你的didFinishLaunchingWithOptions方法,恢复阵列与此代码共享资源:
 NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; NSMutableArray *notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy]; 
  1. 好好享受!

我希望每一步都清楚。 我打算写个帖子来实现,在我的页面图像该解决方案。 您应该考虑的另一点是它不与无声推送通知工作。



Answer 6:

试着要去didReceiveRemoteNotification方法和处理它。 在那里,你可以做条件语句的检查应用程序的状态applicationState ,例如检查,如果它是UIApplicationStateActive或他人。



Answer 7:

试试这个

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


Answer 8:

斯威夫特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
}


文章来源: Handling Push Notifications when App is NOT running