配置iOS VoIP应用程序以在睡眠/后台模式下运行

时间:2014-12-24 05:02:16

标签: ios objective-c sockets voip sleep-mode

我正在开发基于VoIP的iOS(7.1)应用程序。它的底层套接字编程是用C ++而不是客观C编写的。应用程序在前台运行良好,但在进入睡眠/后台模式时,它无法接收来自服务器的任何通信。 根据apple文档,我们必须配置一个用于VoIP使用的app套接字。我无法弄清楚如何配置C ++套接字(因为有很多套接字;即SSL,SIP,RESTful)。

目的是让应用程序处于睡眠模式,直到它被杀死。从SO中尝试了几个链接甚至几个链接,但由于我是新手,我希望这个配置有一步一步的过程。 [注意:在某个地方我找到了 CoreFoudation框架,我是否需要使用它?]

2 个答案:

答案 0 :(得分:13)

编辑:从iOS8开始,Apple推出了PushKit框架,以释放我们配置VoIP应用所需的工作,并且还减少了能源使用。你真的需要迁移到它

有关开发VoIP应用程序的提示,请参考Apple

互联网协议语音(VoIP)应用程序允许用户使用互联网连接而不是设备的蜂窝服务拨打电话。这样的应用程序需要维持与其关联服务的持久网络连接,以便它可以接收传入呼叫和其他相关数据。系统不是让VoIP应用程序始终保持唤醒状态,而是允许它们被暂停,并提供监视其套接字的工具。当检测到传入流量时,系统唤醒VoIP应用程序并将其套接字的控制权返回给它。

实施VoIP应用有几个要求:

  1. 为您的应用启用Voice over IP后台模式。 (由于VoIP应用涉及音频内容,因此建议您还启用音频和AirPlay背景模式。)您可以在Xcode项目的Capabilities选项卡中启用后台模式。
  2. 配置应用程序的其中一个套接字以供VoIP使用。
  3. 在移至后台之前,请调用setKeepAliveTimeout:handler:方法来安装要定期执行的处理程序。您的应用可以使用此处理程序来维护其服务连接。
  4. 配置音频会话以处理往返过渡 积极使用。
  5. 要确保在iPhone上获得更好的用户体验,请使用Core Telephony 用于调整与基于手机的手机相关的行为的框架 电话;请参阅核心电话框架参考。
  6. 要确保VoIP应用程序的良好性能,请使用系统 配置框架,用于检测网络更改并允许您的应用 尽可能多地睡觉。
  7. 启用VoIP后台模式可让系统知道应该允许应用在后台运行以管理其网络套接字。此键还允许您的应用播放背景音频(尽管仍然鼓励启用音频和AirPlay模式)。支持此模式的应用程序也会在系统启动后立即在后台重新启动,以确保VoIP服务始终可用。


    下面的代码显示了如何为VoIP使用配置应用程序套接字。

    第1步:连接到服务器

    uint16_t port ;
    NSString *strIp ;
    char ip[20] = {0} ;
    memset(ip, 0, sizeof(ip)) ;
    memcpy(ip, [strIp UTF8String], [strIp length]) ;
    
    clientSocket = socket(AF_INET, SOCK_STREAM, 0) ;
    struct sockaddr_in server_addr ;
    bzero(&server_addr, sizeof(server_addr)) ;
    server_addr.sin_port = htons(port) ;
    server_addr.sin_addr.s_addr = inet_addr(ip) ;
    server_addr.sin_family = AF_INET ;
    
    int i = connect(clientSocket, (const struct sockaddr *)&server_addr, sizeof(server_addr)) ;
    if (i >= 0) {
    }
    

    服务器端代码可能在C ++环境中,但您可以将clientSocket传递给Objective-C实例,它是int值。

    第2步:创建和配置读写流

    连接到服务器后,您需要创建一个读取和放大器。使用clientSocket根据CFStreamCreatePairWithSocket()写入流,并使用NSStreamNetworkServiceTypeVoIP设置流的属性。

    定义读写流并保持强引用。当连接丢失时关闭并释放它们。

    @property (nonatomic, strong) NSInputStream *inputStream ;
    @property (nonatomic, strong) NSOutputStream *outputStream ;
    

    然后配置流:

    CFReadStreamRef readStreamRef = nil ;
    CFWriteStreamRef writeStreamRef = nil ;
    CFStreamCreatePairWithSocket(NULL, clientSocket, &readStreamRef, &writeStreamRef) ; // the socket must have already been connected.
    _inputStream = (__bridge_transfer NSInputStream *)readStreamRef ;
    _outputStream = (__bridge_transfer NSOutputStream *)writeStreamRef ;
    [_inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
    [_outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
    [_inputStream open] ;
    [_outputStream open] ;
    

    在连接read& amp;之前确保套接字已连接写流。

    第3步:保持连接

    [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
        // the code to check if the socket is connected to server
        // if not, reconnect to server 
        // and re-set the read stream and write stream in step2
    }] ;
    

    当您的应用程序进入后台时,套接字由系统管理,当服务器将数据包发送到您的应用程序时,系统将其唤醒,将数据包传递给它。你只有几秒钟来处理数据,所以不要在这里做太多工作。由于它是一个VoIP应用程序,因此套接字应该用于通知用户呼叫是传入的,您可以推送本地通知以使用户意识到这一点。

    由于VoIP应用程序需要保持运行才能接收来电,因此如果应用程序以非零退出代码退出,系统会自动重新启动应用程序。 (当存在内存压力并且您的应用程序因此终止时,可能会发生此类型的退出。)但是,终止应用程序还会释放其所有套接字,包括用于维护VoIP服务连接的套接字。因此,当应用程序启动时,它总是需要从头开始创建它的套接字。

    我创建了一个示例项目here,相关的服务器端代码here

答案 1 :(得分:2)

在配置套接字之上,您需要对iOS应用Info.plist文件进行一些更改,您应在其中指定voip后台模式。

可在此处找到更多详细信息:Apple Dev Documentation

相关问题