环信官方Demo源码分析及SDK简单应用-IM集成开发详案及具体代码实现
环信官方Demo源码分析及SDK简单应用
环信官方Demo源码分析及SDK简单应用-ChatDemoUI3.0
环信官方Demo源码分析及SDK简单应用-LoginActivity
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-会话界面
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-设置界面
环信官方Demo源码分析及SDK简单应用-EaseUI
环信官方Demo源码分析及SDK简单应用-IM集成开发详案及具体代码实现
前言
手头工作上,正好需要在已有的两个App上集成IM功能。且迭代流程中是有开发详案这一项的。就分享给大家,边写开发详案边写代码。好吧,废话不多说,我们一起来学习如何集成和改造这款简单易用而又非常强大的环信SDK。
具体步骤
迭代点
需要做的功能点及工作
1.集成环信
2.围绕UE和UI进行编码
环信的哥哥们已经帮我们实现了。但是根据要求呢,我没只需要删除会话,所以我们把第二项注释掉。
我们把对应处的判断代码和对应的menu文件em_delete_message中的标签给注释掉。看效果。
从房源详情页进入时,就返回房源详情页,从消息中心进入时,就返回消息中心。直接finish();显示当前咨询人的经纪人姓名,并显示当前咨询的对象的在线状态(在线/离线)官方的EaseUi是这么说的
我们来找下EaseTitleBar
我们来看下他的布局
我们来对title加入一个是否在线的状态1.获取token
所以昵称是在咱自己的体系的。可以从现有的App里提取,如果有的话。我们知道从列表ConversationListFragment->ChatActivity->ChatFragment那么如何接受和发送自己与他人的头像和昵称呢?我们来玩这个ChatFragment
在OnSetMessageAttributes中,设置我们要发送时的消息扩展属性。那么接收怎么办呢,我们来看下DemoHelper中的getUserInfo()方法。
无聊的用鄙人蹩脚的英文写了一把注释。英文若是写的不对就不对吧。标题头中的电话按钮可以直接拨打电话修改删除按钮为打电话,并改动相关代码显示经纪人照片上传的照片,如果经纪人没有上传照片,就显示一个经纪人的占位图(要区别于用户的占位图)修改原demo当前用户头像默认显示当前用户的头像,如果没有头像,就显示一个默认的占位图修改原demo。聊天内容上长按可复制
自带了,后面我们可能需要去掉转发。发送的是手机号码时可以直接打电话。我们再长按后判断其是否为电话号码,如果是添加一项拨打电话。引用关系是这样的ChatFragment->ContextMenuActivity->em_context_menu_for_location.xml最后调回ChatFragment的onActivityResult我们来改em_context_menu_for_location.xml
STM集成在本质上是相同的。不同的是一个是用户端,一个是经纪人端标注下需要注意的几个地方
对于从房源详情进入时带入的房源详情类型的聊天条目,经纪人可以点击查看该房源在STM中的详情。
创建图文chatrow并设置对应点击事件代码。
集成至目标App
不需要的代码,我们只做注释,不删除,防止后面增加了,需要了。避免一系列麻烦。
剔除红包库
在ChatUIDemo3.0的build.gradle中注释编译红包依赖库。
各种编译,遇到报错就删除相关代码
剔除不需要的代码
注意EaseUI下有个SimpleDemo
目标App集成与调试
因为是公司的商业项目,这里就不贴出来了。接着完成需调试才能完成的功能点
总结
好了,至此,我们开发详案写完了,代码也写完了。因为本文写的时候UI还未出,所以后面就是根据UI改改的调整调整界面的小事情了。
有任何问题或者其他事宜请联系我: 5108168@qq.com,欢迎指正和勘误。
环信官方Demo源码分析及SDK简单应用-ChatDemoUI3.0
环信官方Demo源码分析及SDK简单应用-LoginActivity
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-会话界面
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-设置界面
环信官方Demo源码分析及SDK简单应用-EaseUI
环信官方Demo源码分析及SDK简单应用-IM集成开发详案及具体代码实现
前言
手头工作上,正好需要在已有的两个App上集成IM功能。且迭代流程中是有开发详案这一项的。就分享给大家,边写开发详案边写代码。好吧,废话不多说,我们一起来学习如何集成和改造这款简单易用而又非常强大的环信SDK。
具体步骤
迭代点
需要做的功能点及工作
1.集成环信
2.围绕UE和UI进行编码
- 房源详情增加咨询按钮,点击进入咨询对话框,并且将房源信息带入对话框。
- 消息中心
- 根据UE和UI改造聊天窗口(EaseUI库)
环信的哥哥们已经帮我们实现了。但是根据要求呢,我没只需要删除会话,所以我们把第二项注释掉。
我们把对应处的判断代码和对应的menu文件em_delete_message中的标签给注释掉。看效果。
从房源详情页进入时,就返回房源详情页,从消息中心进入时,就返回消息中心。直接finish();显示当前咨询人的经纪人姓名,并显示当前咨询的对象的在线状态(在线/离线)官方的EaseUi是这么说的
我们来找下EaseTitleBar
我们来看下他的布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="@dimen/height_top_bar" android:background="@color/top_bar_normal_bg" android:gravity="center_vertical" > <RelativeLayout android:id="@+id/left_layout" android:layout_width="50dip" android:layout_height="match_parent" android:background="@drawable/ease_common_tab_bg" android:clickable="true" > <ImageView android:id="@+id/left_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:scaleType="centerInside" /> </RelativeLayout> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="#ffffff" android:textSize="20sp" /> <RelativeLayout android:id="@+id/right_layout" android:layout_width="50dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="@drawable/ease_common_tab_bg" > <ImageView android:id="@+id/right_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:scaleType="centerInside" /> </RelativeLayout></RelativeLayout>其实有title和rightview的。
我们来对title加入一个是否在线的状态1.获取token
MacBook:~ mli$ curl -X POST "https://a1.easemob.com/1177170104178912/demo/token" -d '{"grant_type":"client_credentials","client_id":"YXA6vcNInEeatzGVyK0tA","client_secret":"YXA6YACo7qumFfgYdWher3D3Cs"}'
{"access_token":"YWMtOT73nvcIEeaPCCuTQsCAAAVuOB_MQchxsIsxVJFXsW6lZ8f2l__xn8","expires_in":5168429,"application":"bd09c370-d227-11e6-adcc-65700322b4b4"}2.拿token获取用户状态
MacBook:~ mli$ curl -X GET -i -H "Authorization: Bearer YWMtOT73nvcIEeaPCCuTQsC6kwAAAVuOB_MQchxsIsxybVJFXsW6lZ8f2l__xn8" "https://a1.easemob.com/1177170104178912/demo/users/2/status"HTTP/1.1 200 OKServer: Tengine/2.0.3Date: Mon, 20 Feb 2017 05:24:00 GMTContent-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedConnection: keep-aliveAccess-Control-Allow-Origin: *Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Sun, 19-Feb-2017 05:24:00 GMT{ "action" : "get", "uri" : "http://a1.easemob.com/1177170104178912/demo/users/2/status", "entities" : [ ], "data" : { "2" : "offline" }, "timestamp" : 1487568240699, "duration" : 25, "count" : 0}MacBook:~ mli$ curl -X GET -i -H "Authorization: Bearer YWMtOT73nvcIEeaPCCuCkwAAAVuOB_MQchxsIJFXsW6lZ8f2l__xn8" "https://a1.easemob.com/1177170104178912/demo/users/1/status"HTTP/1.1 200 OKServer: Tengine/2.0.3Date: Mon, 20 Feb 2017 05:24:08 GMTContent-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedConnection: keep-aliveAccess-Control-Allow-Origin: *Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Sun, 19-Feb-2017 05:24:08 GMT{ "action" : "get", "uri" : "http://a1.easemob.com/1177170104178912/demo/users/1/status", "entities" : [ ], "data" : { "1" : "online" }, "timestamp" : 1487568248135, "duration" : 14, "count" : 0MacBook:~ mli$我们可以看到2是离线,1是在线的。注意一点
所以昵称是在咱自己的体系的。可以从现有的App里提取,如果有的话。我们知道从列表ConversationListFragment->ChatActivity->ChatFragment那么如何接受和发送自己与他人的头像和昵称呢?我们来玩这个ChatFragment
在OnSetMessageAttributes中,设置我们要发送时的消息扩展属性。那么接收怎么办呢,我们来看下DemoHelper中的getUserInfo()方法。
无聊的用鄙人蹩脚的英文写了一把注释。英文若是写的不对就不对吧。标题头中的电话按钮可以直接拨打电话修改删除按钮为打电话,并改动相关代码显示经纪人照片上传的照片,如果经纪人没有上传照片,就显示一个经纪人的占位图(要区别于用户的占位图)修改原demo当前用户头像默认显示当前用户的头像,如果没有头像,就显示一个默认的占位图修改原demo。聊天内容上长按可复制
自带了,后面我们可能需要去掉转发。发送的是手机号码时可以直接打电话。我们再长按后判断其是否为电话号码,如果是添加一项拨打电话。引用关系是这样的ChatFragment->ContextMenuActivity->em_context_menu_for_location.xml最后调回ChatFragment的onActivityResult我们来改em_context_menu_for_location.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="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="1dp" android:background="@drawable/em_context_menu_item_bg" android:clickable="true" android:gravity="center_vertical" android:onClick="copy" android:padding="10dp" android:text="@string/copy_message" android:textColor="@android:color/black" android:textSize="20sp" /> <View android:layout_width="match_parent" android:layout_height="1px" android:background="@android:color/darker_gray" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/em_context_menu_item_bg" android:clickable="true" android:gravity="center_vertical" android:onClick="delete" android:padding="10dp" android:text="@string/delete_message" android:textColor="@android:color/black" android:textSize="20sp" /><!-- <View android:layout_width="match_parent" android:layout_height="1px" android:background="@android:color/darker_gray" /> <TextView android:id="@+id/forward" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/em_context_menu_item_bg" android:clickable="true" android:gravity="center_vertical" android:onClick="forward" android:padding="10dp" android:text="@string/forward" android:textColor="@android:color/black" android:textSize="20sp" />--> <View android:layout_width="match_parent" android:layout_height="1px" android:background="@android:color/darker_gray" /> <TextView android:id="@+id/call_phone" android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/em_context_menu_item_bg" android:clickable="true" android:gravity="center_vertical" android:onClick="call" android:padding="10dp" android:text="@string/call_phone" android:textColor="@android:color/black" android:textSize="20sp" /></LinearLayout>再来改ContextMenuActivity
/** * Copyright (C) 2016 Hyphenate Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.hyphenate.chatuidemo.ui;import android.content.Intent;import android.os.Bundle;import android.text.TextUtils;import android.view.MotionEvent;import android.view.View;import android.widget.TextView;import com.easemob.redpacketsdk.constant.RPConstant;import com.hyphenate.chat.EMMessage;import com.hyphenate.chatuidemo.Constant;import com.hyphenate.chatuidemo.R;public class ContextMenuActivity extends BaseActivity { public static final int RESULT_CODE_COPY = 1; public static final int RESULT_CODE_DELETE = 2; public static final int RESULT_CODE_FORWARD = 3; public static final int RESUTL_CALL_PHONE = 4; String phoneNumber; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EMMessage message = getIntent().getParcelableExtra("message"); boolean isChatroom = getIntent().getBooleanExtra("ischatroom", false); phoneNumber = getIntent().getStringExtra("phone_number"); int type = message.getType().ordinal(); if (type == EMMessage.Type.TXT.ordinal()) { if(message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false) || message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false) //red packet code : 屏蔽红包消息、转账消息的转发功能 || message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false) || message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)){ //end of red packet code setContentView(R.layout.em_context_menu_for_location); }else if(message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_BIG_EXPRESSION, false)){ setContentView(R.layout.em_context_menu_for_image); }else{ //for text content setContentView(R.layout.em_context_menu_for_text); //for call phone number TextView callPhone = (TextView) findViewById(R.id.call_phone); if(!TextUtils.isEmpty(phoneNumber)){ callPhone.setVisibility(View.VISIBLE); callPhone.setText("拨打电话:" + phoneNumber); }else{ callPhone.setVisibility(View.GONE); } } } else if (type == EMMessage.Type.LOCATION.ordinal()) { setContentView(R.layout.em_context_menu_for_location); } else if (type == EMMessage.Type.IMAGE.ordinal()) { setContentView(R.layout.em_context_menu_for_image); } else if (type == EMMessage.Type.VOICE.ordinal()) { setContentView(R.layout.em_context_menu_for_voice); } else if (type == EMMessage.Type.VIDEO.ordinal()) { setContentView(R.layout.em_context_menu_for_video); } else if (type == EMMessage.Type.FILE.ordinal()) { setContentView(R.layout.em_context_menu_for_location); } if (isChatroom //red packet code : 屏蔽红包消息、转账消息的撤回功能 || message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false) || message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) { //end of red packet code View v = (View) findViewById(R.id.forward); if (v != null) { v.setVisibility(View.GONE); } } } @Override public boolean onTouchEvent(MotionEvent event) { finish(); return true; } public void copy(View view){ setResult(RESULT_CODE_COPY); finish(); } public void delete(View view){ setResult(RESULT_CODE_DELETE); finish(); } public void forward(View view){ setResult(RESULT_CODE_FORWARD); finish(); } public void call(View view) { Intent it = new Intent(); it.putExtra("phone_number",phoneNumber); setResult(RESUTL_CALL_PHONE,it); finish(); }}再来判断内容是否为电话号码
String phoneNumber=""; if(isPhoneNumber(content)){ phoneNumber = content; }// no message forward when in chat room startActivityForResult((new Intent(getActivity(), ContextMenuActivity.class)).putExtra("message",message) //if message's context is a phone number ,make it can be call it. .putExtra("ischatroom", chatType == EaseConstant.CHATTYPE_CHATROOM).putExtra("phone_number",phoneNumber), REQUEST_CODE_CONTEXT_MENU);onActivityResult部分
public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_CONTEXT_MENU) { //for Context MenuActivity Result switch (resultCode) { case ContextMenuActivity.RESULT_CODE_COPY: // copy clipboard.setPrimaryClip(ClipData.newPlainText(null, ((EMTextMessageBody) contextMenuMessage.getBody()).getMessage())); break; case ContextMenuActivity.RESULT_CODE_DELETE: // delete conversation.removeMessage(contextMenuMessage.getMsgId()); messageList.refresh(); break;// case ContextMenuActivity.RESULT_CODE_FORWARD: // forward// Intent intent = new Intent(getActivity(), ForwardMessageActivity.class);// intent.putExtra("forward_msg_id", contextMenuMessage.getMsgId());// startActivity(intent);//// break; case ContextMenuActivity.RESUTL_CALL_PHONE: Intent intent = new Intent(Intent.ACTION_DIAL); Uri callData = Uri.parse("tel:" +data.getStringExtra("phone_number")); intent.setData(callData); startActivity(intent); break; default: break; } }记住先提取字符串中的数字,再去匹配正则。
STM集成在本质上是相同的。不同的是一个是用户端,一个是经纪人端标注下需要注意的几个地方
- 头像和昵称的扩展互通,是SeeHouse和STM两边都需要做的。
- 因为有一条对于从房源详情进入时带入的房源详情类型的聊天条目,经纪人可以点击查看该房源在STM中的详情。是在STM中单独实现的。SeeHouse负责带入,STM负责点击跳转。
对于从房源详情进入时带入的房源详情类型的聊天条目,经纪人可以点击查看该房源在STM中的详情。
创建图文chatrow并设置对应点击事件代码。
集成至目标App
不需要的代码,我们只做注释,不删除,防止后面增加了,需要了。避免一系列麻烦。
剔除红包库
在ChatUIDemo3.0的build.gradle中注释编译红包依赖库。
各种编译,遇到报错就删除相关代码
剔除不需要的代码
注意EaseUI下有个SimpleDemo
目标App集成与调试
因为是公司的商业项目,这里就不贴出来了。接着完成需调试才能完成的功能点
总结
好了,至此,我们开发详案写完了,代码也写完了。因为本文写的时候UI还未出,所以后面就是根据UI改改的调整调整界面的小事情了。
有任何问题或者其他事宜请联系我: 5108168@qq.com,欢迎指正和勘误。