行代码极速为,应用也能促膝交谈

简介

自2018年 LeanCloud
揭橥实时通讯(IM)服务之后,基于顾客反映和技术员对须要的消化和对作业的提炼,上周正式文告了「实时通讯2.0
」。设计思想一直以来是「灵活、解耦、可组成、可定制」,具体能够参照《实时通讯支出指南》,通晓LeanCloud 实时通讯的基本概念和模型。

LeanMessage 手机支付SDK 是由 LeanCloud
提供的,专为 iOS、Android 和 WindowsPhone® 等顾客端程序提供使用内闲谈的
API 和劳务,并且也提供了 JavaScript
API,方便开荒者打通网页和顾客端应用,给最终顾客提供统风度翩翩的利用体验。使用
LeanMessage
API,您能够非常快地以起码职业量令你的位移使用支撑实时闲谈,获得少年老成种如Wechat日常的关系体验。

20 行代码极速为 App 加上谈天功用,极速app

今天数不胜数 App 都急需集成 IM 效能,今日就为我们分享一下集成 IM
基本成效的手续。本文内容以 JMessage 为例。
极光 IM ( JMessage 卡塔尔(英语:State of Qatar) = 极光推送 ( JPush 卡塔尔 + IM,本篇只论述个中的 IM
部分,为大家快捷集成 IM 成效提供一个通晓的表率。

我们先来看一下 IM 的基本效用与本文内容的附和关系:

图片 1

下载和装置

可以到 LeanCloud
官方下载点下载
LeanCloud IM SDK v2 本子。将下载到的 jar 包参与工程即可。

始发从前
出于本文的目标,我如若您曾经丰富熟练使用 JSON、Android 和 Eclipse
进行移动使用编制程序的基本概念。在你持续读书本文从前,请访问 leancloud.cn
并创办您的应用程序。只需依据注册页面中的轻松指令就能够。

line 0:筹算职业


  • 下载 SDK
  • 集成 SDK

拾叁分的文件闲谈

作者们先从最轻易易行的环节动手,看看怎么用 LeanCloud IM SDK v2
完成后生可畏对一文本闲聊。

正文介绍了包罗单聊、群聊、历史记录和利用鉴权的基本 API
类。您将学习怎样轻松实行客户间风姿浪漫对生机勃勃单聊,甚至哪些创立群组让多客户进行群聊,还宛如何通过签订合同来对闲聊通道举办支配,以维护选择和客户的有苦难言。示例均创设于
LeanMessage SDK for Android
之上(请参阅Android开拓指南)。

line 1:引进头文件


#import <JMessage/JMessage.h>

JMessage
主旨头文件。这是独步天下需求导入到你的类型里的头文件,它援用了里面必要动用的头文件。

初始化

和 LeanCloud 其他服务一样,实时闲谈服务的开首化也是在 Application 的
onCreate 方法中张开的:

public class MyApplication extends Application{

    public void onCreate(){
      ...
      AVOSCloud.initialize(this,"{{appId}}","{{appKey}}");
      ...
    }
}

何况在AndroidManifest.xml中间注脚:

<manifest>
   ...

   <application
        android:name=".MyApplication"
        ....>
        ...

        <service android:name="com.avos.avoscloud.PushService" />

        <receiver android:name="com.avos.avoscloud.AVBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.USER_PRESENT" />
            </intent-filter>
        </receiver>
        ...
   </application>

</manifest>

接下去大家必要变成客户登入。

基本概念和类

line 2:开启事件监听


[JMessage addDelegate:self withConversation:nil];
  • 用来监听各个全局事件
  • 建议写在 line 3 早先
  • Parameters:
    • delegate:填入对象急需得以达成 <JMessageDelegate>
    • conversation:nil 监听全数通告,非 nil 监听钦定会话

登录

万后生可畏闲聊发起方名字为 汤姆,为直观起见,大家运用顾客名来作为 clientId
登陆闲聊系统(LeanCloud 云端只必要 clientId
在动用内唯一就能够,具体用什么样数据由应用层决定),代码如下:

AVIMClient imClient = AVIMClient.getInstance("Tom");
imClient.open(new IMClientCallback(){
  @Override
  public void done(AVIMClient client, AVException e) {
    if (null != e) {
      // 出错了,可能是网络问题无法连接 LeanCloud 云端,请检查网络之后重试。
      // 此时聊天服务不可用。
      e.printStackTrace();
    } else {
      // 成功登录,可以开始进行聊天了(假设为 MainActivity)。
      Intent intent = new Intent(currentActivity, MainActivity.class);
      currentActivity.startActivity(intent);
    };
  }
});

谈心参加者 Peer

在 LeanMessage 实时音讯世界中,每三个参与者(经常来讲是「人」)都以三个Peer。Peer 具有多少个在选取内唯风流倜傥标记自个儿的 ID(称为
PeerID,字符串类型,长度不超越 50
字节,具体数值由运用本身明确),系统中的每一条音讯都源于于一个Peer,发送到多个或三个 Peer。何况,LeanMessage 的消息服务允许叁个 Peer
在多少个不等器械上登入,也同意三个器械上还要登入两个Peer,毕竟该怎么接纳,由使用依据使用情况温馨选用。

那边要介怀的是,PeerID 是由运用开荒者本身賦值的,LeanMessage
本人并从未别的强制必要,所以:

  • 实时音信系统是足以和客商账户种类解耦合的,应用开垦者无需把除了
    PeerID 以外的别的新闻报告 LeanMessage;
  • LeanMessage 在音信转载的时候是遵照 PeerID
    来独一定位的,因而只要利用自己援救同意气风发账户的多点登陆,那么
    LeanMessage 就能把音讯通告到持有终端;
  • 无名谈心/非无名氏闲谈那都是应用层自身决定的,如若接受自己能为佚名客户内定二个唯豆蔻梢头的
    ID,那么那些顾客参加到闲聊系统里来,是一心没十分的。

为了幸免扰攘,叁个 Peer
须求先关注(watch)了对方能力给对方发送消息;因为 LeanMessage
提供了更加细粒度的权位调节,应用开采者能够在关注(watch)动作上加码签字来确定保证卫安全全性。那或多或少末尾交易会开详尽表达。

line 3:启动 SDK


[JMessage setupJMessage:launchOptions
                 appKey:@"your appkey"
                channel:@"channel name"
       apsForProduction:NO
               category:nil];
  • 提议写在 application:didFinishLaunchingWithOptions:
  • Parameters:
    • launchOptions:运转函数的参数 launchingOption
    • appKey:获取格局 line 0 – 集成 SDK
    • channel:应用的水道名
    • isProduction:是还是不是为生育形式
    • category:iOS8 新添通告快捷按键参数

创建对话

若果我们要跟「鲍勃」那么些顾客实行闲谈,我们先创设贰个对话,代码如下:

List<String> clientIds = new ArrayList<String>();
clientIds.add("Tom");
clientIds.add("Bob");

// 我们给对话增加一个自定义属性 type,表示单聊还是群聊
// 常量定义:
// int ConversationType_OneOne = 0; // 两个人之间的单聊
// int ConversationType_Group = 1;  // 多人之间的群聊
Map<String, Object> attr = new HashMap<String, Object>();
attr.put("type", ConversationType_OneOne);

imClient.createConversation(clientIds, attr, new AVIMConversationCreatedCallback() {
  @Override
  public void done(AVIMConversation conversation, AVException e) {
    if (null != conversation) {
      // 成功了,这时候可以显示对话的 Activity 页面(假定为 ChatActivity)了。
      Intent intent = new Intent(this, ChatActivity.class);
      Intent.putExtra(“conversation”, conversation);
      startActivity(intent);
    }
  }
});

确立的「对话」在调节台怎么查看

如您所见,大家创制三个会话的时候,钦赐了成员(汤姆 和
鲍伯)和三个万分的习性({type: 0})。那个数量保存到云端后,你在
控制台 -> 存储 -> 数据 里面探问到,_Conversation
表中扩张了一条记下,新记录的 m 属性值为["Tom", "Bob"]attr
属性值为{"type":0}。如你所料,m 属性正是对应着成员列表,attr
属性便是客商扩大的额外属性值(以目的的款式积存)。

实时信息 AVMessage

在 LeanMessage 中保有的音讯都是 AVMessage 的实例,AVMessage
只帮助文件,况且长度无法超越5KB。音讯分为暂态(transient)和长久新闻两体系型。全部悠久新闻都会在
LeanMessage
云端保存,所以客商离线之后也足以拿走照料和接受,而暂态音讯并不会离线保存,契合开采者用来开展磋商决定。

AVMessage 的概念如清单 1 所示:

public class AVMessage implements Parcelable {
  private List<String> toPeerIds; // 消息接收方的 PeerID,支持一个或多个

  String groupId; // 消息所属群组的ID,对于普通一对一聊天消息而言,此值为空
  String message; // 消息体
  long timestamp; // 消息发送时间戳
  boolean isTransient; // 是否是暂态消息
  String fromPeerId; // 消息发送方的 PeerID

  public AVMessage();
  public AVMessage(String message);
  public AVMessage(String message, List<String> toPeerIds, boolean isTransient);
  public AVMessage(String message, boolean isTransient);
}

LeanMessage
为具备历史消息都提供了积累和询问的效果,存款和储蓄时间则依照开荒者的种类有所不一样。

line 4:注册新客商


[JMSGUser registerWithUsername:@"username" 
                      password:@"password"
             completionHandler:^(id resultObject, NSError *error) {
}];

Parameters:

  • username:用户名
  • password:密码
  • handler:error 为 nil 时调用成功(下均同)

发送消息

确立好对话之后,要发送音信是非常粗大略的:

AVIMMessage message = new AVIMMessage();
message.setContent("hello");
conversation.sendMessage(message, new AVIMConversationCallback() {
  @Override
  public void done(AVException e) {
    if (null != e) {
      // 出错了。。。
      e.printStackTrace();
    } else {
      Logger.d("发送成功,msgId=" + message.getMessageId());
    }
  }
});

好了,那样一条新闻就发送过去了。然则难点来了,对于「Bob」来说,他怎么才具收到外人发给她的新闻呢?

闲谈会话 Session

每七个 Peer 通过开启(open)二个对话(Session)而投入实时音讯服务,Peer
可以在一个会话中关切(watch)三个或七个Peer,当被关怀者上下线时,会收到文告。Peer
在开启对话后只可以向和谐关心的别样 Peers 发送新闻,但足以吸取任何 Peer
发来的音信,也正是说单向关切时,音信能够安枕无忧地由关怀者发往被关心者。

Session 宛如下三种景况:

  • opened。 Session 被常常张开,那时得以开展不荒谬的通讯;
  • pause。 互连网特别(举例 wifi 断开,3G/2G 切换,iOS
    应用步向后台,等),Session 步入暂停状态,当网络恢复生机时,Session
    会自动重连;
  • resume。 应用转入前台,会话重新创设起来(此情况只在 iOS 设备上有效性)
  • closed。 Session 截至,仅在呈现调用了 Session.close
    方法时才会产生。顾客注销实时通讯服务,不再能够吸收接纳到音信或推送通告;

Session 上能够展开的操作有:

  • open 以一个 Peer ID 打开 Session
  • watch 关切生龙活虎组 Peer ID,关切后得以接纳这些 Peer
    的上下线文告,发送新闻
  • unwatch 废除对黄金年代组 Peer ID 的关爱
  • sendMessage 给豆蔻梢头组 Peer ID 发送消息
  • queryOnlinePeer 查找当前在线的 Peers
  • getHistoryMessageQuery 查找历史新闻
  • setSignatureFactory 设置具名类(为了确认保证卫安全全性,后边会陈诉)
  • close 注销服务,关闭 Session

line 5:登录


[JMSGUser loginWithUsername:@"username" 
                   password:@"password" 
          completionHandler:^(id resultObject, NSError *error) {
}];

音信选取

在 鲍伯 那风度翩翩端,要能接受到音讯,需求如下几步:

1,实行开头化;

2,完成团结的 AVIMMessageHandler,响应新音讯到达文告,首尽管之类函数:

public void onMessage(AVIMMessage message, AVIMConversation conversation, AVIMClient client);

对于 汤姆 发过来的音讯,要显得出来,我们只需兑现 onMessage
即可,示例代码如下:

class CustomMessageHandler extends AVIMMessageHandler {
  @Override
  public void onMessage(AVIMMessage message, AVIMConversation conversation, AVIMClient client) {
    // 新消息到来了。在这里增加你自己的处理代码。
    String msgContent = message.getContent();
    Logger.d(conversation.getConversationid() + " 收到一条新消息:" + msgContent);
  }
}

3,进行登入,代码也与发送端同样。

总体代码如下:

// 自定义消息响应类
class CustomMessageHandler extends AVIMMessageHandler {
  @Override
  public void onMessage(AVIMMessage message, AVIMConversation conversation, AVIMClient client) {
    // 新消息到来了。在这里增加你自己的处理代码。
    String msgContent = message.getContent();
    Logger.d(conversation.getConversationid() + " 收到一条新消息:" + msgContent);
  }
}

// application 的初始化部分
public void onCreate(){
  ...
  AVOSCloud.initialize(this,"{{appId}}","{{appKey}}");
  AVIMMessageManager.registerDefaultMessageHandler(new CustomMessageHandler());
  ...
}

// 用户登录部分
AVIMClient imClient = AVIMClient.getInstance("Bob");
imClient.open(new IMClientCallback(){
  @Override
  public void done(AVIMClient client, AVException e) {
    if (null != e) {
      // 出错了,可能是网络问题无法连接 LeanCloud 云端,请检查网络之后重试。
      // 此时聊天服务不可用。
      e.printStackTrace();
    } else {
      // 成功登录,可以开始进行聊天了。
    };
  }
});

注意!
AVIMMessageManager.registerDefaultMessageHandler() 必须求在
AVIMClient.open() 早前调用,不然大概引致服务器发回去的后生可畏部分新闻遗失。

格外的文件闲谈

领悟了那多个概念之后,大家就足以起来步入实际聊天环节了。

先是大家必要在 application 的 onCreate 函数中张开 LeanCloud
最基本的发轫化:

@Override
public void onCreate() {
  super.onCreate();
  AVOSCloud.initialize(this, "pleaseReplaceWithYourAppId", "pleaseReplaceWithYourAppKey");
}

接下去大家来看一下哪些进行一定的着力聊天。首先,大家须求敞开一个会话(Session),示例代码如项目清单2 所示:

SessionManager session = SessionManager.getInstance(selfId);//获取SessionManager实例,以便于后续的操作。这里的 selfId 可以是用户的实际 id,也可以是其他唯一的字符串,譬如「Tom」。
List<String> watchedIds = new LinkedList<String>();
session.open(watchedIds); //打开Session,同时关注一些 PeerID。此时没有关注对象

注意!

相符来讲,会话的张开是在客户登陆之后的 RootActivity
中举办的。对于帮忙无名闲谈的行使,也得以在 Application
运行的时候进行。千万不要在二个有的时候或短暂的 Activity
中展开闲谈会话。上边代码中 SessionManager 也是 Session
的子类,所以能够直接调用 Session 的方法。

接下去,我们初阶跟「鲍伯」这一个客商举办闲扯。为了给他发送音讯,大家先要关心(watch)他,代码如下:

List<String> peerIds = new LinkedList<String>();
peerIds.add("Bob");
session.watchPeers(peerIds);

然后大家给「鲍伯」发送一条消息:

List<String> peerIds = new LinkedList<String>();
peerIds.add("Bob");
session.sendMessage(new AVMessage("嗨,你好,我是 Tom", peers, false));

好了,那样一条音信就发送过去了。但是难点来了,对于「鲍勃」来讲,他怎么技艺选用外人发给他的音讯啊?

地方对于 Session 的保有操作都以异步的。与日常 Android
异步方法调用分化,LeanMessage SDK 的异步实际不是因此 Callback 或然近似ENVISIONsyncTask 的体制落成的,而是通过持续 AVMessageReceiver 那黄金年代BoardcastReceiver,完成以下办法来拍卖来自服务器端的响应的。AVMessageReceiver
接口定义如清单 3 所示:

/**
 * 当服务器成功与客户端打开session时产生本次回调
 */
public abstract void onSessionOpen(Context context, Session session);

/**
 * 在 session 暂停时调用,一般都是由网络连接丢失导致的隐性调用
 */
public abstract void onSessionPaused(Context context, Session session);

/**
 * Session 恢复时,一般都是网络连接恢复以后的
 * 这个时候你可以处理一些由于网络异常导致的失败消息
 */
public abstract void onSessionResumed(Context context, Session session);

/**
 * 从某个Peer接收到消息时,会收到一次调用
 */
public abstract void onMessage(Context context, Session session,
        AVMessage msg);

/**
 * 服务器反馈消息已经成功发送时,会收到调用
 */
public abstract void onMessageSent(Context context, Session session,
        AVMessage msg);

/**
 * 在消息发送失败时,产生的调用 在这里你可以保存一下发送失败的消息以便未来重发
 */
public abstract void onMessageFailure(Context context, Session session,
        AVMessage msg);

/**
 * 当关注的一些peers上线时,产生的调用
 */
public abstract void onStatusOnline(Context context, Session session,
        List<String> peerIds);

/**
 * 当关注的一些peers下线时,产生的调用
 */
public abstract void onStatusOffline(Context context, Session session,
        List<String> peerIds);

/**
 * 当与服务器发生交互的过程中的任何错误,都在这里被返回
 */
public abstract void onError(Context context, Session session, Throwable e);

从上边接口的概念中,大家得以看看,要收下到人家发过来的音信,只需求响应
onMessage(卡塔尔(قطر‎ 方法就可以。代码示举例项目清单 4 所示:

public class CustomeMsgReceiver extends AVMessageReceiver {
    @Override
    public void onMessage(final Context context, Session session, AVMessage avMsg) {
        Logger.d("onMessage "+avMsg.getMessage());
        // 进行上层逻辑处理,譬如 UI 展示,或者消息提醒。
    }
}

// 在 AndroidManifest.xml 文件中声明这一 BoardcastReceiver。
<receiver android:name=".receiver.CustomeMsgReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="com.avoscloud.session.action" />
    </intent-filter>
</receiver>

line 6:创造单聊会话


[JMSGConversation createSingleConversationWithUsername:@"username" 
                                     completionHandler:^(id resultObject, NSError *error) {
}];
  • 对话是全方位 IM 的焦点,全数的新闻作为都依照「会话」
  • 该会话不设有会回来新会话,存在会回来本来就有对话
  • Parameters:
    • handler:平常重临时 resultObject 为 JMSGConversation 会话对象
    • ((JMSGConversation*卡塔尔(英语:State of Qatar)resultObject卡塔尔(قطر‎.target:会话的对方指标:
      • 客商对象 JMSGUser
      • 群组对象 JMSGGroup
  • Related APIs:
    • 开创单聊跨应用会话
    • 创办群聊会话

多少个根本的回调接口

从地点的事例中能够见到,要接到到别人给您发送的音信,必要重载
AVIMMessageHandler 类。从 v2 版在此以前,LeanCloud IM SDK
大量使用回调来报告操作结果,不过对于某个被动的音讯文告,则照旧选择接口来达成的,包蕴:

  • 时下网络现身转移
  • 对话中有新的消息
  • 对话中有新成员插手
  • 对话中有成员离开
  • 被诚邀参与某对话
  • 被踢出对话

LeanCloud IM SDK 内部使用了两种接口来响应那一个事件。

支撑富媒体的闲谈音信

下面的代码演示了哪些发送文书音讯,可是今后的交互作用方式已经特别多种化,图片、语音、摄像已经是非平时见的传播媒介类型。而从
AVMessage 的概念来看,只辅助不超过 5KB 大小的文件,那么 LeanMessage
又怎么着能支撑富媒体的闲谈音讯吧?

记得 LeanStorage 中的 AVFile 吗?
AVFile 是 LeanStorage
提供的非布局化数据存款和储蓄解决方案,能够让您的应用程序将二进制文件存款和储蓄到云端服务器中,况兼自动提供
CDN
加快服务,能带来客户更敏捷的下载体验。举个例子大面积的文件类型图像文件、影象文件、音乐文件和别的别的二进制数据都得以动用。具体表明能够敬重Android
开荒文书档案

对此图片、语音、摄像那类一点都不小的非构造化数据,存款和储蓄到云端文件系统之后,在音信中发送
url 已经是业界惯例,何况 LeanMessage 中 AVMessage
类的定义并不曾规定新闻体是什么品种,所以大家得以足够利用那少年老成增加空间,结合
AVFile 来发送、选拔富媒体的闲谈新闻。落成方式如事项清单 5 所示:

AVFile file = AVFile.withAbsoluteLocalPath("test.jpg", Environment.getExternalStorageDirectory() + "/test.jpg");
file.saveInBackground(new SaveCallback() {
    // override
    public void done(AVException ex) {
        if (null != ex) {
            // error
        } else {
            // construct message body under json format.
            HashMap<String, Object> params = new HashMap<String, Object>();
            params.put("type", "image");
            params.put("context", "嗨,你好,我是 Tom");
            params.put("attachment", file.getUrl());

            List<String> peerIds = new LinkedList<String>();
            peerIds.add("Bob");
            session.sendMessage(new AVMessage(JSON.toJSONString(params), peers, false));
        }
    }
});

新本子的 LeanMessage SDK
会帮衬富媒体新闻,防止让种种开采者都再度做形似的办事。

line 7:发送文书音信


[(JMSGConversation*)resultObject sendTextMessage:@"text"];
  • 转型 line 6 – handler 中的 resultObject,并发送文书音信
  • Related APIs:
    • 出殡图片新闻
    • 出殡语音讯息
    • 出殡文书音信
    • 出殡地理地方音信

互连网事件响招待口

重要用以管理互联网生成事件,接口定义在
AVIMClientEventHandler,主要函数为:

  /**
   * 实现本方法以处理网络断开事件
   */
  public abstract void onConnectionPaused(AVIMClient client);

  /**
   * 实现本方法以处理网络恢复事件
   */
  public abstract void onConnectionResume(AVIMClient client);

在互连网中断的状态下,全数的音讯收发和对话操作都会出现难题。

通过 AVIMClient.setClientEventHandler(AVIMClientEventHandler handler)
能够设定全局的 ClientEventHandler。

群组闲谈

在闲谈的供给里,还应该有三个很首要的情景,就是群组谈心。从最近 AVMessage
的定义大家能够猜到,LeanMessage
应该是扶持群聊的,那实在该怎么落实呢?上边大家一步一步来尝试一下。

line 8~12:选取文本新闻


- (void)onReceiveMessage:(JMSGMessage *)message error:(NSError *)error{
    if (message.content == kJMSGContentTypeText) {
        NSString *text = ((JMSGTextContent *)message.content).text;
    }
}
  • 在 line 2 中增添了 <JMessageDelegate> 的类,能够监听该措施
  • 当 App 吸收接纳(文本、图片等各种)音信时该措施被调用
  • 根据 message.contentType 决断新闻类型
  • 转型 message.content 为文本内容并获得文本 text 以展示 UI
  • Related APIs:
    • 图表内容
    • 声音内容
    • 文件内容

对话成员变动响招待口

要害用来管理对话中成员变动的平地风波,接口定义在
AVIMConversationEventHandler,首要函数为:

  /**
   * 实现本方法以处理聊天对话中的参与者离开事件
   *
   * @param members 离开的参与者
   * @param kickedBy 踢人者,自愿退出的情况下踢人者就是参与者
   */
  public abstract void onMemberLeft(AVIMClient client,
      AVIMConversation conversation, List<String> members, String kickedBy);

  /**
   * 实现本方法以处理聊天对话中的参与者加入事件
   *
   * @param members 加入的参与者
   * @param invitedBy 邀请人,有可能是加入的参与者本身
   */
  public abstract void onMemberJoined(AVIMClient client,
      AVIMConversation conversation, List<String> members, String invitedBy);

  /**
   * 实现本方法来处理当前用户被踢出某个聊天对话事件
   *
   * @param kickedBy 踢出你的人
   */
  public abstract void onKicked(AVIMClient client, AVIMConversation conversation,
      String kickedBy);

  /**
   * 实现本方法来处理当前用户被邀请到某个聊天对话事件
   *
   * @param conversation 被邀请的聊天对话
   * @param operator 邀请你的人
   */
  public abstract void onInvited(AVIMClient client, AVIMConversation conversation,
      String operator);

通过
AVIMMessageManager.setConversationEventHandler(AVIMConversationEventHandler handler)
能够安装全局的 Conversation伊夫ntHandler。

基本概念

与数不胜数的单聊比较,群聊增添了之类三个基本概念:

  • 群组 AVGroup

AVGroup
代表多少个闲聊群组,能够对应到实际的两个人闲话、谈心群、闲谈室等,各类AVGroup 有二个唯风流罗曼蒂克的 ID(groupID,由 LeanMessage
云端分配),其定义如清单 6 所示:

   public class AVGroup implements Group {
      String roomId;
      String selfId;
      Session session;
   }

一个 Peer
出席群后向群发送的消息能够被有着群成员采取。当有新成员步入恐怕既有成员退出时,全数群成员都会拿走照管。AVGroup
上能够进行的操作有:

public interface Group{
    public void join();
    public void sendMessage(AVMessage msg);
    public void kickMember(List<String> peerIds);
    public void inviteMember(List<String> peerIds);
    public void quit();
    public String getGroupId();
    public String getSelfId();
    public AVHistoryMessageQuery getHistoryMessageQuery();
}
  • 群组新闻接纳器 AVGroupMessageReceiver

与 AVMessageReceiver 相像,AVGroupMessageReceiver
首要用来管理群组操作的结果。其详细定义如清单 7 所示:

  /**
   *在加入聊天室成功后被调用 如果join时,没有带groupId,您可以在返回的group中间获取groupId
   */
  @Override
  public abstract void onJoined(Context context, Group group);

  /**
   * 当你被别人邀请进入某个聊天室以后
   * 
   * @param group
   * @param byPeerId
   *        这个人邀请了你
   */
  @Override
  public abstract void onInvited(Context context, Group group, String byPeerId);

  /**
   * 当你被别人踢出聊天室以后
   * 
   * @param group
   * @param byPeerId
   *            是他踢了你
   */
  @Override
  public abstract void onKicked(Context context, Group group, String byPeerId);

  /**
   * 处理消息发送成功事件
   */
  @Override
  public abstract void onMessageSent(Context context, Group group,
        AVMessage message);

  /**
   * 用来处理消息发送失败事件
   * 可以缓存起来,事后重发
   */
  @Override
  public abstract void onMessageFailure(Context context, Group group,
        AVMessage message);

  /**
   * 收到消息以后被调用
   * 一般通过这个接口来处理和接受来自Group的消息
   * @param context
   * @param group
   * @param message
   * @param fromPeerId
   *            发消息者
   */
  @Override
  public abstract void onMessage(Context context, Group group,
        AVMessage message);

  /**
   * 处理退出成功事件
   */
  @Override
  public abstract void onQuit(Context context, Group group);

  /**
   * 处理Group操作被拒绝的时间
   * @param context
   * @param group
   * @param op 这里可能存在的操作有 "join","invite","kick"
   * @param targetIds
   *            一般来说是指被操作的对象,在join操作中间就是指groupId本身,
   *            invite和kick中则指被邀请或者被踢除的peerIds
   */
  @Override
  public abstract void onReject(Context context, Group group, String op,
        List<String> targetIds);

  /**
   * 处理新用户加入事件
   */
  @Override
  public abstract void onMemberJoin(Context context, Group group,
        List<String> joinedPeerIds);

  /**
   * 处理用户退出事件
   */
  @Override
  public abstract void onMemberLeft(Context context, Group group,
        List<String> leftPeerIds);

  /**
   * 处理所有Group相关的异常
   */
  @Override
  public abstract void onError(Context context, Group group, Throwable e);

line 13:获取历史音信


NSArray *messages = [(JMSGConversation*)resultObject messageArrayFromNewestWithOffset:nil limit:nil];
  • 利用 line 6 中的 resultObject 转型后得到
  • 单聊群聊均可
  • Parameters:
    • 返回 NSArray<JMSGMessage* >
    • offset:起源。nil 从最新一条最早,n 从新型第 n 条往历史查究
    • limit:数量。nil 表全部

音讯响款待口

首要用以管理新音讯达到事件,接口定义在
MessageHandlerAVIMMessageHandler
是五个空的兑现类,我们应当经过重载 AVIMMessageHandler
的有关办法来成功音信管理。首要的艺术有:

  // 收到新的消息
  @Override
  public void onMessage(AVIMMessage message, AVIMConversation conversation);

  // 自己发送的消息已经被对方接收
  @Override
  public void onMessageReceipt(AVIMMessage message, AVIMConversation conversation, AVIMClient client);

通过 AVIMMessageManager.registerDefaultMessageHandler(handler)
能够设置全局的 MessageHandler。

大家兑现这三类接口,就足以拍卖全部的布告音信了。示例代码如下:

class CustomNetworkHandler extends AVIMClientEventHandler {
  @Override
  public void onConnectionPaused(AVIMClient client) {
    // 请按自己需求改写
    Logger.d("connect paused");
  }

  @Override
  public void onConnectionResume(AVIMClient client) {
    // 请按自己需求改写
    Logger.d("connect resume");
  }
}

class CustomConversationHandler extends AVIMConversationEventHandler {
  public private Context gContext = null;
  private void toast(String str) {
    Toast.makeText(gContext, str, Toast.LENGTH_SHORT).show();
  }
  private void toast(Context context, String str) {
    Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
  }

  @Override
  public void onMemberLeft(AVIMClient client, AVIMConversation conversation, List<String> members, String kickedBy) {
    // 请按自己需求改写
    toast(MsgUtils.nameByUserIds(members) + " left, kicked by " + MsgUtils.nameByUserId(kickedBy));
    //注:MsgUtils 是一个辅助类,nameByUserIds 用来将 userId 转换成用户名
  }

  @Override
  public void onMemberJoined(AVIMClient client, AVIMConversation conversation, List<String> members, String invitedBy) {
    // 请按自己需求改写
    toast(MsgUtils.nameByUserIds(members) + " joined , invited by " + MsgUtils.nameByUserId(invitedBy));
    //注:MsgUtils 是一个辅助类,nameByUserIds 用来将 userId 转换成用户名
  }

  @Override
  public void onKicked(AVIMClient client, AVIMConversation conversation, String kickedBy) {
    // 请按自己需求改写
    toast("you are kicked by " + MsgUtils.nameByUserId(kickedBy));
  }

  @Override
  public void onInvited(AVIMClient client, AVIMConversation conversation, String operator) {
    // 请按自己需求改写
    toast("you are invited by " + MsgUtils.nameByUserId(operator));
  }
};

class CustomMsgHandler extends AVIMMessageHandler {
  @Override
  public void onMessage(AVIMMessage message, AVIMConversation conversation, AVIMClient client) {
    // 请按自己需求改写
    String msgContent = message.getContent();
    Logger.d(conversation.getConversationid() + " 收到一条新消息:" + msgContent);
  }

  @Override
  public void onMessageReceipt(AVIMMessage message, AVIMConversation conversation, AVIMClient client) {
    // 请按自己需求改写
    Logger.d("发往对话 " + conversation.getConversationid() + " 的消息 "+ message.getMessageId() +" 已被接收");
  }
}

// 设置事件响应接口
AVIMClient.setClientEventHandler(new CustomNetworkHandler());
AVIMMessageManager.setConversationEventHandler(new CustomConversationHandler());
AVIMMessageManager.registerDefaultMessageHandler(new CustomMsgHandler());

投入闲聊室

鉴于全部实时通讯功用都以创立在 Session
的底工上,所以大家要投入叁个闲聊室也须要树立在一个早就展开的 Session
上。 已经开采三个 Session 现在,能够经过以下操作来参预七个 Group:

    Group group = SessionManager.getInstance(selfId).getGroup();//准备新建一个聊天室
    //Group group = SessionManager.getInstance(selfId).getGroup(groupId); 加入一个已经存在的聊天室
    group.join(); // LeanMessage 云端会判断 groupId 是否存在,如果不存在就新建一个 Group,否则加入已有 Group

参预成功之后 AVGroupMessageReceiver 子类中的 onJoined 方法就能被调用。

line 14~15:清零单聊未读音讯数


JMSGConversation *conversation = [JMSGConversation singleConversationWithUsername:username];
[conversation clearUnreadCount];
  • Related APIs:
    • 清零群聊

接济富媒体的推抢音信

上边的代码演示了什么样发送轻易文本信息,不过以后的交互作用情势已经特别各个化,图像、语音、录制已经是非平常见的消息类型。v2
版的 LeanCloud IM SDK 已经能够很好地帮忙那几个富媒体新闻,具体表达如下:

往闲话室发送新闻

发送消息特轻便,通过如下代码就能够向特定闲谈室发送音信了:

    Group group = SessionManager.getInstance(selfId).getGroup(groupId);
    group.sendMessage(new AVMessage("hello world"));

发送成功以往,AVGroupMessageReceiver 子类中的 onMessageSent
方法会被调用,反之则 onMessageFailure 方法会被调用。

line 16:获取会话列表


[JMSGConversation allConversations:^(id resultObject, NSError *error) {
}];
  • 批量到手具备会话列表
  • 依据会话类型剖断是单聊依旧群聊
  • Parameters:
    • resultObject:NSArray<JMSGConversation*>

基类:AVIMTypedMessage

装有富媒体消息的基类,其注明为

//SDK定义的消息类型,LeanCloud SDK 自身使用的类型是负数,所有正数留给开发者自定义扩展类型使用,0 作为「没有类型」被保留起来。
enum AVIMReservedMessageType {
  UnsupportedMessageType(0),
  TextMessageType(-1),
  ImageMessageType(-2),
  AudioMessageType(-3),
  VideoMessageType(-4),
  LocationMessageType(-5),
  FileMessageType(-6);
};

public abstract class AVIMTypedMessage extends AVIMMessage {
  public AVIMTypedMessage();

  public int getMessageType();

  @Override
  public final String getContent();

  @Override
  public final void setContent(String content);
}

选取闲聊室新闻

收纳叁个闲谈室的音讯,与吸取单聊的音信未有差距于,需求开拓者达成AVGroupMessageReceiver 接口,并在 AndroidManifest.xml
中登记就能够,如代码清单 8 所示:

public class CustomeGroupMsgReceiver extends AVGroupMessageReceiver {
    ...
    @Override
    public void onMessage(final Context context, Group group, AVMessage avMsg) {
        Logger.d("onMessage "+avMsg.getMessage());
        // 进行上层逻辑处理,譬如 UI 展示,或者消息提醒。
    }
    ...
}

// 在 AndroidManifest.xml 文件中声明这一 BoardcastReceiver。
<receiver android:name=".receiver.CustomeGroupMsgReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="com.avoscloud.session.action" />
    </intent-filter>
</receiver>

line 17:删除单聊会话


BOOL success = [JMSGConversation deleteSingleConversationWithUsername:username];
  • Related APIs:
    • 剔除单聊跨应用会话
    • 去除群聊会话

文本音信(AVIMTextMessage)

AVIMTypedMessage 子类,表示经常的文本音讯,其声称为

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);
}

能够看看,对于文本新闻,首要的习性有 textattr 四个,通过轻易的
getter/setter 就足以访谈到。要发送文书音讯,示例代码为:

AVIMTextMessage message = new AVIMTextMessage();
message.setText("hello");
conversation.sendMessage(message, new AVIMConversationCallback() {
  @Override
  public void done(AVException e) {
    if (null != e) {
      // 出错了。。。
      e.printStackTrace();
    } else {
      Logger.d("message sent.");
    }
  }
});

查询聊天室成员

在步入一个闲谈室之后,大家第一步正是拜会有何样人在这里个群组里面。LeanMessage
和 LeanStorage 是结合在协同的,通过使用 LeanStorage
的数量存款和储蓄功能,来保存五个闲谈室的主干新闻(表名:AVOSRealtimeGroups),在
LeanStorage 应用项理平台的数码主导,大家得以看见 AVOSRealtimeGroups
的享有字段。

LeanStorage
的数量基本
LeanStorage
也是 LeanCloud
平台的中坚服务之豆蔻年华,提供了采纳内数据和文件数量的积存功用。对于利用内数据,LeanStorage
帮衬 schema free 的存放,开拓者无需事情未发生前定义数据的情势,只要顺应 JSON
格式的 Object 都可以猖獗存款和储蓄到 LeanStorage 云端。同时,LeanStorage
也提供二个 Web
版的多少管理分界面,能够十一分便于地增、删、改、查任何数据。

本来,在咱们知晓一个闲谈室的 groupId 的时候,也能够在代码中,通过
AVObject 的 fetch 接口来查阅那个闲聊室的组员情状,代码如项目清单 9 所示:

    AVObject groupObject = AVObject.createWithoutData("AVOSRealtimeGroups",groupId);
    groupObject.fetch();//如果您在UI进程中,请使用异步方法调用
    List groupMembers= groupObject.getList("m");

防止系统线程阻塞!
遥想一下,在运动应用程序中,长日子的操作(如互联网、文件或长的猜测)不应有在主系统线程上成功。相反,应在贰个独门的办事线程中实践它们。堵塞系统线程会对应用程序的顾客界面包车型大巴响应本事发生消极的一面影响,有比十分的大大概形成强行关闭您的应用程序。

line 18:批量到手顾客实际情况


[JMSGUser userInfoArrayWithUsernameArray:nameArr completionHandler:^(id resultObject, NSError *error) {
}];
  • Parameters:
    • nameArray:NSArray<NSString*>
    • resultObject:NSArray<JMSGUser*>
  • Related APIs:
    • 获得本客户详细情形
    • 更改本顾客详细情形
    • 改进本客户密码

文本新闻(AVIMFileMessage)

AVIMTypedMessage
子类,用来发送带附属类小零部件的音信,开辟者能够用它来发送「离线文件」。对于此类音信,LeanCloud
IM SDK 内部会先把公文上传到 LeanCloud 文件存储服务器(自带 CDN
功效),然后把公文元数据(url,文件大小等等)放在新闻包内发送到
LeanCloud 实时通讯服务端。其构造函数注明为:

// 传入本地文件路径,构造消息对象
public AVIMFileessage(String localPath) throws FileNotFoundException, IOException;
// 传入本地文件,构造消息对象
public AVIMFileMessage(File localFile) throws FileNotFoundException, IOException;
// 传入 AVFile 实例,构造消息对象
public AVIMFileMessage(AVFile file);

与公事消息看似,文件音讯也帮忙附带文本和别的自定义属性,能够因而如下方法加多/ 获取更加多音讯:

  • String getText() / void setText(String text)
  • Map<String, Object> getAttrs() / void setAttrs(Map<String,
    Object> attr);

发送文书新闻的演示代码为:

String localZipfilePath;
try {
  AVIMFileMessage message = new AVIMFileMessage(localZipfilePath);
  message.setText("这是你要的文档");
  conversation.sendMessage(message, new AVIMConversationCallback() {
    @Override
    public void done(AVException e) {
      if (null != e) {
        // 出错了。。。
        e.printStackTrace();
      } else {
        Logger.d("message sent");
      }
    }
  });
} catch (Exception ex) {
}

收下到那般音信随后,开辟者能够因而以下方法,获取到文件元数据(size
等)和一个蕴含二进制数据的 AVFile 对象:

  • AVFile getAVFile() 方法会重回四个二进制文件的 AVFile
    实例,之后能够透过 AVFile 来形成多少下载或然此外操作,具体能够参见
    AVFile
    说明
  • String getFileUrl() 方法会重返二进制文件的 url
  • long getSize() 方法会再次来到二进制文件的实际上尺寸(单位:byte)
  • Map<String, Object> getFileMetaData()
    能够得到二进制文件的其余元数据消息。

成员管理

在查询到闲聊室成员之后,能够让顾客约请一些团结的对象参预,作为管理员也足以去除一些「可怕」的成员。代码如清单10 所示:

    Group group = SessionManager.getInstance(selfId).getGroup(groupId);
    List<String> toInvite = Arrays.asList("peerId1","peerId2","peerId3");
    group.inviteMember(toInvite);
    List<String> toKickOff = Arrays.asList("badBoy1","badBoy2");
    group.kickMembers(toKickOff);

诚邀成功现在,通告的流程是这么的:

    操作者(管理员)                           被邀请者                        其他人
1,发出请求 inviteMember
2,AVGroupMessageReceiver.onInvited
3,                                      AVGroupMessageReceiver.onJoined
4,AVGroupMessageReceiver.onMemberJoin                          AVGroupMessageReceiver.onMemberJoin

对应地,踢人的流水生产线如下:

    操作者(管理员)                           被踢者                         其他人
1,发出请求 kickMember
2,AVGroupMessageReceiver.onKicked
3,                                    AVGroupMessageReceiver.onQuit
4,AVGroupMessageReceiver.onMemberLeft                         AVGroupMessageReceiver.onMemberLeft

line 19:创制群组及相关操作


[JMSGGroup createGroupWithName:name desc:desc memberArray:members completionHandler:^(id resultObject, NSError *error) {
}];
  • Parameters:
    • name:群名
    • desc:群组描述
    • memberArray:成员列表,NSArray<NSString*>
    • resultObject:群组对象 JMSGGroup
  • Related APIs:
    • 获得自己的群组列表
    • 收获群组成员列表
    • 丰裕分子
    • 除去成员
    • 退群
    • 获取群组详细情形
    • 修正群组实际情况

图像音信(AVIMImageMessage)

AVIMFileMessage
子类,特意用来发送图像和附带文本的交集音讯,其布局函数注解为:

// 传入本地文件路径,构造消息对象
public AVIMImageMessage(String localPath) throws FileNotFoundException, IOException;
// 传入本地文件,构造消息对象
public AVIMImageMessage(File localFile) throws FileNotFoundException, IOException;
// 传入 AVFile 实例,构造消息对象
public AVIMImageMessage(AVFile file);

出殡图像音信的示范代码为:

String localImagePath;
try {
  AVIMImageMessage message = new AVIMImageMessage(localImagePath);
  message.setText("你说我好看不?");
  conversation.sendMessage(message, new AVIMConversationCallback() {
    @Override
    public void done(AVException e) {
      if (null != e) {
        // 出错了。。。
        e.printStackTrace();
      } else {
        Logger.d("message sent");
      }
    }
  });
} catch (Exception ex) {
}

收下到那样音信之后,开荒者能够通过如下方法,获取到几何图像元数据(width,height,图像
size)和八个含有图像数据的 AVFile 对象:

  • int getWidth() 方法会再次来到图像的宽度(单位:pixel)
  • int getHeight() 方法会重返图像的可观(单位:pixel)
  • AVFile getAVFile() (世袭自
    AVIMFileMessage)方法会再次回到叁个图像文件的 AVFile 实例
  • String getFileUrl() (世袭自 AVIMFileMessage)方法会再次回到图像文件的
    url
  • long getSize() (世襲自
    AVIMFileMessage)方法会重返图像文件的其实尺寸(单位:byte)
  • String getText() (世袭自
    AVIMFileMessage)方法会再次回到随图像一同发送的文本音信。
  • Map<String, Object> getFileMetaData() (世袭自
    AVIMFileMessage)能够获得图像的其余元数据新闻。

查询历史音信

LeanMessage 会将非暂态音讯自动保存在云端,之后开辟者能够通过
AVHistoryMessageQuery 那么些指标来开展询问。AVHistoryMessageQuery
定义如项目清单 11 所示:

public class AVHistoryMessageQuery {
    int limit;
    String convid;
    String from;
    long timestamp;

    /**
     * 设置查询返回集合的大小
     * 默认100,最大1000
     */
    public void setLimit(int limit);

    /**
     * 设定聊天的发起人是谁
     */
    public void setFrom(String from);

    /**
     * 设置查询从哪个时间开始的聊天记录
     */
    public void setTimestamp(long timestamp);

    /**
     * 指定聊天记录查询条件中,聊天发送的对象条件
     */
    public void setPeerIds(List<String> peerIds);

    /**
     * 同步方法查询聊天记录
     * 请确保在一个异步方法中调用此方法,否则会出现UI线程中的网络请求而导致的UI卡死
     */
    public List<AVHistoryMessage> find() throws AVException;

    /**
     * 异步方法查询聊天记录
     */
    public void findInBackground(HistoryMessageCallback callback);

    /**
     * 此接口为异步查询聊天记录的回调类
     */
    public static interface HistoryMessageCallback;
}

经过 AVHistoryMessageQuery 查询得到的结果是
AVHistoryMessage,该类的定义如清单 12 所示:

public class AVHistoryMessage extends AVMessage {
    /**
     * 查看是否属于聊天室聊天记录
     */
    public boolean isRoom();

    /**
     * 查看聊天记录所在的conversation Id,对于 Group 来说等于 GroupID,对于单聊来说,是内部生成的一个值。
     */
    public String getConvid();
}

聊天记录的查询的基本措施跟 AVQuery 相像不过略有不一样。 针对 Session
的闲聊记录和谈心室 Group
的聊天记录查询略有不一样,可是基本流程是千篇风流倜傥律(代码清单 12):

       String selfId = "Tom";
       SessionManager sm = SessionManager.getInstance(selfId);
       List<String> peers = new ArrayList<String>();
       peers.add(selfId);
       peers.add("Bob");
       AVHistroyMessageQuery sessionHistoryQuery = sm.getHistroyMessageQuery();
       sessionHistoryQuery.setLimit(100);  //设置查询结果大小
       sessionHistoryQuery.setPeerIds(peers); // 设置单聊的参与方,多个参与者之间是「与」的关系
       sessionHistoryQuery.setTimestamp(1413184345686);  //查询时间片1413184345686以前的聊天记录
       sessionHistoryQuery.findInBackground(new HistoryMessageCallback() {
             @Override
             public void done(List<AVHistoryMessage> messages, AVException error) {
                  System.out.println(messages.size());
             }
       });//查询session里的聊天记录

       Group group = sm.getGroup("140a534fd092809500e6d651e73400c7");
       AVHistroyMessageQuery groupHistoryQuery = group.getHistoryMessageQuery();//获取AVHistoryMessageQuery对象来查询聊天室的聊天记录
       groupHistoryQuery.findInBackground(new HistoryMessageCallback(){
            @Override
            public void done(List<AVHistoryMessage> messages,AVException error){
              for(AVHistoryMessage msg:messages){
                 System.out.println(msg.getMessage());
              }
            }
       })

下边第一个查询会得到「汤姆」和「Bob」在一定期刻点早先的 100
条闲聊记录;第叁个查询会获得特定闲谈室的享有闲扯记录(若是总的数量不抢先1000 条的话)。

line 20:退出登入


[JMSGUser logout:^(id resultObject, NSError *error) {
}];

节奏消息(AVIM奥迪oMessage)

AVIMFileMessage
子类,特地用来发送语音和附带文本的搅动新闻,其构造函数注解为:

// 传入本地文件路径,构造消息对象
public AVIMAudioMessage(String localPath) throws FileNotFoundException, IOException;
// 传入本地文件,构造消息对象
public AVIMAudioMessage(File localFile) throws FileNotFoundException, IOException;   
// 传入 AVFile 实例,构造消息对象
public AVIMAudioMessage(AVFile file);

发送音频音信的躬行实践代码为:

String localAudioPath;
try {
  AVIMAudioMessage message = new AVIMAudioMessage(localAudioPath);
  message.setText("听听我唱的小苹果:)");
  conversation.sendMessage(message, new AVIMConversationCallback() {
    @Override
    public void done(AVException e) {
      if (null != e) {
        // 出错了。。。
        e.printStackTrace();
      } else {
        Logger.d("message sent");
      }
    }
  });
} catch (Exception ex) {
}

抽出到这么新闻随后,开拓者可以经过如下方法,获取到多少音频元数据(时间长度duration、音频 size)和八个满含音频数据的 AVFile 对象:

  • double getDuration() 方法会重返音频的长度(单位:秒)
  • AVFile getAVFile() (世袭自
    AVIMFileMessage)方法会再次回到八个音频文件的 AVFile 实例
  • String getFileUrl() (世襲自 AVIMFileMessage)方法会重返音频文件的
    url
  • long getSize() (世襲自
    AVIMFileMessage)方法会重临音频文件的其实尺寸(单位:byte)
  • String getText() (世襲自
    AVIMFileMessage)方法会再次来到随音频一齐发送的文件音讯。
  • Map<String, Object> getFileMetaData() (世襲自
    AVIMFileMessage)能够博得音频的其他元数据音讯。

纵览查看全部闲聊室

翻开全数谈天室的章程和查阅单个闲谈室成员的措施肖似,都以一向通过 AVQuery
或许 AVObject 来遍历 AVOSRealtimeGroups 表达成的,这里不再赘述。

至此多个 IM 的种种基本操作就完了,是否

摄像新闻(AVIMVideoMessage)

AVIMFileMessage
子类,特意用来发送录像和附带文本的混合音讯,其布局函数阐明为:

// 传入本地文件路径,构造消息对象
public AVIMVideoMessage(String localPath) throws FileNotFoundException, IOException;
// 传入本地文件,构造消息对象
public AVIMVideoMessage(File localFile) throws FileNotFoundException, IOException;
// 传入 AVFile 文件,构造消息对象
public AVIMVideoMessage(AVFile file);

发送摄像音信的身体力行代码为:

String localVideoPath;
try {
  AVIMVideoMessage message = new AVIMVideoMessage(localVideoPath);
  message.setText("敢不敢跟我比一比");
  conversation.sendMessage(message, new AVIMConversationCallback() {
    @Override
    public void done(AVException e) {
      if (null != e) {
        // 出错了。。。
        e.printStackTrace();
      } else {
        Logger.d("message sent");
      }
    }
  });
} catch (Exception ex) {
}

收起到这么新闻随后,开荒者能够能够透过如下方法,获取到多少录制元数据(时间长度duration、录像 size)和一个含有录像数据的 AVFile 对象:

  • double getDuration() 方法会再次回到摄像的长度(单位:秒)
  • AVFile getAVFile() (世袭自
    AVIMFileMessage)方法会再次来到一个录制文件的 AVFile 实例
  • String getFileUrl() (世襲自 AVIMFileMessage)方法会再次来到录制文件的
    url
  • long getSize() (世袭自
    AVIMFileMessage)方法会重回录制文件的其实尺寸(单位:byte)
  • String getText() (世襲自
    AVIMFileMessage)方法会再次回到随录像一同发送的文件新闻。
  • Map<String, Object> getFileMetaData() (继承自
    AVIMFileMessage)能够博得录制的别的元数据消息。

谈心记录和平安

前边完成了单聊、群聊、富媒体闲扯许多作用,可是开荒者大概已经发掘了,那都以一直调用
LeanMessage SDK
来贯彻的,对于大家开采者来讲,能垄断(monopoly卡塔尔的事物少之又少,在安全性上会存在有的揪心。举例:万一无法无天的人破解了本身的
appId 和 appKey,是或不是就足以在自小编的闲聊社区里头飞扬放肆?

为了知足开采者对权力和验证的供给,LeanMessage
还布署了操作具名的机制。大家得以在 LeanCloud
应用调控台、设置、应用选项中强制启用具名(生硬推荐那样做)。启用后,全数的
Session open 和 watch
行为都急需验证具名,那样开采者就可以对客户登入以致他得以关心怎么样人,进而能够给哪个人发音讯进行足够的调节。

签名接收 Hmac-sha1 算法,输出字节流的十七进制字符串 (hex
dump卡塔尔(英语:State of Qatar),签字的新闻格式如下:

app_id:peer_id:watch_peer_ids:timestamp:nonce

其中:

  • app_id 是您的利用 ID
  • peer_id 是开采此 Session 的 Peer ID
  • watch_peer_ids 是 open 或 watch 央求中关切的 peer
    ids,升序排序后以: 分隔
  • timestamp 是近年来的 UTC 时间隔断 unix epoch 的秒数
  • nonce 为随机字符串

在群组操作中,LeanMessage
对加群、邀约和踢出群那八个动作也允许参与具名,它的签名格式是:

app_id:peer_id:group_id:group_peer_ids:timestamp:nonce:action

其中:

  • app_id, peer_id, timestamp 和 nonce 同上
  • group_id 是此番作为涉嫌的群组 ID,对于开创群尚未有 id
    的景观,group_id 是空字符串
  • group_peer_ids 是: 分隔的升序排序的 peer id,即诚邀和踢出的
    peer_id;对参加群的状态,这里是空字符串
  • action 是本次作为的动作,三种表现分别对应常量 join, invite 和 kick

签订公约的 key 是利用的 master key。开垦者可以达成和煦的
SignatureFactory,调用远程的服务器的签字接口拿到签字。若无团结的服务器,能够平昔在
LeanCloud 的云代码上经过 Web Hosting
动态接口实现和煦的签订左券接口。在运动应用中一贯做签字是丰富危险的,它大概导致你的
master key 泄漏。

LeanCloud 的 appKey 分类
在 LeanCloud 平台上申请了应用之后,LeanCloud 会分配给大家八个key:八个 appKey,四个 master Key。个中 appKey
能够实践一些平日的操作,并且受到 LeanCloud
平台安全设置的节制,雷同于操作系统中的普通 User
账号,所以能够直接用在客户端;master Key
则怀有有着权限,相似于操作系统中的 Root/Administrator
账号,所以请安妥保管。

好,有了签字机制之后,我们到底该怎样运用啊?大家只须要完结和煦的
SignatureFactory,然后在拉开 session 的时候,把这一个 signatureFactory
传进去就能够。示例代码如清单 13 所示:

// Signature 定义如下,由 LeanMessage 提供
public class Signature {
    private String signature;
    private long timestamp;
    private String nonce;
    private List<String> signedPeerIds;

    // getter / setter for properties
    ......
}
// customise signature factory,由开发者实现
public MySignatureFactory implements SignatureFactory {
    @override
    public Signature createSignature(String selfId, List<String> watchIds) {
        // call remote server for correct signature.
    }
   @override
    public Signature createGroupSignature(String groupId, String selfId, List<String> targetPeerIds,
  String action) {
        // call remote server for correct group signature.
    }
}

// open session with signature factory.
SignatureFactory signatureFacatory = new MySignatureFactory();
SessionManager sm = SessionManager.getInstance(selfId);
sm.setSignatureFactory(signatureFactory);
sm.open(selfId);

设定了 SignatureFactory 之后,对于急需鉴权的操作,LeanMessage SDK
与劳动器端通信的时候都会带上应用本人生成的 Signature 消息,那样
LeanMessage 服务器端就能够动用 app 的 masterKey
来验证消息的管事,保证谈心渠道的安全。

很简单?


作者: pikacode - 极光( jpush 为极光团队账号)
原文:20 行代码极速为 App 加上聊天功能
知乎专栏:极光日报

http://www.bkjia.com/IOSjc/1199118.htmlwww.bkjia.comtruehttp://www.bkjia.com/IOSjc/1199118.htmlTechArticle20 行代码极速为 App 加上闲谈功效,极速app
未来广大 App 都亟需集成 IM 功效,明日就为大家享用一下集成 IM
基本效用的手续。本文内容以…

地理地方消息(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);
}

与公事音讯看似,地理地点信息只是充实了二个 AVGeoPoint 的 Location
属性。要发送地方音信的示范代码为:

AVIMLocationMessage message = new AVIMLocationMessage();
message.setText("快点过来!");
message.setLocation(new AVGeoPoint(15.9, 56.4));
conversation.sendMessage(message, new AVIMConversationCallback() {
  @Override
  public void done(AVException e) {
    if (null != e) {
      // 出错了。。。
      e.printStackTrace();
    } else {
      Logger.d("message sent");
    }
  }
});

收纳到那般的音讯之后,开拓者能够取拿到现实的地理位置数据。

结束语

LeanMessage
是一个老大安静可信赖的闲谈服务平台,提供的功力也足以知足大家使用开拓者的需求。这里自身经过介绍
LeanMessage API 来落到实处利用内的单聊、群聊、富媒体音讯等底蕴用,不过LeanMessage 还扶持更加的多高阶作用,譬喻 Super
Peer、敏感词过滤、新闻实时监听等等,有乐趣的意中人能够三翻五次研究。

怎么接纳富媒体音信

新版 LeanCloud IM SDK 内部封装了对富媒体音信的支撑,全数富媒体信息都以从
AVIMTypedMessage 派生出来的。发送的时候能够直接调用
conversation.sendMessage()
函数。在接纳端,我们也特意扩充了生机勃勃类回调接口
AVIMTypedMessageHandler,其定义为:

public class AVIMTypedMessageHandler<T extends AVIMTypedMessage> extends MessageHandler<T> {

  @Override
  public void onMessage(T message, AVIMConversation conversation, AVIMClient client);

  @Override
  public void onMessageReceipt(T message, AVIMConversation conversation, AVIMClient client);
}

开辟者能够编写自个儿的消息管理 handler,然后调用
AVIMMessageManager.registerMessageHandler(Class<? extends AVIMMessage> clazz, MessageHandler<?> handler)
函数来注册目的 handler。

接纳端对于富媒体音信的布告管理的示范代码如下:

class MsgHandler extends AVIMTypedMessageHandler<AVIMTypedMessage> {

  @Override
  public void onMessage(AVIMTypedMessage message, AVIMConversation conversation, AVIMClient client) {
    // 请按自己需求改写
    switch(message.getMessageType()) {
    case AVIMReservedMessageType.TextMessageType:
      AVIMTextMessage textMsg = (AVIMTextMessage)message;
      Logger.d("收到文本消息:" + textMsg.getText() + ", msgId:" + textMsg.getMessageId());
      break;
    case AVIMReservedMessageType.FileMessageType:
      AVIMFileMessage fileMsg = (AVIMFileMessage)message;
      Logger.id("收到文件消息。msgId=" + fileMsg.getMessageId() + ", url=" + fileMsg.getFileUrl() + ", size=" + fileMsg.getSize());
      break;
    case AVIMReservedMessageType.ImageMessageType:
      AVIMImageMessage imageMsg = (AVIMImageMessage)message;
      Logger.id("收到图片消息。msgId=" + imageMsg.getMessageId() + ", url=" + imageMsg.getFileUrl() + ", width=" + imageMsg.getWidth() + ", height=" + imageMsg.getHeight());
      break;
    case AVIMReservedMessageType.AudioMessageType:
      AVIMAudioMessage audioMsg = (AVIMAudioMessage)message;
      Logger.id("收到音频消息。msgId=" + audioMsg.getMessageId() + ", url=" + audioMsg.getFileUrl() + ", duration=" + audioMsg.getDuration());
      break;
    case AVIMReservedMessageType.VideoMessageType:
      AVIMVideoMessage videoMsg = (AVIMAudioMessage)message;
      Logger.id("收到视频消息。msgId=" + videoMsg.getMessageId() + ", url=" + videoMsg.getFileUrl() + ", duration=" + videoMsg.getDuration());
      break;
    case AVIMReservedMessageType.LocationMessageType:
      AVIMLocationMessage locMsg = (AVIMLocationMessage)message;
      Logger.id("收到位置消息。msgId=" + locMsg.getMessageId() + ", latitude=" + locMsg.getLocation().getLatitude() + ", longitude=" + locMsg.getLocation().getLongitude());
      break;
    }
  }

  @Override
  public void onMessageReceipt(AVIMTypedMessage message, AVIMConversation conversation, AVIMClient client) {
  }
}
MsgHandler msgHandler = new MsgHandler();
AVIMMessageManager.registerMessageHandler(AVIMTypedMessage.class, msgHandler);

LeanCloud IM SDK 内部新闻分发的逻辑是如此的:对于收受的任少年老成新新闻,SDK
内部都会先剖判新闻的档案的次序,依照项目找到开荒者为这一门类注册的拍卖
handler,然后逐生机勃勃调用那些 handler 的 onMessage
函数。若无找到特意管理这生机勃勃品种消息的 handler,就能够传送给
defaultHandler 管理。

那样一来,在开荒者为 TypedMessage(及其子类) 钦赐了特地的
handler,也内定了全局的 defaultHandler
了的时候,要是发送端发送的是通用的 AVIMMessage 新闻,那么选拔端就是
AVIMMessageManager.registerDefaultMessageHandler(卡塔尔(英语:State of Qatar)中钦点的 handler
被调用;倘若发送的是 AVIMTypedMessage(及其子类)的信息,那么选拔摆正是
AVIMMessageManager.registerMessageHandler(卡塔尔中钦命的 handler 被调用。

怎么着扩展本身的富媒体音讯

接轨于
AVIMTypedMessage,开辟者也得以扩大本身的富媒体新闻。其须求和手续是:

  • 完结新的新闻类型,继承自 AVIMTypedMessage。这里须要留意两点:
    • 在 class 上扩大叁个 @AVIMMessageType(type=123卡塔尔国 的
      Annotation,具体消息类型的值(123)由开垦者本人说了算(LeanCloud
      内建的音讯类型应用负数,所有正数都留给给开拓者增添使用)。
    • 在音信内部属性上要加进 @AVIMMessageField(name=””卡塔尔 的
      Annotation,name
      为可选字段在宣称字段属性,同临时间自定义的字段要有照管的
      getter/setter 方法。
  • 调用
    AVIMMessageManager.registerAVIMMessageType(Class<? extends AVIMTypedMessage> messageType)
    函数进行项目注册
  • 调用
    AVIMMessageManager.registerMessageHandler(Class<? extends AVIMMessage> clazz, MessageHandler<?> handler)
    函数实行音讯管理 handler 注册。

AVIMTextMessage 的源码如下,可供参谋:

@AVIMMessageType(type = -1)
public class AVIMTextMessage extends AVIMTypedMessage {

  @AVIMMessageField(name = "_lctext")
  String text;
  @AVIMMessageField(name = "_lcattrs")
  Map<String, Object> attrs;

  public String getText() {
    return this.text;
  }

  public void setText(String text) {
    this.text = text;
  }

  public Map<String, Object> getAttrs() {
    return this.attrs;
  }

  public void setAttrs(Map<String, Object> attr) {
    this.attrs = attr;
  }
}

群组谈心

与前方的单聊相仿,群组闲聊也急需先创造三个会话(AVIMConversation),然后发送、接纳新的消息。

开创群组

和单聊近似,建构一个几个人闲谈的群组也是很简单的。例如:

Map<String, Object> attr = new HashMap<String, Object>();
attr.put("type", ConversationType_Group);
imClient.createConversation(clientIds, attr, new AVIMConversationCreatedCallback() {
  @Override
  public void done(AVIMConversation conversation, AVException e) {
    if (null != conversation) {
      // 成功了!
      Intent intent = new Intent(currentActivity, ChatActivity.class);
      Intent.putExtra(“conversation”, conversation);
      currentActivity.startActivity(intent);
    }
  }
});

成功将来,大家就足以进来聊天分界面了。

往群组发送新闻

发送消息很简单,与前面单聊的风貌形似。

我们会注意到,AVIMConversation 还恐怕有三个出殡和安葬消息的章程:

public void sendMessage(final AVIMMessage message, final int messageFlag,
      final AVIMConversationCallback callback)

而这里 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 如下:

// 假设需要邀请 Alex,Ben,Chad 三人加入对话
List<String> userIds = new ArrayList<String>();
userIds.add("Alex");
userIds.add("Ben");
userIds.add("Chad");
conversation.addMembers(userIds, new AVIMConversationCallback() {
  @Override
  public void done(AVException error) {
    if (null != error) {
      // 加入失败,报错.
      error.printStackTrace();
    } else {
      // 发出邀请,此后新成员就可以看到这个对话中的所有消息了。
      Logger.d("invited.");
    }
  }
});

特邀成功之后,相关方收到布告的时序是那样的:

    操作者(管理员)                    被邀请者                        其他人
1, 发出请求 addMembers
2,                               收到 onInvited 通知
3, 收到 onMemberJoined 通知      收到 onMemberJoined 通知      收到 onMemberJoined 通知

对应地,踢人时的调用 API 是:

List<String> userIds = new ArrayList<String>();
userIds.add("Alex");
conversation.kickMembers(userIds, new AVIMConversationCallback() {
  @Override
  public void done(AVException error) {
    if (null != error) {
      // 失败,报错.
      error.printStackTrace();
    } else {
      // 成功。
      Logger.d("kicked.");
    }
  }
});

踢人时,相关方收到通告的时序如下:

    操作者(管理员)                被踢者                       其他人
1, 发出请求 kickMembers
2,                          收到 onKicked 通知
3, 收到 onMemberLeft 通知                             收到 onMemberLeft 通知

注意!
要是诚邀、踢人操作发生的时候,被邀约者/被踢者当前不在线,那么公告消息并不会被离线缓存,所以他们再上线的时候将不会吸取公告。

收获历史音信

LeanMessage 会将非暂态音讯自动保存在云端,之后开辟者能够通过
AVIMConversation 来获取该对话的享有历史音讯。获取历史消息的 API 如下:

String oldestMsgId;
long oldestMsgTimestamp;
conversation.queryMessages(oldestMsgId,oldestMsgTimestamp, limit, new AVIMHistoryMessageCallback(){
  @Override
  public void done(List<AVIMMessage> messages, AVException e) {
    if (null != e) {
      // 出错了:(
    } else {
      // 成功,可以将消息加入缓存,同时更新 UI
    }
  }
});

注意:
获取历史新闻的时候,LeanCloud
云端是从某条音信最初,往前寻觅开垦者钦命的 N
条音信,重临给顾客端。为此,获取历史音讯需求传入多少个参数:最初音讯的
msgId,开始消息的出殡时间戳,要求拿到的新闻条数。

通过那生机勃勃 API 获得的消息便是 AVIMMessage 依旧 AVIMTypedMessage
实例数组,开拓者能够像早前选用新音信通知生龙活虎致管理。

启用离线新闻推送(仅对 iOS 平台客商有效)

无论是是单聊仍然群聊,当客商 A
发出新闻后,假使目的对话中有意气风发部分客户近日不在线,LeanCloud
云端能够提供离线推送的主意来提醒客商。那黄金时代功力私下认可是关门的,你能够在
LeanCloud 应用调控新北张开它。开启方法如下:

  • 报到 LeanCloud 应用调整台,接受正确的应用踏入;
  • 选择最上端的「新闻」服务,依次点击侧面菜单「实时新闻」->「设置」;
  • 在左手「iOS
    顾客离线时的推送内容」下填好你要推送出去的消息内容,保存;

这么 iOS 平台上的客商就足以吸取 Push Notification
了(当然,前提是使用自身申请到了 RemoteNotification
权限,也将科学的推送证书上传到了 LeanCloud 调整台)。

群组音信免打扰(仅对 iOS 平台顾客有效)

甭管是单聊照旧群聊,对于发往普通的 Conversation
的常备音信,假设选用方当前不在线,LeanCloud 云端补助通过 Push
Notification
的章程进行提醒。经常意况下那都以很好的,不过只要某些群组非常活跃,那离线顾客就能够接到过多的推送,会产生一点都不小的侵扰。

对此 LeanCloud IM 服务也同意单个客户来关闭/打开有些对话的离线推送功效。

搜寻群组

任由是单聊,依旧群聊,在 LeanCloud IM SDK
里面都以对话(Conversation)。我们给对话设置了之类三种属性:

  • conversationId,字符串,对话 id,只读,对话制造之后由 LeanCloud
    云端付与贰个大局唯风流倜傥的 id。
  • creator,字符串,对话创立者 id,只读,标记对话创建者音信
  • members,数组,对话参预者,这里记录了具备的到场者
  • name,字符串,对话的名字,optional,可用来对于群组命名
  • attributes,Map/Dict,自定义属性,optional,供开拓者本人强大用。

我们提供了特别的类,来搜索一定的群组:通过 imClient.getQuery()
获得一个 AVIMConversationQuery 实例,然后调用
AVIMConversationQuery.wherexxx
多种措施来扩展限定标准。举个例子要查究当前登陆客户出席的有所群聊对话,其代码为

// 搜索 Tom 参与的所有群组对话
List<String> clients = new ArrayList<String>();
clients.add("Tom");
AVIMConversationQuery conversationQuery = imClient.getQuery();
conversationQuery.containsMember(clients);

// 之前有常量定义:
// const int ConversationType_OneOne = 0;
// const int ConversationType_Group = 1;
conversationQuery.whereEqualTo("attr.type", ConversationType_Group);

conversationQuery.findInBackground(new AVIMConversationQueryCallback(){
  @Override
  public void done(List<AVIMConversation> conversations, AVException e) {
    if (null != e) {
      // 出错了。。。
      e.printStackTrace();
    } else {
      if (null != conversation) {
        Logger.d("找到了符合条件的 " + conversations.size() + " 个对话");
      } else {
        Logger.d("没有找到符合条件的对话");
      }
    }
  }
});

AVIMConversationQuery 中设置条件的法子与 AVQuery 类似。这里
conversationQuery.containsMember()
表示对话的积极分子中足足含有这几个人口,可用来根据部分成员查找对话;与此相像的还也许有五个
conversationQuery.withMembers()
则表示有且唯有那些成员,用来依照全部成员查找目的对话;conversationQuery.whereXXX()
层层措施可用来界定对话名称和自定义属性,这里要强调的一些是,对于自定义属性的牢笼原则,属性名必须要以
attr 起初,如上例所示,约束额外的 type 条件的时候必要钦定的属性名是
attr.type。具体可以参见其头文件。

绽开闲谈室

绽开聊天室(也叫暂态对话)能够用来比较多地点,比方弹幕、直播等等。在
LeanCloud IM SDK
中,开放谈心室是大器晚成类特殊的群组,它也支撑成立、参加/踢出成员等操作,音信记录会被封存并可供获取;与何奇之有群组不生龙活虎致的地点实际展现为:

  • 不襄协助调查询成员列表,你能够经过有关 API 查询在眼线数;
  • 不帮助离线音信、离线推送公告等职能;
  • 从未有过成员步入、离开的照顾;
  • 三个客商叁次登入只好步入三个开花闲聊室,参预新的开放闲话室后会自动离开原先的闲聊室;
  • 加盟后三拾贰分钟内断网重连会自行步向原闲谈室,当先那么些时刻则需求重新到场;

创立开放聊天室

和平时性的群组相似,创立三个吐放聊天室也是超轻便的,只是在
AVIMClient.createConversation(conversationMembers, name, attributes, isTransient, callback)
中大家须求传入 isTransient=true 选项。例如:

Map<String, Object> attr = new HashMap<String, Object>();
attr.put("type", ConversationType_Group);
imClient.createConversation(clientIds, name, attr, true, new AVIMConversationCreatedCallback() {
  @Override
  public void done(AVIMConversation conversation, AVException e) {
    if (null != conversation) {
      // 成功了,进入聊天室
      Intent intent = new Intent(currentActivity, ChatActivity.class);
      Intent.putExtra(“conversation”, conversation);
      currentActivity.startActivity(intent);
    }
  }
});

创建设成功之后,我们就能够进来闲聊分界面了。开放闲聊室的任何操作,都与普通群组操作同样。

投入开放闲聊室

借使任何极端客商都足以步入开放聊天室。作为开拓者,大家能够由此通过特定条件检索到全体开放闲聊室,然后允许顾客自由加盟,其演示代码为:

conversation.join(new AVIMConversationCallback(){
  @Override
  public void done(AVException e) {
    if (null != e) {
      // 出错了:(
    } else {
      // 成功,此时可以进入聊天界面了。。。
      Intent intent = new Intent(currentActivity, ChatActivity.class);
      Intent.putExtra(“conversation”, conversation);
      currentActivity.startActivity(intent);
    }
  }
});

询问在窥探数

通过 AVIMConversation.getMemberCount()
方法能够实时查询开放闲谈室的在窥探数。示例代码如下:

conversation.getMemberCount(new AVIMConversationMemberCountCallback(){
  @Override
  public void done(Integer memberCount, AVException e) {
    if (null != e) {
      // 出错了:(
    } else {
      // 成功,此时 memberCount 的数值就是实时在线人数
    }
  }
});

签订和河池

为了满意开拓者对权力和注解的必要,LeanCloud
还布署了操作具名的建制。大家得以在 LeanCloud
应用调控高雄的「设置」->「应用选项」->「闲扯推送」上面勾选「聊天服务签订协议认证」来启用具名(猛烈推荐那样做)。启用后,全体的客商登陆、对话创立/插足、诚邀成员、踢出成员等操作都亟待表达具名,那样开辟者就足以对音信举行足够的调整。

客商端那边毕竟该怎么使用啊?大家只需求落到实处 SignatureFactory
接口,然后在客商登陆从前,把这些接口的实例赋值给 AVIMClient
就能够(AVIMClient.setSignatureFactory(factory))。

设定了 signatureFactory 之后,对于要求鉴权的操作,LeanCloud IM SDK
与劳务器端通讯的时候都会带上应用自身生成的 Signature 消息,LeanCloud
云端会选拔 app 的 masterKey 来证实音讯的管用,保证闲聊门路的辽源。

对此 SignatureFactory 接口,大家只须要完毕这多少个函数就可以:

  /**
   * 实现一个基础签名方法 其中的签名算法会在SessionManager和AVIMClient(V2)中被使用
   */
  public Signature createSignature(String peerId, List<String> watchIds) throws SignatureException;

  /**
   * 实现AVIMConversation相关的签名计算
   */
  public Signature createConversationSignature(String conversationId, String clientId,
      List<String> targetIds, String action) throws SignatureException;

createSignature
函数会在客户登陆的时候被调用,createConversationSignature
会在对话创制/参与、邀约成员、踢出成员等操作时被调用。

你需求做的正是遵纪守法前文所述的具名算法完结签约,当中 Signature
申明如下:

public class Signature {
  public List<String> getSignedPeerIds();
  public void setSignedPeerIds(List<String> signedPeerIds);

  public String getSignature();
  public void setSignature(String signature);

  public long getTimestamp();
  public void setTimestamp(long timestamp);

  public String getNonce();
  public void setNonce(String nonce);
}

里头多个天性分别是:

  • signature 签名
  • timestamp 时间戳,单位秒
  • nonce 随机字符串 nonce
  • signedPeerIds 放行的 clientId 列表,v2 中已经甩掉不用

下边包车型地铁代码呈现了基于 LeanCloud
云代码举办签约时,顾客端的得以完成部分,你能够参见它来成功自个儿的逻辑完结:

public class KeepAliveSignatureFactory implements SignatureFactory {
 @Override
 public Signature createSignature(String peerId, List<String> watchIds) {
   Map<String,Object> params = new HashMap<String,Object>();
   params.put("self_id",peerId);
   params.put("watch_ids",watchIds);

   try{
     Object result =  AVCloud.callFunction("sign",params);
     if(result instanceof Map){
       Map<String,Object> serverSignature = (Map<String,Object>) result;
       Signature signature = new Signature();
       signature.setSignature((String)serverSignature.get("signature"));
       signature.setTimestamp((Long)serverSignature.get("timestamp"));
       signature.setNonce((String)serverSignature.get("nonce"));
       return signature;
     }
   }catch(AVException e){
     throw (SignatureFactory.SignatureException) e;
   }
   return null;
 }

  @Override
  public Signature createConversationSignature(String convId, String peerId, List<String> targetPeerIds,String action){
   Map<String,Object> params = new HashMap<String,Object>();
   params.put("self_id",peerId);
   params.put("group_id",convId);
   params.put("group_peer_ids",targetPeerIds);
   params.put("action",action);

   try{
     Object result = AVCloud.callFunction("group_sign",params);
     if(result instanceof Map){
        Map<String,Object> serverSignature = (Map<String,Object>) result;
        Signature signature = new Signature();
        signature.setSignature((String)serverSignature.get("signature"));
        signature.setTimestamp((Long)serverSignature.get("timestamp"));
        signature.setNonce((String)serverSignature.get("nonce"));
        return signature;
     }
   }catch(AVException e){
     throw (SignatureFactory.SignatureException) e;
   }
   return null;
  }
}

LeanCloud IM SDK
静心做好底层的电视发表服务,有愈来愈多能够定制化的地点,比如说:

  • 账户系列和 IM 系统是分手的;
  • 消息成为离线推送的时候,推送内容开辟者是能够定制的;
  • 经过 web hook,开辟者能够对消息进行更加多管理;
  • 闲聊进度中经过消息鉴权机制,开垦者能够有更加多调节;

因为缺少 UI
组件,安分守己地讲在新客户接入花销只怕稍高,可是在工作范围扩展、成品供给变多之后,相信我们会愈加中意LeanCloud 这种随便灵活的利用体验,以致稳固急忙的劳务品质。