Voip网络电话之PJSIP(二)

不知道小伙伴们服务器搭建好了没有,如果有什么问题可以加我QQ:294988383,验证:PJSIP。
接下来我们来编译PJSIP,关于这么PJSIP编译(坑很多):
首先官方的文档:
https://trac.pjsip.org/repos/wiki/Getting-Started/iPhone
官方文档什么鬼,全英文,不知道我英文不好么?所以我就找了别人的编译翻译:
http://blog.makeex.com/2014/06/28/pjsip-for-ios-build-mutil-target-support/
我是照着这个大神编译过程来的,前面都没有问题,编译都完成了,卡在最后合并和连接静态库上了。不懂脚本语言,所以就使用最原始的方法合并和提取。至于怎么合并和提取请搜索,iOS静态库制作。

小伙伴们拿到最后的静态库和头文件,接下来就要来实现了。
首先新建一个项目,把编译好的静态库和头文件拖进去:

2.png

目录就是这样子,接下来我们command+b 编译一下会报这样的错误:



这是因为头文件路径错误导致的,我们打开项目的setting设置一下就好了:

找到 Header Search Path 添加:

4.png

还要设置:


6.png

最后还有:


屏幕快照 2016-11-22 下午7.15.06.png

接下来我们开始正式的代码编写,首先新建一个PjsipManager的单利:
导入头文件#import"pjsua.h",一个初始化Psjip的类方法:
+ (void)pjsipInit{
    ///状态标示
    pj_status_t status;
    
    ///注册线程
    pj_bool_t bool_t = pj_thread_is_registered();
    if (!bool_t) {
        pj_thread_desc desc;
        pj_thread_t* thed;
        status = pj_thread_register(NULL,desc,&thed);
        if (status != PJ_SUCCESS)
        {
            NSLog(@"线程注册失败");
        }
    }
    
    status = pjsua_destroy();
    if (status != PJ_SUCCESS)
    {
        NSLog(@"清除信息");
    }
    
    ///初始化程序
    status = pjsua_create();
    if (status != PJ_SUCCESS){
        NSLog(@"pjsua初始化失败");
    }
    else{//初始化pjsua配置
        
        ///初始化通话配置
        pjsua_config config;
        pjsua_config_default (&config);
        //设置登录状态改变回调
        config.cb.on_reg_state2 = &on_reg_state2;
        //设置来电回调
        config.cb.on_incoming_call = &on_incoming_call;
        //设置呼叫状态改变回调
        config.cb.on_call_media_state = &on_call_media_state;
        //设置通话状态改变回调
        config.cb.on_call_state = &on_call_state;
        
        //初始化日志配置
        pjsua_logging_config log_config;
        pjsua_logging_config_default(&log_config);
        //日记等级0不打印日记 4打印详情日记
        log_config.console_level = 0;
        status = pjsua_init(&config, &log_config, NULL);
        //判断是否初始化成功
        if (status != PJ_SUCCESS)
        {
            NSLog(@"创初始化pjsua配置失败");
        }
    }
}

还有4个回调方法:

///登录状态改变回调
static void on_reg_state2(pjsua_acc_id acc_id, pjsua_reg_info *info){
    if (info->renew != 0) {
        if (info->cbparam->code == 200) {
            NSLog(@"登录成功");
        }
        else{
            NSLog(@"登录失败code:%d ",info->cbparam->code);
        }
    }
    else{
        if (info->cbparam->code == 200)
        {
            NSLog(@"SIP退出登录成功");
        }
    }
}

///来电回调
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata){
    //获取来电信息
    pjsua_call_info info;
    pjsua_call_get_info(call_id, &info);
    NSString *callStr = [NSString stringWithUTF8String:info.remote_info.ptr];
    //这里发送一个通知
    [[NSNotificationCenter defaultCenter] postNotificationName:@"calling" object:nil userInfo:@{@"calledCAcount":callStr}];
    NSLog(@"%@",callStr);
}

///呼叫回调
static void on_call_media_state(pjsua_call_id call_id)
{
    //获取呼叫信息
    pjsua_call_info info;
    pjsua_call_get_info(call_id, &info);
    
    if (info.media_status == PJSUA_CALL_MEDIA_ACTIVE)
    {//呼叫接通
        
        //建立单向媒体流从源到汇
        pjsua_conf_connect(info.conf_slot, 0);
        pjsua_conf_connect(0, info.conf_slot);
        
        NSLog(@"呼叫成功,等待对方接听");
    }
}

//通话状态改变回调
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
    
    // 通话状态:CALLING
    // 通话状态:EARLY
    // 通话状态:EARLY
    // 呼叫成功,等待对方接听
    // 通话状态:CONNECTING
    // 通话状态:CONFIRMED
    // DISCONNCTD  对方挂断
    //获取通话信息
    pjsua_call_info ci;
    pjsua_call_get_info(call_id, &ci);
    
    NSString *status = [NSString stringWithUTF8String:ci.state_text.ptr];
    NSLog(@"通话状态:%@",status);
    
    
}

还有呼叫、接应、挂断方法,也要有:


///呼叫
- (void)callAccount:(NSString *)accountsString{
    
    char accountChar[50];
    sprintf(accountChar,"sip:%s@%s",[accountsString UTF8String],[self.ip UTF8String]);
    pj_str_t url = pj_str(accountChar);
    
    //初始化呼叫
    pjsua_call_setting  call_set;
    pjsua_call_setting_default(&call_set);
    
    pj_status_t status = pjsua_call_make_call(_acc_id, &url, &call_set, NULL, NULL, NULL);
    if (status != PJ_SUCCESS)
    {
        NSLog(@"呼叫失败");
    }
}

///挂断
- (void)hangUp{
    //获账户信息
    pjsua_call_info config;
    pjsua_call_get_info(_acc_id, &config);
    
    ///判断是否在通话中
    if (config.media_status == PJSUA_CALL_MEDIA_ACTIVE)
    {
        pjsua_call_hangup_all();
    }
}

///接电话
- (void)answerCall{
    pjsua_call_answer(_called_id, 200, NULL, NULL);
}

哈哈,以上功能基本能实现接打电话功能了,接下来我们来实战,首先在AppDelegate里项目启动的时候要初始化Pjsua,当然了我们之前封装好了的,直接调用就可以了。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //初始化pjsip设置回调
    [PjsipManager pjsipInit];
    return YES;
}

页面的话,在SB里拖几个控件就行了,像这样:

Paste_Image.png

拖几条线,然后实现功能就行了,哎呀,功能我们之前已经封装好的,直接调用就行,还有就是别忘了监听通知显示来电号码哦.

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #3d1d81}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #294c50}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; min-height: 21.0px}span.s1 {font-variant-ligatures: no-common-ligatures}span.s2 {font-variant-ligatures: no-common-ligatures; color: #c32275}span.s3 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s4 {font-variant-ligatures: no-common-ligatures; color: #539aa4}span.s5 {font-variant-ligatures: no-common-ligatures; color: #3c828c}span.s6 {font-variant-ligatures: no-common-ligatures; color: #6122ae}span.s7 {font-variant-ligatures: no-common-ligatures; color: #c91b13}span.s8 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.s9 {font-variant-ligatures: no-common-ligatures; color: #3d1d81}span.s10 {font: 18.0px 'PingFang SC'; font-variant-ligatures: no-common-ligatures; color: #c91b13}

- (void)viewDidLoad {
    [super viewDidLoad];
    _manager = [PjsipManager sharedPjsipManager];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(calling:) name:@"calling" object:nil];
}

- (void)calling:(NSNotification *)notification{
    NSString *callId = notification.userInfo[@"calledCAcount"];
    _calledAccount.text = [NSString stringWithFormat:@"来电:%@",callId];
}

好了代码功能已经完成,小伙伴们已经等不及测试了吧?好吧,那让我们先启动sip服务器(有服务器的跳过了)控制台输入:
udo /usr/local/sbin/kamctl start

Paste_Image.png

启动成功,万事俱备只欠东风。

Paste_Image.png

看见控制台打印那几个字没有,登录成功,耶,登录成功了啊。那让我们来试试打电话吧,

Paste_Image.png

控制台打印了,通话状态calling 正在呼叫 disconnctd 通话断开,怎么回事呢,是因为,我另一个号lmt还没有登录,现在让我手机上跑一个项目测试下打电话.

Paste_Image.png

WTF天公不作美啊,Xcode版本太低了,我现在就升级,那么通话的测试就交给小伙伴们了。
demo我已经上传到github了,欢迎大家下载点赞。
https://github.com/SilmeLyy/PjsipDemo
另外这是实现了最基本的功能,还有好多bug,希望有大神看到了,完善项目,做一个带视频的,基于pjsip的Voip项目,期待大神的项目。
想使用linphone的小伙伴们有福了,linphone官网已经有编译好的库文件,可以直接下载使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容