iOS Voip Socket不会在后台运行

Joe*_*oel 21 voip objective-c background-process cfreadstream ios4

我正在获得一个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);
Run Code Online (Sandbox Code Playgroud)

然后我的回调设置如下:

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];
}
Run Code Online (Sandbox Code Playgroud)

当我收到数据并且应用程序处于打开状态时,"Callback Happened"会被调用,但如果应用程序被最小化则不会.但是,当应用程序恢复时,它会处理收到的所有数据,同时最小化.

我将voip标签添加到info.plist中.我的CFReadStreamSetProperty返回true.我在设备上运行而不是模拟器.它仍然无法正常工作,所以我不知道我的问题是什么.我可能只是做了一些愚蠢的事情,但几乎没有任何在线检查我的代码.

编辑:我无法测试任何答案,因为我不再在这个项目上工作,也无法访问mac/iOs sdk.如果有类似问题的人发现下面的答案之一有用,请告诉我,我会投票给他最好的答案.

Joe*_*ian 28

如果你想让你的VOIP应用程序在后台运行,除了plist文件中的那些基本设置,你需要一个TCP套接字,其属性设置为VOIP,当你的应用程序进入后台时,iOS系统将为你照顾这个套接字,每个东西都是'睡眠',除了tcp socket.如果VOIP服务器发送一些认为TCP套接字的数据,你的应用程序将被唤醒10秒.在此期间,您可以发布本地通知.

只有Tcp套接字可以设置为VOIP套接字.但据我所知,大多数VOIP应用程序都基于UDP套接字.如果您不想将控制套接字与数据套接字分开.你应该创建另一个专注于"唤醒"你的应用程序的tcp套接字,根据我的个人经验,很难保持这个"清醒"信号和真正的sip控制信号同步,应用程序总是会错过sip邀请请求.

因此,最好的方法是将sip控件单独与UDP数据套接字分开,使其成为tcp套接字,这是最佳解决方案,但绝不使用tcp套接字来传输语音数据.

另一种肮脏的方式:让应用程序始终保持清醒状态.正如我所说,每个TCP单应用程序收到认为'VOIP'tcp套接字,将使应用程序保持唤醒10秒,所以在此持续时间结束时(9秒后),您可以向服务器发送响应以请求另一个信号,当下一个信号到达时,应用程序将再次唤醒,9秒后,再次发送响应.继续这样做,你的应用程序将永远清醒.

  • 金色知识 (11认同)

avi*_*hic 5

我陷入了完全相同的情况.
我的问题是我配置了多个插槽作为Voip插座.

您可以在Apple关于voip的文档中看到他们说:
" 为VoIP使用配置一个应用程序套接字"

我猜他们只是根据一个插座唤醒你的应用程序.

提到的所有其他内容仍然是正确的:

  • kCFStreamNetworkServiceTypeVoIP
  • 'info.plist'UIBackgroundModes:voip,audio
  • 'info.plist'UIRequiresPersistentWifi键
  • 不会在模拟器上工作