项目总结之即时通讯
新项目尹始,项目有个模块称之为即时通讯,何谓即时通讯?通过与产品经理交流得知,做个类似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"
/>
效果图如下:
布局搞好了,我们要创建一个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的用户名称。
具体解决方法:
(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