EASession, EAAccessoryDelegate и "ОШИБКА - сбой открытия сеанса"
Я работаю с платформой внешних аксессуаров. У меня возникают проблемы с восстановлением EASession после того, как приложение переходит в фоновый режим, а затем возвращается на передний план. Если я завершу свое приложение и перезапущу, то соединение Bluetooth будет восстановлено, как и следовало ожидать. Я подозреваю, что есть какая-то часть разрыва, которого я пропускаю - или который не разоблачен (??).
[EAAccessoryManager sharedAccessoryManager] connectedAccessories]] возвращает подключенный аксессуар, и я могу запросить его, чтобы получить имя, номер модели и т. Д. Однако в следующей строке для _session устанавливается значение nil.
_session = [[EASession alloc] initWithAccessory:_accessory forProtocol:_protocolString];
Есть ли способ диагностировать причину неудачной инициализации EASession?
Есть ли какая-то мантра для очистки старой EASession?
Этот вопрос связан с этим, но я не спрашиваю совета, по какому пути идти. Я спрашиваю, почему этот путь имеет такую большую ловушку и как пройти по нему.
5 ответов
Я обнаружил (в мире постов iOS4.1), что выход из приложения (фоновый режим или выход из него) вызовет отключение DidDisconnectNotification. В случае просто нажатия кнопки питания или отключения устройства; мы не видим, что связь обрывается.
Теперь, если устройство BT выходит за пределы диапазона или переходит в режим сна. Затем связь обрывается.
В результате мы больше не зависим ни от чего, кроме уведомлений о соединениях. Мы даже не доверяем [[EAAccessoryManager sharedAccessoryManager] connectedAccessories]
список, потому что мы обнаружили, что иногда он может содержать "аксессуары-призраки", которые будут сообщать о том, что они подключены, и иметь потоки, к которым вы можете подключиться и получать доступные события записи даже после того, как вся система bluetooth вышла из строя (значок BT выключен)
Уведомления Connection кэшируются, когда вы находитесь в фоновом режиме, поэтому вы должны получить новое состояние при повторном входе в приложение.
Конечно на первой записи; Вы хотите убедиться, что вы правильно настроили всех слушателей (и т. д.).
У меня была та же проблема, и я решил ее с небольшим фокусом. Я зарегистрировал серийный номер аксессуара, когда открыл сеанс, и вошел, когда закрыл сеанс.
Вот так я и увидел, что некоторые сессии не были закрыты. Поэтому, когда мое приложение переходит в фоновый режим, я определенно закрываю все открытые сессии по устройству.
-(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];
}
Надеюсь, это поможет кому-то еще.
Насколько я могу судить, нет очистки старых экземпляров EASession. Я могу предположить, но я действительно не знаю, почему это так. Я подозреваю, что установленная EASession не освобождает свою связь со своим аксессуаром - и это препятствует успешному ассоциированию последующих экземпляров EASession с тем же аксессуаром.
Я решил оставить EASession в такте, когда приложение уходит в отставку. Кажется, это работает. В ходе тестирования я подключился к аксессуару Bluetooth, запустил свое приложение, получил доступ к аксессуару, отправил свое приложение в фоновый режим, отключил / повторно подключил аксессуар BT, вывел приложение на передний план и смог снова получить доступ к аксессуару. Это то, на что я мог надеяться.
Одно предостережение: с iOS 4.0 возможно иметь более одного аксессуара. Например, видеокабель и устройство Bluetooth являются аксессуарами.
У меня такая же проблема. Я разрабатывал приложение, которое бы открывал внешний Bluetooth-аксессуар через определенный промежуток времени, считывал некоторые данные, а затем закрывал потоки. Это работало отлично в течение нескольких дней, а затем однажды вдруг перестало работать именно с этой проблемой. Сообщение также было зарегистрировано в консоли.
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, когда она работала нормально в течение нескольких дней.
Я был озадачен и провел три дня, ударяясь головой о стену. Я искал в Google и попал сюда, я прочитал руководства Apple по общению с внешними аксессуарами и руководство по программированию NSStream. Код был все правильно.
Наконец, на третий день я услышал звуковой сигнал в углу моего стола, в моем Android-телефоне кончился сок. У меня в голове погасла лампочка. Я выключил телефон и альт, проблема на устройстве iOS ушла.
Это действительно проблема RF, а не проблема программирования, но я привожу здесь свою историю, если кто-нибудь еще столкнется с этой проблемой, Google привезет вас сюда. Выключите все другие Bluetooth-радиостанции поблизости, поскольку они являются источниками шума и могут привести к этой проблеме.
Я поднимал ту же проблему. В моем случае объект сеанса сразу после создания имеет retainCount = 3, поэтому при получении DidDisconnectNotification было недостаточно одного вызова [освобождение сеанса]. Убедитесь, что вы действительно освободили объект сеанса после получения уведомления DidDisconnectNotification.