10

我正在使用外部附件框架。在应用程序进入后台然后返回前台后,我在重新建立 EASession 时遇到问题。如果我终止我的应用程序并重新启动,那么蓝牙连接会按照预期重新建立。我怀疑我遗漏了拆解的某些部分 - 或者没有暴露 (??)。

[EAAccessoryManager sharedAccessoryManager] connectedAccessories]] 正在返回我连接的附件,我可以查询它以获取名称、型号等。但是,以下行将 _session 设置为 nil。

_session = [[EASession alloc] initWithAccessory:_accessory forProtocol:_protocolString];

有什么方法可以诊断 EASession 初始化失败的原因吗?

是否有一些清除旧 EASession 的咒语?

这个问题与这个问题有关-但我并不是在寻求关于遵循哪条路径的建议。我在问为什么这条路径有这么大的陷阱以及如何绕过它。

4

5 回答 5

8

我发现(在 iOS4.1 之后的世界中)离开应用程序(后台或退出)会导致 DidDisconnectNotification 触发。在只是按下电源按钮或让设备休眠的情况下;我们没有看到连接断开。

现在,如果 BT 设备超出范围或自行进入睡眠状态。然后连接断开。

结果,我们不再依赖 ConnectionNotifications 以外的任何东西。我们甚至不信任该[[EAAccessoryManager sharedAccessoryManager] connectedAccessories]列表,因为我们发现它有时可能包含“幽灵配件”,这些配件会说它们已连接,并且即使在整个蓝牙系统出现故障后,您也可以连接并获取写入可用事件的流(BT图标关闭)

当您在后台时,ConnectionNotifications 会被缓存,因此当您重新进入应用程序时,您应该会获得一个全新的状态。

当然是第一次进入;您要确保已正确设置所有侦听器(等)。

于 2010-12-16T05:21:20.983 回答
2

我有同样的问题,并用一个小技巧解决了它。我在打开会话时记录了配件的序列号,并在关闭会话时记录了附件的序列号。

这就是我看到一些会话没有关闭的方式。因此,当我的应用程序进入后台模式时,我肯定会按设备关闭所有打开的会话。

-(void) closeSessionForDevice:(EAAccessory*) device{
EASession *lclSession = (EASession*) [sessionDictionary valueForKey:[device serialNumber]];
[[lclSession inputStream] close];
[[lclSession inputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[lclSession inputStream] setDelegate:nil];

[[lclSession outputStream] close];
[[lclSession outputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[lclSession outputStream] setDelegate:nil];

lclSession = nil;

NSLog(@"Session Closed for : %@", [device serialNumber]);

[device setDelegate:nil];
}

希望它可以帮助别人。

于 2014-05-06T15:05:35.133 回答
2

据我所知,没有清除旧的 EASession 实例。我可以假设,但我真的不知道为什么会这样。我怀疑已建立的 EASession 不会释放其与其附件的关联 - 这会阻止后续 EASession 实例与同一附件成功关联。

当应用程序退出活动时,我选择保留 EASession。这似乎奏效了。在测试中,我已连接到蓝牙配件,启动我的应用程序,访问配件,将我的应用程序发送到后台,断开/重新连接 BT 配件,将应用程序带到前台并能够再次访问配件。这是我所希望的。

一个警告:在 iOS 4.0 中,可以有多个附件。例如,视频线和蓝牙设备都是附件。

于 2010-12-14T20:11:42.647 回答
2

我有同样的问题。我正在开发一个应用程序,它将按时间间隔打开一个外部蓝牙附件,读取一些数据,然后关闭流。这几天一直运行良好,然后突然有一天它停止处理这个确切的问题。控制台也记录了一条消息。

2015-06-20 23:54:43.371 MyApp[2083:404019] ERROR - opening session failed
1 2015-06-20 23:54:43.371 MyApp[2083:404019] ERROR - /SourceCache/ExternalAccessory/ExternalAccessory-288.20.7/       EASession.m:-[EASession dealloc] - 141 unable to close session for _accessory=0x174018750 and sessionID=65536

Apple 文档很清楚,每次只允许打开每个协议的一个实例,并且任何先前的实例都会自动释放。但是,为什么 iOS 在之前的 EASession 已经运行了好几天时,却突然无法解除分配。

我很困惑,我花了三天时间把头撞在墙上。我搜索了谷歌并最终来到这里,我阅读了 Apple 关于与外部配件通信的指南和 NSStream 编程指南。代码都是正确的。

终于在第三天,我听到桌角传来一声哔哔声,我的安卓手机没电了。一个灯泡在我脑海里熄灭了。我关掉手机,中提琴,iOS 设备上的问题消失了。

这确实是一个 RF 问题,而不是编程问题,但我在这里写下我的故事,以防其他人遇到这个问题,谷歌会把你带到这里。关闭附近的所有其他蓝牙无线电,因为它们是噪音源并可能导致此问题。

于 2015-06-21T19:33:23.827 回答
-1

我遇到了同样的问题。在我的例子中,会话对象在创建之后,retainCount = 3,因此在接收 DidDisconnectNotification 时调用 [会话释放] 是不够的。确保在收到 DidDisconnectNotification 通知后确实释放了会话对象。

于 2011-01-15T13:40:22.477 回答