前一阵时间一直以为环信不能被个人用户注册,结果现在想试试结果真的注册进来了,各种打脸。今天趁着晚上有时间把环信继承的步骤做一个记录,方便以后的童鞋们能够快速的集成。

1.第一步:肯定是创建应用喽

那么具体步骤为了避免大家看的烦躁,我就不一一截图了,而是将官网的连接地址给大家po过来

http://docs.easemob.com/im/000quickstart/10register

当然从这个连接中可以清楚的看到

感觉这一巴掌真痛!!!

当然官方的文档多少有点出入,没关系,只需要创建好自己的应用就可以了。

第一步so easy

2.第二步:下载sdk

不用多说,照着文档下载就行。po上网址:

http://www.easemob.com/download/im

解压后是这样的。

考虑到开发者需求不一样,在下载的 SDK 中,提供了两个不同的 jar 包:

  • 一个是 libs 下带实时语音功能和实时视频功能的 jar 包和 so 文件。
  • 如果你不需要实时语音、实时视频功能,那就直接用 libs.without.audio 文件夹下的 jar 包及 so 文件。

在这里主要介绍后面四个文件夹内容:

  • doc 文件夹:SDK 相关 API 文档
  • examples 文件夹:ChatDemoUI3.0(Demo,依赖 EaseUI 库)、EaseUI
  • libs 文件夹:包含IM和实时音视频功能所需要的 jar 和 so 文件
  • libs.without.audio 文件夹:无实时语音、实时视频功能的 SDK 包,如果项目中只用到聊天功能,可以把项目里的 jar 和 so 文件替换成此文件夹里的

3.第三步:配置工程环境

简单的说,就是往你的项目中去粘贴东西就行了。

在自行开发的应用中,集成环信聊天需要把 libs 文件夹下的 jar 及 so 文件复制到你的项目的 libs 文件夹相应位置,如果不需要语音和视频通话功能,导入libs.without.audio 下的文件即可。

如图:

至于这些三方的so文件怎么导入请看我的另一篇文章

http://blog.csdn.net/JerryWu145/article/details/52507658

4.第四步,配置代码环境

在清单文件 AndroidManifest.xml 里加入以下权限,以及写上你注册的 AppKey。

权限配置(实际开发中可能需要更多的权限,可参考 Demo):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="us.mifeng.guaju.huanxin"><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.GET_TASKS" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><applicationandroid:name="app.MyApp"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".LoginActivity"></activity><activityandroid:name=".ChatActivity"android:windowSoftInputMode="adjustResize|stateHidden"></activity><meta-data android:name="EASEMOB_APPKEY"  android:value="guajujerry#im" /><!-- 声明SDK所需的service SDK核心功能--><service android:name="com.hyphenate.chat.EMChatService" android:exported="true"/><!-- 声明SDK所需的receiver --><receiver android:name="com.hyphenate.chat.EMMonitorReceiver"><intent-filter><action android:name="android.intent.action.PACKAGE_REMOVED"/><data android:scheme="package"/></intent-filter><!-- 可选filter --><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/><action android:name="android.intent.action.USER_PRESENT" /></intent-filter></receiver></application></manifest>

关于 EASEMOB_APPKEY 对应的 value 获取,在创建应用后,申请 AppKey 并进行相关配置。(环信 Demo 中 AppKey 为 easemob-demo#chatdemoui)

接下来是对自己创建的application进行初始化配置:

package app;import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMOptions;import java.util.Iterator;
import java.util.List;/*** Created by guaju on 2016/9/12.*/
public class MyApp extends Application {// 上下文菜单private Context mContext;// 记录是否已经初始化private boolean isInit = false;@Overridepublic void onCreate() {super.onCreate();mContext = this;// 初始化环信SDKinitEasemob();}/****/private void initEasemob() {// 获取当前进程 id 并取得进程名int pid = android.os.Process.myPid();String processAppName = getAppName(pid);/*** 如果app启用了远程的service,此application:onCreate会被调用2次* 为了防止环信SDK被初始化2次,加此判断会保证SDK被初始化1次* 默认的app会在以包名为默认的process name下运行,如果查到的process name不是app的process name就立即返回*/if (processAppName == null || !processAppName.equalsIgnoreCase(mContext.getPackageName())) {// 则此application的onCreate 是被service 调用的,直接返回return;}if (isInit) {return;}/*** SDK初始化的一些配置* 关于 EMOptions 可以参考官方的 API 文档* http://www.easemob.com/apidoc/android/chat3.0/classcom_1_1hyphenate_1_1chat_1_1_e_m_options.html*/EMOptions options = new EMOptions();// 设置Appkey,如果配置文件已经配置,这里可以不用设置// options.setAppKey("guaju");// 设置自动登录options.setAutoLogin(true);// 设置是否需要发送已读回执options.setRequireAck(true);// 设置是否需要发送回执,TODO 这个暂时有bug,上层收不到发送回执options.setRequireDeliveryAck(true);// 设置是否需要服务器收到消息确认options.setRequireServerAck(true);// 收到好友申请是否自动同意,如果是自动同意就不会收到好友请求的回调,因为sdk会自动处理,默认为trueoptions.setAcceptInvitationAlways(false);// 设置是否自动接收加群邀请,如果设置了当收到群邀请会自动同意加入options.setAutoAcceptGroupInvitation(false);// 设置(主动或被动)退出群组时,是否删除群聊聊天记录options.setDeleteMessagesAsExitGroup(false);// 设置是否允许聊天室的Owner 离开并删除聊天室的会话options.allowChatroomOwnerLeave(true);// 设置google GCM推送id,国内可以不用设置// options.setGCMNumber(MLConstants.ML_GCM_NUMBER);// 设置集成小米推送的appid和appkey// options.setMipushConfig(MLConstants.ML_MI_APP_ID, MLConstants.ML_MI_APP_KEY);// 调用初始化方法初始化sdkEMClient.getInstance().init(mContext, options);// 设置开启debug模式EMClient.getInstance().setDebugMode(true);// 设置初始化已经完成isInit = true;}/*** 根据Pid获取当前进程的名字,一般就是当前app的包名** @param pid 进程的id* @return 返回进程的名字*/private String getAppName(int pid) {String processName = null;ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);List list = activityManager.getRunningAppProcesses();Iterator i = list.iterator();while (i.hasNext()) {ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());try {if (info.pid == pid) {// 根据进程的信息获取当前进程的名字processName = info.processName;// 返回当前进程名return processName;}} catch (Exception e) {e.printStackTrace();}}// 没有匹配的项,返回为nullreturn null;}
}

主界面

app启动后默认会进入到MainActivity,不过在主界面会先判断一下是否登录成功过,如果没有,就会跳转到登录页面,然后我们调用登录的时候,在登录方法的onSuccess()回调中我们进行了界面的跳转,跳转到主界面,在主界面我们可以发起回话。
看下主界面的详细代码实现:

package us.mifeng.guaju.huanxin;import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;import com.hyphenate.EMCallBack;
import com.hyphenate.chat.EMClient;public class MainActivity extends AppCompatActivity {// 发起聊天 username 输入框private EditText mChatIdEdit;// 发起聊天private Button mStartChatBtn;// 退出登录private Button mSignOutBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 判断sdk是否登录成功过,并没有退出和被踢,否则跳转到登陆界面if (!EMClient.getInstance().isLoggedInBefore()) {Intent intent = new Intent(MainActivity.this, LoginActivity.class);startActivity(intent);finish();return;}setContentView(R.layout.activity_main);initView();}/*** 初始化界面*/private void initView() {mChatIdEdit = (EditText) findViewById(R.id.ec_edit_chat_id);mStartChatBtn = (Button) findViewById(R.id.ec_btn_start_chat);mStartChatBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 获取我们发起聊天的者的usernameString chatId = mChatIdEdit.getText().toString().trim();if (!TextUtils.isEmpty(chatId)) {// 获取当前登录用户的 usernameString currUsername = EMClient.getInstance().getCurrentUser();if (chatId.equals(currUsername)) {Toast.makeText(MainActivity.this, "不能和自己聊天", Toast.LENGTH_SHORT).show();return;}// 跳转到聊天界面,开始聊天Intent intent = new Intent(MainActivity.this, ChatActivity.class);intent.putExtra("ec_chat_id", chatId);startActivity(intent);} else {Toast.makeText(MainActivity.this, "Username 不能为空", Toast.LENGTH_LONG).show();}}});mSignOutBtn = (Button) findViewById(R.id.ec_btn_sign_out);mSignOutBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {signOut();}});}/*** 退出登录*/private void signOut() {// 调用sdk的退出登录方法,第一个参数表示是否解绑推送的token,没有使用推送或者被踢都要传falseEMClient.getInstance().logout(false, new EMCallBack() {@Overridepublic void onSuccess() {Log.i("lzan13", "logout success");// 调用退出成功,结束appfinish();}@Overridepublic void onError(int i, String s) {Log.i("lzan13", "logout error " + i + " - " + s);}@Overridepublic void onProgress(int i, String s) {}});}
}}

登录及注册界面

package us.mifeng.guaju.huanxin;import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;import com.hyphenate.EMCallBack;
import com.hyphenate.EMError;
import com.hyphenate.chat.EMClient;
import com.hyphenate.exceptions.HyphenateException;public class LoginActivity extends Activity {// 弹出框private ProgressDialog mDialog;// username 输入框private EditText mUsernameEdit;// 密码输入框private EditText mPasswordEdit;// 注册按钮private Button mSignUpBtn;// 登录按钮private Button mSignInBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);initView();}/*** 初始化界面控件*/private void initView() {mUsernameEdit = (EditText) findViewById(R.id.ec_edit_username);mPasswordEdit = (EditText) findViewById(R.id.ec_edit_password);mSignUpBtn = (Button) findViewById(R.id.ec_btn_sign_up);mSignUpBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {signUp();}});mSignInBtn = (Button) findViewById(R.id.ec_btn_sign_in);mSignInBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {signIn();}});}/*** 注册方法*/private void signUp() {// 注册是耗时过程,所以要显示一个dialog来提示下用户mDialog = new ProgressDialog(this);mDialog.setMessage("注册中,请稍后...");mDialog.show();new Thread(new Runnable() {@Overridepublic void run() {try {String username = mUsernameEdit.getText().toString().trim();String password = mPasswordEdit.getText().toString().trim();EMClient.getInstance().createAccount(username, password);runOnUiThread(new Runnable() {@Overridepublic void run() {if (!LoginActivity.this.isFinishing()) {mDialog.dismiss();}Toast.makeText(LoginActivity.this, "注册成功", Toast.LENGTH_LONG).show();}});} catch (final HyphenateException e) {e.printStackTrace();runOnUiThread(new Runnable() {@Overridepublic void run() {if (!LoginActivity.this.isFinishing()) {mDialog.dismiss();}/*** 关于错误码可以参考官方api详细说明* http://www.easemob.com/apidoc/android/chat3.0/classcom_1_1hyphenate_1_1_e_m_error.html*/int errorCode = e.getErrorCode();String message = e.getMessage();Log.d("lzan13", String.format("sign up - errorCode:%d, errorMsg:%s", errorCode, e.getMessage()));switch (errorCode) {// 网络错误case EMError.NETWORK_ERROR:Toast.makeText(LoginActivity.this, "网络错误 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();break;// 用户已存在case EMError.USER_ALREADY_EXIST:Toast.makeText(LoginActivity.this, "用户已存在 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();break;// 参数不合法,一般情况是username 使用了uuid导致,不能使用uuid注册case EMError.USER_ILLEGAL_ARGUMENT:Toast.makeText(LoginActivity.this, "参数不合法,一般情况是username 使用了uuid导致,不能使用uuid注册 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();break;// 服务器未知错误case EMError.SERVER_UNKNOWN_ERROR:Toast.makeText(LoginActivity.this, "服务器未知错误 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();break;case EMError.USER_REG_FAILED:Toast.makeText(LoginActivity.this, "账户注册失败 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();break;default:Toast.makeText(LoginActivity.this, "ml_sign_up_failed code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();break;}}});} catch (Exception e) {e.printStackTrace();}}}).start();}/*** 登录方法*/private void signIn() {mDialog = new ProgressDialog(this);mDialog.setMessage("正在登陆,请稍后...");mDialog.show();String username = mUsernameEdit.getText().toString().trim();String password = mPasswordEdit.getText().toString().trim();EMClient.getInstance().login(username, password, new EMCallBack() {/*** 登陆成功的回调*/@Overridepublic void onSuccess() {runOnUiThread(new Runnable() {@Overridepublic void run() {mDialog.dismiss();// 加载所有会话到内存EMClient.getInstance().chatManager().loadAllConversations();// 加载所有群组到内存,如果使用了群组的话// EMClient.getInstance().groupManager().loadAllGroups();// 登录成功跳转界面Intent intent = new Intent(LoginActivity.this, MainActivity.class);startActivity(intent);finish();}});}/*** 登陆错误的回调* @param i* @param s*/@Overridepublic void onError(final int i, final String s) {runOnUiThread(new Runnable() {@Overridepublic void run() {mDialog.dismiss();Log.d("lzan13", "登录失败 Error code:" + i + ", message:" + s);/*** 关于错误码可以参考官方api详细说明* http://www.easemob.com/apidoc/android/chat3.0/classcom_1_1hyphenate_1_1_e_m_error.html*/switch (i) {// 网络异常 2case EMError.NETWORK_ERROR:Toast.makeText(LoginActivity.this, "网络错误 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 无效的用户名 101case EMError.INVALID_USER_NAME:Toast.makeText(LoginActivity.this, "无效的用户名 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 无效的密码 102case EMError.INVALID_PASSWORD:Toast.makeText(LoginActivity.this, "无效的密码 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 用户认证失败,用户名或密码错误 202case EMError.USER_AUTHENTICATION_FAILED:Toast.makeText(LoginActivity.this, "用户认证失败,用户名或密码错误 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 用户不存在 204case EMError.USER_NOT_FOUND:Toast.makeText(LoginActivity.this, "用户不存在 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 无法访问到服务器 300case EMError.SERVER_NOT_REACHABLE:Toast.makeText(LoginActivity.this, "无法访问到服务器 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 等待服务器响应超时 301case EMError.SERVER_TIMEOUT:Toast.makeText(LoginActivity.this, "等待服务器响应超时 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 服务器繁忙 302case EMError.SERVER_BUSY:Toast.makeText(LoginActivity.this, "服务器繁忙 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;// 未知 Server 异常 303 一般断网会出现这个错误case EMError.SERVER_UNKNOWN_ERROR:Toast.makeText(LoginActivity.this, "未知的服务器异常 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;default:Toast.makeText(LoginActivity.this, "ml_sign_in_failed code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();break;}}});}@Overridepublic void onProgress(int i, String s) {}});}
}

界面布局

界面的实现也是非常简单,这里直接贴一下:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/ec_edit_chat_id"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="对方的username"/><Buttonandroid:id="@+id/ec_btn_start_chat"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="发起聊天"/><Buttonandroid:id="@+id/ec_btn_sign_out"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="退出登录"/></LinearLayout>
</RelativeLayout>

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/ec_edit_username"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="username"/><EditTextandroid:id="@+id/ec_edit_password"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="password"/><Buttonandroid:id="@+id/ec_btn_sign_up"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="注册"/><Buttonandroid:id="@+id/ec_btn_sign_in"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="登录"/></LinearLayout>
</RelativeLayout>

activity_chat.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"><!--输入框--><RelativeLayoutandroid:id="@+id/ec_layout_input"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"><Buttonandroid:id="@+id/ec_btn_send"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:text="Send"/><EditTextandroid:id="@+id/ec_edit_message_input"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_toLeftOf="@id/ec_btn_send"/></RelativeLayout><!--展示消息内容--><TextViewandroid:id="@+id/ec_text_content"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@id/ec_layout_input"android:maxLines="15"android:scrollbars="vertical"/>
</RelativeLayout>

我是分割线-------------------------------------------------

补上ChatActivity的代码

package us.mifeng.guaju.huanxin;import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;import com.hyphenate.EMCallBack;
import com.hyphenate.EMMessageListener;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMCmdMessageBody;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.chat.EMTextMessageBody;import java.util.List;/*** Created by guaju on 2016/9/12.*/
public class ChatActivity extends AppCompatActivity implements EMMessageListener {// 聊天信息输入框private EditText mInputEdit;// 发送按钮private Button mSendBtn;// 显示内容的 TextViewprivate TextView mContentText;// 消息监听器private EMMessageListener mMessageListener;// 当前聊天的 IDprivate String mChatId;// 当前会话对象private EMConversation mConversation;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_chat);// 获取当前会话的username(如果是群聊就是群id)mChatId = getIntent().getStringExtra("ec_chat_id");mMessageListener = this;initView();initConversation();}/*** 初始化界面*/private void initView() {mInputEdit = (EditText) findViewById(R.id.ec_edit_message_input);mSendBtn = (Button) findViewById(R.id.ec_btn_send);mContentText = (TextView) findViewById(R.id.ec_text_content);// 设置textview可滚动,需配合xml布局设置mContentText.setMovementMethod(new ScrollingMovementMethod());// 设置发送按钮的点击事件mSendBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String content = mInputEdit.getText().toString().trim();if (!TextUtils.isEmpty(content)) {mInputEdit.setText("");// 创建一条新消息,第一个参数为消息内容,第二个为接受者usernameEMMessage message = EMMessage.createTxtSendMessage(content, mChatId);// 将新的消息内容和时间加入到下边mContentText.setText(mContentText.getText() + "\n" + content + " -> " + message.getMsgTime());// 调用发送消息的方法EMClient.getInstance().chatManager().sendMessage(message);// 为消息设置回调message.setMessageStatusCallback(new EMCallBack() {@Overridepublic void onSuccess() {// 消息发送成功,打印下日志,正常操作应该去刷新uiLog.i("lzan13", "send message on success");}@Overridepublic void onError(int i, String s) {// 消息发送失败,打印下失败的信息,正常操作应该去刷新uiLog.i("lzan13", "send message on error " + i + " - " + s);}@Overridepublic void onProgress(int i, String s) {// 消息发送进度,一般只有在发送图片和文件等消息才会有回调,txt不回调}});}}});}/*** 初始化会话对象,并且根据需要加载更多消息*/private void initConversation() {/*** 初始化会话对象,这里有三个参数么,* 第一个表示会话的当前聊天的 useranme 或者 groupid* 第二个是绘画类型可以为空* 第三个表示如果会话不存在是否创建*/mConversation = EMClient.getInstance().chatManager().getConversation(mChatId, null, true);// 设置当前会话未读数为 0mConversation.markAllMessagesAsRead();int count = mConversation.getAllMessages().size();if (count < mConversation.getAllMsgCount() && count < 20) {// 获取已经在列表中的最上边的一条消息idString msgId = mConversation.getAllMessages().get(0).getMsgId();// 分页加载更多消息,需要传递已经加载的消息的最上边一条消息的id,以及需要加载的消息的条数mConversation.loadMoreMsgFromDB(msgId, 20 - count);}// 打开聊天界面获取最后一条消息内容并显示if (mConversation.getAllMessages().size() > 0) {EMMessage messge = mConversation.getLastMessage();EMTextMessageBody body = (EMTextMessageBody) messge.getBody();// 将消息内容和时间显示出来mContentText.setText(body.getMessage() + " - " + mConversation.getLastMessage().getMsgTime());}}/*** 自定义实现Handler,主要用于刷新UI操作*/Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 0:EMMessage message = (EMMessage) msg.obj;// 这里只是简单的demo,也只是测试文字消息的收发,所以直接将body转为EMTextMessageBody去获取内容EMTextMessageBody body = (EMTextMessageBody) message.getBody();// 将新的消息内容和时间加入到下边mContentText.setText(mContentText.getText() + "\n" + body.getMessage() + " <- " + message.getMsgTime());break;}}};@Overrideprotected void onResume() {super.onResume();// 添加消息监听EMClient.getInstance().chatManager().addMessageListener(mMessageListener);}@Overrideprotected void onStop() {super.onStop();// 移除消息监听EMClient.getInstance().chatManager().removeMessageListener(mMessageListener);}/*** --------------------------------- Message Listener -------------------------------------* 环信消息监听主要方法*//*** 收到新消息** @param list 收到的新消息集合*/@Overridepublic void onMessageReceived(List<EMMessage> list) {// 循环遍历当前收到的消息for (EMMessage message : list) {if (message.getFrom().equals(mChatId)) {// 设置消息为已读mConversation.markMessageAsRead(message.getMsgId());// 因为消息监听回调这里是非ui线程,所以要用handler去更新uiMessage msg = mHandler.obtainMessage();msg.what = 0;msg.obj = message;mHandler.sendMessage(msg);} else {// 如果消息不是当前会话的消息发送通知栏通知}}}/*** 收到新的 CMD 消息** @param list*/@Overridepublic void onCmdMessageReceived(List<EMMessage> list) {for (int i = 0; i < list.size(); i++) {// 透传消息EMMessage cmdMessage = list.get(i);EMCmdMessageBody body = (EMCmdMessageBody) cmdMessage.getBody();Log.i("lzan13", body.action());}}/*** 收到新的已读回执** @param list 收到消息已读回执*/@Overridepublic void onMessageReadAckReceived(List<EMMessage> list) {}/*** 收到新的发送回执* TODO 无效 暂时有bug** @param list 收到发送回执的消息集合*/@Overridepublic void onMessageDeliveryAckReceived(List<EMMessage> list) {}/*** 消息的状态改变** @param message 发生改变的消息* @param object  包含改变的消息*/@Overridepublic void onMessageChanged(EMMessage message, Object object) {}
}

OK, 终于大功告成,我们可以测试使用了,但是请记住,一定得联网哦,还有把自己的应用设置为“开放注册”,切记

最新Android集成环信步骤详解相关推荐

  1. 最新安卓集成环信SDK3.5.1步骤详解大白菜版本,记录下

    最近两天一直在查找集成环信SDK的博客与文章,找来找去,最新的集成过程详解也是环信官方SDK更新前的,大部分都是SDK3.4.1之前的,刚才测试环信SDK3.5.1测试成功后就来写篇文章记录下,在这里 ...

  2. Android集成环信easeui,设置圆形头像,修改气泡和扩展栏,跳过打包冲突

    初次集成环信的话还是有很多坑的, 我也是个新手,技术客服各种问,各种找人,才堪堪摸到门槛,记录下一点东西,希望给那些初次集成的朋友一点tips. 1,集成环信的时候,如果你不需要很多如视频聊天,等的功 ...

  3. Android集成环信IM,实现聊天置顶功能

    首先是,要实现置顶聊天,那么我们就要有两个List集合,一个是置顶的,一个是不是置顶的.这里,环信给出了EMConversation的一个方法,带大家看看技术文档. 看下这个文档里面说的非常清楚,也就 ...

  4. Android 集成环信实现单点登录校验,账号异地被挤下线功能。

    前言 其实所说的被挤下线功能,就是一个账号在A客户端保持登陆状态,然后又在B客户端进行了登陆操作,那么A客户端就会被顶下线 很多伙伴在开发自己公司产品的时候,一般都会考虑用户账号安全,或者用户账号功能 ...

  5. android 集成环信SDK

    集成步骤: 1. 首先在你的项目根目录build.gradle文件的allprojects→repositories属性下加入远程库地址 allprojects {repositories {goog ...

  6. Oracle 19c集群重装步骤详解

    墨墨导读:重装操作系统.集群软件.数据库软件重装,然后把之前的数据库纳入到新创建的集群中. 重装说明 重装操作系统.集群软件.数据库软件,然后把之前的数据库纳入到新创建的集群中. 环境概述 Redha ...

  7. Android 集成环信IM,实现头像和昵称的显示

    环信中要设置昵称和头像有两种方法,一种是通过请求服务器获得,一种是通过发送扩展消息获得.本人推荐通过发送扩展消息获得,简单又方便.所以下面我就只讲通过发送扩展消息获取的方法. 具体的实现步骤如下: 1 ...

  8. android中样式文件步骤,详解Android主题开发的样式教程

    Android中的样式和css样式作用相似,都是用于为界面元素定义显示风格,它是一个包含一个或者多个view 控件属性的集合.主题是一个包含一种或者多种格式化属性的集合,你可以将其为一个单位用在应用中 ...

  9. Android 集成环信后 无法启动,关于androidx升级后环信sdk集成遇到的问题

    18年谷歌对support包等依赖混乱的问题进行了决策并推出androidx,可以有效的解决support包的问题,但版本迁移带给我们程序员很多麻烦的问题,就是之前的sdk很多都会报错,这里用环信的s ...

最新文章

  1. 使用MEF实现通用参数设置
  2. windows 远程登录用户管理
  3. SharePoint 2013 APP 开发示例 (三)使用远程的web资源
  4. Spring Boot Runner启动器
  5. MySql绿色版安装过程记录
  6. 数据库之间数据转换最快方法
  7. Linux(16)-Vim编辑器的使用
  8. 在 Windows 8 中支持传感器
  9. struts工作原理(图解)
  10. 08TensorFlow2.0基础--8.2创建张量
  11. virtualbox 桥接模式下虚拟机ping不通网关
  12. Installshield停止操作系统进程的代码 --IS6及以上版本适用
  13. excel如何删除空白行_QA|表单数据如何导入、导出?
  14. score函数 机器学习_scikit-learn中的cross_val_score函数scoring参数设置
  15. ----发现一款可以代替双手的软件 “按键精灵”
  16. js打印window.print()图片打印
  17. go time.Ticker与time.Timer使用
  18. SQL面试题练习记录
  19. 【软考 系统架构设计师】计算机组成与体系结构⑥ 流水线
  20. 为什么每个语言都要和Java作比较?一文带你搞懂!

热门文章

  1. TimeSpan的用法
  2. 没加班帮同事完成工作,4年工龄的她被逼辞职
  3. 你的工资够高了吗?薪资计算器告诉你
  4. 关于样本方差分母为什么是n-1理解
  5. 图的连通性 —— 连通性的相关知识
  6. 006❤网络瓶颈效应
  7. 为什么屠呦呦获得了诺贝尔奖却没被评上中科院院士?
  8. k8s podPreset更改所有容器时间为当地时间。
  9. php gif图片加字,gif图片添加文字软件 怎么给gif动态图片加文字
  10. 15-445 lecture#1 Relational Model Relational Algebrae