项目总结之即时通讯
2015-09-16 16:38
417 查看
项目总结之即时通讯
新项目尹始,项目有个模块称之为即时通讯,何谓即时通讯?通过与产品经理交流得知,做个类似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
相关文章推荐
- 3.4. Model persistence
- zynq 上 mjpg的移植
- DNS 主从同步
- 文章标题
- CRC16校验C语言程序源码(转载)
- iOS objc_msgSend 报错解决方案
- 深度学习
- 利用poi从excel中导入数据到数据库
- 类成员函数后面加const
- cocos2d-x 3.x游戏开发学习笔记(1)--mac下配置cocos2d-x 3.x开发环境
- Unity3d游戏开发之C#开发(一)
- centos压缩与解压缩
- Xcode 物理文件夹与工程文件夹
- iOS中使用RNCryptor对文件进行AES加密/解密
- AI-N Queen Problem(bfs)
- 为什么人人都爱黑产品经理?
- 公众号第三方平台开发 教程二 component_verify_ticket和accessToken的获取
- AI-N Queen Problem(dfs)
- JS获取URL中参数值(QueryString)的4种方法分享
- android OOM(out of memory)异常的处理