- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Android 应用APP加入聊天功能由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
简介 。
自去年 LeanCloud 发布实时通信(IM)服务之后,基于用户反馈和工程师对需求的消化和对业务的提炼,上周正式发布了「实时通信 2.0 」。设计理念依然是「灵活、解耦、可组合、可定制」,具体可以参考《实时通信开发指南》,了解 LeanCloud 实时通信的基本概念和模型.
下载和安装 。
可以到 LeanCloud 官方下载点下载 LeanCloud IM SDK v2 版本。将下载到的 jar 包加入工程即可.
一对一的文本聊天 。
我们先从最简单的环节入手,看看怎么用 LeanCloud IM SDK v2 实现一对一文本聊天.
初始化 。
和 LeanCloud 其他服务一样,实时聊天服务的初始化也是在 Application 的 onCreate 方法中进行的:
。
。
并且在AndroidManifest.xml中间声明:
。
。
接下来我们需要完成用户登录.
登录 。
假定聊天发起方名叫 Tom,为直观起见,我们使用用户名来作为 clientId 登录聊天系统(LeanCloud 云端只要求 clientId 在应用内唯一即可,具体用什么数据由应用层决定),代码如下:
。
。
建立对话 。
假定我们要跟「Bob」这个用户进行聊天,我们先创建一个对话,代码如下:
。
。
如何查询「对话」 。
如你所见,我们创建一个对话的时候,指定了成员(Tom 和 Bob)和一个额外的属性({type: 0})。这些数据保存到云端后,你在 控制台 -> 存储 -> 数据 里面会看到,_Conversation 表中增加了一条记录,新记录的 m 属性值为["Tom", "Bob"],attr 属性值为{"type":0}。如你所料,m 属性就是对应着成员列表,attr 属性就是用户增加的额外属性值(以对象的形式存储).
与 AVObject 的检索方法一样,要检索这样的对话,我们需要通过 imClient.getQuery() 得到一个 AVIMConversationQuery 实例,然后调用 conversationQuery.withMembers() 来限定成员列表,调用 conversationQuery.whereEqualTo() 来限定额外的 attr 属性。按照 AVQuery 的惯例,限定额外的 type 条件的时候需要指定的属性名是 attr.type。 发送消息 。
建立好对话之后,要发送消息是很简单的:
。
。
好了,这样一条消息就发送过去了。但是问题来了,对于「Bob」而言,他怎么才能收到别人发给他的消息呢?
消息接收 。
在 Bob 这一端,要能接收到消息,需要如下几步:
1,进行初始化和登录,代码与发送端并无二致; 。
2,实现自己的 AVIMMessageHandler,响应新消息到达通知,主要是如下函数:
。
。
对于 Tom 发过来的消息,要显示出来,我们只需实现 onMessage 即可,示例代码如下:
。
。
几个主要的回调接口 。
从上面的例子中可以看到,要接收到别人给你发送的消息,需要实现自己的 AVIMMessageHandler 类。从 v2 版开始,LeanCloud IM SDK 大量采用回调来反馈操作结果,但是对于一些被动的消息通知,则还是采用接口来实现的,包括:
当前网络出现变化 对话中有新的消息 对话中有新成员加入 对话中有成员离开 被邀请加入某对话 被踢出对话 LeanCloud IM SDK 内部使用了三种接口来响应这些事件.
网络事件响应接口(AVIMClientEventHandler) 。
主要用来处理网络变化事件,主要函数为:
。
。
在网络中断的情况下,所有的消息收发和对话操作都会出现问题.
通过 AVIMClient.setClientEventHandler(AVIMClientEventHandler handler) 可以设定全局的 ClientEventHandler.
对话成员变化响应接口(AVIMConversationEventHandler) 。
主要用来处理对话中成员变化的事件,主要函数为:
。
。
通过 AVIMMessageManager.setConversationEventHandler(AVIMConversationEventHandler handler) 可以设置全局的 ConversationEventHandler.
消息响应接口(MessageHandler) 。
主要用来处理新消息到达事件,主要的函数为:
。
。
通过 AVIMMessageManager.registerDefaultMessageHandler(MessageHandler handler) 可以设置全局的 MessageHandler.
我们实现这三类接口,就可以处理所有的通知消息了(注意:LeanCloud IM SDK 内部实现了一个空的 AVIMMessageHandler,你可以从这里派生出进行实际处理的 handler).
支持富媒体的聊天消息 。
上面的代码演示了如何发送简单文本信息,但是现在的交互方式已经越来越多样化,图片、语音、视频已是非常普遍的消息类型。v2 版的 LeanCloud IM SDK 已经可以很好地支持这些富媒体消息,具体说明如下:
基类:AVIMTypedMessage 。
所有富媒体消息的基类,其声明为 。
。
。
文本消息(AVIMTextMessage) 。
AVIMTypedMessage 子类,表示一般的文本消息,其声明为 。
。
@AVIMMessageType(type = -1) public class AVIMTextMessage extends AVIMTypedMessage { public String getText(),
。
public void setText(String text),
public Map<String, Object> getAttrs(),
public void setAttrs(Map<String, Object> attr); } 。
。
要发送文本消息,示例代码为:
。
。
图像消息(AVIMImageMessage) 。
AVIMTypedMessage 子类,支持发送图片和附带文本的混合消息,其声明为:
。
。
接收到这样消息之后,开发者可以获取到若干图片元数据(width,height,图片 size,图片 format)和一个包含图片数据的 AVFile 对象.
音频消息(AVIMAudioMessage) 。
AVIMTypedMessage 子类,支持发送语音和附带文本的混合消息,其声明为:
。
public class AVIMAudioMessage extends AVIMFileMessage { public AVIMAudioMessage(); public AVIMAudioMessage(String localPath) throws FileNotFoundException, IOException; public AVIMAudioMessage(File localFile) throws FileNotFoundException, IOException; public AVIMAudioMessage(AVFile file); /** * 获取文件的metaData * * @return */ @Override public Map<String, Object> getFileMetaData(),
。
/** * 获取音频的时长 * * @return */ public double getDuration(); } 。
。
发送音频消息的示例代码为:
。
。
接收到这样消息之后,开发者可以获取到若干音频元数据(时长 duration、音频 size,音频 format)和一个包含音频数据的 AVFile 对象.
视频消息(AVIMVideoMessage) 。
AVIMTypedMessage 子类,支持发送视频和附带文本的混合消息,其声明为:
。
public class AVIMVideoMessage extends AVIMFileMessage { public AVIMVideoMessage(),
。
public AVIMVideoMessage(String localPath) throws FileNotFoundException, IOException; public AVIMVideoMessage(File localFile) throws FileNotFoundException, IOException; public AVIMVideoMessage(AVFile file),
/** * 获取文件的metaData * * @return */ @Override public Map<String, Object> getFileMetaData(),
/** * 获取时长 * * @return */ public double getDuration(); } 。
。
发送视频消息的示例代码为:
。
。
接收到这样消息之后,开发者可以获取到若干视频元数据(时长 duration、视频 size,视频 format)和一个包含视频数据的 AVFile 对象.
地理位置消息(AVIMLocationMessage) 。
AVIMTypedMessage 子类,支持发送地理位置信息和附带文本的混合消息,其声明为:
。
public class AVIMLocationMessage extends AVIMTypedMessage { public String getText(); public void setText(String text),
。
public Map<String, Object> getAttrs(); public void setAttrs(Map<String, Object> attr),
public AVGeoPoint getLocation(); public void setLocation(AVGeoPoint location); } 。
。
要发送位置消息的示例代码为:
。
。
接收到这样的消息之后,开发者可以获取到具体的地理位置数据.
如何接收富媒体消息 。
新版 LeanCloud IM SDK 内部封装了对富媒体消息的支持,所有富媒体消息都是从 AVIMTypedMessage 派生出来的。发送的时候可以直接调用 conversation.sendMessage 函数。在接收端,我们也专门增加了一类回调接口:
。
。
开发者可以编写自己的消息处理 handler,然后调用 AVIMMessageManager.registerMessageHandler(Class<? extends AVIMMessage> clazz, MessageHandler<?> handler) 函数来注册目标 handler.
LeanCloud IM SDK 内部消息分发的逻辑是这样的:对于收到的任一新消息,SDK 内部都会先解析消息的类型,根据类型找到开发者为这一类型注册的处理 handler,然后逐一调用这些 handler 的 onMessage 函数。如果没有找到专门处理这一类型消息的 handler,就会转交给 defaultHandler 处理.
这样一来,在开发者为 TypedMessage(及其子类) 指定了专门的 handler,也指定了全局的 defaultHandler 了的时候,如果发送端发送的是通用的 AVIMMessage 消息,那么接受端就是 AVIMMessageManager.registerDefaultMessageHandler()中指定的 handler 被调用;如果发送的是 AVIMTypedMessage(及其子类)的消息,那么接受端就是 AVIMMessageManager.registerMessageHandler()中指定的 handler 被调用.
接收端对于富媒体消息的通知处理代码片段如下:
。
。
如何扩展自己的富媒体消息 。
继承于 AVIMTypedMessage,开发者也可以扩展自己的富媒体消息,这一部分属于高阶内容,大家有兴趣可以参看这篇文档,这里不再赘述.
群组聊天 。
与前面的单聊类似,群组聊天也需要先建立一个对话(AVIMConversation),然后发送、接收新的消息.
创建群组 。
和单聊类似,建立一个多人聊天的群组也是很简单的。例如:
。
。
成功之后,我们就可以进入聊天界面了.
往群组发送消息 。
发送消息非常简单,与前面单聊的场景一样.
我们会注意到,AVIMConversation 还有一个发送消息的方法:
。
。
而这里 flag 的定义有如下三种类型:
暂态消息(AVIMConversation.TRANSIENT_MESSAGE_FLAG)。这种消息不会被自动保存(以后在历史消息中无法找到它),也不支持延迟接收,离线用户更不会收到推送通知,所以适合用来做控制协议。譬如聊天过程中「某某正在输入中...」这样的状态信息,就适合通过暂态消息来发送。 普通消息(AVIMConversation.NONTRANSIENT_MESSAGE_FLAG)。这种消息就是我们最常用的消息类型,在 LeanCloud 云端会自动保存起来,支持延迟接收和离线推送,以后在历史消息中可以找到它。 待回执消息(AVIMConversation.RECEIPT_MESSAGE_FLAG)。这也是一种普通消息,只是消息被对方收到之后 LeanCloud 服务端会发送一个回执通知给发送方(这就是 AVIMMessageHandler 中 public void onMessageReceipt(AVIMMessage message, AVIMConversation conversation, AVIMClient client) 函数被调用的时机)。 接收群组消息 。
接收一个群组的消息,与接收单聊的消息也是一样的.
成员管理 。
在查询到聊天室成员之后,可以让用户邀请一些自己的朋友加入,作为管理员也可以剔除一些「可怕」的成员。 加入新成员的 API 如下:
。
。
邀请成功以后,通知的流程是这样的:
操作者(管理员) 被邀请者 其他人 1, 发出请求 addMembers 2, 收到 onInvited 通知 3, 收到 onMemberJoined 通知 收到 onMemberJoined 通知 收到 onMemberJoined 通知 相应地,踢人时的调用 API 是:
。
。
踢人的通知流程如下:
操作者(管理员) 被踢者 其他人 1, 发出请求 kickMembers 2, 收到 onKicked 通知 3, 收到 onMemberLeft 通知 收到 onMemberLeft 通知 注意! 如果邀请、踢人操作发生的时候,被邀请者/被踢者当前不在线,那么通知消息并不会被离线缓存,所以他们再上线的时候将不会收到通知。 获取历史消息 。
LeanMessage 会将非暂态消息自动保存在云端,之后开发者可以通过 AVIMConversation 来获取该对话的所有历史消息。获取历史消息的 API 如下:
。
。
注意: 获取历史消息的时候,LeanCloud 云端是从某条消息开始,往前查找开发者指定的 N 条消息,返回给客户端。为此,获取历史消息需要传入三个参数:起始消息的 msgId,起始消息的发送时间戳,需要获取的消息条数。 通过这一 API 拿到的消息就是 AVIMMessage 或者 AVIMTypedMessage 实例数组,开发者可以像之前收到新消息通知一样处理.
启用离线消息推送(仅对 iOS 平台用户有效) 。
不管是单聊还是群聊,当用户 A 发出消息后,如果目标对话中有部分用户当前不在线,LeanCloud 云端可以提供离线推送的方式来提醒用户。这一功能默认是关闭的,你可以在 LeanCloud 应用控制台中开启它。开启方法如下:
登录 LeanCloud 应用控制台,选择正确的应用进入; 选择最顶端的「消息」服务,依次点击左侧菜单「实时消息」->「设置」; 在右侧「iOS 用户离线时的推送内容」下填好你要推送出去的消息内容,保存; 这样 iOS 平台上的用户就可以收到 Push Notification 了(当然,前提是应用本身申请到了 RemoteNotification 权限,也将正确的推送证书上传到了 LeanCloud 控制台).
群组消息免打扰(仅对 iOS 平台用户有效) 。
不管是单聊还是群聊,对于发往普通的 Conversation 的普通消息,如果接收方当前不在线,LeanCloud 云端支持通过 Push Notification 的方式进行提醒。一般情况下这都是很好的,但是如果某个群组特别活跃,那离线用户就会收到过多的推送,会形成不小的干扰。 对此 LeanCloud IM 服务也允许单个用户来关闭/打开某个对话的离线推送功能。调用 API 如下:
。
。
搜索群组 。
不管是单聊,还是群聊,在 LeanCloud IM SDK 里面都是对话(Conversation)。我们给对话设置了如下几种属性:
conversationId,字符串,对话 id,只读,对话创建之后由 LeanCloud 云端赋予一个全局唯一的 id。 creator,字符串,对话创建者 id,只读,标识对话创建者信息 members,数组,对话参与者,这里记录了所有的参与者 name,字符串,对话的名字,optional,可用来对于群组命名 attributes,Map/Dict,自定义属性,optional,供开发者自己扩展用。 我们提供了专门的类,来搜索特定的群组。例如要搜索当前登录用户参与的所有群聊对话,其代码为 。
。
。
AVIMConversationQuery 中设置条件的方法与 AVQuery 类似,具体可以参看其头文件。这里要强调的一点是,对于自定义属性的约束条件,属性名一定要以 attr 开头.
开放聊天室 。
开放聊天室(也叫暂态对话)可以用于很多地方,譬如弹幕、直播等等。在 LeanCloud IM SDK 中,开放聊天室是一类特殊的群组,它也支持创建、加入/踢出成员等操作,消息记录会被保存并可供获取;与普通群组不一样的地方具体体现为:
不支持查询成员列表,你可以通过相关 API 查询在线人数; 不支持离线消息、离线推送通知等功能; 没有成员加入、离开的通知; 一个用户一次登录只能加入一个开放聊天室,加入新的开放聊天室后会自动离开原来的聊天室; 加入后半小时内断网重连会自动加入原聊天室,超过这个时间则需要重新加入; 创建开放聊天室 。
和普通的群组类似,建立一个开放聊天室也是很简单的,只是在 AVIMClient.createConversation(conversationMembers, name, attributes, isTransient, callback) 中我们需要传入 isTransient=true 选项。例如:
。
。
加入成功之后,我们就可以进入聊天界面了。开放聊天室的其他操作,都与普通群组操作一样.
查询在线人数 。
通过 AVIMConversation.getMemberCount() 方法可以实时查询开放聊天室的在线人数。示例代码如下:
。
。
签名和安全 。
为了满足开发者对权限和认证的要求,LeanCloud 还设计了操作签名的机制。我们可以在 LeanCloud 应用控制台中的「设置」->「应用选项」->「聊天推送」下面勾选「聊天服务签名认证」来启用签名(强烈推荐这样做)。启用后,所有的用户登录、对话创建/加入、邀请成员、踢出成员等操作都需要验证签名,这样开发者就可以对消息进行充分的控制.
客户端这边究竟该如何使用呢?我们只需要实现 SignatureFactory 接口,然后在用户登录之前,把这个接口的实例赋值给 AVIMClient 即可(AVIMClient.setSignatureFactory(factory)).
设定了 signatureFactory 之后,对于需要鉴权的操作,LeanCloud IM SDK 与服务器端通讯的时候都会带上应用自己生成的 Signature 信息,LeanCloud 云端会使用 app 的 masterKey 来验证信息的有效性,保证聊天渠道的安全.
对于 SignatureFactory 接口,我们只需要实现这两个函数即可:
。
。
createSignature 函数会在用户登录的时候被调用,createConversationSignature 会在对话创建/加入、邀请成员、踢出成员等操作时被调用.
你需要做的就是按照前文所述的签名算法实现签名,其中 Signature 声明如下:
。
。
其中四个属性分别是
signature 签名 timestamp 时间戳,单位秒 nonce 随机字符串 nonce signedPeerIds 放行的 clientId 列表,v2 中已经废弃不用 下面的代码展示了基于 LeanCloud 云代码进行签名时,客户端的实现片段:
。
。
LeanCloud IM SDK 专注做好底层的通讯服务,有更多可以定制化的地方,譬如说:
账户系统和 IM 系统是分离的; 消息变成离线推送的时候,推送内容开发者是可以定制的; 通过 web hook,开发者可以对消息进行更多处理; 聊天过程中通过消息鉴权机制,开发者可以有更多控制; 因为缺少 UI 组件,实事求是地讲在新用户接入成本可能稍高,但是在业务规模扩大、产品需求变多之后,相信大家会越来越喜欢 LeanCloud 这种自由灵活的使用体验,以及稳定迅捷的服务质量.
以上所述就是本文的全部内容了,希望大家能够喜欢.
请您花一点时间将文章分享给您的朋友或者留下评论。我们将会由衷感谢您的支持! 。
最后此篇关于Android 应用APP加入聊天功能的文章就讲到这里了,如果你想了解更多关于Android 应用APP加入聊天功能的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在构建一个 RCP 应用程序,其中每个季度都会更新功能/插件。因此,如果用户选择自动更新功能/插件,则会下载更新插件的新 jar,但旧插件仍在使用我不再使用的磁盘空间。 我厌倦了删除包含旧 jar
我如何从外部 Controller 功能中调用 Controller 内部的功能,例如电话间隙回调功能 这是 Controller 外部定义的功能 function onDeviceReady()
如果某个功能(例如 MediaSource)可用,我如何使用 Google Dart 检查。 new MediaSource() 抛出一个错误。如何以编程方式检查此类或功能是否存在?有任何想法吗?是否
我正在尝试运行 Azure Orchestrations,突然我开始从 statusQueryGetUri 收到错误: 协调器函数“UploadDocumentOrchestrator”失败:函数“U
我见过 iPhone 上的应用程序,如果在 3.0 上运行,将使用 3.0 功能/API,例如应用内电子邮件编辑器,如果在 2.x 上运行,则不使用这些功能,并退出应用程序以启动邮件相反。 这是怎么做
这是 DB 规范化理论中的一个概念: Third normal form is violated when a non-key field is a fact about another non-ke
如果我定义 #if SOMETHING #endif 而且我还没有在任何地方定义 SOMETHING。 #if 中的代码会编译吗? 最佳答案 当#if的参数表达式中使用的名称未定义为宏时(在所有其他宏
我刚刚澄清了 A* 路径查找应该如何在两条路径具有相等值的 [情况] 下运行,无论是在计算期间还是在结束时,如果有两条相等的短路径。 例如,我在我的起始节点,我可以扩展到两个可能的节点,但它们都具有相
Java有没有类似下面的东西 宏 一种遍历所有私有(private)字段的方法 类似于 smalltalk symbols 的东西——即用于快速比较静态字符串的东西? 请注意,我正在尝试为 black
这个程序应该将华氏度转换为摄氏度: #include int main() { float fahrenheit, celsius; int max, min, step;
当打开PC缓存功能后, 软件将采用先进先出的原则排队对示波器采集的每一帧数据, 进行帧缓存。 当发现屏幕中有感兴趣的波形掠过时, 鼠标点击软件的(暂停)按钮, 可以选择回看某一帧的波形
我有一个特殊的(虚拟)函数,我想在沙盒环境中使用它: disable.system.call eval(parse(text = 'model.frame("1 ~ 1")'), envir = e
使用新的 Service 实现,我是否必须为我的所有服务提供一个 Options 方法? 使用我的所有服务当前使用的旧 ServiceBase 方法,OPTIONS 返回 OK,但没有 Access-
我正在阅读 Fogus 的关于 Clojure 的喜悦的书,在并行编程章节中,我看到了一个函数定义,它肯定想说明一些重要的事情,但我不知道是什么。此外,我看不到这个函数有什么用 - 当我执行时,它什么
我有大量的 C 代码,大部分代码被注释掉和/或 #if 0。当我使用 % 键匹配 if-else 的左括号和右括号时,它也匹配注释掉的代码。 有没有办法或vim插件在匹配括号时不考虑注释掉或#if 0
我有这个功能: map(map(fn x =>[x])) [[],[1],[2,3,4]]; 产生: val it = [[],[[1]],[[2],[3],[4]]] 我不明白这个功能是如何工作的。
我使用 Visual Studio 代码创建了一个函数应用程序,然后发布了它。功能应用程序运行良好。我现在在功能门户中使用代码部署功能(KUDU)并跳过构建。下面是日志 9:55:46 AM
我有一个数据框df: userID Score Task_Alpha Task_Beta Task_Charlie Task_Delta 3108 -8.00 Easy Easy
我真的无法解决这个问题: 我有一个返回数据框的函数。但是,数据框仅打印在我的控制台中,尽管我希望将其存储在工作空间中。我怎样才能做到这一点? 样本数据: n <- 32640 t <- seq(3*p
有没有办法找出所有可能的激活器命令行选项? activator -help仅提供最低限度的可用选项/功能列表,但所有好的东西都隐藏起来,即使在 typesafe 网站在线文档中也不可用。 到目前为止,
我是一名优秀的程序员,十分优秀!