持续更新中。。。
尝试用蓝牙hid协议
文章目录
- 1.个人实践
- 1.1 app在后台处于没有被系统杀死时,可以自动重连和发数据
- 1.2 但在后台被系统杀死(没有被收到杀死),当连接状态发生变化的时候,系统会唤醒app,扫描后会调用
- 1.3 因为后台获取位置时,即使app被手动杀死,系统也会唤醒app获取位置。所有应该可以用iBeacon实现在app被手动杀死的情况下也可以发蓝牙数据。下面是本人亲测有效的app被杀死的情况下上报位置的博客
- 1.4 app连接外设后被挂起,这时其他设备搜不到外设,外设还是和app连接的,这时再手动杀死app,这时其他设备还是搜不到外设;这时关闭外设使得连接断开,app会被系统唤醒
- 1.5 app在后台或是挂起后被系统唤醒时,开定时器0.1秒调用readRSSI方法,didReadRSSI代理方法只会被调用10次。如果2秒调用一次,只会调用1~2次,也就是说只会活跃很短的一段时间,貌似是10秒
- 2.苹果官网文档 - 蓝牙后台运行
- 2.我的测试结果总结
- 3.比较有用的参考博客
- 4. iBeacon苹果官网文档和我另一篇博客
- 5.其他参考博客
1.个人实践
- 下图箭头的地方打印始终是nil
- 在xcode中点击终止(stop)后再点击运行,开始扫描的时候,下面的代理方法会被调用,并且搜不到原来的设备。如果用户手动杀死app,再扫描时,下面的代理方法不会被调用,可以搜到原来的蓝牙设备
- 有时会报出下面的错误
API MISUSE: Cancelling connection for unused peripheral <CBPeripheral: 0x282ed8280, identifier = E5FACCFF-D897xx-4353-BF95-998905C0FF07, name = (null), state = connecting>, Did you forget to keep a reference to it?
[CoreBluetooth] API MISUSE: Cancelling connection for unused peripheral
1.1 app在后台处于没有被系统杀死时,可以自动重连和发数据
1.2 但在后台被系统杀死(没有被收到杀死),当连接状态发生变化的时候,系统会唤醒app,扫描后会调用
1.3 因为后台获取位置时,即使app被手动杀死,系统也会唤醒app获取位置。所有应该可以用iBeacon实现在app被手动杀死的情况下也可以发蓝牙数据。下面是本人亲测有效的app被杀死的情况下上报位置的博客
iOS swift 在app被杀死的情况下获取(上报)位置 后台 定位 本人实测有效
1.4 app连接外设后被挂起,这时其他设备搜不到外设,外设还是和app连接的,这时再手动杀死app,这时其他设备还是搜不到外设;这时关闭外设使得连接断开,app会被系统唤醒
- 先挂起(在xcode上按stop)后手动杀死,关闭外设,app会被唤醒(百发百中)。然后再手动打开app的时候launchOptions?[UIApplication.LaunchOptionsKey.bluetoothCentrals]有值,会走willRestoreState方法。然后再手动杀死,其他设备还是搜不到外设。这时app还是处于唤醒状态。再手动打开,再app搜不到设备,再手动杀死。其他设备才可以搜到外设
- 直接手动杀死外设,关闭外设,app不会被唤醒
- app被挂起后,发数据已经测试成功
- app被挂起后手动杀死,只要外设的开关状态变化,app就会被系统唤醒(百发百中)
- app在唤醒状态下被收到打开didFinishLaunchingWithOptions方法不会被调用
- 连续几次手动打开关闭app,才会再走didFinishLaunchingWithOptions方法,launchOptions为nil,willRestoreState方法不被调用,其他设备可以搜到外设
- 调用centralManager的扫描方法,willRestoreState代理方法才会被调用
1.5 app在后台或是挂起后被系统唤醒时,开定时器0.1秒调用readRSSI方法,didReadRSSI代理方法只会被调用10次。如果2秒调用一次,只会调用1~2次,也就是说只会活跃很短的一段时间,貌似是10秒
- 定时器方法如果不进行复杂操作,一般是调用10次
2.苹果官网文档 - 蓝牙后台运行
2.我的测试结果总结
始终获取位置的弹框
弹出框不再有“始终允许”这个选项。让它们能一直获取用户位置的唯一方法是手动进入“设置>隐私>定位服务”,点击对应的程序,然后选择“始终”选项(有些App还没有这选项)。
- 下面的弹框不知道什么时候弹出,好像是app被关闭后
2.1 因ibeacon被系统唤醒后,搜索蓝牙
2.2 用ibeacon,APP被手动杀死,也是可以进行无钥匙解锁的,但是需要用到网络(蓝牙设备那边可以和服务器通讯)
2.3 通过ibeacon广播蓝牙,广播关闭后,要大概一分钟,蓝牙中心才会显示断开
2.3 蓝牙什么时候可以被系统唤醒
可以被唤醒
- 在后台被系统挂起
- 在后台被系统挂起后,然后被手动杀死
- 在后台被系统挂起后,然后被手动杀死,然后手机关机再开机
不能被唤醒
- 在前台或是在后台被手动杀死
2.4 ibeacon被系统唤醒后会活跃10秒钟
3.比较有用的参考博客
iOS App 蓝牙在程序关闭的情况下能否自动连接?如果可以应该怎么处理?
使用iBeacon在程序杀死的情况下唤醒BLE功能 - GitHub
iBeacon
详解iOS的iBeacon 后台运行
ios - iBeacon-可以使用startRangingBeacons进行检测,但不能用于didEnterRegion
Hunting the beacon: CLBeaconRegion
background fetch
stack overflow - ios background fetch
IOS后台运行 之 Background Fetch
4. iBeacon苹果官网文档和我另一篇博客
4.1 app从杀死状态,被系统唤醒后会活跃10秒,本人亲测
- 定时器设为1秒会上报10次,2秒会上报5次
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("index \(MyFileManager.shared.userDefaultIndex)")
// MyFileManager.shared.userDefaultIndex = 0
if let launch = launchOptions {
let num = launch[UIApplication.LaunchOptionsKey.location] as! NSNumber
MyFileManager.shared.sendBluetoothState(state: "didFinishLaunchingWithOptions", content: String(num.intValue))
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { (timer) in
MyFileManager.shared.sendBluetoothState(state: "timer", content:"timer")
}
}else{
MyFileManager.shared.sendBluetoothState(state: "didFinishLaunchingWithOptions", content: "noLaunchOptions")
}
return true
}
4.1.1 像下面没有声明要后台操作的定时器,一到后台就会立刻停止
4.2 ibeacon广播设备开关状态发生变化时,APP就会被唤醒,反复开关变化,app会反复的被唤醒。
- 但didFinishLaunchingWithOptions方法可能只会被调用一次。
- 关闭ibeacon的时候触发的时间比较长,打开的时候很快就触发定时器上传数据
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("index \(MyFileManager.shared.userDefaultIndex)")
// MyFileManager.shared.userDefaultIndex = 0
if let launch = launchOptions {
let num = launch[UIApplication.LaunchOptionsKey.location] as! NSNumber
MyFileManager.shared.sendBluetoothState(state: "didFinishLaunchingWithOptions", content: String(num.intValue))
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { (timer) in
MyFileManager.shared.sendBluetoothState(state: "timer", content:"timer")
}
}else{
MyFileManager.shared.sendBluetoothState(state: "didFinishLaunchingWithOptions", content: "noLaunchOptions")
}
return true
}
5.其他参考博客
iOS开发中APP在后台运行与扫描蓝牙遇到的坑
iOS 唤醒被Kill的APP保证蓝牙的长连接
Getting Location Updates for iOS 7 and 8 when the App is Killed/ Terminated/ Suspended