最新Android集成环信步骤详解
来源:互联网 发布:坑爹哥的淘宝店 编辑:程序博客网 时间:2024/06/05 17:24
前一阵时间一直以为环信不能被个人用户注册,结果现在想试试结果真的注册进来了,各种打脸。今天趁着晚上有时间把环信继承的步骤做一个记录,方便以后的童鞋们能够快速的集成。
1.第一步:肯定是创建应用喽
那么具体步骤为了避免大家看的烦躁,我就不一一截图了,而是将官网的连接地址给大家po过来
http://docs.easemob.com/im/000quickstart/10register
当然从这个连接中可以清楚的看到
感觉这一巴掌真痛!!!
当然官方的文档多少有点出入,没关系,只需要创建好自己的应用就可以了。
第一步so easy
2.第二步:下载sdk
不用多说,照着文档下载就行。po上网址:
http://www.easemob.com/download/im
解压后是这样的。
考虑到开发者需求不一样,在下载的 SDK 中,提供了两个不同的 jar 包:
在这里主要介绍后面四个文件夹内容:
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" /> <application android: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> <activity android: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; @Override public void onCreate() { super.onCreate(); mContext = this; // 初始化环信SDK initEasemob(); } /** * */ 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会自动处理,默认为true options.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); // 调用初始化方法初始化sdk EMClient.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(); } } // 没有匹配的项,返回为null return 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; @Override protected 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() { @Override public void onClick(View v) { // 获取我们发起聊天的者的username String chatId = mChatIdEdit.getText().toString().trim(); if (!TextUtils.isEmpty(chatId)) { // 获取当前登录用户的 username String 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() { @Override public void onClick(View v) { signOut(); } }); } /** * 退出登录 */ private void signOut() { // 调用sdk的退出登录方法,第一个参数表示是否解绑推送的token,没有使用推送或者被踢都要传false EMClient.getInstance().logout(false, new EMCallBack() { @Override public void onSuccess() { Log.i("lzan13", "logout success"); // 调用退出成功,结束app finish(); } @Override public void onError(int i, String s) { Log.i("lzan13", "logout error " + i + " - " + s); } @Override public 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; @Override protected 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() { @Override public void onClick(View v) { signUp(); } }); mSignInBtn = (Button) findViewById(R.id.ec_btn_sign_in); mSignInBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { signIn(); } }); } /** * 注册方法 */ private void signUp() { // 注册是耗时过程,所以要显示一个dialog来提示下用户 mDialog = new ProgressDialog(this); mDialog.setMessage("注册中,请稍后..."); mDialog.show(); new Thread(new Runnable() { @Override public void run() { try { String username = mUsernameEdit.getText().toString().trim(); String password = mPasswordEdit.getText().toString().trim(); EMClient.getInstance().createAccount(username, password); runOnUiThread(new Runnable() { @Override public 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() { @Override public 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() { /** * 登陆成功的回调 */ @Override public void onSuccess() { runOnUiThread(new Runnable() { @Override public 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 */ @Override public void onError(final int i, final String s) { runOnUiThread(new Runnable() { @Override public 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) { // 网络异常 2 case EMError.NETWORK_ERROR: Toast.makeText(LoginActivity.this, "网络错误 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show(); break; // 无效的用户名 101 case EMError.INVALID_USER_NAME: Toast.makeText(LoginActivity.this, "无效的用户名 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show(); break; // 无效的密码 102 case EMError.INVALID_PASSWORD: Toast.makeText(LoginActivity.this, "无效的密码 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show(); break; // 用户认证失败,用户名或密码错误 202 case EMError.USER_AUTHENTICATION_FAILED: Toast.makeText(LoginActivity.this, "用户认证失败,用户名或密码错误 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show(); break; // 用户不存在 204 case EMError.USER_NOT_FOUND: Toast.makeText(LoginActivity.this, "用户不存在 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show(); break; // 无法访问到服务器 300 case EMError.SERVER_NOT_REACHABLE: Toast.makeText(LoginActivity.this, "无法访问到服务器 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show(); break; // 等待服务器响应超时 301 case EMError.SERVER_TIMEOUT: Toast.makeText(LoginActivity.this, "等待服务器响应超时 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show(); break; // 服务器繁忙 302 case 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; } } }); } @Override public void onProgress(int i, String s) { } }); }}
界面布局
界面的实现也是非常简单,这里直接贴一下:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns: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" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/ec_edit_chat_id" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="对方的username"/> <Button android:id="@+id/ec_btn_start_chat" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发起聊天"/> <Button android: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"?><RelativeLayout xmlns: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" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/ec_edit_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="username"/> <EditText android:id="@+id/ec_edit_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="password"/> <Button android:id="@+id/ec_btn_sign_up" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注册"/> <Button android: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"?><RelativeLayout xmlns: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" > <!--输入框--> <RelativeLayout android:id="@+id/ec_layout_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true"> <Button android:id="@+id/ec_btn_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="Send"/> <EditText android: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> <!--展示消息内容--> <TextView android: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; // 显示内容的 TextView private TextView mContentText; // 消息监听器 private EMMessageListener mMessageListener; // 当前聊天的 ID private String mChatId; // 当前会话对象 private EMConversation mConversation; @Override protected 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() { @Override public void onClick(View v) { String content = mInputEdit.getText().toString().trim(); if (!TextUtils.isEmpty(content)) { mInputEdit.setText(""); // 创建一条新消息,第一个参数为消息内容,第二个为接受者username EMMessage message = EMMessage.createTxtSendMessage(content, mChatId); // 将新的消息内容和时间加入到下边 mContentText.setText(mContentText.getText() + "\n" + content + " -> " + message.getMsgTime()); // 调用发送消息的方法 EMClient.getInstance().chatManager().sendMessage(message); // 为消息设置回调 message.setMessageStatusCallback(new EMCallBack() { @Override public void onSuccess() { // 消息发送成功,打印下日志,正常操作应该去刷新ui Log.i("lzan13", "send message on success"); } @Override public void onError(int i, String s) { // 消息发送失败,打印下失败的信息,正常操作应该去刷新ui Log.i("lzan13", "send message on error " + i + " - " + s); } @Override public void onProgress(int i, String s) { // 消息发送进度,一般只有在发送图片和文件等消息才会有回调,txt不回调 } }); } } }); } /** * 初始化会话对象,并且根据需要加载更多消息 */ private void initConversation() { /** * 初始化会话对象,这里有三个参数么, * 第一个表示会话的当前聊天的 useranme 或者 groupid * 第二个是绘画类型可以为空 * 第三个表示如果会话不存在是否创建 */ mConversation = EMClient.getInstance().chatManager().getConversation(mChatId, null, true); // 设置当前会话未读数为 0 mConversation.markAllMessagesAsRead(); int count = mConversation.getAllMessages().size(); if (count < mConversation.getAllMsgCount() && count < 20) { // 获取已经在列表中的最上边的一条消息id String 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() { @Override public 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; } } }; @Override protected void onResume() { super.onResume(); // 添加消息监听 EMClient.getInstance().chatManager().addMessageListener(mMessageListener); } @Override protected void onStop() { super.onStop(); // 移除消息监听 EMClient.getInstance().chatManager().removeMessageListener(mMessageListener); } /** * --------------------------------- Message Listener ------------------------------------- * 环信消息监听主要方法 */ /** * 收到新消息 * * @param list 收到的新消息集合 */ @Override public void onMessageReceived(List<EMMessage> list) { // 循环遍历当前收到的消息 for (EMMessage message : list) { if (message.getFrom().equals(mChatId)) { // 设置消息为已读 mConversation.markMessageAsRead(message.getMsgId()); // 因为消息监听回调这里是非ui线程,所以要用handler去更新ui Message msg = mHandler.obtainMessage(); msg.what = 0; msg.obj = message; mHandler.sendMessage(msg); } else { // 如果消息不是当前会话的消息发送通知栏通知 } } } /** * 收到新的 CMD 消息 * * @param list */ @Override public 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 收到消息已读回执 */ @Override public void onMessageReadAckReceived(List<EMMessage> list) { } /** * 收到新的发送回执 * TODO 无效 暂时有bug * * @param list 收到发送回执的消息集合 */ @Override public void onMessageDeliveryAckReceived(List<EMMessage> list) { } /** * 消息的状态改变 * * @param message 发生改变的消息 * @param object 包含改变的消息 */ @Override public void onMessageChanged(EMMessage message, Object object) { }}
- 最新Android集成环信步骤详解
- android集成环信步骤
- Android 集成微信支付步骤详解
- Android微信支付集成步骤
- android微信支付集成步骤
- 手把手教你Android集成微信支付详解步骤大全
- iOS 环信UI集成步骤
- 环信3.0版本的集成步骤
- Android微信登录以及分享集成步骤
- Android微信登录以及分享集成步骤
- android集成环信流程
- Android 环信集成 fileuriexposedexception
- android studio集成环信
- Android 集成环信EaseUI
- iOS开发:环信集成步骤以及常见错误
- 环信Android客户端集成文档
- Android使用EaseUI集成环信3.0
- Android环信EaseUI的快速集成
- ApexPages.currentPage().getParameters().get('XXX')用法
- thymeleaf SpringEl 生成引号
- 增量备份、差异备份、增量备份的区别?
- vb百列
- 微信公众平台开发Python 版本
- 最新Android集成环信步骤详解
- LeetCode 136. Single Number
- UnityShader - 屏幕特效 - 高斯模糊(Gaussian Blur)
- HDU 3488Tour 最大完美匹配
- test
- g2048游戏2-android
- 基于Redux的ReactNative项目开发总结(一)
- 工作两周年记
- ios开发之小总结「类与对象的判断方法和遍历字典的方法」