- 最近两三个月会研究网络电话linPhone的iOS应用,网上的学习资料比较少,所以这里记录整理一下学习到的东西,分享一下,希望可以帮助到其他人。
1.linPhone源码编译
- linphone源码GitLab
-
linphone源码GitHub
源码编译完成可以得到linphoneiOS集成用到的SDK,同时源码中还有一个官方的linphoneDemo应用。所有的API调用基本都是需要从这个官方的linphoneDemo中学习。
源码编译方法,只有官方上面两个源码地址的ReadMe文件中的几步,写的很简单,但是实际操作起来问题会比较多。
这边提供当时看的几篇文章,应该可以解决大部分问题。
1.linphone-iphone的安装与调试
2.快速移植Linphone到自己的项目
3.最新linphone-iphone Demo编译运行
另外遇到问题也可以去GitHub上的issues栏搜索下问题。我之前是在移动硬盘中进行源码编译,移动硬盘的名字要是英文的,如果是中文可能会遇到问题。我之前一直编译不成功之后改了英文就可以了。 - 另外linphone支持cocoapods安装了,具体如何操作没有研究
2.linphoneSDK 方法介绍
- 源码编译虽然问题比较多,但是本文还是专注方法介绍。
2.1初始化、注册、拨打、接听、挂断、状态监听
可以参考快速移植Linphone到自己的项目 基本已经列出
transport有三种方式UDP、TCP、TLS。前面两个不需要配置什么,TLS应该是需要配置证书,具体如何操作还没有弄明白。
每次调用注册方法都会把配置信息添加到LinphoneCore中,LinphoneCore做了本地持久处理,所以LinphoneCore中的帐号配置信息会越来越多,需要调用
linphone_core_clear_proxy_config([LinphoneManager getLc]);
linphone_core_clear_all_auth_info([LinphoneManager getLc]);
可以清理到所有配置信息。
2.2 部分操作方法
每个LinphoneCore的有一个默认的配置信息,和多个其他配置信息。一个配置信息对应一个sip帐号。
配置信息对应结构体 LinphoneProxyConfig
- LinphoneProxyConfig操作方法
//获取所有配置列表
const bctbx_list_t *accounts = linphone_core_get_proxy_config_list(LC);
size_t count = bctbx_list_size(accounts);
for (size_t i = 1; i <= count; i++, accounts = accounts->next) {
LinphoneProxyConfig *proxy = (LinphoneProxyConfig *)accounts->data;
}
//获取注册状态
LinphoneRegistrationState state = linphone_proxy_config_get_state(proxy);
//获取整个sip注册帐号地址信息
const LinphoneAddress *adrs = linphone_proxy_config_get_identity_address(proxy);
//获取注册地址
NSString *domain = [[NSString alloc] initWithUTF8String:linphone_address_get_domain(adrs)];
//获取注册sip帐号
NSString *userName = [[NSString alloc] initWithUTF8String:linphone_address_get_username(adrs)];
//获取注册sip昵称
NSString *domain = [[NSString alloc] initWithUTF8String:linphone_address_get_display_name(adrs)];
//获取注册端口
NSString *domain = [[NSString alloc] initWithUTF8String:linphone_address_get_port(adrs)];
//获取注册transport
LinphoneTransportType transport = linphone_address_get_transport(adrs);
//编辑配置信息
//开始编辑
linphone_proxy_config_edit(proxy);
linphone_proxy_config_enable_register(proxy, TRUE);
//结束编辑
linphone_proxy_config_done(proxy);
- LinphoneCore操作方法(大部分初始化和配置设置都是通过linphone_core设置)
//设置超时
linphone_core_set_inc_timeout(LC, 60);
//创建配置表
LinphoneProxyConfig *proxyCfg = linphone_core_create_proxy_config(LC);
//添加注册认证证书
linphone_core_add_auth_info(LC, authInfo);
//添加到配置表,添加到linphone_core
linphone_core_add_proxy_config(LC, proxyCfg);
//设置成默认配置表
linphone_core_set_default_proxy_config(LC, proxyCfg);
//获取默认配置表
LinphoneProxyConfig *default_proxy = linphone_core_get_default_proxy_config(LC);
//获取所有配置列表
const bctbx_list_t *accounts = linphone_core_get_proxy_config_list(LC);
//重新注册所有配置信息(刷新状态)
linphone_core_refresh_registers(LC);
2.3音视频编码设置(注册帐号的时候设置)
- 音频编码设置
const bctbx_list_t *codescs = linphone_core_get_audio_codecs(LC);
- (void)synchronizeCodecs:(const MSList *)codecs {
PayloadType *pt;
const MSList *elem;
for (elem = codecs; elem != NULL; elem = elem->next) {
pt = (PayloadType *)elem->data;
NSString *sreung = [NSString stringWithFormat:@"%s", pt->mime_type];
NSString *normalBt = [NSString stringWithFormat:@"%d",pt->clock_rate];
//sreung 有这些值 opus,speex,PCMU,PCMA,GSM,G722,G729,iLBC,mpeg4-generic,iSAC,L16
//设置音频编码格式 G711-u,G711-a
if ([sreung isEqualToString:@"PCMU"]||[sreung isEqualToString:@"PCMA"]) {
linphone_core_enable_payload_type(LC,pt, TRUE);
}else
{
linphone_core_enable_payload_type(LC, pt, FALSE);
}
}
}
- 视频编码设置
const bctbx_list_t *codescs = linphone_core_get_video_codecs(LC);
- (void)synchronizeVideoCodecs:(const MSList *)codecs {
PayloadType *pt;
const MSList *elem;
for (elem = codecs; elem != NULL; elem = elem->next) {
pt = (PayloadType *)elem->data;
NSString *sreung = [NSString stringWithFormat:@"%s", pt->mime_type];
if ([sreung isEqualToString:@"H264"]) {
linphone_core_enable_payload_type(LC, pt, 1);
}else {
linphone_core_enable_payload_type(LC, pt, 0);
}
}
}
2.4铃声设置
铃声设置调用API设置
NSString *path = [[NSBundle mainBundle] pathForResource:@"notes_of_the_optimistic" ofType:@"caf"];
const char *cPath = [path UTF8String];
linphone_core_set_ring(LC, cPath);
2.5通话记录获取
官方Demo中的 HistoryListTableView.m 中有代码。通话记录存储在本地DB中
NSString *db = [NSString stringWithUTF8String:linphone_core_get_call_logs_database_path(LC)];
NSLog(@"history DB:%@",db);
历史记录
//获取所有本地通话logs
const bctbx_list_t *logs = linphone_core_get_call_logs(LC);
//获取1001帐号本地通话logs
// LinphoneAddress *adr = [LinphoneUtils normalizeSipOrPhoneAddress:@"1001"];
// bctbx_list_t *logs = linphone_core_get_call_history_for_address(LC, adr);
//遍历所有通话记录
// while (logs != NULL) {
// LinphoneCallLog *log = (LinphoneCallLog *)logs->data;
//}
//打印一条记录
if(logs!=NULL){
LinphoneCallLog *log = (LinphoneCallLog *)logs->data;
//通话开始时间
NSDate *startDate = [NSDate
dateWithTimeIntervalSince1970:linphone_call_log_get_start_date(log)];
//通话状态类型
LinphoneCallStatus status = linphone_call_log_get_status(log);
//拨打方 LinphoneAddress
LinphoneAddress *fromAddress = linphone_call_log_get_from_address(log);
//接听方 LinphoneAddress
LinphoneAddress *toAddress = linphone_call_log_get_to_address(log);
//对方 LinphoneAddress
LinphoneAddress *remoteAddress = linphone_call_log_get_remote_address(log);
NSString *callStatus = @"None";
switch (status) {
case LinphoneCallSuccess:
callStatus = @"LinphoneCallSuccess";
break;
case LinphoneCallAborted:
callStatus = @"LinphoneCallAborted";
break;
case LinphoneCallMissed:
callStatus = @"LinphoneCallMissed";
break;
case LinphoneCallDeclined:
callStatus = @"LinphoneCallDeclined";
break;
case LinphoneCallEarlyAborted:
callStatus = @"LinphoneCallEarlyAborted";
break;
case LinphoneCallAcceptedElsewhere:
callStatus = @"LinphoneCallAcceptedElsewhere";
break;
case LinphoneCallDeclinedElsewhere:
callStatus = @"LinphoneCallDeclinedElsewhere";
default:
break;
}
//通过address 获取名字 地址等等
NSString *fromName = [NSString stringWithUTF8String:linphone_address_get_username(fromAddress)];
NSString *toName = [NSString stringWithUTF8String:linphone_address_get_username(toAddress)];
NSString *remoteName = [NSString stringWithUTF8String:linphone_address_get_username(remoteAddress)];
NSString *fromDomain = [NSString stringWithUTF8String:linphone_address_get_domain(fromAddress)];
NSString *toDomain = [NSString stringWithUTF8String:linphone_address_get_domain(toAddress)];
NSString *remoteDomain = [NSString stringWithUTF8String:linphone_address_get_domain(remoteAddress)];
NSString *callDir = @"None";
//获取通话类型 拨出 打进
LinphoneCallDir direction = linphone_call_log_get_dir(log);
switch (direction) {
case LinphoneCallIncoming:
callDir = @"LinphoneCallIncoming";
break;
case LinphoneCallOutgoing:
callDir = @"LinphoneCallOutgoing";
break;
default:
break;
}
//通话时长 s
int duration = linphone_call_log_get_duration(log);
NSLog(@"startTime:%@,LinphoneCallStatus:%@,fromName:%@,fromDomain:%@,toName:%@,toDomain:%@,remoteName:%@,remoteDomain:%@,callDir:%@,duration:%d",startDate,callStatus,fromName,fromDomain,toName,toDomain,remoteName,remoteDomain,callDir,duration);
}
3.freeSwitch安装
安装流程链接: https://pan.baidu.com/s/1ZamVLvc-fXjmRTyjKvIWIw 提取码: e7h4
4.sip协议通话流程
5.linphone源码修改 (sip信令修改)
linphone源码都是在执行sdk编译命令的目录下的submodules里面,如果需要修改就需要看这部分的内容。
可以通过命令 查找文件名或者文件内容一个个找。。。。
列举一下我修改的源码。主要是sip信令的内容。
5.1 CSeq数字修改
Sequence Number linphone 默认从20开始
修改的地方在 Submodules/linphone/src/sal/op.cpp 522行
image.png
5.2 去除Contact参数后面的+sip.instance +org.linphone.specs
修改的地方也在oc.cpp 710行
image.png
5.3 修改401 unauthorized 之后register 中的Authorization中的CNonce
Submodules/belle-sip/src/auth_helper 25 行 修改生成的位数 默认16位
image.png
修改生成规则 Submodules/belle-sip/src/belle_sip_utils.c 267行和278行
选取的字符串数组
image.png
生成随机字符串,如果改了symbols,需要修改下图中的63。修改为symbols的长度-1;顺便提一下 我没见过 (val & 63)这样取数字的方法。😓
image.png
其他可以通过sdk api设置
5.4修改自定义header头
linphone_proxy_config_set_custom_header(proxyCfg, [@"Accept" UTF8String], [@"application/sdp" UTF8String]);
5.5修改Contact参数
linphone_proxy_config_set_contact_parameters(proxyCfg, [@"expires=3600" UTF8String]);
5.6修改信令中的expires
linphone_proxy_config_set_expires(proxyCfg,3600);
5.7修改User-Agent
NSString *device = [[NSMutableString alloc]
initWithString:[NSString
stringWithFormat:@"%@_iOS%@",
[NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"],
UIDevice.currentDevice.systemVersion]];
device = [device stringByReplacingOccurrencesOfString:@"," withString:@"."];
device = [device stringByReplacingOccurrencesOfString:@" " withString:@"."];
linphone_core_set_user_agent(theLinphoneCore, device.UTF8String, "3.16-122-g79a8bb2");
网友评论