不知道小伙伴們服務(wù)器搭建好了沒有,如果有什么問題可以加我QQ:294988383,驗(yàn)證:PJSIP。
接下來我們來編譯PJSIP,關(guān)于這么PJSIP編譯(坑很多):
首先官方的文檔:
https://trac.pjsip.org/repos/wiki/Getting-Started/iPhone
官方文檔什么鬼,全英文,不知道我英文不好么?所以我就找了別人的編譯翻譯:
http://blog.makeex.com/2014/06/28/pjsip-for-ios-build-mutil-target-support/
我是照著這個(gè)大神編譯過程來的,前面都沒有問題,編譯都完成了,卡在最后合并和連接靜態(tài)庫上了。不懂腳本語言,所以就使用最原始的方法合并和提取。至于怎么合并和提取請(qǐng)搜索,iOS靜態(tài)庫制作。
小伙伴們拿到最后的靜態(tài)庫和頭文件,接下來就要來實(shí)現(xiàn)了。
首先新建一個(gè)項(xiàng)目,把編譯好的靜態(tài)庫和頭文件拖進(jìn)去:

目錄就是這樣子,接下來我們command+b 編譯一下會(huì)報(bào)這樣的錯(cuò)誤:

這是因?yàn)轭^文件路徑錯(cuò)誤導(dǎo)致的,我們打開項(xiàng)目的setting設(shè)置一下就好了:
找到 Header Search Path 添加:

還要設(shè)置:

最后還有:

接下來我們開始正式的代碼編寫,首先新建一個(gè)PjsipManager的單利:
導(dǎo)入頭文件#import"pjsua.h",一個(gè)初始化Psjip的類方法:
+ (void)pjsipInit{
///狀態(tài)標(biāo)示
pj_status_t status;
///注冊(cè)線程
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(@"線程注冊(cè)失敗");
}
}
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);
//設(shè)置登錄狀態(tài)改變回調(diào)
config.cb.on_reg_state2 = &on_reg_state2;
//設(shè)置來電回調(diào)
config.cb.on_incoming_call = &on_incoming_call;
//設(shè)置呼叫狀態(tài)改變回調(diào)
config.cb.on_call_media_state = &on_call_media_state;
//設(shè)置通話狀態(tài)改變回調(diào)
config.cb.on_call_state = &on_call_state;
//初始化日志配置
pjsua_logging_config log_config;
pjsua_logging_config_default(&log_config);
//日記等級(jí)0不打印日記 4打印詳情日記
log_config.console_level = 0;
status = pjsua_init(&config, &log_config, NULL);
//判斷是否初始化成功
if (status != PJ_SUCCESS)
{
NSLog(@"創(chuàng)初始化pjsua配置失敗");
}
}
}
還有4個(gè)回調(diào)方法:
///登錄狀態(tài)改變回調(diào)
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退出登錄成功");
}
}
}
///來電回調(diào)
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];
//這里發(fā)送一個(gè)通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"calling" object:nil userInfo:@{@"calledCAcount":callStr}];
NSLog(@"%@",callStr);
}
///呼叫回調(diào)
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(@"呼叫成功,等待對(duì)方接聽");
}
}
//通話狀態(tài)改變回調(diào)
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
// 通話狀態(tài):CALLING
// 通話狀態(tài):EARLY
// 通話狀態(tài):EARLY
// 呼叫成功,等待對(duì)方接聽
// 通話狀態(tài):CONNECTING
// 通話狀態(tài):CONFIRMED
// DISCONNCTD 對(duì)方掛斷
//獲取通話信息
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
NSString *status = [NSString stringWithUTF8String:ci.state_text.ptr];
NSLog(@"通話狀態(tài):%@",status);
}
還有呼叫、接應(yīng)、掛斷方法,也要有:
///呼叫
- (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);
}
哈哈,以上功能基本能實(shí)現(xiàn)接打電話功能了,接下來我們來實(shí)戰(zhàn),首先在AppDelegate里項(xiàng)目啟動(dòng)的時(shí)候要初始化Pjsua,當(dāng)然了我們之前封裝好了的,直接調(diào)用就可以了。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//初始化pjsip設(shè)置回調(diào)
[PjsipManager pjsipInit];
return YES;
}
頁面的話,在SB里拖幾個(gè)控件就行了,像這樣:

拖幾條線,然后實(shí)現(xiàn)功能就行了,哎呀,功能我們之前已經(jīng)封裝好的,直接調(diào)用就行,還有就是別忘了監(jiān)聽通知顯示來電號(hào)碼哦.
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];
}
好了代碼功能已經(jīng)完成,小伙伴們已經(jīng)等不及測(cè)試了吧?好吧,那讓我們先啟動(dòng)sip服務(wù)器(有服務(wù)器的跳過了)控制臺(tái)輸入:
udo /usr/local/sbin/kamctl start

啟動(dòng)成功,萬事俱備只欠東風(fēng)。

看見控制臺(tái)打印那幾個(gè)字沒有,登錄成功,耶,登錄成功了啊。那讓我們來試試打電話吧,

控制臺(tái)打印了,通話狀態(tài)calling 正在呼叫 disconnctd 通話斷開,怎么回事呢,是因?yàn)?,我另一個(gè)號(hào)lmt還沒有登錄,現(xiàn)在讓我手機(jī)上跑一個(gè)項(xiàng)目測(cè)試下打電話.

WTF天公不作美啊,Xcode版本太低了,我現(xiàn)在就升級(jí),那么通話的測(cè)試就交給小伙伴們了。
demo我已經(jīng)上傳到github了,歡迎大家下載點(diǎn)贊。
https://github.com/SilmeLyy/PjsipDemo
另外這是實(shí)現(xiàn)了最基本的功能,還有好多bug,希望有大神看到了,完善項(xiàng)目,做一個(gè)帶視頻的,基于pjsip的Voip項(xiàng)目,期待大神的項(xiàng)目。
想使用linphone的小伙伴們有福了,linphone官網(wǎng)已經(jīng)有編譯好的庫文件,可以直接下載使用。