我聊模块两个核心类
MJMessagesBubbleController类

MJStatusBarController类

点击我聊图标,启动我聊过程详细步骤:
mj_modules::ShowMsgBubble("", true) {
1. 判断是否登录和是否存在组织
2. 是否启动应用ID为kDockClientMsgBoxIdentifierKey的应用
(1).如果没启动则启动
(2).如果有启动则获取MJStatusBarController全局单例,
并调用showBubbleWithURL:base::SysUTF8ToNSString(str_url) openlast:is_open_last_new fromType:fromType]显示
}
- (void)showBubbleWithURL:(NSString*) str_url openlast:(bool)is_open_last_new fromType:(mj_modules::ShowMsgFromType)fromType {
1. 判断是否从热键中启动
2.[self showWindowWithTitle:str_title_ url:str_url profile:[self getProfile]] 显示
}
- (void)showWindowWithTitle:(NSString *)str_title url:(NSString *)str_url profile:(Profile *) profile{
1. MJMessagesBubbleController 调用实例方法 showMessageBubble
}
- (void)showMessageBubble {
// 显示
}
Dock栏图标与115浏览器之间的通讯
当点击我聊图标时
-
MJStatusBarController类提供了一个类方法,全局获取单例 + (MJStatusBarController *)GetGloabInstance
-
初始化方法中有对MJMessagesBubbleController的引用,以及监听应用菜单栏和dock栏我聊图标的状态.
-
Dock栏我聊显示属于第三方app,不是在115浏览器项目内.所以Dock栏上我聊图标的跟新显示已经启动我聊窗口,是通过进程之间的通讯实现。
-
115浏览器内,启动Dock我聊以及状态栏图标时,添加了监听Dock栏我聊状态。
Dock栏我聊是个独立APP,作为消息的发送者,需要构建发送信息的数据:
// 生成Remote port
CFMessagePortRef remotePort;
remotePort = CFMessagePortCreateRemote(nil, (CFStringRef)kDistributedObjectServerForDockMsgBoxNameKey)
// 构建发送数据(string)
NSData *data = [NSJSONSerialization dataWithJSONObject:dicSend options:nil error:nil];
CFDataRef dataPtr = CFDataCreate(kCFAllocatorDefault,data.bytes, data.length);
// 执行发送操作
SInt32 status = CFMessagePortSendRequest(remotePort, messageID, dataPtr, timeout, timeout, NULL, NULL);
代码说明:
- CFMessagePortCreateRemote会根据MACH_PORT_REMOTE定义的字符串为唯一标识获取消息接收者通过CFMessagePortCreateLocal使用相同字符串创建的底层mach port端口,从而实现向消息接收者发送信息。
115浏览器作为消息接收者,需要注册消息监听:
NSString *kDistributedObjectServerForDockMsgBoxNameKey = @"115Browser.MsgBox.Dock.Chanel";
if (localPort) {
CFRelease(localPort);
}
if (runLoopSource) {
CFRelease(runLoopSource);
}
localPort = CFMessagePortCreateLocal(nil, (CFStringRef)kDistributedObjectServerForDockMsgBoxNameKey, CallbackMsgFromClient, nil,nil);
runLoopSource = CFMessagePortCreateRunLoopSource(nil, localPort, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
NSLog(@"start listenning");
代码说明:
- 通过CFMessagePortCreateLocal可以创建一个本地CFMessagePortRef对象
- CFMessagePort对象是靠一个字符串来唯一标识的,这一点非常重要,在这里字符串是由宏kDistributedObjectServerForDockMsgBoxNameKey定义的;
- 创建CFMessagePort对象的同时设置了端口源事件的回调函数CallbackMsgFromClient,用于处理端口源事件;
- 将创建的对象作为输入源添加到Runloop中,从而实现对端口源事件的监听,当Runloop收到对应的端口源事件时,会调用上一步中指定的回调芳芳;
在回调方法CallbackMsgFromClient内接受来自Dock栏我聊发送的信息。
static CFDataRef CallbackMsgFromClient(CFMessagePortRef port, SInt32 messageID, CFDataRef data, void *info)
{
NSLog(@"onRecvMessageCallBack is called");
.....
}
回调函数各个参数的含义为:
- CFMessagePortRef local
当前接收消息的CFMessagePortRef对象。 - SInt32 msgid
这个字段非常有用,用于标识消息。如果通信双方进程约定号每个msgid对应的数据结构,即可实现较为复杂的通信。 - CFDataRef data
通信的真正数据部分。 - void *info
为使用CFMessagePortCreateLocal方法创建port端口时指定的CFMessagePortContext对象的info字段,通常为空。
该回调方法可以返回一个CFDataRef类型的数据给port消息的发送者,以实现有效的双方通信,这一点也非常重要。
网友评论