背景
我想使用linphone的朋友都有下載官方的demo揪罕。但是里面真的是耦合度太高了蠢莺。讀了好多遍發(fā)現(xiàn)他控制器跳轉(zhuǎn)的代碼都是很舊的了雄可,所以想把他功能給擇出來是有一定的難度的购公。 我從網(wǎng)上找到ESSipManager
這個文件 芯侥。大家可以在github上搜索下泊交。不過這個人封裝的工程中引用的linphone
sdk比較舊了。好像官網(wǎng)上是把那個sdk刪除了柱查。所以下載下來會報錯活合。我就是在他的基礎(chǔ)上改了點東西。 感覺基本上可以實現(xiàn)常規(guī)的功能物赶,所以分享給大家白指。
SDK的安裝
目前SDK安裝已經(jīng)支持cocoaPods 所以在你原來的podfile代碼里加上" pod 'linphone-sdk' , '4.3'
如果請求過程很慢的話 再把源指定下source "https://gitlab.linphone.org/BC/public/podspec.git"
使用
//
// ESSipManager.m
// EasySip
// edit by ivna.evecom. 1361817133@qq.com
#import "ESSipManager.h"
#import "LinphoneManager.h"
#import "FastAddressBook.h"
#define LC ([LinphoneManager getLc])
NSString *const ES_ON_REMOTE_OPEN_CEMERA = @"ES_ON_REMOTE_OPEN_CEMERA";
NSString *const ES_ON_CALL_COMMING = @"ES_ON_CALL_COMMING";
NSString *const ES_ON_CALL_END = @"ES_ON_CALL_END";
NSString *const ES_ON_CALL_STREAM_UPDATE = @"ES_ON_CALL_STREAM_UPDATE";
NSString *const ES_ON_Call_StateOutgoingInit = @"ES_ON_CallStateOutgoingInit";
NSString *const ES_ON_REGISTER_STATE = @"ES_ON_REGISTER_STATE";
@implementation ESSipManager
static ESSipManager* _instance = nil;
+(instancetype) instance
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:NULL] init] ;
}) ;
return _instance ;
}
+(id)allocWithZone:(struct _NSZone *)zone
{
return [ESSipManager instance];
}
-(id)copyWithZone:(struct _NSZone *)zone
{
return [ESSipManager instance];
}
- (instancetype)init {
self = [super init];
if (self) {
[[LinphoneManager instance] startLinphoneCore];
LinphoneLoggingService * logService = linphone_logging_service_get();
linphone_logging_service_set_log_level(logService,LinphoneLogLevelFatal);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onCallUpdate:) name:kLinphoneCallUpdate object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(registrationUpdate:)
name:kLinphoneRegistrationUpdate
object:nil];
}
return self;
}
- (void)registrationUpdate:(NSNotification *)notif {
LinphoneRegistrationState state = [[notif.userInfo objectForKey:@"state"] intValue];
if (state == LinphoneRegistrationFailed &&
[UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
[[NSNotificationCenter defaultCenter]postNotificationName:ES_ON_REGISTER_STATE object:self userInfo:@{@"state":@"failed",@"message":[notif.userInfo objectForKey:@"message"]}];
} else if (state == LinphoneRegistrationOk) {
DLog(@"注冊成功!");
[[NSNotificationCenter defaultCenter]postNotificationName:ES_ON_REGISTER_STATE object:self userInfo:@{@"state":@"success",@"message":[notif.userInfo objectForKey:@"message"]}];
}
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void) login: (NSString*) username password: (NSString*) password displayName: (NSString*) displayName domain: (NSString*) domain port: (NSString *) port withTransport: (NSString*) transport {
LinphoneProxyConfig *config = linphone_core_create_proxy_config(LC);
LinphoneAddress *addr = linphone_address_new(NULL);
LinphoneAddress *tmpAddr = linphone_address_new([NSString stringWithFormat:@"sip:%@",domain].UTF8String);
linphone_address_set_username(addr, username.UTF8String);
linphone_address_set_port(addr, linphone_address_get_port(tmpAddr));
linphone_address_set_domain(addr, linphone_address_get_domain(tmpAddr));
if (displayName && ![displayName isEqualToString:@""]) {
linphone_address_set_display_name(addr, displayName.UTF8String);
}
linphone_proxy_config_set_identity_address(config, addr);
if (transport) {
linphone_proxy_config_set_route(
config,
[NSString stringWithFormat:@"%s;transport=%s", domain.UTF8String, transport.lowercaseString.UTF8String]
.UTF8String);
linphone_proxy_config_set_server_addr(
config,
[NSString stringWithFormat:@"%s;transport=%s", domain.UTF8String, transport.lowercaseString.UTF8String]
.UTF8String);
}
linphone_proxy_config_enable_publish(config, FALSE);
linphone_proxy_config_enable_register(config, TRUE);
LinphoneAuthInfo *info =
linphone_auth_info_new(linphone_address_get_username(addr), // username
NULL, // user id
password.UTF8String, // passwd
NULL, // ha1
linphone_address_get_domain(addr), // realm - assumed to be domain
linphone_address_get_domain(addr) // domain
);
linphone_core_add_auth_info(LC, info);
linphone_address_unref(addr);
linphone_address_unref(tmpAddr);
LCSipTransports linp = {-1,-1,-1,-1};
//linphone_core_set_sip_transports
if (linphone_core_set_sip_transports(LC, &linp)) { //設(shè)置隨機端口
}
if (config) {
[[LinphoneManager instance] configurePushTokenForProxyConfig:config];
if (linphone_core_add_proxy_config(LC, config) != -1) {
linphone_core_set_default_proxy_config(LC, config);
// reload address book to prepend proxy config domain to contacts' phone number
// todo: STOP doing that!
// [LinphoneManager instance]
// [[LinphoneManager.instance fastAddressBook] fetchContactsInBackGroundThread];
// [PhoneMainView.instance changeCurrentView:DialerView.compositeViewDescription];
} else {
// [self displayAssistantConfigurationError];
}
} else {
// [self displayAssistantConfigurationError];
}
NSLog(@"登陸信息配置成功!\nusername:%@,\npassword:%@,\ndisplayName:%@\ndomain:%@,\nport:%@\ntransport:%@", username, password, displayName, domain, port, transport);
}
- (void) logout {
[[LinphoneManager instance] lpConfigSetBool:FALSE forKey:@"pushnotification_preference"];
LinphoneCore *lc = [LinphoneManager getLc];
LCSipTransports transportValue = {5060,5060,-1,-1};
if (linphone_core_set_sip_transports(lc, &transportValue)) {
NSLog(@"cannot set transport");
}
[[LinphoneManager instance] lpConfigSetString:@"" forKey:@"sharing_server_preference"];
[[LinphoneManager instance] lpConfigSetBool:FALSE forKey:@"ice_preference"];
[[LinphoneManager instance] lpConfigSetString:@"" forKey:@"stun_preference"];
linphone_core_set_stun_server(lc, NULL);
linphone_core_set_firewall_policy(lc, LinphonePolicyNoFirewall);
// linphone_core_set_nat_policy()
// linphone_core_set_nat_policy(LC,&LinphonePolicyNoFirewall);
}
- (void) call: (NSString*) username displayName: (NSString*) displayName {
LinphoneCall *call = [[LinphoneManager instance] callByUsername:username];
if (call == nil) {
NSLog(@"撥打失敗");
} else {
NSLog(@"正在撥叫...\naddress:%@,\ndisplayName:%@", username, displayName);
}
}
- (void) acceptCall: (LinphoneCall*) call {
[[LinphoneManager instance] acceptCall:call evenWithVideo:true];
NSLog(@"接聽電話");
}
- (void) hangUpCall {
LinphoneCore* lc = [LinphoneManager getLc];
LinphoneCall* currentcall = linphone_core_get_current_call(lc);
if (linphone_core_is_in_conference(lc) || // In conference
(linphone_core_get_conference_size(lc) > 0) // Only one conf
) {
linphone_core_terminate_conference(lc);
} else if(currentcall != NULL) { // In a call
// linphone_core_terminate_call(lc, currentcall);
//linphone_call_terminate()
linphone_call_terminate(currentcall);
// linphone_core_terminate_all_calls(lc)
} else {
const MSList* calls = linphone_core_get_calls(lc);
//bctbx_list_size()
if (bctbx_list_size(calls) == 1) { // Only one call
// linphone_core_terminate_call(lc,(LinphoneCall*)(calls->data));
linphone_core_terminate_all_calls(lc);
}
}
NSLog(@"掛斷");
}
- (void) configVideo: (UIView*) videoView cameraView: (UIView*) cameraView {
linphone_core_set_native_video_window_id([LinphoneManager getLc], (__bridge void *)(videoView));
linphone_core_set_native_preview_window_id([LinphoneManager getLc], (__bridge void *)(cameraView));
}
- (void) requestOpenCamera {
if (!linphone_core_video_display_enabled(LC)){
NSLog(@"1111");
return;
}
LinphoneCall *call = linphone_core_get_current_call(LC);
if (call) {
NSLog(@"2222");
LinphoneCallAppData *callAppData = (__bridge LinphoneCallAppData *)linphone_call_get_user_data(call);
callAppData->videoRequested = TRUE; /* will be used later to notify user if video was not activated because of the linphone core*/
LinphoneCallParams *call_params = linphone_core_create_call_params(LC,call);
linphone_call_params_enable_video(call_params, TRUE);
linphone_core_update_call(LC, call, call_params);
linphone_call_params_destroy(call_params);
} else {
NSLog(@"Cannot toggle video button, because no current call");
}
}
- (void) closeCamera {
if (!linphone_core_video_display_enabled(LC))
return;
[LinphoneManager.instance setSpeakerEnabled:FALSE];
LinphoneCall *call = linphone_core_get_current_call(LC);
if (call) {
LinphoneCallParams *call_params = linphone_core_create_call_params(LC,call);
linphone_call_params_enable_video(call_params, FALSE);
linphone_core_update_call(LC, call, call_params);
linphone_call_params_destroy(call_params);
} else {
NSLog(@"Cannot toggle video button, because no current call");
}
}
-(BOOL)isVideoEnabled{
bool video_enabled = false;
LinphoneCall *currentCall = linphone_core_get_current_call(LC);
if (linphone_core_video_supported(LC)) {
if (linphone_core_video_display_enabled(LC) && currentCall && !linphone_core_sound_resources_locked(LC) &&
linphone_call_get_state(currentCall) == LinphoneCallStreamsRunning) {
video_enabled = TRUE;
}
}
if (video_enabled) {
video_enabled = linphone_call_params_video_enabled(linphone_call_get_current_params(currentCall));
}
return video_enabled;
}
- (void) onCallUpdate: (NSNotification*) notification {
NSDictionary* userInfo = [notification userInfo];
NSValue* c = [userInfo valueForKey:@"call"];
// int state = (int)[userInfo valueForKey:@"state"];
LinphoneCallState state = [[userInfo objectForKey:@"state"] intValue];
NSString* message = [userInfo valueForKey:@"message"];
NSLog(@"========== state: %d, message: %@", state, message);
LinphoneCall* call = c.pointerValue;
NSDictionary *dict = @{@"call" : [NSValue valueWithPointer:call],
@"state" : [NSNumber numberWithInt:state],
@"message" : message};
switch (state) {
case LinphoneCallIncomingReceived:
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_CALL_COMMING object: self userInfo:dict];
case LinphoneCallOutgoingInit:
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_Call_StateOutgoingInit object:self userInfo:dict];
case LinphoneCallConnected:
case LinphoneCallStreamsRunning: {
// check video
if (![self isVideoEnabled]) {
const LinphoneCallParams *param = linphone_call_get_current_params(call);
const LinphoneCallAppData *callAppData =
(__bridge const LinphoneCallAppData *)(linphone_call_get_user_data(call));
if (state == LinphoneCallStreamsRunning && callAppData->videoRequested &&
linphone_call_params_low_bandwidth_enabled(param)) {
// too bad video was not enabled because low bandwidth
NSLog(@"帶寬太低,無法開啟視頻通話");
callAppData->videoRequested = FALSE; /*reset field*/
}
}
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_CALL_STREAM_UPDATE object:self userInfo:dict];
break;
}
case LinphoneCallUpdatedByRemote: {
const LinphoneCallParams *current = linphone_call_get_current_params(call);
const LinphoneCallParams *remote = linphone_call_get_remote_params(call);
DLog(@"%d",(linphone_core_video_display_enabled([LinphoneManager getLc])));
DLog(@"%d",!linphone_call_params_video_enabled(current));
DLog(@"%d",linphone_call_params_video_enabled(remote));
DLog(@"%d",!linphone_core_get_video_policy([LinphoneManager getLc])->automatically_accept);
/* remote wants to add video */
if ((linphone_core_video_display_enabled([LinphoneManager getLc]) && !linphone_call_params_video_enabled(current) &&
linphone_call_params_video_enabled(remote)) &&
(!linphone_core_get_video_policy([LinphoneManager getLc])->automatically_accept ||
(([UIApplication sharedApplication].applicationState != UIApplicationStateActive) &&
floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max))) {
linphone_core_defer_call_update([LinphoneManager getLc], call);
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_REMOTE_OPEN_CEMERA object: self userInfo:dict];
} else if (linphone_call_params_video_enabled(current) && !linphone_call_params_video_enabled(remote)) {
}
break;
}
case LinphoneCallUpdating:
break;
case LinphoneCallPausing:
case LinphoneCallPaused:
break;
case LinphoneCallPausedByRemote:
break;
case LinphoneCallEnd://LinphoneCallEnd
[NSNotificationCenter.defaultCenter postNotificationName:ES_ON_CALL_END object: self userInfo:NULL];
case LinphoneCallError:
default:
break;
}
}
-(void) allowToOpenCameraByRemote: (LinphoneCall*)call {
LinphoneCallParams *params = linphone_core_create_call_params([LinphoneManager getLc], call);
linphone_call_params_enable_video(params, TRUE);
linphone_call_accept_update(call, params);
linphone_call_params_destroy(params);
}
-(void) refuseToOpenCameraByRemote: (LinphoneCall*)call {
LinphoneCallParams *params = linphone_core_create_call_params(LC, call);
linphone_call_params_enable_video(params, FALSE);
linphone_call_accept_update(call, params);
linphone_call_params_destroy(params);
}
-(void)switchCamera{
const char *currentCamId = (char *)linphone_core_get_video_device(LC);
const char **cameras = linphone_core_get_video_devices(LC);
const char *newCamId = NULL;
int i;
for (i = 0; cameras[i] != NULL; ++i) {
if (strcmp(cameras[i], "StaticImage: Static picture") == 0)
continue;
if (strcmp(cameras[i], currentCamId) != 0) {
newCamId = cameras[i];
break;
}
}
if (newCamId) {
// LOGI(@"Switching from [%s] to [%s]", currentCamId, newCamId);
linphone_core_set_video_device(LC, newCamId);
LinphoneCall *call = linphone_core_get_current_call(LC);
if (call != NULL) {
linphone_call_update(call, NULL);
}
}
}
-(BOOL)turnOnVideo{
if (!linphone_core_video_display_enabled(LC)){
DLog(@"執(zhí)行到這里...");
return false;
}
LinphoneCall *call = linphone_core_get_current_call(LC);
if (call) {
LinphoneCallAppData *callAppData = (__bridge LinphoneCallAppData *)linphone_call_get_user_data(call);
callAppData->videoRequested =
TRUE; /* will be used later to notify user if video was not activated because of the linphone core*/
LinphoneCallParams *call_params = linphone_core_create_call_params(LC,call);
linphone_call_params_enable_video(call_params, TRUE);
linphone_call_update(call, call_params);
linphone_call_params_unref(call_params);
DLog(@"執(zhí)行到這里...");
return true;
} else {
DLog(@"執(zhí)行到這里...");
// LOGW(@"Cannot toggle video button, because no current call");
return false;
}
}
-(BOOL)turnOffVideo{
if (!linphone_core_video_display_enabled(LC))
return false;
[LinphoneManager.instance setSpeakerEnabled:FALSE];
// [self setEnabled:FALSE];
// [waitView startAnimating];
LinphoneCall *call = linphone_core_get_current_call(LC);
if (call) {
LinphoneCallParams *call_params = linphone_core_create_call_params(LC,call);
linphone_call_params_enable_video(call_params, FALSE);
linphone_core_update_call(LC, call, call_params);
linphone_call_params_destroy(call_params);
return true;
} else {
// LOGW(@"Cannot toggle video button, because no current call");
return false;
}
}
-(NSString*) getCallName: (LinphoneCall*)call {
if (call == NULL)
return NULL;
LinphoneAddress *addr = linphone_call_get_remote_address(call);
return [FastAddressBook displayNameForAddress:addr];
}
@end
如上圖所示 每個方法都有介紹了酵紫。
注冊 domin 填入你們自己的地址
func loginWithInfo(_ info:JSON){
let userInfo = info["userinfo"].stringValue
let dic = SimpleOperation.getDictionaryFromJSONString(jsonString:userInfo)
consoleLine(message: dic)
let videoPhone = dic["videophone"] as? String ?? ""
consoleLine(message: videoPhone)
let name = dic["name"] as? String ?? ""
ESSipManager.instance()?.login(videoPhone, password: "123456", displayName: name, domain: "", port: "5060", withTransport: "TCP")
}
func logOut(){
ESSipManager.instance()?.logout()
}
退出
func logOut(){
ESSipManager.instance()?.logout()
}
撥打電話
ESSipManager.instance()?.call(phone, displayName: name)
接聽電話 注冊一個通知 然后接聽到之后 進行跳轉(zhuǎn)
最后.電腦端 下載一個Linphone 手機端運行下告嘲。倆端互撥 。慢慢調(diào)咯奖地。祝各位好運橄唬。