iOS 15 在进入 BLE 信标区域时没有唤醒应用程序

iOS 15 does not awake app while entering BLE beacon region

我的 iOS 应用程序中有 BLE 信标检测功能。这意味着如果用户打开了蓝牙和位置并且如果用户进入信标范围,系统会自动唤醒应用程序如果它不是运行(被杀死状态)。

这在 iOS 14 及以下版本上运行良好。昨天我将我的设备更新为 iOS 15,即使我在设置中启用了“始终”位置权限,进入 ble beacon 区域时应用程序也不再被唤醒。

有什么想法吗?

我的测试表明 iOS 15 次在进入信标区域时成功将应用程序从停止状态启动到后台。

测试步骤:

  1. 使用 iOS 14.8 在我的 phone 上安装此应用程序:https://github.com/davidgyoung/CoreLocationRegionLaunchDemo

  2. 运行 应用程序,始终授予通知和位置权限。

  3. 转到设置并验证位置权限始终

  4. 打开信标,确认进入通知到达。然后关闭信标,确认退出通知到达。

  5. 重新启动 phone。等5分钟。打开信标,然后验证进入通知到达。关闭信标并验证退出通知是否到达。

  6. 升级到iOS15.

  7. 等待 5 分钟。

  8. 打开信标。确认进入通知到达。

查看屏幕截图 -- 抱歉,它们很丑,但我必须先完成 XCode 13 的巨大下载,然后才能将屏幕截图直接发送到我的计算机。

很奇怪,就我而言,重启似乎可以解决问题。

经过 trial/error、测试以及与 Apple 的对话,我可以确认这不是区域监控的错误,而是 Apple's new prewarming feature in iOS 15 的错误。

简而言之,iOS 15 将在 iOS 认为此人会使用的后台静默半启动应用程序。在我们的测试中,这种情况大约每半小时发生一次。它使应用程序启动感觉更快,因为一堆应用程序已经加载并准备就绪。

如果 Apple 预热了您的应用程序,并且用户没有完全启动它,然后区域监视器需要通知您的应用程序,则不会发生这种情况。有时区域监控会提醒您的应用程序,有时则不会。如果您的应用程序“冷”,它会工作。如果您的应用程序在内存中,它就会工作。如果您的应用处于这种预热状态,那么您就完蛋了。

重新启动整个 phone 有效,因为您正在逐出任何处于预热状态的应用程序。

我从 Apple 那里得知这确实是多个错误,一些已修复,一些尚未修复。 iOS 15.2 测试版中的注释还特别提到这也可能影响 HealthKit。

解决此错误的解决方案是在 main.m 中检测 Apple 何时预热您的应用程序和 exit。这不允许您的应用程序在 Apple 预热时启动并强制您的应用程序在时机成熟时完全启动。

这是 main.mmain() 方法的代码。请注意,添加 iOS 版本检测是明智的,这样当 Apple 确实修复此问题时,它最终可以被逐步淘汰和删除。

double systemVersion = [[UIDevice currentDevice] systemVersion].doubleValue;
if (systemVersion >= 15.0) {
    NSDictionary* environment = [[NSProcessInfo processInfo] environment];
    BOOL prewarmed = false;
    for (NSString *key in environment.allKeys) {
        if ([key.lowercaseString containsString:@"prewarm"]) {
            prewarmed = true;
            break;
        }
    }

    if (prewarmed) {
        exit(0);
    }
}