iOS UIBackgroundMode远程通知不适用于4G

时间:2014-07-24 08:24:22

标签: ios background push-notification wifi 4g

我正在测试内容可用= 1的推送通知,除非在Wi-Fi上,否则它们似乎不会在后台传送到应用。

我在推送通知处理程序的开头有一个简单的日志语句:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
                                                    fetchCompletionHandler:(void (^)   (UIBackgroundFetchResult))completionHandler {

    NSLog(@"Notification received: %@", userInfo);
    completionHandler(UIBackgroundFetchResultNewData);
}

这是我的测试:

  1. 运行应用程序,然后按主页按钮将应用程序置于后台。
  2. 发送包含content-available = 1
  3. 的推送通知
  4. 观看控制台日志
  5. 在Wi-Fi上,控制台日志显示通知。如果我转到“设置”并关闭Wi-Fi,切换到4G,日志中不再显示通知(尽管它们会在屏幕顶部滑入,因此我知道它们正在交付)。

    没有崩溃日志,如果我手动点击它,则会记录通知。此外,如果我在Xcode中调试应用程序,则不会发生此问题。 (即,如果我在Xcode中调试,该应用程序将在后台接收4G通知)。有没有其他人经历过这种行为?或者我做错了什么?

    修改: 具体来说:根据我的测试,如果满足以下条件,则不会调用上面的远程通知委托方法:

    1. 应用程序正在后台运行
    2. 手机在LTE网络上,未连接到Wi-Fi
    3. App未在Xcode调试器中运行
    4. 手机收到内容可用= 1的通知
    5. 但是,如果删除了条件2(即手机连接到Wi-Fi),则会调用该处理程序。

3 个答案:

答案 0 :(得分:3)

请尝试以下代码:

// AppDelegate.h

@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{

    NSString *DeviceToken;
    NSMutableDictionary *App_Messages;

    NSString *Longitude,*Latitude;
    NSMutableDictionary * badge;
}

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewcontrollervc;

@property (strong, nonatomic) UINavigationController *navcontroller;

@property (nonatomic,retain)NSMutableDictionary *badge;

@property (nonatomic,retain)NSString *DeviceToken;

// AppDelegate.m

#import "ViewController.h"

@implementation AppDelegate

@synthesize badge,DeviceToken;

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

    self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
    self.viewcontrollervc = [[ViewController alloc]initWithNibName:@"ViewController" bundle:nil];
    self.navcontroller = [[UINavigationController alloc]initWithRootViewController:self.viewcontrollervc];
    self.window.rootViewController = self.navcontroller;
    self.navcontroller.navigationBarHidden = YES;


    //Notification
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    NSDictionary * remoteNotificationObj = [launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"];
    if (remoteNotificationObj)
    {
        [self performSelector:@selector(handleRemoteNotificationWithUserInfo:) withObject:remoteNotificationObj afterDelay:3.0];
    }

    [self.window makeKeyAndVisible];
    return YES;

}


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

    [self handleRemoteNotificationWithUserInfo:userInfo];

}

-(void)handleRemoteNotificationWithUserInfo:(NSDictionary *)userInfo
{

    NSLog(@"userInfo - %@",userInfo);
    NSDictionary *alertData = [userInfo objectForKey:@"aps"];
    NSDictionary *returnDatalert=[alertData objectForKey:@"alert"];
    NSString *alertmsg=[returnDatalert objectForKey:@"body"];

    NSLog(@"alertmsg %@",alertmsg);
    self.badge = [NSMutableDictionary dictionaryWithDictionary:[alertData objectForKey:@"badge"]];
    NSString *notificationtype=[badge objectForKey:@"fnct"];

    NSLog(@"%@",notificationtype);

}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{

   NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken);
    NSString *dt = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    dt = [dt stringByReplacingOccurrencesOfString:@" " withString:@""];
    self.DeviceToken=dt;
    NSLog(@"~~~~devToken(dv)=%@",deviceToken);

}

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{

    NSLog(@"Failed to get token, error: %@", error);

}

答案 1 :(得分:1)

根据此处评论者的反馈以及在多个设备上重复测试,这似乎是iOS上的错误(或预期行为)。

答案 2 :(得分:0)

对我来说,它适用于Wi-Fi和4G(在蜂窝设置中强制关闭LTE),但不适用于LTE。

更新:经过大量调试后,我发现这个问题与我在LTE上的两件事有关。一个是力量。我发现如果iPhone插在墙上,应用程序会按预期被唤醒。如果未插入,则应用程序未响应content-available = 1而被唤醒。其次,是设备设置。即使每个相关设置都设置正确,执行“重置所有设置”也可以解决问题。

假设这不是Apple的错误,我的猜测是iOS开发了给定应用程序标识符的电源配置文件,它在某些情况下(网络状态,电池状态等)选择不唤醒使用过多背景的应用程序周期。例如,错误地使用beginBackgroundTaskWithExpirationHandler,导致应用程序在后台保持活动状态并强制iOS使其过期。即使修复过多的背景使用情况也可能无法解决问题,因为iOS已经确定您的应用是背景。这可以解释“Rest all Settings”为我解决问题。

不幸的是,所有这些只是基于2-3天调试此问题的猜测,我们可能永远不会确定,因为推送通知中有很多变量,更不用说含糊不清的文档了。