前言

  • 本篇为开篇,会涉及很多基本的东西,所以篇幅较大,若是觉得行文啰嗦还请各位大佬不要打我。
  • 本篇目的,是从0开始到实现单聊则打住,后续的特定需求会新开特定篇来写。
  • 若是跟着文章走,遇见了坑请看文末的坑总结章节,相信很快你就能成功接入。
  • 去融云开发平台申请key什么的我就不说了,会申请QQ号就会申请这个
  • 有什么问题请直接留言指出,欢迎批评指正。

跑个官方Demo压压惊


不管怎样,接入三方SDK最快的方式——官方Demo
所以起手我们还是把Demo打开玩一玩

相关资料:
融云IM Demo
融云新手指导
融云Android SDK集成指南
融云Server开发指南
融云开发者平台
融云sdk下载地址
PS:API调试入口:我的控制台——>左侧栏目API调试

运行效果:

Demo在手,天下我有。

分析:

来一个感性的认知。
从这个Demo来看,它的使用场景基本是:
点击一个列表item ——> 进入点对点的聊天界面。
在这个聊天界面内有可以发送许多类型的消息。地图位置,图片,文本等等。

总结下特征就是:

  • 聊天模式(点对点)
  • 消息类型(多种)

信息很有限,不过也是最直观的东西,所以我准备以此作为一个切入点来进行聊天的学习。

知识点铺垫


虽然Demo已经跑起来了,但是我还是懵逼的,我们还需要了解下融云相关的知识点。

基本概念

基础概念篇幅太大,其中包含业务篇,开发篇,我准备划俩个相对重要的,其他的则不作赘述,具体参考:http://www.rongcloud.cn/docs/quick_start.html#basic_concept

App Key / Secret

App Key / Secret 相当于您的 App 在融云的帐号和密码。是融云 SDK 连接服务器所必需的标识,每一个 App 对应一套 App Key / Secret。

Token

  • Token 即用户令牌,相当于您 APP 上当前用户连接融云的身份凭证。每个用户连接服务器都需要一个 Token,用户更换即需要更换 Token。每次初始化连接服务器时,都需要向服务器提交 Token。
  • Token 称为用户令牌。
  • Token 则是您 App 上的每一个用户的身份授权象征。
  • 您可以通过提交 userId 等信息来获得一个该用户对应的 Token,并使用这个 Token 作为该用户的唯一身份凭证与其他用户进行通信。
  • Token 的主要作用是身份授权和安全,因此不能通过客户端直接访问融云服务器获取 Token,您必须通过 Server API 从融云服务器 获取 Token 返回给您的 App,并在之后连接时使用。详细描述请参考 Server开发指南中的用户服务和获取Token方法小节。

官方流程图:

分析:
我们的最终目的是通过connect方法去连接聊天服务器,但是官方服务器需要我们带Token,但是token我们没有并且也不能自己维护token,所以我们就需要去请求服务器拿token,然而要拿这个token我们就需要从本地拿到我们登录时得到的userId作为一个请求参数去哪token,这样一个流程走下来我们就能去连接聊天服务器了。

那么我们如何获取一个测试token呢?
这就要用到官方提供的API调试工具了,接着往下看。

Api调试的的使用


利用Api调试获取测试token

最开始我就PS了,API调试入口:我的控制台——>左侧栏目API调试
这个东西在我们初期调试时很重要,因为你也可以看到token是通信必须,而我们在前期服务器没调试完成的情况下,**如何来拿这个token呢?**这个时候就需要用到api调试这个功能。

如图:

可以看到这里我们获取到的信息是:

userId:zj666
name:测试用户呵
portraitUri:https://ss3.baidu.com/-rVXeDTa2gU2pMbgoY3K/it/u=225869644,1383753585&fm=202&mola=new&crop=v1请求结果:
{"code":200,"userId":"zj666","token":"wxS1DLbYEHlYRvEGldlHlLv9HaIuPBiUqpl0jm19YznutxcjH0D1Z2Yo81ijEZhZLPWs7qwNNlTGuKduIiTDBg=="
}

一顿操作猛如虎


来不及解释了,带上你的老年卡赶紧上车吧,滴,滴滴。

SDK引入

SDK下载地址:http://www.rongcloud.cn/downloads

既然是学习,我就全勾选下载了。

汇总

Name Type Desc 引入姿势
IMKit 界面 融云 IM 界面组件 Import Moudle
CallKit 界面 融云音视频界面组件 Import Moudle
IMLib 融云 IM 通讯能力库 armeabi, armeabi-v7a, arm64-v8a, x86 Import Moudle
CallLib 融云音视频核心组件 armeabi-v7a, x86 Import Moudle
LocationLib 融云位置相关库,高德地图的低版本jar包。 copy jar int your libs direct
RedPacket 融云红包相关库 Import Moudle

另外一点疑问,如图:

一般来说Kit和Lib都下载,因为它lib里边的库不全,但你用的话可以选择性的用,但是一点,用Kit必用Lib,但Kit不是必须的。

引入后的项目目录结构

配置文件

gradle文件依赖

dependencies {//kit 内依赖了lib 所以不必再依赖lib 又因为第一行 fileTree ,所以不必再额外依赖location jar包compile project(':IMKit')compile project(':CallKit')compile project(':RedPacket')
}

IMLib Module # AndroidManifest.xml

<meta-dataandroid:name="RONG_CLOUD_APP_KEY"android:value="您的应用 AppKey" />

App Module # AndroidManifest.xml (位置依赖相关)

<meta-dataandroid:name="com.amap.api.v2.apikey"android:value="高德地图的 AppKey" />

App Module # AndroidManifest.xml (FileProvider)

<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="您的应用包名.FileProvider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/rc_file_path" />
</provider>
<meta-dataandroid:name="com.amap.api.v2.apikey"android:value="高德地图的 AppKey" />

初始化

public class IMApplication extends Application {@Overridepublic void onCreate() {super.onCreate();RongIM.init(this);}}

配置会话列表

不啰嗦,直接看代码,默认为Main为消息页载体:

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.zj.imrydemo.MainActivity"><fragmentandroid:id="@+id/conversationlist"android:name="io.rong.imkit.fragment.ConversationListFragment"android:layout_width="match_parent"android:layout_height="0px"android:layout_weight="1" /></LinearLayout>

看见没,他这个是直接写死Fragment:

android:name=“io.rong.imkit.fragment.ConversationListFragment”

清单文件:

    <application><!--会话列表--><activityandroid:name=".MainActivity"android:screenOrientation="portrait"android:windowSoftInputMode="stateHidden|adjustResize"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><dataandroid:host="com.zj.imrydemo"android:pathPrefix="/conversationlist"android:scheme="rong" /></intent-filter></activity></application>

这人注意下我是双Intent-Fillter,实际上只需要一个。另外看下注释,有个host得改成自己的包名。

    <intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><dataandroid:host="com.zj.imrydemo" //注意这儿喲,得写自己包名android:pathPrefix="/conversationlist"android:scheme="rong" /></intent-filter>

看下效果吧:

连接聊天服务器

从上面的图也看到了,“无法连接到服务器”,那么这里我们就来说说如何连接到服务器。

一般的,我们就在进入这个页面之前进行连接,比如我们的闪屏页。

这里我就不写闪屏页了,懒得搞,知道这个意思就行。

    String portraitUri = "https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=616492013,3957489063&fm=179&w=56&h=56&img.PNG";String nickName = "蛟龙87";String token = "wxS1DLbYEHlYRvEGldlHlLv9HaIuPBiUqpl0jm19YznutxcjH0D1Z2Yo81ijEZhZLPWs7qwNNlTGuKduIiTDBg==";RongIM.connect(token, new RongIMClient.ConnectCallback() {@Overridepublic void onTokenIncorrect() {Log.d(TAG, "onTokenIncorrect");}@Overridepublic void onSuccess(String userId) {Log.d(TAG, "ConnectCallback connect onSuccess=" + userId);}@Overridepublic void onError(RongIMClient.ErrorCode errorCode) {Log.d(TAG, "ConnectCallback connect onError-ErrorCode=" + errorCode);}});

重新运行之后,观察输出结果:

04-18 17:46:31.908 27639-27639/com.zj.imrydemo D/RongYunAbout: ConnectCallback connect onSuccess=zj666

这只是连接上了服务器罢了,可以注意到返回的参数是我们的userId.
但这离我们实现单聊的目的还差一丢丢,咱接着往下走。

单聊实现

若你是一步步跟着坐过来的,你会发现你在api调试上发一条消息到本机,消息是能收到,但是呢,列表没动静。
言归正传,会产生上述问题的原因是,我们还少干了俩件事。

初始化ConversationListFragment

   private void initConversationList() {FragmentManager supportFragmentManager = getSupportFragmentManager();ConversationListFragment conversationlistFragment = (ConversationListFragment) supportFragmentManager.findFragmentById(R.id.conversationlist);conversationlistFragment.getActivity();Uri uri = Uri.parse("rong://" + getApplicationInfo().packageName).buildUpon().appendPath("conversationlist").appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false") //设置私聊会话非聚合显示.appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "true")//设置群组会话聚合显示.appendQueryParameter(Conversation.ConversationType.DISCUSSION.getName(), "false")//设置讨论组会话非聚合显示.appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "false")//设置系统会话非聚合显示.build();conversationlistFragment.setUri(uri);}

是不是这波去拿静态fragment实例的操作有点骚?是的,因为我们xml里是静态定义的fargment,所以我们就这么拿,但也可以动态的去定义,动态的定义也是我们平时项目中常用的fragment用法,所以这里我也不多说了,注意下Fragment是v4的fragment以及其manager就行。

定义聊天详情页面

这一步也不能省的,因为如果你不定义这个,那么你点击的消息列表内就无法进入聊天详情页面。

  • 新建一个Activity,(是FragmentActivity的子类)
  • 定义它的布局,类似于上面回话列表的布局内一个静态的fragment
  • 清单文件内进行配置

注意这三个点,然后我分别贴出相关代码:

activity_talk_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.zj.imrydemo.TalkDetailActivity"><fragmentandroid:id="@+id/conversation"android:name="io.rong.imkit.fragment.ConversationFragment"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /></LinearLayout>

清单内

      <activity android:name=".TalkDetailActivity"><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><dataandroid:host="com.zj.imrydemo"android:pathPrefix="/conversation/"android:scheme="rong" /></intent-filter></activity>

TalkDetailActivity

package com.zj.imrydemo;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;public class TalkDetailActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_talk_detail);}
}

能够坚持到了这一步,说明骚年你是个有耐心的人,你的努力终将得到回报,现在就把我的力量赐予你吧,骚年,敞开双臂接受我仁慈的一击吧。

Holes (遇见的坑)


Hole #1:Failed to resolve: com.android.support:support-v4:26.0.0

解决:

allprojects {repositories {jcenter()mavenCentral()maven { url "https://jitpack.io" }
//        maven {//            url 'https://maven.google.com/'
//            name 'Google'
//        }maven { url 'https://maven.google.com' }maven {url 'http://developer.huawei.com/repo/'}}
}

Hole #2:Installation failed with message INSTALL_FAILED_DUPLICATE_PERMISSION: Package cn.rongcloud.im attempting to redeclare permission cn.rongcloud.im.permission.C2D_MESSAGE already owned by com.aaa.bbb.

2个关键词:

  • INSTALL_FAILED_DUPLICATE_PERMISSION

android编译运行时的结果码。DUPLICATE_PERMISSION,意为权限重复,什么权限重复?看下一条。

  • Package cn.rongcloud.im attempting to redeclare permission cn.rongcloud.im.permission.C2D_MESSAGE already owned by com.aaa.bbb

Package cn.rongcloud.im尝试重新定义权限:cn.rongcloud.im.permission.C2D_MESSAG,但是它已经被com.aaa.bbb抢占了。但是这个权限究竟是用来干嘛的呢?
目前我了解是推送相关的需要这个权限。如果说它具备唯一性,那么可能会出现一个手机上,同时俩个app集成了融云的情况下(因为cn.rongcloud.im.permission是官方SDK自带的定义),有可能会导致后安装的app安装不上。如果是,那么这个问题是很严重的,本文着重走大流程,这个问题也就不展开了,所以这里暂时存疑,等后面测试的时候再来验证这个问题。

解决:

  • 将与之冲突的包删除。
  • DIY融云包内的权限名前缀(未验证可行与否)。

Hole #3:libSqlite

 FATAL EXCEPTION: mainProcess: com.zj.imrydemo:ipc, PID: 8201java.lang.UnsatisfiedLinkError: dlopen failed: library "libsqlite.so" not found

去下载这个sqlite库放在IMkit的lib下边。
这里我提供了下载地址:https://download.csdn.net/download/user11223344abc/10359170

Hole #4:No static method getFont(Landroid/content/Context;II)

 FATAL EXCEPTION: mainProcess: com.zj.imrydemo, PID: 5752java.lang.NoSuchMethodError: No static method getFont(Landroid/content/Context;II)Landroid/support/v4/graphics/TypefaceCompat$TypefaceHolder; in class Landroid/support/v4/content/res/ResourcesCompat;or its super classes (declaration of 'android.support.v4.content.res.ResourcesCompat' appearsin /data/app/com.zj.imrydemo-1/base.apk)

解决这个坑的方法为:统一各项版本号,一般情况下是统一app/build.gradle。

compile_sdk_version = 27
build_tools_version = '27.0.2'
target_sdk_version = 27
support_version = '27.0.2'

Hole #5:app moudle 内的清单文件找不到 provider 标签。

解决方式:
gradle.properties

android.enableAapt2=false

信息备忘

本文Demo:https://github.com/zj614android/RongYunIM_single_talk

融云开放平台账号:
账号:410那个Q
密码:123那个密码

融云IM接入记录(1)——单聊相关推荐

  1. android讨论功能,集成融云Android SDK实现在群聊/讨论组中@人的功能

    集成融云Android SDK实现在群聊/讨论组中@人的功能 可以确定的是融云SDK本身不提供@的功能,需要自定义实现. 在实现这个功能时,基本模仿微信的做法: 在列表中显示有人@了你 通知显示有人@ ...

  2. 调用融云SDK创建讨论组失败bug记录

    问题描述 项目集成融云SDK,在调用融云创建讨论组的时候,第一次创建失败,第二次创建成功. 猜测一: 猜测是因为创建的讨论组的时候,讨论组成员中有userId是融云中没有的,于是去向融云技术支持提工单 ...

  3. Android 项目接入网易云信IM单聊,群聊

    首先需要去网易云信注册账号: https://app.yunxin.163.com/index?clueFrom=nim&from=nim#/create 账号注册成功后去新建项目拿到集成需要 ...

  4. 融云android聊天界面,Android 融云IM集成以及使用详解(一)

    Android 融云IM集成以及使用详解(一) 集成 1.具体的集成步骤就不在详细介绍,我们只说干货,附上融云IM官方文档地址,里面有更为详细的集成介绍 https://www.rongcloud.c ...

  5. 融云 web 即时通讯

    融云 web 即时通讯 ☺ 官网https://www.rongcloud.cn/?utm_source=baiduBrand&utm_term=rongyun 老版本但更为详细的开发文档ht ...

  6. “攀哥”离场 不掩融云组最强战舰技术顶流如云

    职场人"攀哥"的变与不变 攀哥,是融云内部对前联合创始人兼CTO杨攀的亲切称谓.今年2月,"攀哥"的身份已经转变为另外一家围绕"大数据"创业 ...

  7. 融云im callkit 会话遇到的坑融云研究

    1.应用收不到消息 下面是来自融云的官方解释: 1.1首先,需要搞清楚两个概念: push 消息,后台消息. 收到这两种消息的时候,在终端上的表现形式是一样的,都是在通知栏显示一条通知.但实际上它们走 ...

  8. 【APICloud系列|41】融云单聊及消息的处理的对接与实现

    包含了单聊及消息的处理.主要分三个页面处理完成,入口首页(index).消息列表页(message).会话页面(chat) index.html var rong;apiready=function( ...

  9. Android 融云单聊与群聊消息免打扰功能设置与消息删除功能实现

    一.设置群聊与单聊消息免打扰功能: 1.下面直接进入逻辑代码: 实现监听事件: /*** 设置会话列表界面操作的监听器.*/RongIM.setConversationListBehaviorList ...

最新文章

  1. CentOS6下编译安装zabbix_agent3.0客户端
  2. KL 损失的边界框回归
  3. Swift之深入解析反射Mirror与错误处理
  4. 蘑菇街撸掉80%研发岗,产品竟然裁到只剩2个人?
  5. java保留小数点后几位,不足的用0补
  6. C语言初学必练100道
  7. 工业机器人工具中心点标定的意义_如何理解工业机器人的工具中心点(TCP)?...
  8. Briefings in bioinformatics2021 | MolGNet+:基于分子全局表征的高效自监督框架,用于药物发现
  9. 华大单片机移植TencentOS
  10. 小学四则运算练习软件需求说明
  11. 自己制作脚手架——完整版
  12. Windows PC上创建大数据职业技能竞赛实验环境之五--hadoop、hive和spark编程
  13. 电池管理系统(BMS)软硬件介绍
  14. PySpark 之 map
  15. 雅马哈笔试_汉英翻译
  16. 2O19 江大计算机有调剂,江南大学2019考研调剂公告
  17. 基于matlab/simulink的交流电机调速系统建模与仿真,基于MATLABSIMULINK的交流电机调速系统建模与仿真...
  18. mysql、mysqli、PDO
  19. GIF动画导入到FLASH的应用
  20. vue二维码生成和打印

热门文章

  1. (留念)第一个视频教程 U盘超级加密软件的原理详解与解密
  2. 个推大数据降本提效实战分享-技术问答精选
  3. 绩效考核管理系统使用说明3
  4. 华为华三思科 配置arp IP地址和mac地址绑定
  5. EVE-NG 添加win7 镜像
  6. 罗斯蒙特3051S2TG4A2E11A1AB4M5K5D1压力变送器
  7. 程序,进程,线程的区别和联系
  8. C/C++语言的服务器LS调研 (Language Server 实现代码索引 跳转定义 智能提示等功能)
  9. HDMI_CECARC
  10. 中国游戏行业市场分析(一)关于国内游戏制作的问题