项目总结之即时通讯

项目总结之即时通讯

新项目尹始,项目有个模块称之为即时通讯,何谓即时通讯?通过与产品经理交流得知,做个类似QQ聊天方式的通讯工具。大白话就是让app的使用者之间能够相互聊天,发送消息、发送图片之类的。听到这,果断一头雾水外加一脸茫然,没搞过这玩意啊!有问题肯定要问大神啊!其实,百度上搜搜,及时通讯的第三方工具还是比较多的,比如:容联云通讯、亲加通讯云、融云等等。最后确定使用融云通讯,总体说来使用还是比较方便的。另外说一句,融云的服务真是快,有问题提工单,工程师回答速度快,可以很方便解决实际开发中的问题。作为总结,我们还是随便聊聊融云的使用吧!

第一步,使用第三方的东西肯定要去他们的官网注册一个开发者账号,步骤很简单,一步步填写,下一步就行。注意手机号的填写,还是要填写真实的,貌似有条规定,如果手机号为空号可能会导致他们不会给改用户下的app提供服务,所以为了安全起见还是填写真实的手机号码。注册链接地址

第二步:下载SDK,建议SDK别使用当前太低版本、因为有些功能可能不支持。下载SDK时,我们也要把官方提供的demo下载下来,毕竟这是第一手资料,官网提供的demo功能还是比较丰富的,如果应用要求的功能不是很多,demo里面提供的基本功能使应该能满足的。demo可能是托管在github上的,所以还要有个git账号。请自行注册,毕竟开发者还是应该多去上面看看大牛写的开源东西来学习。

第三步:注册应用,使用第三方的工具,不注册怎么用呢?个人中心填写下应用的基本情况应该没啥问题了。

简要的几个步骤,具体使用可以参照官方提供的帮助文档,官方文档地址戳这里

上面的弄好了,我们可以下载官方的demo来体验一把效果如何。总体来说还是不错的,下面我们直接切入我们的项目正题,我们项目比较简单,只需要提供单聊功能、讨论组功能、以及会话列表展示的功能,所以功能还是比较简单,功能使用官网的demo基本能搞定,当然中途还会遇到一些问题,稍后我们慢慢聊。

功能介绍

前沿简介

融云为不同层次应用提供了不同两个开发库,融云 SDK 包括两部分:IM 界面组件和 IM 通讯能力库。

  • IM 界面组件 - IMKit
    IMKit 是融云 SDK 的核心特色之一。融云将即时通讯产品中最复杂的会话列表、聊天窗口、消息内容展现、会话设置等功能封装为组件,通过简短的代码,您就可以直接将以上界面集成到您的 App 产品中,省去大量的开发调试时间。融云同时支持业内最丰富的自定义界面组件功能,您可以针对自己界面需求自由设计开发。IMKit 的核心类在 Android 平台是 RongIM,在 iOS 平台是 RCIM,这两个类在今后的开发中和 IMKit 代表相同的意义。
  • IM 通讯能力库 - IMLib
    IMLib 是不含界面的基础 IM 通讯能力库,封装了通信能力和会话、消息等对象。引用到 App 工程中后,需要开发者自己实现 UI 界面,相对较轻量,适用于对 UI 有较高订制需求的开发者。
    IMLib 的核心类在 Android 平台是 RongIMClient,在 iOS 平台是 RCIMClient,这两个类在今后的开发中和 IMLib 代表相同的意义。

所以根据上面的介绍,在结合我们项目中的需求,我们肯定使用IMKit库进行开发,节省时间方便。

前奏

使用第三方的库,首先就需要进行第三方要求的初始化操作,这部分代码,基本直接copy官网提供的就可以,这样可以保证准确性。所以这里简要介绍需要我们处理的几个点。

1、Manifest.xml文件中:
(1)、添加user-permission权限,如下:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 获取机型信息权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />

    <!-- 查看 Wi-Fi 状态 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!-- 查看网络状态 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <!-- 录音 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <!-- 控制振动器 -->
    <uses-permission android:name="android.permission.VIBRATE" />
    <!-- 防止设备休眠 -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
    <!--获取联系人信息,demo中演示发送通讯录消息-->
    <uses-permission android:name="android.permission.READ_CONTACTS" />

(2)、添加融云必备的activity、服务、广播的声明。有几点需要修改:

  • android:host选项的值全部为自己应用的包名。例如:android:host=”com.dsw.infor”
  • meta-data标签中的appkey的值要改为自己应用申请的appkey
     <!--begin rongcloud-->
        <activity
            android:name="io.rong.voipkit.activity.CallSideActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

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

                <data
                    android:host="io.rong.app"
                    android:pathPrefix="/VoIPCall"
                    android:scheme="rong" />
            </intent-filter>
        </activity>

        <activity
            android:name="io.rong.voipkit.activity.CalledSideActivity"
            android:excludeFromRecents="true"
            android:screenOrientation="portrait">

            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

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

                <data
                    android:host="io.rong.app"
                    android:pathPrefix="/VoIPAccept"
                    android:scheme="rong" />
            </intent-filter>
        </activity>

        <service
            android:name="io.rong.push.PushService"
            android:process="io.rong.push" >
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />

                <action android:name="io.rong.push" />
            </intent-filter>
        </service>
        <service
            android:name="io.rong.push.CommandService"
            android:process="io.rong.push" > <!-- Waring: The name of the push process can't be changed!!! -->
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />

                <action android:name="io.rong.command" />
            </intent-filter>
        </service>

        <receiver
            android:name="io.rong.push.PushReceiver"
            android:process="io.rong.push" > <!-- Waring: The name of the push process can't be changed!!! -->
            <intent-filter>
                <action android:name="io.rong.imlib.action.push.heartbeat" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.USER_PRESENT" />
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_REMOVED" />

                <data android:scheme="package" />
            </intent-filter>
        </receiver>

         <activity
            android:name="io.rong.imkit.tools.SelectPictureActivity"
            android:screenOrientation="portrait" />
        <activity
            android:name="io.rong.imkit.tools.PreviewPictureActivity"
            android:screenOrientation="portrait" />
        <activity
            android:name="io.rong.imkit.tools.RongWebviewActivity"
            android:screenOrientation="portrait" />
        <activity
            android:name="io.rong.imkit.widget.provider.TakingPicturesActivity"
            android:configChanges="orientation|keyboardHidden"
            android:screenOrientation="portrait" />

        <service
            android:name="io.rong.imlib.ipc.RongService"
            android:process=":ipc" >
        </service>
        <service android:name="io.rong.imlib.ReConnectService" />

        <receiver android:name="io.rong.imlib.ConnectChangeReceiver" />
        <receiver android:name="io.rong.imlib.ipc.PushMessageReceiver" >
            <intent-filter>
                <action android:name="io.rong.push.message" />
            </intent-filter>
        </receiver>
        <receiver
            android:name="io.rong.imlib.HeartbeatReceiver"
            android:process=":ipc" />
        <meta-data
            android:name="RONG_CLOUD_APP_KEY"
            android:value="z3v5yqkbv8v30" />

        <!--end rongcloud-->

2、在我们的Application中进行初始化,执行RongIM.init(this);
代码如下:

    public class App extends Application {

    @Override
    public void onCreate() {

        super.onCreate();

        /**
         * 注意:
         *
         * IMKit SDK调用第一步 初始化
         *
         * context上下文
         *
         * 只有两个进程需要初始化,主进程和 push 进程
         */
        if("io.rong.app".equals(getCurProcessName(getApplicationContext())) ||
           "io.rong.push".equals(getCurProcessName(getApplicationContext()))) {

            RongIM.init(this);
        }
    }

    public static String getCurProcessName(Context context) {
        int pid = android.os.Process.myPid();
        ActivityManager activityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : activityManager
                .getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                return appProcess.processName;
            }
        }
        return null;
    }
    }

3、初始化的工作完成后,然后我们就在我们成功登陆后,进行服务器的链接。此时,我们需要调用我们的后台来获取融云认证的token信息。测试阶段,我们可以使用api调试,手动生成来用。

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

                    @Override
                    public void onSuccess(String arg0) {
                        Log.d("RongClound", "RongClound: Tocken Success");
                    }

                    @Override
                    public void onError(ErrorCode arg0) {
                        Log.d("RongClound", "RongClound: Tocken Error,ErrorCode:" + arg0);
                    }

                    @Override
                    public void onTokenIncorrect() {
                        Log.d("RongClound", "RongClound: onTokenIncorrect");
                    }
                });`

至此,我们已经完成所有的初始化工作。接下来就可以针对我们的需求进行开发了。

单聊功能

由于我们项目使用的IMKit包,所以使用起来很方便。简要介绍下单聊:
单聊是最基本的聊天界面,提供文字、表情、语音片段、图片、VoIP 等多种输入内容,解决 App 内用户的沟通瓶颈。会话关系由融云负责建立并保持,退出聊天界面或者离线后可以收到推送通知。

前提条件:

  • RongIM.init(this),接口已经执行。
  • RongIM.connect(….),接口已经执行且 onSuccess() 被回调。
  • 会话 Activity 已经在 AndroidManifest.xml 文件中,配制了对应的 intent-filter,详见配置说明文档。

由于IMKit中融云提供的界面都是基于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:background="#ffffff"
        android:orientation="vertical" >
        <RelativeLayout
            android:id="@+id/relative_title"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:background="@color/shenglvse"
            android:orientation="horizontal" >
           <ImageView
               android:id="@+id/iv_return"
               android:layout_width="45dp"
               android:layout_height="45dp"
               android:layout_alignParentBottom="true"
               android:layout_alignParentLeft="true"
               android:layout_marginBottom="6dp"
               android:layout_marginTop="6dp"
               android:contentDescription="@null"
               android:src="@drawable/back_icon" />

           <TextView
               android:id="@+id/tv_title"
               android:layout_width="wrap_content"
               android:layout_height="match_parent"
               android:layout_centerInParent="true"
               android:gravity="center_vertical"
               android:text="会话界面"
               android:textColor="@color/white"
               android:textSize="17sp" />
        </RelativeLayout>
        <fragment 
            android:id="@+id/conversaction"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name="io.rong.imkit.fragment.ConversationFragment"
            />
    </LinearLayout>

主要就是一定要包含:

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

效果图如下:
conv

布局搞好了,我们要创建一个ConversationActivity来进行显示。

    public class ConversationActivity extends FragmentActivity {

        @Override
        protected void onCreate(Bundle arg0) {
            super.onCreate(arg0);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.conversation);
            ImageView iv_return = (ImageView) findViewById(R.id.iv_return);
            iv_return.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    ConversationActivity.this.finish();
                }
            });
        }
    }

Activity创建好自然要在Manifest中进行声明

    <activity 
            android:name="com.dsw.infor.activity.communication.ConversationActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data
                    android:host="com.dsw.infor"
                    android:pathPrefix="/conversation/"
                    android:scheme="rong" />
            </intent-filter>
     </activity>

这些都配置好了,我们就可以指定用户在app中的唯一标识,比如id,来进入与该id用户进行单聊的界面。代码:

 /**
     * 启动单聊界面。
     *
     * @param context      应用上下文。
     * @param targetUserId 要与之聊天的用户 Id。
     * @param title        聊天的标题,如果传入空值,则默认显示与之聊天的用户名称。
     */
    RongIM.getInstance().startPrivateChat(getActivity(), "9527", "标题");

建立讨论组

前提条件同单聊,主要介绍几个方法。
(1)、打开讨论组聊天窗口:

 /**
     * 启动讨论组聊天界面。
     *
     * @param context            应用上下文。
     * @param targetDiscussionId 要聊天的讨论组 Id。
     * @param title              聊天的标题,如果传入空值,则默认显示讨论组名称。
     */
    RongIM.getInstance().startDiscussionChat(getActivity(), "9527", "标题");

(2)、创建讨论组会话并进入会话界面:

ArrayList<String> userIds = new ArrayList<String>();
       userIds.add("101");//增加 userId。
       userIds.add("102");//增加 userId。
       userIds.add("103");//增加 userId

       /**
        * 创建讨论组会话并进入会话界面。
        *
        * @param context       应用上下文。
        * @param targetUserIds 要与之聊天的讨论组用户 Id 列表。
        * @param title         聊天的标题,如果传入空值,则默认显示与之聊天的用户名称。
        */
       RongIM.getInstance().createDiscussionChat(getActivity(), userIds, "讨论组名称");

所以,我们可以根据我们通讯录中选择的用户,建立一个用户id的集合,然后就可以创建讨论组。

会话列表

会话列表的使用步骤与单聊基本相同,首先是配置布局xml文件中:

<?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:background="#ffffff"
        android:orientation="vertical" >
        <RelativeLayout
            android:id="@+id/relative_title"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:background="@color/shenglvse"
            android:orientation="horizontal" >
           <ImageView
               android:id="@+id/iv_return"
               android:layout_width="45dp"
               android:layout_height="45dp"
               android:layout_alignParentBottom="true"
               android:layout_alignParentLeft="true"
               android:layout_marginBottom="6dp"
               android:layout_marginTop="6dp"
               android:contentDescription="@null"
               android:src="@drawable/back_icon_pressed" />

           <TextView
               android:id="@+id/tv_title"
               android:layout_width="wrap_content"
               android:layout_height="match_parent"
               android:layout_centerInParent="true"
               android:gravity="center_vertical"
               android:text="会话列表"
               android:textColor="@color/white"
               android:textSize="17sp" />
        </RelativeLayout>
        <fragment
            android:id="@+id/conversaction_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name="io.rong.imkit.fragment.ConversationListFragment"
            />

    </LinearLayout>

然后创建ConversationListActivity来进行会话列表的展现。

    public class ConversationListActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.conversation_list);
        ImageView iv_return = (ImageView) findViewById(R.id.iv_return);
        iv_return.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                ConversationListActivity.this.finish();
            }
        });
    }
    }

创建好之后,就是在Manifest文件中声明。

<activity 
            android:name="com.dsw.infor.activity.communication.ConversationListActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data
                    android:host="com.dsw.infor"
                    android:pathPrefix="/conversationlist"
                    android:scheme="rong" />
            </intent-filter>
        </activity>

创建好后,我们点击按钮进入会话列表页面。

RongIM.getInstance().startConversationList(_this);

至此,所有的基本功能点在IMKit包中都能很快实现。接下来,我们说说我遇到的几个问题吧!

一、会话列表中展示单聊会话框的名称不对,只展示id

这种问题困扰我很久的,后来通过提工单才知道要实现UserInfoProvider接口,然后重写public UserInfo getUserInfo(String userId)方法。原因:用户之间的好友关系是我们来维护,所以在打开某个会话时候,我们需要告诉系统对应id的用户名称。
pro
具体解决方法:
(1)、建立Friend实体,

    public class Friend {

    private String userId;

    private String userName;

    private String portraitUri;

    public Friend(String userId,String userName,String portraitUri){
        this.userId = userId;
        this.userName = userName;
        this.portraitUri = portraitUri;
    }

    public String getUserId() {
        return userId;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPortraitUri() {
        return portraitUri;
    }

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

(2)根据我们的用户关系表建立一个用户的个人信息集合。

friendList = new ArrayList<Friend>();
    for(int i=0;i<contactList.size();i++){
        contact = contactList.get(i);
        friend = new Friend(contact.getUser_Id()+"", contact.getContacts_Name(), "");
        friendList.add(friend);
    }

(3)重写public UserInfo getUserInfo(String userId),根据id返回用户信息。

@Override
    public UserInfo getUserInfo(String userId) {
        for (Friend i : friendList) {
            if (i.getUserId().equals(userId)) {
                return new UserInfo(i.getUserId(),i.getUserName(),Uri.parse(i.getPortraitUri()));
            }
        }
        return null;
    }

通过这样处理,我们的会话列表就会展示用户名称。

二、语音通话使用问题

1、语音通话无法使用,这是我们需要检查我们是否在Manifest文件中注册了相关的语音服务。如果注册了,我们是否将android:host的值修改为我们的包,基本就是这两方面的问题。

<activity
            android:name="io.rong.voipkit.activity.CallSideActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data
                    android:host="com.dsw.infor"
                    android:pathPrefix="/VoIPCall"
                    android:scheme="rong" />
            </intent-filter>
        </activity>
        <activity
            android:screenOrientation="portrait"
            android:name="io.rong.voipkit.activity.CalledSideActivity"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data
                    android:host="com.dsw.infor"
                    android:pathPrefix="/VoIPAccept"
                    android:scheme="rong"/>
            </intent-filter>
        </activity>

2、语音通话,名称显示融云客服,接收方显示张三。这个问题同样是我们用户的信息没有提供给融云,所以它就显示默认的了。解决办法同上面的会话列表显示id不显示名称问题。

三、初始化失败等一些问题

这类问题展现的很多,我也没有截图了,原因就是系统自带的v4包的版本比较低,导致达不到系统要求的v4包的要求,下载个高版本的v4包替换即可。下载地址。或者使用v7包。

四、创建讨论组的id怎么获取

我们上面提供的进入和创建讨论组的方法中,都没有获取讨论组id的信息,通过提工单,可以通过这个方法。

 RongIM.getInstance().getRongIMClient().
        createDiscussion(reason, list, new CreateDiscussionCallback() {

            @Override
            public void onSuccess(String discussId) {
                RongIM.getInstance().startDiscussionChat(_this, discussId, reason);
                Log.v("CreateDiscussion", "CreateDiscussion Success");
            }

            @Override
            public void onError(ErrorCode errorCode) {
                Log.v("CreateDiscussion", "CreateDiscussion Error,Code:" + errorCode);
            }
        });
会话界面底部的工具栏怎么定置,如拍照、定位等

这部分属于用户自己定置的功能,当然我们也可以使用一些融云提供好的服务。我们定制哪些功能,需要我们在Application的onCreate方法中进行执行。通过ExtendProvider定制扩展功能。

    if("com.drision.militia_infor".equals(getCurProcessName(getApplicationContext())) ||
                   "io.rong.push".equals(getCurProcessName(getApplicationContext()))) {
            RongIM.init(this);

            //定义会话框中的功能选项
            ExtendProvider [] ep = {
                    new ImageInputProvider(RongContext.getInstance()),
                    new NewCameraInputProviders(RongContext.getInstance()),
                    // 语音通话
                    new VoIPInputProvider(RongContext.getInstance()),
                    //注意图标要放在xhdpi目录下,不然不对齐
                    new ContactsProvider(RongContext.getInstance())};
            RongIM.resetInputExtensionProvider(ConversationType.PRIVATE, ep);
        }

我们定制了拍照、语音通话、图片选择、联系人四个工具。其中图片选择、语音通话时系统提供的,那么我们怎么实现我们自定义的。
实现自定义的,需要我们继承InputProvider.ExtendProvider来进行实现,然后定制到工具栏中。
下面我直接提出来源码:

1、拍照功能:

    public class NewCameraInputProviders extends InputProvider.ExtendProvider {

    HandlerThread mWorkThread;

    Handler mUploadHandler;

    @SuppressWarnings("unused")
    private RongContext mContext;
    private File photoFile;

    public NewCameraInputProviders(RongContext context) {
        super(context);
        this.mContext = context;
        // 来自融云demo
        mWorkThread = new HandlerThread("RongDemo");
        mWorkThread.start();
        mUploadHandler = new Handler(mWorkThread.getLooper());

    }

    @Override
    public Drawable obtainPluginDrawable(Context arg0) {
        return arg0.getResources().getDrawable(R.drawable.rc_ic_camera);
    }

    @Override
    public CharSequence obtainPluginTitle(Context arg0) {
        return "拍照";
    }

    @Override
    public void onPluginClick(View arg0) {
        // 点击跳转至拍照
        photoFile = new File(Environment.getExternalStorageDirectory()
                + "/my_camera/" + UUID.randomUUID() + ".jpg");// 图片储存路径
        if (!photoFile.getParentFile().exists()) {
            photoFile.getParentFile().mkdirs();
        }
        Intent intent = new Intent();
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent, 1);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        Log.e("TAG", "---requestCode-" + requestCode + "---resultCode--" + resultCode);
        // 根据选择完毕的图片返回值,直接上传文件
        if (requestCode == 1) {// 拍照
            String localStrPath = photoFile.getPath();
            byte[] compressBitmap = BitmapUtils.compressBitmap(480 * 480,
                    localStrPath);
            if (null != compressBitmap) {
                Bitmap bmPhoto = BitmapUtils.Bytes2Bimap(compressBitmap);
                if (null != bmPhoto) {
                    String strTempPhotoPath;
                    try {
                        strTempPhotoPath = BitmapUtils.saveFile(bmPhoto,
                                UUID.randomUUID() + ".jpeg");
                        if (bmPhoto != null) {
                            bmPhoto.recycle();
                            bmPhoto = null;
                        }
                        if (null != strTempPhotoPath
                                && !"".equals(strTempPhotoPath)) {
                            localStrPath = strTempPhotoPath;
                        }
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                localStrPath = "file://" + localStrPath;
                Uri pathUri = Uri.parse(localStrPath);
                mUploadHandler.post(new MyRunnable(pathUri));
            }
        }
    }

    /**
     * 用于显示文件的异步线程
     */
    class MyRunnable implements Runnable {

        Uri mUri;

        public MyRunnable(Uri uri) {
            mUri = uri;
        }

        @Override
        public void run() {

            // 封装image类型的IM消息
            final ImageMessage content = ImageMessage.obtain(mUri, mUri);

            if (RongIM.getInstance() != null
                    && RongIM.getInstance().getRongIMClient() != null)
                RongIM.getInstance()
                        .getRongIMClient()
                        .sendImageMessage(
                                getCurrentConversation().getConversationType(),
                                getCurrentConversation().getTargetId(),
                                content, null, null,
                                new RongIMClient.SendImageMessageCallback() {
                                    @Override
                                    public void onAttached(Message message) {

                                    }

                                    @Override
                                    public void onError(Message message,
                                                        RongIMClient.ErrorCode errorCode) {

                                    }

                                    @Override
                                    public void onSuccess(Message message) {

                                    }

                                    @Override
                                    public void onProgress(Message message,
                                                           int i) {

                                    }
                                });

        }
    }

    }

2、联系人功能源码:

public class ContactsProvider extends InputProvider.ExtendProvider {

    HandlerThread mWorkThread;
    Handler mUploadHandler;
    private int REQUEST_CONTACT = 20;

    public ContactsProvider(RongContext context) {
        super(context);
        mWorkThread = new HandlerThread("RongDemo");
        mWorkThread.start();
        mUploadHandler = new Handler(mWorkThread.getLooper());
    }

    /**
     * 设置展示的图标
     * @param context
     * @return
     */
    @Override
    public Drawable obtainPluginDrawable(Context context) {
        return context.getResources().getDrawable(R.drawable.de_contacts);
    }

    /**
     * 设置图标下的title
     * @param context
     * @return
     */
    @Override
    public CharSequence obtainPluginTitle(Context context) {
        return "通讯录";
    }

    /**
     * click 事件
     * @param view
     */
    @Override
    public void onPluginClick(View view) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        intent.setData(ContactsContract.Contacts.CONTENT_URI);
        startActivityForResult(intent, REQUEST_CONTACT);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode != Activity.RESULT_OK)
            return;

        if (data.getData() != null && "content".equals(data.getData().getScheme())) {
            mUploadHandler.post(new MyRunnable(data.getData()));
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    class MyRunnable implements Runnable {

        Uri mUri;

        public MyRunnable(Uri uri) {
            mUri = uri;
        }

        @Override
        public void run() {
            String[] contact = getPhoneContacts(mUri);

            String showMessage = contact[0] + "\n" + contact[1];
            final TextMessage content = TextMessage.obtain(showMessage);

            if (RongIM.getInstance().getRongIMClient() != null)
                RongIM.getInstance().getRongIMClient().sendMessage(getCurrentConversation().getConversationType(), getCurrentConversation().getTargetId(), content, null, null, new RongIMClient.SendMessageCallback() {
                    @Override
                    public void onError(Integer integer, RongIMClient.ErrorCode errorCode) {
                        Log.d("ExtendProvider", "onError--" + errorCode);
                    }

                    @Override
                    public void onSuccess(Integer integer) {
                        Log.d("ExtendProvider", "onSuccess--" + integer);
                    }
                });
        }
    }

    private String[] getPhoneContacts(Uri uri) {

        String[] contact = new String[2];
        ContentResolver cr = getContext().getContentResolver();
        Cursor cursor = cr.query(uri, null, null, null, null);
        cursor.moveToFirst();
        if (cursor != null) {
            cursor.moveToFirst();
            int nameFieldColumnIndex = cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME);
            contact[0] = cursor.getString(nameFieldColumnIndex);

            String ContactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
            Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + ContactId, null, null);

            if (phone != null) {
                phone.moveToFirst();
                contact[1] = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            }
            phone.close();
            cursor.close();
        }
        return contact;
    }
    }

以上就是关于融云在项目中的使用,融云提供很多功能,希望以后有机会再深入研究吧!
简单demo下载地址

========================================
作者:mr_dsw 欢迎转载,与人分享是进步的源泉!

转载请保留地址:http://blog.csdn.net/mr_dsw

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值