didReceiveRemoteNotification:fetchCompletionHandler not being called when app is in background and not connected to Xcode

前端 未结 10 1604
别那么骄傲
别那么骄傲 2020-11-28 04:27

I\'ve a very strange problem, I implemented:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchComp         


        
10条回答
  •  有刺的猬
    2020-11-28 05:20

    Code that works fetching remote notifications, enable te remote notifications capability in background modes and i have background fetch enabled too (i don't know if it is necessary) I use this code:

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler{
    DLog(@"899- didReceiveRemoteNotification userInfo: %@",userInfo);
    NSDictionary *custom=userInfo[@"custom"];
    if(custom){
        NSInteger code = [custom[@"code"] integerValue];
        NSInteger info = [custom[@"info"] integerValue];
    
        NSDictionary *messageInfo = userInfo[@"aps"];
    
        [[eInfoController singleton] remoteNotificationReceived:code info:info messageInfo:messageInfo appInBackground:[UIApplication sharedApplication].applicationState==UIApplicationStateBackground];
    
        handler(UIBackgroundFetchResultNewData);
    }
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
    DLog(@"899- didReceiveRemoteNotification userInfo: %@",userInfo);
    NSDictionary *custom=userInfo[@"custom"];
    if(custom){
        NSInteger code = [custom[@"code"] integerValue];
        NSInteger info = [custom[@"info"] integerValue];
    
        NSDictionary *messageInfo = userInfo[@"aps"];
    
        [[eInfoController singleton] remoteNotificationReceived:code info:info messageInfo:messageInfo appInBackground:[UIApplication sharedApplication].applicationState==UIApplicationStateBackground];
    
    }
    }
    
    - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
    {
    //NSLog(@"My token is: %@", deviceToken);
    const unsigned *tokenBytes = (const unsigned *)[deviceToken bytes];
    NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
                          ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
                          ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
                          ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
    
    [[eInfoController singleton] setPushNotificationToken:hexToken];
    }
    
    - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
    {
    NSLog(@"Failed to get token, error: %@", error);
    }
    

    Code that stores the notification when it background, the key for me was to start a background download task to allow me to download the information in order to store it and then when app becomes active method is triggered i check if there is a missing notification stored to show it.

    -(void)remoteNotificationReceived:(NSInteger)code info:(NSInteger)info messageInfo:(NSDictionary*)messageInfo appInBackground:(BOOL)appInBackground{
    
    DLog(@"Notification received appInBackground: %d,pushCode: %ld, messageInfo: %@",appInBackground, (long)code,messageInfo);
    
    switch (code){
        case 0:
            break;
        case 1:
        {
            NSArray *pendingAdNotifiacations=[[NSUserDefaults standardUserDefaults] objectForKey:@"pendingAdNotifiacations"];
            NSMutableDictionary *addDictionary=[[NSMutableDictionary alloc] initWithDictionary:messageInfo copyItems:YES];
            [addDictionary setObject:[NSNumber numberWithInteger:info] forKey:@"ad_id"];
    
            if(!pendingAdNotifiacations){
                pendingAdNotifiacations=[NSArray arrayWithObject:addDictionary];
            }else{
                pendingAdNotifiacations=[pendingAdNotifiacations arrayByAddingObject:addDictionary];
            }
            [addDictionary release];
    
            [[NSUserDefaults standardUserDefaults] setObject:pendingAdNotifiacations forKey:@"pendingAdNotifiacations"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            DLog(@"pendingAdNotifiacations received: %@.",pendingAdNotifiacations);
            [[UIApplication sharedApplication] setApplicationIconBadgeNumber:(pendingAdNotifiacations)?[pendingAdNotifiacations count]:0];
            DLog(@"783- pendingAdNotifiacations: %lu.",(unsigned long)((pendingAdNotifiacations)?[pendingAdNotifiacations count]:0));
            if(appInBackground){
    
                [AdManager requestAndStoreAd:info];
            }else{
                [AdManager requestAndShowAd:info];
            }
        }
            break;
        default:
            break;
    }
    
    }
    

    This is the relevant code to download the info in the background using a background task:

    -(void)requestAdinBackgroundMode:(NSInteger)adId{
    DLog(@"744- requestAdinBackgroundMode begin");
    if(_backgroundTask==UIBackgroundTaskInvalid){
        DLog(@"744- requestAdinBackgroundMode begin dispatcher");
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        DLog(@"744- passed dispatcher");
        [self beginBackgroundUpdateTask];
    
        NSURL *requestURL=[self requestURL:adId];
        if(requestURL){
            NSURLRequest *request = [NSURLRequest requestWithURL:requestURL];
    
            NSURLResponse * response = nil;
            NSError  * error = nil;
            DLog(@"744- NSURLConnection url: %@",requestURL);
            NSData * responseData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
    
            if(NSClassFromString(@"NSJSONSerialization"))
            {
                NSError *error = nil;
                id responseObject = [NSJSONSerialization
                         JSONObjectWithData:responseData
                         options:0
                         error:&error];
    
                if(error) {
                    NSLog(@"JSON reading error: %@.",[error localizedDescription]);
                    /* JSON was malformed, act appropriately here */ }
                else{
    
                if(responseObject && [responseObject isKindOfClass:[NSDictionary class]]){
                    if(responseObject && [[responseObject objectForKey:@"success"] integerValue]==1){
                        NSMutableDictionary *adDictionary=[[[NSMutableDictionary alloc] initWithDictionary:[responseObject objectForKey:@"ad"]] autorelease];
                        DLog(@"744- NSURLConnection everythig ok store: %@",adDictionary);
                        [self storeAd: adDictionary];
                    }
                }
                }
            }
        }
    
        // Do something with the result
    
        [self endBackgroundUpdateTask];
    });
    }
    } 
    
    - (void) beginBackgroundUpdateTask
    {
    DLog(@"744- requestAdinBackgroundMode begin");
    _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [self endBackgroundUpdateTask];
    }];
    }
    
    - (void) endBackgroundUpdateTask
    {
    DLog(@"744- End background task");
    [[UIApplication sharedApplication] endBackgroundTask: _backgroundTask];
    _backgroundTask = UIBackgroundTaskInvalid;
    }
    

    Well this is all I think, I post it because someone asked me to post an update, I hope it may help someone...

提交回复
热议问题