葡京在线开户让你的 Android 应用也能促膝交谈(第二版)

创造对话

如若我们要跟「Bob」这一个用户展开聊天,我们先创立一个会话,代码如下:

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
属性就是用户扩充的额外属性值(以目标的样式储存)。

三、品牌公关(品牌培训)

阿尔·里斯(Rhys)认为:品牌广告的首要对象是品牌维护,品牌公关的第一对象是品牌作育。公关是透过媒体联络举办品牌传播,以拿到民众关心与体会。

互联网经济平台应当怎么进行公关工作,参见笔者的另一篇著作《盘点互联网经济品牌公关的常用手法》,这篇作品对互联网经济品牌公关有相比详细的下结论和概括。建设型公关如上线庆典、上线发布会、融资宣布会;社会型公关如公益活动和生意赞助;交际型公关如线下考察、投资人会合会、政坛走访调研;服务型公关如完善网站体验、提高客服工作质地、提高平台透明度、确保平台安全可靠;宣传型公关包括对内宣传和对外做广告,对外做广告的款型如:媒体报道、媒体采访、事件公关、媒体合作、软文撰写和传媒会见会;维系型公关如借势合作伙伴、借势行业协会、借势论坛会议、借势名家效应和借势奖项荣誉;防御型公关如风险预警机制的确立;进攻型公关如互金行业污名化背景下的正名之战、矫正型公关即危机公关。

初始化

和 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>

接下去大家需要完成用户登录。

有的是人张口闭口谈品牌,要给“品牌”一个精准的定义,这就让很四个人为难了。个人比较认同Interbrand集团对品牌的定义:“品牌是顾客在享有的品牌接触点(店铺,电视机,杂志,网络,公司员工等)暴发的一种体验的总数。”

得到历史消息

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
实例数组,开发者可以像往日接受新信息通知一致处理。

四、品牌广告(品牌维护)

广告是因而购买广告位让品牌宣传直接到达消费群体。品牌广告可概括分为线下品牌广告和线上品牌广告。

(一)线下品牌广告

1、分众广告

分众广告是采用技术手段让信息直达目的受众的一种广告格局。广告渠道如:分众传媒、巴士在线。分众传媒的写字楼广告,就可以很好的掩盖白领群体,而白领群体又是互联网理财的精准客户。

2、交通工具(站点、沿线)广告

广告渠道如:公交广告、地铁广告、高铁广告、机场广告、火车站广告、高速路牌广告、城市道路路牌广告等。以地铁广告为例,地铁广告具备覆盖面广、记念点较好的优点,也是P2P网贷平台最偏好的线下投放渠道之一。地铁广告投放的重要情势有车厢广告、车厢拉手广告、隧道灯箱广告、站台语音广告等。通过此渠道投放的阳台包括人们贷、你本身贷、信而富等20家阳台。

3、纸质媒体广告

广告渠道如:报纸(如南方周末、南方城市报等)、杂志(汽车、财经、旅游等各个杂志),广告格局诸如:专题报道、人物专访、内容营销合作和任何硬广。2016年1月,互联网金融平台点融网包下新京报等报刊头版打出正名宣言:“真的,不跑路”,利用纸质媒体的影响力,将自己身处聚光灯下,接受社会各方的审视,主动谋求与消费者对话。

4、电影院线广告

观影人群重点为青春白领和学生,15~30岁居多,大部分观众受过优秀的携带,消费劲量也强,更容易接受P2P这一新生消费形式以及理财情势。宜信财富、天弘基金、信和财富和人们投等都投放过院线广告,那么些商家的投放区域基本以北、上、广、深等一线城市为主。

5、广场液晶屏广告

除却选取国内液晶屏广告资源,互联网金融公司还把视线投向海外,玩起“出口转内”的一手,2016年新年之间,美国伦敦时代广场刊登了国内100家商厦邀请世界人民一道过新年的宣扬内容,其中就包括易贷网在内的境内7家互金平台。

6、楼宇广告

排放楼宇广告的阳台如团贷网、宜人贷、你自己贷等。但楼宇广告重要集中在一、二线城市,尤其以北上广深一线城市为主,并且内容情势相比较单一,播放监测困难,成本较高。

(二)线上品牌广告

1、T类显示广告

广告渠道如:乐乎、网易、新浪、凤凰、APP开屏广告、互联网金融门户网站等。

2、电台广告

广告渠道如:传统电台(麦纳麦广播电台、交通音乐电台等)、互联网电台(喜马拉雅、荔枝FM等),比如,有车贷产品的P2P网贷平台相比较合适在电台投放广告,尤其是交通广播电台,覆盖有车一族。

3、电视广告

广告格局如:硬广、访谈、独家赞助、公益植入等。利用电视机这种“权威”媒体为品牌背书,增信效果相比显然(效果完全呈下降势头),但价格不菲,2014年12月1日起,信和财富在央视一套天气预报播报中插播“信和财富说话算数”的宣扬广告,后又陆续登陆湖北卫视、海南卫视、东方卫视等地点卫录像道举行宣传拓宽,据估量,此轮宣传广告费达数千万人民币。

4、录像广告

广告渠道如:优酷、爱奇艺等;广告情势如:贴片广告、暂停广告、开机广告等。

其它,流量广告投放(SEM、网盟、DSP、导航等)、跨界合作、线上运动、线下地推、自媒体运营、社会化营销等营销方法,也是品牌建设的有效途径,但不是品牌建设的重中之重途径,他们更爱抚流量获取或用户运营,笔者将在“流量获取”“用户运营”专题开展详尽介绍。

简介

自二〇一八年 LeanCloud
发表实时通信(IM)服务之后,基于用户举报和工程师对需求的消化和对事情的提炼,下周专业发布了「实时通信
2.0
」。设计理念一如既往是「灵活、解耦、可组合、可定制」,具体可以参见《实时通信支出指南》,掌握LeanCloud 实时通信的基本概念和模型。

一、品牌设计

品牌设计须依照市场营销战略制定,笔者在《互金集团市场营销战略设计的三个步骤》一文中,对互联网经济公司市场战略设计形式做了介绍,品牌计划则可从以下三下面先导。

(一)品牌称号

品牌称号须遵照独特性、简单易记、有故事、无歧义这多少个规则,好的品牌名字可以推向品牌的宣扬推广。反面案例,例如:“穗金所、房金所、票金所、e金所、友金所、前金所、楚金所、微金所、汇金所、贷金所……“,品牌名缺少独特性,不易于记念,常被理财用户混淆。

(二)品牌一定

品牌一定是公司针对地下的顾客开展营销规划,创立品牌在暧昧顾客心目中的某种形象或个性特征,从而得到竞争优势。定位的真面目就是打下消费者的“心智”,拿到消费者激情上的认可,互联网经济品牌常用的固定模式有以下四种。

1、依据产品性能和效能定位

一个新的品牌应强调一种属性,遵照产品自己的属性以及经过给客户拉动的实际好处固化。如网贷之家定位“你身边的网贷之家”,众筹超市定位“专业的众筹导购平台”。

2、依照品牌的市场馆位定位

据品牌的商海地位定位,在操作规模有二种政策可采用:
一是“首席定位”策略,力求使品牌成为本行业中的领导者或第一品牌。如众筹中国固定“最具影响力的众筹资讯门户”。二是“加强定位”策略,即强调巩固与增长自己在市面和买主心中中现有的地方。

3、依据品牌的USP定位

基于品牌向消费者提供的裨益固化,并且这一利益点是此外品牌不能够提供的,是惟一的。运用USP定位,在同类品牌众多、竞争剧烈的意况下,可以卓越品牌的特点和优势。

4、遵照品牌客户类型定位

基于品牌客户定位,是以目的客户的年华、性别、身份、地理地点、行为偏好、规模、性质等为坐标的一定方法。

(1)遵照个人客户类型定位:

比如,以个人客户的年龄为定位坐标,网筹金融,一家专注服务80后的金融理财平台;

(2)依照单位客户类型:

比如说,以机构客户所在同行业为定点坐标,珠宝贷,一家专注于珠宝行业投融资的服务平台;麻布袋,一家专注于农业领域的P2P网贷平台。

(三)目的客户定位

妇孺皆知的靶子客户定位,有助于急忙地确立消费者与品牌之间的牵连,从而“对号落座”,集团的品牌也能快捷地被目的客户人群所收受。

1、定位目的客户群体

相似遵照年龄,性别,出生日期,收入,职业,居住地,兴趣爱好,性格特征等维度来定义目的客户群体。

2、目标客户画像

依据目标客户定位,围绕目的客户特征,建立客户角色卡片。以某p2p网贷品牌为例,建立一个客户角色卡片:张三,28岁,互联网商家运营主管,年薪20万,10万元盈余可用以网贷理财,居住地上海,熟知互联网和理财。

地理地点音信(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");
    }
  }
});

收受到这般的音信随后,开发者可以赢得到具体的地理地点数据。

二、品牌因素导入

总体的品牌因素可参考CIS理论,一个品牌的识别系统包括:视觉识别、理念识别和作为识别。本文仅从品牌视觉形象和品牌焕发内涵两下面做简单演说。

(一)完善品牌视觉形象

1、品牌logo

品牌符号化是最简易直接的传播形式。品牌标志化能协理顾客简化他们对品牌的判断,对于公司而言,是下跌交换成本的有效途径。大红鹰的“V”代表着胜利,7-Up的“青色”代表着活力。人们看来一个“红钩”就会想到耐克,看到大大的“M”就会想到麦当劳,看到“三个圈”就会想到Audi汽车。

2、色彩计划:

Hellokitty的核心颜色为绿色,立顿茶叶的主旨色为绿色,摩托罗拉手机的主旨色为青色。他们都有特别清楚的色彩定位。于互联网金融平台而言,色彩规划不仅涉嫌品牌形象,也平昔影响了网站和APP的赏心悦目和用户体验。

3、吉祥物

品牌吉祥物能够起到传递经营理念、扩充品牌无形资产积累的效率。为我们熟识的吉祥物:百度的度熊,腾讯的企鹅,天猫的黑猫,京东的金属虎,网易的狐狸,UC浏览器的松鼠,迅雷的蜂鸟。在互联网金融行业,付融宝的阿法狗,点融网的点小融,小牛在线的小牛犇犇,也都可圈可点。

(二)注入品牌内涵

1、品牌焕发

Pepsi-Cola可以风靡世界,卖的不是商品,卖的是一种知识,是一种米利坚旺盛。朵唯将自己的品牌概念为女性手机,鼓励女性在成长的旅途勇敢去尝尝新东西。这么些品牌焕发满意了顾客心理、心境层面的需要,成为品牌营销与组织的根本因素。同理,假诺大家得以给互联网经济平台注入品牌精神,与客户达成心理和心思层面的关联,就显示愈加紧要。2016年2月,宜人贷赞助了武汉2016年马拉松赛,宜人贷采取赞助马拉松,既是对市场的纯粹把握,更是对马拉松精神的确认。

2、品牌故事

品牌故事的素材能够来自产品、创办人、公司、员工或者优异用户。雕爷牛腩花500万买秘方,西少爷肉夹馍创办人的痛心爱情故事,褚橙褚时健的此伏彼起人生,阿里上市快递员敲钟。在互金行业,团贷网创办者唐军用213万人民币拍下史玉柱三钟头午餐时间,这么些都是品牌故事。当然,品牌故事最关键的使命是传递品牌精神。

3、品牌slogan

Slogan对消费者的意思在于其所传递的信用社的产品意见,它所强调的是一家商家和它的制品最为优秀的性状。互联网经济品牌应该如何撰写slogan,笔者在《行业就不曾不土的Slogan吗?》一文中总括了金融品牌slogan创作的七大套路:Slogan发出行动指令、Slogan给予效用承诺、Slogan优异品牌一定、在Slogan中突出独特卖点、通过Slogan唤起情绪共鸣、通过Slogan传递对目的受众的关切、通过Slogan传递品牌理念。

信息接收

在 鲍勃(Bob) 这一端,要能接收到音讯,需要如下几步:

1,举办起先化;

2,实现自己的 AVIMMessageHandler,响应新消息到达通告,紧假若之类函数:

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

对于 Tom 发过来的信息,要显示出来,大家只需兑现 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() 在此之前调用,否则可能导致服务器发回去的有些信息丢失。

闻名度、美誉度、认知度、联想度和忠诚度一般被当小说牌的五项基金,所有的品牌工作也都围绕五项目的展开。互联网金融平台品牌建设,在履行层面,品牌建设可从品牌设计、品牌因素导入、品牌公关(品牌打造)和品牌广告(品牌维护)四方面动手。

创设群组

和单聊类似,建立一个两人聊天的群组也是很粗略的。例如:

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

打响之后,我们就可以进去聊天界面了。

一定的文件聊天

咱们先从最简便易行的环节出手,看看怎么用 LeanCloud IM SDK v2
落实一对一文本闲话。

始建开放聊天室

和平时的群组类似,建立一个开放聊天室也是很简单的,只是在
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);
    }
  }
});

始建成功之后,我们就足以进去聊天界面了。开放聊天室的其他操作,都与常见群组操作一样。

支撑富媒体的闲话音信

地点的代码演示了何等发送简单文本信息,但是现在的交互形式已经越发多样化,图像、语音、视频已是异常广阔的音信类型。v2
版的 LeanCloud IM SDK 已经可以很好地支撑这一个富媒体音讯,具体表达如下:

往群组发送新闻

发送信息相当简单,与前面单聊的面貌一样。

咱俩会注意到,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)
    函数被调用的机会)。

文本新闻(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.");
    }
  }
});

对话成员变动响应接口

重点用来处理对话中成员变动的轩然大波,接口定义在
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。

下载和装置

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

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

任凭是单聊仍然群聊,对于发往普通的 Conversation
的平凡信息,倘使接收方当前不在线,LeanCloud 云端帮忙通过 Push
Notification
的艺术举办提示。一般情状下这都是很好的,不过只要某个群组特别活泼,这离线用户就会接收过多的推送,会形成不小的烦扰。

对此 LeanCloud IM 服务也允许单个用户来关闭/打开某个对话的离线推送效用。

多少个举足轻重的回调接口

从地方的例证中得以看出,要收到到旁人给你发送的音讯,需要重载
AVIMMessageHandler 类。从 v2 版起头,LeanCloud IM SDK
大量运用回调来举报操作结果,不过对于有些被动的音讯通知,则依然利用接口来贯彻的,包括:

  • 眼前网络出现变化
  • 对话中有新的音信
  • 对话中有新成员插足
  • 对话中有成员离开
  • 被特邀参预某对话
  • 被踢出对话

LeanCloud IM SDK 内部采纳了三种接口来响应这些事件。

收纳群组音讯

采纳一个群组的音信,与接受单聊的音信也是同样的。

查询在线人数

通过 AVIMConversation.getMemberCount()
方法可以实时查询开放聊天室的在线人数。示例代码如下:

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

节奏音信(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)能够赢得音频的其它元数据消息。

出殡信息

建立好对话之后,要发送信息是很简单的:

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」而言,他怎么才能接受别人发给她的新闻吧?

网络事件响应接口

重点用以处理网络转移事件,接口定义在
AVIMClientEventHandler,首要函数为:

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

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

在网络中断的动静下,所有的音信收发和对话操作都会合世问题。

通过 AVIMClient.setClientEventHandler(AVIMClientEventHandler handler)
能够设定全局的 Client伊芙ntHandler。

绽开聊天室

绽开聊天室(也叫暂态对话)可以用于很多位置,譬如弹幕、直播等等。在
LeanCloud IM SDK
中,开放聊天室是一类相当的群组,它也支撑创立、插足/踢出成员等操作,音讯记录会被保存并可供获取;与平日群组不相同的地点实际展示为:

  • 不援助查询成员列表,你可以经过有关 API 查询在线人数;
  • 不匡助离线音讯、离线推送通告等功能;
  • 未曾成员进入、离开的布告;
  • 一个用户五遍登录只可以进入一个开花聊天室,参加新的怒放聊天室后会自动离开原先的聊天室;
  • 加盟后半钟头内断网重连会活动进入原聊天室,领先这些刻钟则需要重新参加;

签署和平安

为了满意开发者对权力和认证的要求,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 这种随意灵活的行使体验,以及稳定迅速的劳务质地。

登录

假如聊天发起方名叫 Tom,为直观起见,我们采取用户名来作为 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);
    };
  }
});

群组聊天

与前边的单聊类似,群组聊天也亟需先创设一个会话(AVIMConversation),然后发送、接收新的消息。

成员管理

在询问到聊天室成员之后,可以让用户邀请部分自己的心上人参与,作为管理员也得以去除一些「可怕」的分子。
参预新成员的 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 通知

注意!
假若邀请、踢人操作爆发的时候,被邀请者/被踢者当前不在线,那么文告信息并不会被离线缓存,所以她们再上线的时候将不会接受通知。

视频音讯(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)可以获取视频的其他元数据信息。

怎么样扩充自己的富媒体音讯

持续于
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;
  }
}

基类: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);
}

什么选取富媒体音信

新版 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()中指定的 handler
被调用;假诺发送的是 AVIMTypedMessage(及其子类)的音信,那么接受端就是
AVIMMessageManager.registerMessageHandler()中指定的 handler 被调用。

文件信息(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()
    可以收获二进制文件的其他元数据音讯。

音讯响应接口

一言九鼎用于处理新信息到达事件,接口定义在
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());

图像消息(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)可以拿到图像的此外元数据音讯。

投入开放聊天室

假诺任何极端用户都可以投入开放聊天室。作为开发者,我们可以通过通过特定条件检索到独具开放聊天室,然后允许用户自由参预,其出现说法代码为:

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

启用离线信息推送(仅对 iOS 平台用户有效)

随便是单聊依旧群聊,当用户 A
发出信息后,尽管目的对话中有一对用户眼前不在线,LeanCloud
云端可以提供离线推送的法子来唤起用户。这一职能默认是倒闭的,你可以在
LeanCloud 应用控制马赛拉开它。开启方法如下:

  • 报到 LeanCloud 应用控制台,采纳正确的施用进入;
  • 选用最顶端的「信息」服务,依次点击左边菜单「实时音讯」->「设置」;
  • 在左边「iOS
    用户离线时的推送内容」下填好你要推送出去的音讯内容,保存;

这样 iOS 平台上的用户就足以接受 Push Notification
了(当然,前提是使用本身申请到了 RemoteNotification
权限,也将科学的推送证书上传到了 LeanCloud 控制台)。

检索群组

不论是是单聊,仍然群聊,在 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。具体可以参照其头文件。