核心蓝牙状态保存和恢复不起作用,无法重新启动应用程序到后台

woo*_*oof 13 ios core-bluetooth bluetooth-lowenergy cbcentralmanager state-restoration

即使它没有运行,我也试图让核心蓝牙唤醒应用程序.

正如Apple所说,"因为状态保存和恢复是内置于Core Bluetooth,您的应用程序可以选择使用此功能来要求系统保留应用程序的中央和外围管理器的状态,并继续执行某些与蓝牙相关的任务.代表他们,即使你的应用程序不再运行.当其中一个任务完成后,系统会将你的应用程序重新启动到后台,并让你的应用程序有机会恢复其状态并适当地处理事件."

我添加了以下代码以选择加入此功能:

 myCentralManager =
        [[CBCentralManager alloc] initWithDelegate:self queue:nil
         options:@{ CBCentralManagerOptionRestoreIdentifierKey:
         @"myCentralManagerIdentifier" }];
Run Code Online (Sandbox Code Playgroud)

但应用程序醒来时的回调从未被触发.

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

-(void)centralManager:(CBCentralManager *)central
      willRestoreState:(NSDictionary *)state {
}
Run Code Online (Sandbox Code Playgroud)

这两个从未被称为.

我正在测试这个唤醒功能的方式:

  1. 我在info.plist中的后台模式中添加了"bluetooth central",因此BLE在后台运行.

  2. 在我的iphone No.1中启动centralManager.开始扫描.

  3. 按下主页然后退出,玩一些内存沉重的游戏,在调试日志中我会看到:"因内存压力而终止.进程已完成退出代码0".这是为了模拟ios系统如何因内存压力而终止后台应用程序.

  4. 与另一部iphone No.2开始一个灯塔并开始广播.

  5. 结果:那些重新启动的回调永远不会被调用.

任何想法为什么这不起作用?如果这是一个API问题,当你的手机接近BLE信标时,还有其他方法可以将你的应用重新启动到BLE的后台吗?我已经尝试使用ibeacon唤醒应用程序,但核心蓝牙中央管理器将不允许您在后台连接到ibeacon.

谢谢!

小智 13

当您单击主页按钮将应用程序发送到后台时,它会暂停,并且可以处理蓝牙代表并在后台运行10秒,此功能可以通过"在info.plist中的后台模式中添加蓝牙中心"来实现,而不是使用国家保护和恢复.

如果您的应用程序被IOS终止,由于内存压力,它无法再处理蓝牙代表.在这种情况下,如果您使用状态保存和恢复,您的应用程序可以重新启动到后台再次运行,也只有10秒.10秒后,它将进入暂停状态. 只有在这种情况下,才能触发CBCentralManager的willRestoreState.

您可以添加代码

kill(getpid(),SIGKILL);

对于按钮操作,当您单击该按钮时,您的应用程序将被IOS终止,就像被内存压力杀死一样,然后将触发"willRestoreState".

祝好运.

  • @Etan这个真的有用!应用程序不应连接到XCode,因为它会影响信号处理. (2认同)

小智 5

我在后台扫描具有已知服务的外围设备时也遇到这个问题UUIDs。也许这是 iOS 中的一个错误。我发现 iOS 在发现外围设备时确实会重新启动应用程序,通过观察 XCode 中设备管理器的控制台输出可以看出这一点。委托didFinishLaunchingWithOptions被调用,但对委托的调用CBCentralManager's willRestoreState会延迟,直到用户手动将应用程序带到前台。

就好像主线程上的事件循环没有运行,即使应用程序已经启动。例如添加代码时:

dispatch_async(dispatch_get_main_queue(), ^{
  NSLog(@"Hello from the main thread");
});
Run Code Online (Sandbox Code Playgroud)

对于didFinishLaunchingWithOptions委托,在应用程序移至前台之前,该消息不会显示在调试控制台中。

我的解决方法是使用在单独线程上运行的自定义队列,而不是queue:nil在创建CBCentralManager. 这样,当应用程序仍在后台时,就会调用代表。


Tom*_*voy 4

CoreBluetooth状态恢复仅适用于连接和外设事件。目前不支持仅依靠扫描。