10

我正在测试 content-available=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. 观看控制台日志

在 Wi-Fi 上,控制台日志会显示通知。如果我转到“设置”并关闭 Wi-Fi,切换到 4G,则通知不再出现在日志中(尽管它们确实在屏幕顶部滑入,所以我知道它们正在传递)。

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

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

  1. 应用程序在后台运行
  2. 手机在 LTE 网络上,未连接到 Wi-Fi
  3. 应用程序未在 Xcode 调试器中运行
  4. 手机收到 content-available=1 的通知

但是,如果条件 2 被移除(即手机连接到 Wi-Fi),则将调用处理程序。

4

3 回答 3

4

试试下面的代码:

// 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);

}
于 2014-08-01T07:20:26.847 回答
1

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

于 2014-08-06T21:47:28.863 回答
0

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

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

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

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

于 2014-11-21T21:39:02.763 回答