IOS Voip Socket не будет работать в фоновом режиме
Я получаю сокет VOIP для запуска в фоновом режиме в приложении iOS.
Мое соединение работает нормально, но оно не проснется, когда мое приложение перейдет в фоновый режим. Однако, если я открываю приложение, оно отвечает на любые сообщения, которые он получил, пока он спал.
Я установил свой поток следующим образом:
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(CFStringRef) @"test.iusealocaltestserver.com",
5060,
&myReadStream,
&myWriteStream);
CFReadStreamSetProperty ( myReadStream,
kCFStreamNetworkServiceType,
kCFStreamNetworkServiceTypeVoIP
);
CFSocketNativeHandle native;
CFDataRef nativeProp = CFReadStreamCopyProperty(myReadStream, kCFStreamPropertySocketNativeHandle);
CFDataGetBytes(nativeProp, CFRangeMake(0, CFDataGetLength(nativeProp)), (UInt8 *)&native);
CFRelease(nativeProp);
CFSocketRef theSocket = CFSocketCreateWithNative(kCFAllocatorDefault, native, 0, NULL, NULL);
CFSocketGetContext(theSocket,&theContext);
CFOptionFlags readStreamEvents = kCFStreamEventHasBytesAvailable |
kCFStreamEventErrorOccurred |
kCFStreamEventEndEncountered |
kCFStreamEventOpenCompleted;
CFReadStreamSetClient(myReadStream,
readStreamEvents,
(CFReadStreamClientCallBack)&MyCFReadStreamCallback,
(CFStreamClientContext *)(&theContext));
CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
Затем мой обратный вызов настроен следующим образом:
static void MyCFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void *pInfo);
static void MyCFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Callback Happened");
[pool release];
}
"Callback Happened" получает вызов, когда я получаю данные, и приложение открыто, но это не так, если приложение сведено к минимуму. Тем не менее, когда приложение возвращается, оно обрабатывает любые полученные данные и минимизируется.
Я добавил тег voip в info.plist. Мой CFReadStreamSetProperty возвращает true. Я запускаю устройство, а не симулятор. Это все еще не работает, поэтому я не знаю, что может быть с моей проблемой. Я, наверное, просто сделал что-то глупое, но почти ничего не было, чтобы проверить мой код.
EDIT: я не могу проверить ни один из ответов, потому что я больше не работаю над этим проектом и не имею доступа к mac/iOs sdk. Если кто-то с подобной проблемой нашел один из приведенных ниже ответов полезным, дайте мне знать, и я проголосую за его лучший ответ.
Ответы
Ответ 1
Если вы хотите, чтобы ваше приложение VOIP выполнялось в фоновом режиме, за исключением тех базовых настроек в файле plist, вам нужен сокет TCP, для которого установлено значение VOIP, чем система iOS позаботится о том, что ваш сокет для вас, когда ваше приложение введите фон, каждая вещь была "спящей", за исключением того, что tcp socket. и если сервер VOIP отправит некоторые данные, которые считают, что TCP-сокет, ваше приложение пробудится в течение 10 секунд. в течение этого времени вы можете публиковать локальное уведомление.
Только гнездо Tcp может быть установлено как VOIP Socket. Но я знаю, в основном приложение VOIP основано на сокете UDP. если вы не хотите отделять управляющий сокет от гнезда данных. вы должны создать еще один сокет tcp, который фокусируется на "бодрствовании" вашего приложения, и из моего личного опыта очень сложно сохранить этот "активный" сигнал, а реальный сигнал управления sip синхронизируется, приложение всегда пропускает запрос приглашения sip.
Итак, лучший способ - отделить сингл-сингл от сокета данных UDP, сделать его как сокет tcp, это лучшее решение, но никогда не использовать tcp-сокет для передачи голосовых данных.
Другой грязный способ: постоянно поддерживать приложение. Как я уже сказал, каждый TCP-сингл, полученный приложением, считал, что "VOIP" tcp-сокет будет поддерживать приложение в течение 10 секунд, поэтому в конце этой продолжительности (через 9 секунд) вы можете отправить ответ на сервер, чтобы попросить другой сигнал, когда поступит следующий сигнал, приложение снова проснется, после 9 секунд отправьте ответ еще раз. продолжайте делать это, ваше приложение пробудится навсегда.
Ответ 2
Я застрял в одном и том же сценарии.
Моя проблема заключалась в том, что я сконфигурировал несколько сокетов в качестве сокета Voip.
вы можете увидеть в документацию Apple о voip, которую они говорят:
"Настроить один из сокетов приложений для использования VoIP"
Я предполагаю, что они только пробуждают ваше приложение в соответствии с одним сокетом.
все остальные упоминаемые вещи все еще верны:
- kCFStreamNetworkServiceTypeVoIP
- 'info.plist' UIBackgroundModes: voip, audio
- 'info.plist' ключ UIRequiresPersistentWifi
- НЕ будет работать над симулятором
Ответ 3
У меня тоже такая же проблема. но в моем случае все работает нормально, если не произойдут изменения сети. Я использовал класс "достижимости" для обнаружения изменений в сети. если приложение находится в фоновом режиме до того момента, когда мой сокет работает, даже если я вручную переключил свою сеть на следующие.
После некоторого времени, скажем, снова попробуйте сетевой переключатель вручную. ничего не случилось, кажется, что мое приложение не обнаруживает изменения в сети. Я прочитал ниже яблочный документ. я уверен, что неправильно (или) не понял шаги 3 и 6.
Существует несколько требований для применения VoIP-приложения:
1. Добавьте ключ UIBackgroundModes в файл Info.plist вашего приложения. Установите значение этой клавиши в массив, содержащий строку voip.
-
Настройте один из сокетов приложений для использования VoIP.
-
Прежде чем переходить на задний план, вызовите метод setKeepAliveTimeout: обработчик: для установки обработчика, который будет выполняться периодически. Ваше приложение может использовать этот обработчик для поддержания своего сервисного соединения.
-
Настройте свой сеанс аудио для обработки переходов в активном режиме и из него.
5. Чтобы обеспечить лучший пользовательский интерфейс на iPhone, используйте инфраструктуру Core Telephony, чтобы настроить свое поведение по отношению к телефонным звонкам на сотовой основе; см. ссылку на базовую платформу телефонии.
- Чтобы обеспечить хорошую производительность для вашего VoIP-приложения, используйте инфраструктуру System Configuration для обнаружения изменений в сети и позволяйте вашему приложению спать как можно больше.
Ответ 4
Вам может потребоваться установить <key>UIBackgroundModes</key><array><string>audio</string></array>
в Info.plist, и вам нужно убедиться, что сеанс аудио активен/работает/независимо от того, как вы переключаете приложения (предполагается, что вы не начнете внезапно начать запись/воспроизведение музыка/что угодно, когда ваше приложение находится в фоновом режиме).
Документы говорят, что "аудио" позволяет воспроизводить аудио в фоновом режиме, но, предположительно, это также относится к записи звука. Если это не сработает, вы можете попробовать несколько вещей:
- Установите "voip" и "audio".
- Слушать тишину (это может быть проще всего сделать с Audio Queue API).
Ответ 5
У вас есть 'applicationDidEnterBackground:' в делетете приложения. Я почти уверен, что где-то читал (чего не могу найти), что вам нужно определить, что ios распознает, что вы поддерживаете фоновый режим. Вам не нужно ничего внедрять в нем.
например.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}