Android融云即时通讯 适配Android8.0以及 SDK版本2.8.27的集成与使用

集成阶段

这一阶段我们不必详细说明,因为融云官网给我们的SDK文档相当详细顺着他的步骤即可。

融云SDK集成步骤

使用阶段

融云初始化

public class App extends Application{
    @Override
    public void onCreate() {
        super.onCreate();
        //初始化融云
        RongIM.init(this);

    }
}

在mainactivity中连接融云,注意测试阶段可以简单的使用融云的测试token连接

 //kris  这个token为融云调试token   真正项目中一般会在登录接口中给你返回token 替换即可
        String token = "/J0eHW43mJdYDJg+0gKKZPRTe2GHWU4uO8Hvo+MUDHW6IduhjEa5yInXxsWDUOk5GH9WTfGOBnqoqulyj8HViQ==";

        RongIM.connect(token, new RongIMClient.ConnectCallback() {

            @Override
            public void onSuccess(String userId) {
                Log.e("MainActivity", "——onSuccess—-" + userId);

                Toast.makeText(MainActivity.this,"用户id"+userId,Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onError(RongIMClient.ErrorCode errorCode) {
                Log.e("MainActivity", "——onError—-" + errorCode);
            }

            @Override
            public void onTokenIncorrect() {
                //Connect Token 失效的状态处理,需要重新获取 Token
            }
        });


        /**
         * 启动单聊
         * context - 应用上下文。
         * targetUserId - 要与之聊天的用户 Id。
         * title - 聊天的标题,如果传入空值,则默认显示与之聊天的用户名称。
         */
        if (RongIM.getInstance() != null) {
            RongIM.getInstance().startPrivateChat(MainActivity.this, "1234", "");
        }


        /**

         * 启动群组聊天界面。
         *
         * @param context       应用上下文。
         * @param targetGroupId 要聊天的群组 Id。
         * @param title         聊天的标题。开发者需要在聊天界面通过intent.getData().getQueryParameter("title")获取该值, 再手动设置为聊天界面的标题。
         */

//        if ( RongIM.getInstance()!=null) {
//            //发起群聊天
//            RongIM.getInstance().startGroupChat(mActivity, groupID, groupName);
//        }else{
//            Tip.tipshort(mActivity,"群聊内容为空");
//        }

此时,我们就开始运行程序检测token是否连接融云成功,如果你使用的是Android7.0手机的话你会发现怎么都不能发送消息。然后,在顺着SDK文档找上一遍发现还是没有问题呀,为什么会出现这个问题呢,然后详细看了日志会提示这样一个错误

java.lang.UnsatisfiedLinkError: dlopen failed: library "libsqlite.so" not found
at java.lang.Runtime.load0(Runtime.java:897)
at java.lang.System.load(System.java:1505)
at com.getkeepsafe.relinker.SystemLibraryLoader.loadPath(SystemLibraryLoader.java:29)
at com.getkeepsafe.relinker.ReLinkerInstance.loadLibraryInternal(ReLinkerInstance.java:200)
at com.getkeepsafe.relinker.ReLinkerInstance.loadLibrary(ReLinkerInstance.java:140)
at com.getkeepsafe.relinker.ReLinker.loadLibrary(ReLinker.java:70)
at com.getkeepsafe.relinker.ReLinker.loadLibrary(ReLinker.java:51)
at io.rong.imlib.NativeObject.<clinit>(NativeObject.java:13)
at io.rong.imlib.NativeClient.init(NativeClient.java:157)
at io.rong.imlib.LibHandlerStub.init(LibHandlerStub.java:50)
at io.rong.imlib.IHandler$Stub.onTransact(IHandler.java:52)
at android.os.Binder.execTransact(Binder.java:565)

libsqlite.so文件找不见了,好勒,差啥我们就干啥,libsqlite.so下载

放置位置

好了接下来你可能觉得可以了,那到未必。如果你的buildToolsVersion低于26的话问题就是如下了,为啥会报这样的错呢?(已经更新到26的话可以忽略这一步)

Process: com.zontonec.ztteacher, PID: 26682
java.lang.NoClassDefFoundError: Failed resolution of: Lio/rong/push/PushService;
at io.rong.push.RongPushClient.init(RongPushClient.java:146)
at io.rong.imlib.RongIMClient.initSDK(RongIMClient.java:451)
at io.rong.imlib.RongIMClient.init(RongIMClient.java:481)
at io.rong.imkit.RongIM.initSDK(RongIM.java:155)
at io.rong.imkit.RongIM.init(RongIM.java:209)
at com.zontonec.ztteacher.App.onCreate(App.java:66)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1028)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5720)
at android.app.ActivityThread.-wrap2(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1637)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6585)
at java.lang.reflect.Method.invoke(Native Method)

融云 Android SDK 在 2.8.25-Dev 这个版本就对对 Android 8.0 做了适配。
所有项目出错了,因此,对于IMKIT下面的依赖版本一定要大于26以上才能保证正常使用
在升级到 2.8.25-Dev 版本以上时,

需要注意:SDK 中用到了 Support Library 中的比较新的 API,因此在升级 SDK 的时候,需要将工程

项目的 gradle 文件中的 Support Library 依赖升级到 26.0.0 以后,在 IMKit 中 gradle 文件中添加以下代码:

dependencies {
         compile 'com.android.support:support-v4:26.1.0'
}

如果工程中其他的module也用到了 Support Library 相关的库,也需要同步升级到 26.0.0 版本以上;

相应的,compileSdkVersion 和 buildToolsVersion 也需要同步升级到 26.0.0 以上的版本:

compileSdkVersion 26
buildToolsVersion '26.0.2'

另外,如果您工程的 build.gradle 里没有配置对谷歌 marven 仓库的依赖,也需要添加上。如下图所示:

repositories {
    jcenter()
    mavenCentral()
    maven {
        url 'https://maven.google.com/'
        name 'Google'
    }
}

避免出现编译错误。

所有都能正常使用了我们再来看看如何开启会话列表,会话列表页面,以及会话页面的动态静态使用方法

会话页面可以手动开启也可以清单文件加意图过滤器自动开启,

//会话界面
public class ConversationActivity extends FragmentActivity {

    private static final String TAG = ConversationActivity.class.getSimpleName();
    private TextView mName;

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_conversation);

String sId = getIntent().getData().getQueryParameter("targetId");//targetId:单聊即对方ID,群聊即群组ID
        
String title = getIntent().getData().getQueryParameter("title");//获取标题

        mName = (TextView) findViewById(R.id.name);
        mName.setText("王大锤");
    }
}

布局文件,可以自定义需要什么功能

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#000">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_margin="15dp"
            android:text="rongCloud"
            android:textColor="#fff"
            android:textSize="18sp" />
    </LinearLayout>
    <fragment
        android:id="@+id/conversation_id"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="io.rong.imkit.fragment.ConversationFragment"/>

</LinearLayout>

会话列表界面动态方法加载只需要写在你需要加载的fragment或者activity中

      //会话列表
        ConversationListFragment conversationListFragment = new ConversationListFragment();
        Uri uri = Uri.parse("rong://" + getActivity().getApplicationInfo().packageName).buildUpon()
                .appendPath("conversationlist")       .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false") //设置私聊会话,该会话聚合显示
//                .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "true")//设置系统会话,该会话非聚合显示
                .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false")//设置私聊会话是否聚合显示
                .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "false")
                // .appendQueryParameter(Conversation.ConversationType.PUBLIC_SERVICE.getName(), "false")//公共服务号
                //.appendQueryParameter(Conversation.ConversationType.APP_PUBLIC_SERVICE.getName(), "false")//公共服务号
                .appendQueryParameter(Conversation.ConversationType.DISCUSSION.getName(), "false")//设置私聊会话是否聚合显示
                .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "false")//设置私聊会是否聚合显示
                .build();
        conversationListFragment.setUri(uri);

        FragmentManager fragmentManager = getChildFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.rong_container,conversationListFragment);
        transaction.commit();

布局文件如下

<fragment
        android:id="@+id/rong_container"
        android:name="io.rong.imkit.fragment.ConversationListFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

原生效果图如下

会话列表,当然你也可也使用公司给你的接口自己设计

那么,静态的如何实现呢?

清单文件中配置,host配置为自己的包名

    <!-- 会话列表 -->
        <activity
            android:name=".rongcloude.ConversationListActivity"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="com.zontonec.ztteacher"
                    android:path="/conversationlist"
                    android:scheme="rong" />
            </intent-filter>
        </activity>

布局文件,你只需要用<fragment就行,前面的根据需求定义

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:background="@color/white"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/rl_title_bg"
        android:layout_width="fill_parent"
        android:layout_height="45dp"
        android:layout_alignParentBottom="true">

        <ImageButton
            android:id="@+id/title_bar_back"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:background="@color/white"
            android:src="@mipmap/nav_btn_back" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_class_name"
                style="@style/one_text_style"
                android:text="" />


        </LinearLayout>


        <ImageButton
            android:id="@+id/title_bar_right"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="10dp"
            android:background="@color/white"
            android:src="@mipmap/nav_btn_member" />

    </RelativeLayout>

    <fragment
        android:id="@+id/conversationlist"
        android:name="io.rong.imkit.fragment.ConversationListFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

会话列表类

public class ConversationListActivity extends FragmentActivity {

    private static final String TAG = ConversationListActivity.class.getSimpleName();
    private LoadingDialog mDialog;
    private SharedPreferences sp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.conversationlist);
     
    }

}

自此,关于启动单聊,群聊只需要传入id和title即可启动,已经会话,会话列表功能的实现和可能会遇到的一些不起眼的问题。

会话页面

群组

群组类如果使用的是动态加载消息列表的话,有消息他才显示,没消息就不显示,你可以选择接口返回数据比如用listview,recycleview等加载,然后通过

   if (RongIM.getInstance() != null) {
//                            //发起留言群聊天
//                            RongIM.getInstance().startGroupChat(mActivity, groupID, groupName);
//                        } else {
//                            Tip.tipshort(mActivity, "群聊内容为空");
//                        }

开启群聊会话界面。

下面是接着上面的内容完善一下内容,加入了群组列表头像,用户信息头像等。我们可见上图的头像和群列表的标题等都是没有头像和标题的;下面我们先来看看加上头像等后的效果图是怎么样?

这是加入群头像等的动态加载类的消息列表

融云给我们提供了各种需求满足你们的项目实现这类功能,那么我们如何开始呢,首先讲解群组类的,我们可以在fragment或者activity中动态加载消息列表
在onCreat()初始化;

//初始化群组信息提供者
    private void initGroupListener() {
        RongIM.setGroupInfoProvider(this, true);
    }

然后实现接口重写getGroupInfo()方法

public class NewsFragment extends BaseFragment implements RongIM.GroupInfoProvider

下面是重写的方法

    //重新群组信息提供者
    @Override
    public Group getGroupInfo(String s) {

        //首先对群组非空判断 然后增强for循环遍历数据
        if(groupIdList!=null){
            for (Friend f:groupIdList){
                if(f.getGroupId().equals(s)){
                    return new Group(f.getGroupId(), f.getName(),Uri.parse(f.getPortraitUri()));//从bean中获取参数返回给融云
                }
            }
        }
        return null;
    }

Friend是我们自己的bean类 groupIdlist是我们服务器返回的包含头像,昵称等的集合,我们拿到参数后返回给融云SDK就OK了。


    private List<Friend> groupIdList;

    //方法二使用融云动态加载群组头像 昵称等信息
                                groupIdList = new ArrayList<>();
                                for (int i = 0; i < list.size(); i++) {
                                    String groupName = MapUtil.getValueStr(list.get(i), "groupName");
                                    String groupType = MapUtil.getValueStr(list.get(i), "groupType");
                                    String groupPhoto = MapUtil.getValueStr(list.get(i), "groupPhoto");
                                    String groupID = MapUtil.getValueStr(list.get(i), "groupID");

                                    Friend friend = null;
                                    friend = new Friend(groupID,groupName,groupPhoto);
                                    groupIdList.add(friend);
                                    if (i > 0) {
                                        break;
                                    }
                                }

Friend

public class Friend {

    private String groupId;
    private String name;
    private String portraitUri;

    public String getGroupId() {
        return groupId;
    }

    public void setGroupId(String userId) {
        this.groupId = userId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPortraitUri() {
        return portraitUri;
    }

    public void setPortraitUri(String portraitUri) {
        this.portraitUri = portraitUri;
    }

    public Friend(String groupId, String name, String portraitUri) {
        this.groupId = groupId;
        this.name = name;
        this.portraitUri = portraitUri;
    }
}

群组类列表实现就这样就OK了。

下面再看另一张效果图:

这个是会话页面头像效果图

会话页面

那我们是如何实现这个效果的呢,其实,原理和群组是大同小异的;我们来看看代码怎么开始的。

同样,我们需要在onCreat()初始化另一个userinfo

 RongIM.setUserInfoProvider(this, true);

然后实现接口RongIM.UserInfoProvider重写getUserInfo()方法

implements RongIM.UserInfoProvider
    //关系列表
                                relationList = MapUtil
                                        .getSafeMapWhenInteger((List) data
                                                .get("relationList"));
                                String groupType = MapUtil.getValueStr(data, "groupType");//群类型

                                userInfoIdList = new ArrayList<>();
                                for (int j = 0; j < data.size(); j++) {
                                    String photoUrl = MapUtil.getValueStr(data, "photoUrl");//头像
                                    String userID = MapUtil.getValueStr(data, "userID");//用户
                                    String userName = MapUtil.getValueStr(relationList.get(j), "userName");

                                    Friends friends = null;
                                    friends = new Friends(userID, userName, photoUrl);
                                    userInfoIdList.add(friends);

                                    if (j > 0) {
                                        break;
                                    }
                                }

然后,在重写方法中将参数返回给融云SDK,Friends同样是bean类,根据你的需要选择参数传入就行了,getUserInfo(String s) s为用户id和你服务器返回的useid判断,为同一个用户就能够返回给融云然后实现头像等信息的显示。

    //获取用户信息
    @Override
    public UserInfo getUserInfo(String s) {
        //首先对群组非空判断 然后增强for循环遍历数据
        if (userInfoIdList != null) {
            for (Friends i : userInfoIdList) {
                if (i.getUserId().equals(s)) {
                    Tip.tipshort(ConversationActivity.this,"用户id2"+s);
                    Log.e(TAG, i.getPortraitUri());
                    return new UserInfo(i.getUserId(), i.getName(), Uri.parse(i.getPortraitUri()));
                }
            }
        }
        Log.e("ConversationActivity", "UserId is : " + s);
        return null;
    }

同样,当我们单聊等也是以此类推既能够实现用户信息。

如果有哪不对或者有更好意见的欢迎各路大神留个意见,一定改善
demo源码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,395评论 25 707
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,396评论 2 45
  • 元宵节又称上元节,是一个非常重要的汉族传统节日。这天在潮汕,有各种具有潮汕特色的汉族民俗活动。这是因道教信奉三官神...
    陳小魔阅读 2,416评论 8 8
  • 喜欢骑行 是因为 喜欢拥抱 风的感觉 乘风飞扬 我就是风
    零贰O2阅读 212评论 0 0
  • 窗外景色呼啸而过,车内人声鼎沸。她把目光从像少女连衣裙的白云那里收了回来,扫了一眼车厢内,把目光锁定在正在检票...
    差子阅读 261评论 1 1