标签:nap 系统 not found 准备 部分 依赖 表示 sap star
我自己集成的Demo & SDK源码路径
最新版SDK下载地址
开始前先安利下江湖哥简书,当初都是照着这一步步摸索的http://www.jianshu.com/p/2ba2d4aa168e
更新ipv6
见文末
正文开始。 很多场景下,我们的App会使用到VOIP通话,虽然目前各大通讯公司都推出了各自的SDK,相比Linphone,它们对开发者更为友好(体现在有更及时的技术支持、丰富的开发文档),但有些时候,迫于某些需求,也只有掏出Linphone SDK,硬着头皮上了。而我是为了实现纯SIP通话,以及客户需求,所以进行了对Linphone SDK的集成、开发,本文的目的一为记录以便日后翻阅,二为了让后来的开发者少跳一些坑,白白耽误时间。 首先我们要下载一个重要的Linphone Demo ,需要CSDN的2积分,如果没有可以留言问我要。只能在真机上运行。
1. 准备工作 1.1 添加依赖库 为支持新版ipv6 SDK,需要再添加VideoToolBox.framework
1.2 相关配置
1.3 http请求设置 从iOS9开始,苹果建议所有的网络请求都要使用https,如果还想保留原有的http请求方式,开发者需要修改配置文件(注:xcode7.0以下则不需要修改),在工程名的文件夹下面的Supporting Files文件夹中找到并且选择(工程名)lnfo.pList在右边出现的窗口中添加Key:NSAppTransportSecurity,在下面添加项:NSAllowsArbitraryLoads,设置Boolean值为YES,这样平台SDK内部工程才能支持http请求方式。
1.4 后台运行 一般的iOS程序进入后台后会被系统挂起,就会停止执行,不能执行任何操作。
从iOS4开始,苹果增加了特性,很好的支持了语音通话功能:
苹果支持应用可以在后台播放和录制声音;
苹果支持网络托管,保证应用在后台时,还能保持网络连接,能接收到来电;
应用可以设置一个超时处理,程序在后台运行时,周期性地唤醒应用,保证客户端和服务器有长连接,使网络不断开。
SDK封装了这些特性,保证了在iOS平台上,有很好的语音通话体验。 开发者需要修改配置文件,这样iOS工程才能支持这些特性。
在工程名的文件夹下面的Supporting Files文件夹中找到并且选择(工程名)lnfo.pList在右边出现的窗口中添加Key: Required background modes,在下面添加两个项:App plays audio和App provides Voice over IP services。(注:如果只是使用发起通话,并无接听功能,则不需要添加App provides Voice over IP services)
2. 导入Linphone SDK 上面工作做完后就可以开始导入Linphone SDK了。
2.1 首先再回到这个熟悉的页面,点击Add Other
2.2 找到下载好的sdk目录,把所有.a库都选择,如下图。
2.3 查看是否关联 Build Settings搜索 Search Paths,在下列两个选项下观察是否已经关联,如图
顺带说一下这个libxml2,大多数时候是不需要的,如果报一些莫名其妙的错误不妨将其导入,且在Build Phases里添加相应库libxml2.tbd
2.4 编译 如果出现了形如“file not found”的错误提示,回到第三步,检查头文件、静态库是否关联成功
3. 功能实现 这一部分可以参考CSDN Linphone Demo(以下统称为CDemo),也可以直接下载我在github代码里的SDK代码部分,更为直接。
3.1 初始化 需要关注CSDN Demo里的主要功能类LinphoneManage.m 实现如下方法即可
1 2 3 4 5 6 7 8 9 10 11 @author Jozo, 16-06-30 11:06:18 初始化 */ - (void)startUCSphone { [[LinphoneManager instance] startLibLinphone ]; [UCSIPCCSDKLog saveDemoLogInfo:@"初始化成功" withDetail:nil] ; }
3.2 注册 注册方法在CDemo的manager类里没有直接的体现,值得注意的是我标注“三个大坑”的地方,如果有需要用到displayName这个参数的同学一定要注意了,设置好displayName后一定要通过linphone_address_as_string(..)
方法再次获取identity,然后再调用linphone_proxy_config_set_identity(proxyCfg, identity);
将新的identity设置到设置文件中,因为我开始没理清这个proxyCfg的实现逻辑,始终没注意到这一步,还有就是使用了另一个函数linphone_address_as_string_uri_only
的误导 ,是误导 ,后者获取到的仅有“sip:”以及之后的那个字符串,并不会将昵称也带进去传入proxyCfg,导致displayName一直设置不成功,掉坑三日终于在某个狂风乱作的下午解决此bug,导致天气都变得风和日丽起来。
注:以下账号、密码、IP、端口需要自己注册。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 @author Jozo, 16-06-30 11:06:13 登陆 大专栏 怎样将Linphone移植到自己的项目 s="line"> @param username 用户名 @param password 密码 @param displayName 昵称 @param domain 域名或IP @param port 端口 @param transport 连接方式 */ - (BOOL )addProxyConfig:(NSString *)username password:(NSString *)password displayName:(NSString *)displayName domain:(NSString *)domain port:(NSString *)port withTransport:(NSString *)transport { LinphoneCore* lc = [LinphoneManager getLc]; if (lc == nil ) { [self startUCSphone]; lc = [LinphoneManager getLc]; } LinphoneProxyConfig* proxyCfg = linphone_core_create_proxy_config(lc); NSString * server_address = domain; char normalizedUserName[256 ]; linphone_proxy_config_normalize_number(proxyCfg, [username cStringUsingEncoding:[NSString defaultCStringEncoding]], normalizedUserName, sizeof (normalizedUserName)); const char *identity = [[NSString stringWithFormat:@"sip:%@@%@" , username, domain] cStringUsingEncoding:NSUTF8StringEncoding ]; LinphoneAddress* linphoneAddress = linphone_address_new(identity); linphone_address_set_username(linphoneAddress, normalizedUserName); if (displayName && displayName.length != 0 ) { linphone_address_set_display_name(linphoneAddress, (displayName.length ? displayName.UTF8String : NULL )); } if ( domain && [domain length] != 0 ) { if ( transport != nil ){ server_address = [NSString stringWithFormat:@"%@:%@;transport=%@" , server_address, port, [transport lowercaseString]]; } linphone_proxy_config_set_server_addr(proxyCfg, [server_address UTF8String]); linphone_address_set_domain(linphoneAddress, [domain UTF8String]); } identity = linphone_address_as_string(linphoneAddress); linphone_address_destroy(linphoneAddress); LinphoneAuthInfo* info = linphone_auth_info_new([username UTF8String] , NULL , [password UTF8String] , NULL , linphone_proxy_config_get_realm(proxyCfg) ,linphone_proxy_config_get_domain(proxyCfg)); [self setDefaultSettings:proxyCfg]; [self clearProxyConfig]; linphone_proxy_config_set_identity(proxyCfg, identity); linphone_proxy_config_set_expires(proxyCfg, 2000 ); linphone_proxy_config_enable_register(proxyCfg, true ); linphone_core_add_auth_info(lc, info); linphone_core_add_proxy_config(lc, proxyCfg); linphone_core_set_default_proxy_config(lc, proxyCfg); ms_free(identity); [UCSIPCCSDKLog saveDemoLogInfo:@"登陆信息配置成功" withDetail:[NSString stringWithFormat:@"username:%@,npassword:%@,ndisplayName:%@ndomain:%@,nport:%@ntransport:%@" , username, password, displayName, domain, port, transport]]; return TRUE ; }
3.3 拨打电话 接着简单的调用如下方法即可进行SIP呼叫。`
1 [[LinphoneManager instance] call :address displayName :displayName transfer :transfer ];
值得注意的是,呼叫状态、登陆状态的回调都是通过通知来传递的,所以要想获取这些回调,可以监听这些回调,具体通知名在LinphoneManager.h里,形如“kLinphoneCallUpdate”,也可以像我一样,在LinphoneManager.m的各个回调处,将相应的通知改为自己想要设置的代理方法,并设置好代理,可以看我在Github Demo里的LinphoneManager.m处如下方法里的实现。
1 2 3 - (void)on Register:(LinphoneCore *)lc cfg:(LinphoneProxyConfig*) cfg state :(LinphoneRegistrationState) state message:(const char*) message; - (void)on Call :(LinphoneCall *)call StateChanged:(LinphoneCall State)state withMessage:(const char *)message;
4. 为支持ipv 6而导入新版Linphone SDK 旧版SDK不支持ipv6,更后到新版后linphonecore.h增加了一个新的宏LINPHONE_DEPRECATED
,有此标记表示该函数已弃用,而我由于只用到了SIP电话,故直接替换sdk后只报了如下错误,下面一一解决
4.1 替换LINPHONE_DEPRECATED标识的函数 弃用的函数都有对应的新函数,在注释里可以轻易找到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 * @return the default proxy configuration, that is the one used to determine the current identity. * @deprecated Use linphone_core_get_default_proxy_config() instead. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config); * @ingroup media_parameters * Get default call parameters reflecting current linphone core configuration * @param lc LinphoneCore object * @return LinphoneCallParams * @deprecated use linphone_core_create_call_params() */ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc);
4.2 删除弃用库的初始化 在上图中提现为“_libmsilbc_init”, referenced from:..这是因为新版linphone sdk里lib文件夹里的.a库变动,有删有减少,而libmsilbc.a则被移除了,故要在LinphoneManager createLinphoneCore]
里删除libmsilbc_init();
4.3 第三个bug是上两个错误所导致 解决1、2,自然也会解决3。
基本就是这么多了,其实回想起来也不是特别复杂,只是初次上手时网路上没有太多资料文档,大多靠自己摸索,以及在少得可怜的博客中慢慢领悟也是挺辛酸的,希望大家少走弯路吧。
如有其它麻烦可以电邮我 ischenzht@gmail.com
That’s all, thank you.
怎样将Linphone移植到自己的项目
标签:nap 系统 not found 准备 部分 依赖 表示 sap star
原文地址:https://www.cnblogs.com/dajunjun/p/11711248.html