XMPP系列(六)---创建群组
最近公司项目需要,要做一个自己的IMSDK,顺便先把之前没有记录的群聊功能记录一下。
先上资料,查看XMPP群聊相关的资料,可以去这里看协议:XEP-0045 。
创建群组
XMPP 框架里有一个类XMPPRoom,利用这个类可以很容易的创建一个新的群组。
1.创建群组的JID。
群组的JID与用户的JID有一些区别。
用户的JID规则是<userId@domain>。
群组的JID规则是<roomId@subdomain.domain/nick>。
而群组的subdomain 是需要提前在服务器端设置好的。
1.1创建群组的服务
如何创建群组服务呢?
在openfire 后台---> 分组聊天--->分组聊天设置中可以看到创建新的服务按钮。不知道的看下图:
1.2 创建群组JID
怎么写群组的JID呢?
举个例子,如果我们要创建一个叫做abc 的群组,而我们的群组服务subdomain是group,而domain 是im.joker.cn,那么这个群组的JID就是abc@group.im.joker.cn。
JID 很重要,如果服务地址写错了,那么创建群组就没反应。
另外 服务地址,必须是域名,不能是IP,否则也没反应。
至于roomId的规则,这可以看你们的需求咯,比如我这里就是用时间,示例代码:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyyMMddHHmmss"];
NSString *currentTime = [formatter stringFromDate:[NSDate date]];
NSString *roomId = [NSString stringWithFormat:@"%@@group.im.joker.cn/%@",currentTime,[JKXMPPTool sharedInstance].xmppStream.myJID.bare];
XMPPJID *roomJID = [XMPPJID jidWithString:roomId];
2.设置群组的存储策略
// 如果不需要使用自带的CoreData存储,则可以使用这个。
// XMPPRoomMemoryStorage *xmppRoomStorage = [[XMPPRoomMemoryStorage alloc] init];
// 如果使用自带的CoreData存储,可以自己创建一个继承自XMPPCoreDataStorage,并且实现了XMPPRoomStorage协议的类
// XMPPRoomHybridStorage在类注释中,写了这只是一个实现的示例,不太建议直接使用这个,我这里为了图演示方便,就先用XMPPRoomHybridStorage吧。
XMPPRoomHybridStorage *xmppRoomStorage = [XMPPRoomHybridStorage sharedInstance];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomStorage jid:roomJID dispatchQueue:dispatch_get_main_queue()];
3.激活XMPPRoom
XMPPRoom继承自XMPPModule ,所以它也是需要使用XMPPStream来激活,并且也需要设置代理。
[xmppRoom activate:[JKXMPPTool sharedInstance].xmppStream];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
4.加入群组
这一步只有一行代码,但是却有两种不同的情况。
[xmppRoom joinRoomUsingNickname:@"haley" history:nil password:nil];
执行这一步时,如果房间已经存在,则是加入房间的操作。
而如果房间不存在,则会先创建房间,然后再加入房间。
5.设置群组的信息
设置群组的参数,是创建群组成功,并加入群组成功后的代理方法中。
在XEP-0045中创建保留房间的章节下面有一个例子:
例子 147. 例子 149.,里面有比较全的可以配置群组(房间)的参数。具体的可以配置的参数也可以在创建群成功后调用XMPPRoom的{- fetchConfigurationForm}方法,去查看。
| 参数 | 类型 | 说明 |
|---|---|---|
| muc#roomconfig_roomname | text-single | 群名称 |
| muc#roomconfig_roomdesc | text-single | 群的简短描述 |
| muc#roomconfig_changesubject | boolean | 是否允许群成员更改房间的主题 |
| muc#roomconfig_allowinvites | boolean | 是否允许邀请其他人进群 |
| muc#roomconfig_maxusers | list-single | 群成员的最大数量 |
| muc#roomconfig_presencebroadcast | list-multi | 我也不知道干啥的 |
| muc#roomconfig_publicroom | boolean | 群是否是公共的(在获取自己的群列表时,会获取到自己加入的群和公共的群) |
| muc#roomconfig_persistentroom | boolean | 群是否是永久的 |
| muc#roomconfig_moderatedroom | boolean | 房间是适度的(我猜测是标识临时群) |
| muc#roomconfig_membersonly | boolean | 是否只对群成员开放 |
| muc#roomconfig_passwordprotectedroom | boolean | 是否为群设置了密码,如果设置了密码,需要填写密码才能加群 |
| muc#roomconfig_roomsecret | text-private | 群密码 |
| muc#roomconfig_whois | list-single | 谁可以看到成员Jid |
| muc#roomconfig_roomadmins | jid-multi | 设置哪些人为管理员 |
| muc#roomconfig_roomowners | jid-multi | 设置哪些人为群拥有者(不知道干啥的) |
| x-muc#roomconfig_canchangenick | boolean | 是否允许群成员修改自己的群昵称 |
| x-muc#roomconfig_registration | boolean | 是否允许用户注册到房间 |
下面是设置的示例代码:
- (void)configNewRoom:(XMPPRoom *)xmppRoom
{
NSXMLElement *x = [NSXMLElement elementWithName:@"x"xmlns:@"jabber:x:data"];
NSXMLElement *p = [NSXMLElement elementWithName:@"field" ];
[p addAttributeWithName:@"var"stringValue:@"muc#roomconfig_persistentroom"];//永久房间
[p addChild:[NSXMLElement elementWithName:@"value"stringValue:@"1"]];
[x addChild:p];
p = [NSXMLElement elementWithName:@"field" ];
[p addAttributeWithName:@"var"stringValue:@"muc#roomconfig_maxusers"];//最大用户
[p addChild:[NSXMLElement elementWithName:@"value"stringValue:@"10000"]];
[x addChild:p];
p = [NSXMLElement elementWithName:@"field" ];
[p addAttributeWithName:@"var"stringValue:@"muc#roomconfig_changesubject"];//允许改变主题
[p addChild:[NSXMLElement elementWithName:@"value"stringValue:@"1"]];
[x addChild:p];
p = [NSXMLElement elementWithName:@"field" ];
[p addAttributeWithName:@"var"stringValue:@"muc#roomconfig_publicroom"];//公共房间
[p addChild:[NSXMLElement elementWithName:@"value"stringValue:@"0"]];
[x addChild:p];
p = [NSXMLElement elementWithName:@"field" ];
[p addAttributeWithName:@"var"stringValue:@"muc#roomconfig_allowinvites"];//允许邀请
[p addChild:[NSXMLElement elementWithName:@"value"stringValue:@"1"]];
[x addChild:p];
[xmppRoom configureRoomUsingOptions:x];
}
6.XMPPRoom的代理方法
XMPPRoom 相关的代理方法也有很多个,可以在XMPPRoomDelegate中看到,我在下面介绍几个常用的代理方法,其他的大家可以自己去XMPPRoomDelegate中查看。
6.1 创建群成功的代理方法
创建成功的代理方法一般都是调试用,实际场景应该是创建群,并且自己加入群成功之后才提醒创建成功。
- (void)xmppRoomDidCreate:(XMPPRoom *)sender
{
NSLog(@"房间创建成功");
}
6.2 加入群组成功的代理方法
创建者加入群之后,就可以设置一些群的参数信息了。
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
{
NSLog(@"加入房间成功");
// 一般就是在这里设置群组的一些参数
[self configNewRoom:sender];
[sender fetchConfigurationForm];
[sender fetchBanList];
[sender fetchMembersList];
[sender fetchModeratorsList];
}
6.3 查看群组的配置信息
调用XMPPRoom 的 {-fetchConfigurationForm},然后就可以在下面这个回调方法中获取群组的配置信息
- (void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm
{
NSLog(@"configForm:%@",configForm);
}
插入知识
在XMPP 里有 角色、岗位和权限三个概念。
角色有那些呢?
岗位有哪些呢?
已定义的岗位有:
1. 所有者
2. 管理员
3. 成员
4. 被排斥者
5. 无(缺少岗位)
权限又哪些呢?
大部分情况下, 岗位存在一个层次结构. 例如, 一个所有者可以做任何管理员能做的事情, 而一个管理员可以做任何成员能做的事情. 每个岗位拥有其下一级岗位所没有的权限; 这些权限定义在下表中。
作为缺省值, 一个无岗位的用户进入一个被主持的房间的角色是一个游客, 而进入一个开放的房间的角色是一个与会者. 一个成员进入一个房间的角色是与会者. 一个管理员或所有者进入房间的角色是一个主持人.
一个管理员或所有者不能(MUST NOT)撤销另一个管理员或所有者的权限.
6.4 查找被群组拉黑,禁止加群的成员列表
调用XMPPRoom 的{-fetchBanList},然后就可以在下面这个代理方法中获取到被禁止的名单列表了
// 收到禁止名单列表
- (void)xmppRoom:(XMPPRoom *)sender didFetchBanList:(NSArray *)items
{
NSLog(@"%s",__func__);
}
// 获取禁止名单列表失败
- (void)xmppRoom:(XMPPRoom *)sender didNotFetchBanList:(XMPPIQ *)iqError
{
NSLog(@"%s",__func__);
}
6.5 获取群成员列表
从上图可以看出,一个群组里的所有人员,按照一般需求,除了Member,剩下的Admin 和Owner 都可以归为Moderator 这一类。
同样的,调用XMPPRoom 的{-fetchMembersList},就可以在如下代理方法中获取群成员列表
// 收到成员名单列表
- (void)xmppRoom:(XMPPRoom *)sender didFetchMembersList:(NSArray *)items
{
NSLog(@"%s",__func__);
}
// 获取群成员列表失败
- (void)xmppRoom:(XMPPRoom *)sender didNotFetchMembersList:(XMPPIQ *)iqError
{
NSLog(@"%s",__func__);
}
6.6 获取Moderators列表
调用XMPPRoom 的{-fetchModeratorsList}方法,然后在代理方法中能够获取到列表。
// 收到主持人名单列表
- (void)xmppRoom:(XMPPRoom *)sender didFetchModeratorsList:(NSArray *)items
{
NSLog(@"%s",__func__);
}
// 获取主持人名单列表失败
- (void)xmppRoom:(XMPPRoom *)sender didNotFetchModeratorsList:(XMPPIQ *)iqError
{
NSLog(@"%s",__func__);
}
Demo地址:ChatDemo
XMPP系列(六)---创建群组的更多相关文章
- Office 365系列六 ------ 创建sharepoint online网站
这节跟大家介绍简单的创建sharep online私有网站集,sharepoint online 可以给我们提供开箱即用的功能,比如文档库:可以给我们取代File Server,提供了版本管理,版本变 ...
- Centos 7搭建Gitlab服务器以及操作(创建项目,创建群组,创建用户,添加密钥)
一. 安装并配置依赖包 在CentOS系统上安装所需的依赖:ssh,防火墙,postfix(用于邮件通知) ,wget,以下这些命令也会打开 系统防火墙中的HTTP和SSH端口访问 安装前准备 命令: ...
- XMPP系列(七)---获取群组列表
上一篇介绍了如何创建群组,这一篇就介绍一下,如何获取自己的群组列表. 在上一篇有提到,如果我们创建的群组是公共的群组,那么获取自己的群组列表时,会获取到自己的群组列表和那些公共的群组.而实际做社交的应 ...
- Linux 的账号与群组[转自vbird]
Linux 的账号与群组 管理员的工作中,相当重要的一环就是『管理账号』啦!因为整个系统都是你在管理的, 并且所有一般用户的账号申请,都必须要透过你的协助才行!所以你就必须要了解一下如何管理好一个服务 ...
- Linux学习之CentOS(十)----Linux 的账号与群组
Linux 的账号与群组 管理员的工作中,相当重要的一环就是『管理账号』啦!因为整个系统都是你在管理的, 并且所有一般用户的账号申请,都必须要透过你的协助才行!所以你就必须要了解一下如何管理好一个服务 ...
- 详解CorelDRAW中关于群组的操作
CorelDRAW软件中的“群组”功能键主要用于整合多个对象.在进行比较复杂的绘图编辑时,通常会有很多的图形对象,为了方便操作,可以对一些对象设定群组.设定群组以后的多个对象,将被看作一个单独的对象. ...
- linux基础-第六单元 用户、群组和权限
用户及passwd文件 /etc/passwd文件的功能 /etc/passwd文件每个字段的具体含义 shadow文件 /etc/shadow文件的功能 /etc/shadow文件每个字段的具体含义 ...
- linux基础命令--groupadd 创建新的群组
描述 groupadd命令用于创建一个新的群组. groupadd命令默认会根据命令行指定的值和系统下的/etc/login.defs文件定义的值去修改系统下的/etc/group和/etc/gsha ...
- sql server 备份与恢复系列六 文件组备份与还原
一. 概述 文件备份是指备份一个或多个文件或文件组中的所有数据.使用文件备份能够只还原损坏的文件,而不用还原数据库的其余部份,从而加快恢复速度.例如,如果数据库由位于不同磁盘上的若干文件组成,在其中一 ...
随机推荐
- python学习记录 - python3.x中如何实现print不换行
python3.x中如何实现print不换行 大家应该知道python中print之后是默认换行的, 那如何我们不想换行,且不想讲输出内容用一个print函数输出时,就需要改变print默认换行的 ...
- 2018年Java后端面试经历
楼主16年毕业,16年三月份进入上一家公司到今年3月底,所以这是一份两年工作经验面经分享. 都说金三银四,往些年都是听着过没啥特别的感觉.今年自己倒是确确实实体验了一把银四,从3月26裸辞到4月17号 ...
- [Luogu 2265]路边的水沟
Description LYQ市有一个巨大的水沟网络,可以近似看成一个n*m的矩形网格,网格的每个格点都安装了闸门,我们将从水沟网络右下角的闸门到左上角的闸门的一条路径称为水流. 现给定水沟网的长和宽 ...
- 决战 状压dp
决定在这个小巷里排兵布阵.小巷可以抽象成一个们彼此之间并不是十分和♂谐.具体来说,一个哲学家会有一个的矩形.每一位哲学家会占据一个格子.然而哲学家的01矩阵来表示他自己的守备范围.哲学家自己位于这个矩 ...
- bzoj 3261最大异或和
Description 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1. 2.Qlrx:询问操作,你需要 ...
- python3 条件判断,循环,三元表达式
一. 条件判断 条件判断的关键字if elif else,具体规则如下: if condition_1: statement_block_1 elif condition_2: statement_b ...
- php留言板的实现
留言板功能的实现,主要就是通过编程语言对数据库进行操作,简单说也就是插入和查询的实现.不管是什么语言进行实现,道理都是一样的. 应学习需要,这里用php世界上最美的语言来进行实现. 主要步骤为: 连接 ...
- Java 反射实现实体转Map时,父类元素丢失
public class BeanToMap { public static Map<String, Object> ConvertObjToMap(Object obj) { Map&l ...
- ajax 304 bug处理方法
在ie内核中,发现Ajax的请求不会真正的被发送到服务器端,返回的永远是304.这个应该是IE的设计问题,查询解决方法后,看到网上的一段话: "因为ajax请求的时候如果使用get方式请求, ...
- ubuntu14.04+sublime3+latex配置
目的:用题目所说的三个东西写论文. 配置方法:参考 http://blog.csdn.net/bleedingfight/article/details/72810606, 但该博客所提的texliv ...