android集成环信步骤

来源:互联网 发布:神农架值不值得去 知乎 编辑:程序博客网 时间:2024/06/01 08:14

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


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文件有两种方法:

方法一:

   · 在“src/main”目录中新建名为“jniLibs”的目录;

   · 将so文件复制、粘贴到“jniLibs”目录内。
    注:如果没有引用so文件,可能会在程序执行的时候加载类库失败,有类似如下的DEBUG提示:

    java.lang.UnsatisfiedLinkError: Couldn't load library xxxx from loader dalvik.system.PathClassLoader


方法二:

   · 把so文件拷贝到libs文件夹下

   · 在build.gradle文件中配置




好啦,这样就可以轻松的把so文件引入到你的工程中了。

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

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

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

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="us.mifeng.guaju.huanxin">  
  4.     <uses-permission android:name="android.permission.VIBRATE" />  
  5.     <uses-permission android:name="android.permission.INTERNET" />  
  6.     <uses-permission android:name="android.permission.RECORD_AUDIO" />  
  7.     <uses-permission android:name="android.permission.CAMERA" />  
  8.     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  9.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  10.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  11.     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  
  12.     <uses-permission android:name="android.permission.GET_TASKS" />  
  13.     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
  14.     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />  
  15.     <uses-permission android:name="android.permission.WAKE_LOCK" />  
  16.     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />  
  17.     <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
  18.     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  
  19.     <application  
  20.         android:name="app.MyApp"  
  21.         android:allowBackup="true"  
  22.         android:icon="@mipmap/ic_launcher"  
  23.         android:label="@string/app_name"  
  24.         android:supportsRtl="true"  
  25.         android:theme="@style/AppTheme">  
  26.         <activity android:name=".MainActivity">  
  27.             <intent-filter>  
  28.                 <action android:name="android.intent.action.MAIN" />  
  29.                 <category android:name="android.intent.category.LAUNCHER" />  
  30.             </intent-filter>  
  31.         </activity>  
  32.   
  33.         <activity android:name=".LoginActivity">  
  34.         </activity>  
  35.         <activity  
  36.             android:name=".ChatActivity"  
  37.             android:windowSoftInputMode="adjustResize|stateHidden">  
  38.         </activity>  
  39.   
  40.         <meta-data android:name="EASEMOB_APPKEY"  android:value="guajujerry#im" />  
  41.         <!-- 声明SDK所需的service SDK核心功能-->  
  42.         <service android:name="com.hyphenate.chat.EMChatService" android:exported="true"/>  
  43.         <!-- 声明SDK所需的receiver -->  
  44.         <receiver android:name="com.hyphenate.chat.EMMonitorReceiver">  
  45.             <intent-filter>  
  46.                 <action android:name="android.intent.action.PACKAGE_REMOVED"/>  
  47.                 <data android:scheme="package"/>  
  48.             </intent-filter>  
  49.             <!-- 可选filter -->  
  50.             <intent-filter>  
  51.                 <action android:name="android.intent.action.BOOT_COMPLETED"/>  
  52.                 <action android:name="android.intent.action.USER_PRESENT" />  
  53.             </intent-filter>  
  54.         </receiver>  
  55.     </application>  
  56.   
  57. </manifest>  



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

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

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package app;  
  2.   
  3. import android.app.ActivityManager;  
  4. import android.app.Application;  
  5. import android.content.Context;  
  6.   
  7. import com.hyphenate.chat.EMClient;  
  8. import com.hyphenate.chat.EMOptions;  
  9.   
  10. import java.util.Iterator;  
  11. import java.util.List;  
  12.   
  13.   
  14. /** 
  15.  * Created by guaju on 2016/9/12. 
  16.  */  
  17. public class MyApp extends Application {  
  18.   
  19.     // 上下文菜单  
  20.     private Context mContext;  
  21.   
  22.     // 记录是否已经初始化  
  23.     private boolean isInit = false;  
  24.   
  25.     @Override  
  26.     public void onCreate() {  
  27.         super.onCreate();  
  28.         mContext = this;  
  29.   
  30.         // 初始化环信SDK  
  31.         initEasemob();  
  32.     }  
  33.   
  34.     /** 
  35.      * 
  36.      */  
  37.     private void initEasemob() {  
  38.         // 获取当前进程 id 并取得进程名  
  39.         int pid = android.os.Process.myPid();  
  40.         String processAppName = getAppName(pid);  
  41.         /** 
  42.          * 如果app启用了远程的service,此application:onCreate会被调用2次 
  43.          * 为了防止环信SDK被初始化2次,加此判断会保证SDK被初始化1次 
  44.          * 默认的app会在以包名为默认的process name下运行,如果查到的process name不是app的process name就立即返回 
  45.          */  
  46.         if (processAppName == null || !processAppName.equalsIgnoreCase(mContext.getPackageName())) {  
  47.             // 则此application的onCreate 是被service 调用的,直接返回  
  48.             return;  
  49.         }  
  50.         if (isInit) {  
  51.             return;  
  52.         }  
  53.         /** 
  54.          * SDK初始化的一些配置 
  55.          * 关于 EMOptions 可以参考官方的 API 文档 
  56.          * http://www.easemob.com/apidoc/android/chat3.0/classcom_1_1hyphenate_1_1chat_1_1_e_m_options.html 
  57.          */  
  58.         EMOptions options = new EMOptions();  
  59.         // 设置Appkey,如果配置文件已经配置,这里可以不用设置  
  60.         // options.setAppKey("guaju");  
  61.         // 设置自动登录  
  62.         options.setAutoLogin(true);  
  63.         // 设置是否需要发送已读回执  
  64.         options.setRequireAck(true);  
  65.         // 设置是否需要发送回执,TODO 这个暂时有bug,上层收不到发送回执  
  66.         options.setRequireDeliveryAck(true);  
  67.         // 设置是否需要服务器收到消息确认  
  68.         options.setRequireServerAck(true);  
  69.         // 收到好友申请是否自动同意,如果是自动同意就不会收到好友请求的回调,因为sdk会自动处理,默认为true  
  70.         options.setAcceptInvitationAlways(false);  
  71.         // 设置是否自动接收加群邀请,如果设置了当收到群邀请会自动同意加入  
  72.         options.setAutoAcceptGroupInvitation(false);  
  73.         // 设置(主动或被动)退出群组时,是否删除群聊聊天记录  
  74.         options.setDeleteMessagesAsExitGroup(false);  
  75.         // 设置是否允许聊天室的Owner 离开并删除聊天室的会话  
  76.         options.allowChatroomOwnerLeave(true);  
  77.         // 设置google GCM推送id,国内可以不用设置  
  78.         // options.setGCMNumber(MLConstants.ML_GCM_NUMBER);  
  79.         // 设置集成小米推送的appid和appkey  
  80.         // options.setMipushConfig(MLConstants.ML_MI_APP_ID, MLConstants.ML_MI_APP_KEY);  
  81.   
  82.         // 调用初始化方法初始化sdk  
  83.         EMClient.getInstance().init(mContext, options);  
  84.   
  85.         // 设置开启debug模式  
  86.         EMClient.getInstance().setDebugMode(true);  
  87.   
  88.         // 设置初始化已经完成  
  89.         isInit = true;  
  90.     }  
  91.   
  92.     /** 
  93.      * 根据Pid获取当前进程的名字,一般就是当前app的包名 
  94.      * 
  95.      * @param pid 进程的id 
  96.      * @return 返回进程的名字 
  97.      */  
  98.     private String getAppName(int pid) {  
  99.         String processName = null;  
  100.         ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);  
  101.         List list = activityManager.getRunningAppProcesses();  
  102.         Iterator i = list.iterator();  
  103.         while (i.hasNext()) {  
  104.             ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());  
  105.             try {  
  106.                 if (info.pid == pid) {  
  107.                     // 根据进程的信息获取当前进程的名字  
  108.                     processName = info.processName;  
  109.                     // 返回当前进程名  
  110.                     return processName;  
  111.                 }  
  112.             } catch (Exception e) {  
  113.                 e.printStackTrace();  
  114.             }  
  115.         }  
  116.         // 没有匹配的项,返回为null  
  117.         return null;  
  118.     }  
  119. }  

主界面

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


[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package us.mifeng.guaju.huanxin;  
  2.   
  3. import android.content.Intent;  
  4. import android.support.v7.app.AppCompatActivity;  
  5. import android.os.Bundle;  
  6. import android.text.TextUtils;  
  7. import android.util.Log;  
  8. import android.view.View;  
  9. import android.widget.Button;  
  10. import android.widget.EditText;  
  11. import android.widget.Toast;  
  12.   
  13. import com.hyphenate.EMCallBack;  
  14. import com.hyphenate.chat.EMClient;  
  15.   
  16. public class MainActivity extends AppCompatActivity {  
  17.     // 发起聊天 username 输入框  
  18.     private EditText mChatIdEdit;  
  19.     // 发起聊天  
  20.     private Button mStartChatBtn;  
  21.     // 退出登录  
  22.     private Button mSignOutBtn;  
  23.   
  24.   
  25.     @Override  
  26.     protected void onCreate(Bundle savedInstanceState) {  
  27.         super.onCreate(savedInstanceState);  
  28.   
  29.         // 判断sdk是否登录成功过,并没有退出和被踢,否则跳转到登陆界面  
  30.         if (!EMClient.getInstance().isLoggedInBefore()) {  
  31.             Intent intent = new Intent(MainActivity.this, LoginActivity.class);  
  32.             startActivity(intent);  
  33.             finish();  
  34.             return;  
  35.         }  
  36.   
  37.         setContentView(R.layout.activity_main);  
  38.   
  39.         initView();  
  40.     }  
  41.   
  42.     /** 
  43.      * 初始化界面 
  44.      */  
  45.     private void initView() {  
  46.   
  47.         mChatIdEdit = (EditText) findViewById(R.id.ec_edit_chat_id);  
  48.   
  49.         mStartChatBtn = (Button) findViewById(R.id.ec_btn_start_chat);  
  50.         mStartChatBtn.setOnClickListener(new View.OnClickListener() {  
  51.             @Override  
  52.             public void onClick(View v) {  
  53.                 // 获取我们发起聊天的者的username  
  54.                 String chatId = mChatIdEdit.getText().toString().trim();  
  55.                 if (!TextUtils.isEmpty(chatId)) {  
  56.                     // 获取当前登录用户的 username  
  57.                     String currUsername = EMClient.getInstance().getCurrentUser();  
  58.                     if (chatId.equals(currUsername)) {  
  59.                         Toast.makeText(MainActivity.this"不能和自己聊天", Toast.LENGTH_SHORT).show();  
  60.                         return;  
  61.                     }  
  62.                     // 跳转到聊天界面,开始聊天  
  63.                     Intent intent = new Intent(MainActivity.this, ChatActivity.class);  
  64.                     intent.putExtra("ec_chat_id", chatId);  
  65.                     startActivity(intent);  
  66.                 } else {  
  67.                     Toast.makeText(MainActivity.this"Username 不能为空", Toast.LENGTH_LONG).show();  
  68.                 }  
  69.             }  
  70.         });  
  71.   
  72.         mSignOutBtn = (Button) findViewById(R.id.ec_btn_sign_out);  
  73.         mSignOutBtn.setOnClickListener(new View.OnClickListener() {  
  74.             @Override  
  75.             public void onClick(View v) {  
  76.                 signOut();  
  77.             }  
  78.         });  
  79.     }  
  80.   
  81.     /** 
  82.      * 退出登录 
  83.      */  
  84.     private void signOut() {  
  85.         // 调用sdk的退出登录方法,第一个参数表示是否解绑推送的token,没有使用推送或者被踢都要传false  
  86.         EMClient.getInstance().logout(falsenew EMCallBack() {  
  87.             @Override  
  88.             public void onSuccess() {  
  89.                 Log.i("lzan13""logout success");  
  90.                 // 调用退出成功,结束app  
  91.                 finish();  
  92.             }  
  93.   
  94.             @Override  
  95.             public void onError(int i, String s) {  
  96.                 Log.i("lzan13""logout error " + i + " - " + s);  
  97.             }  
  98.   
  99.             @Override  
  100.             public void onProgress(int i, String s) {  
  101.   
  102.             }  
  103.         });  
  104.     }  
  105. }  
  106.   
  107. }  


登录及注册界面


[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package us.mifeng.guaju.huanxin;  
  2.   
  3. import android.app.Activity;  
  4. import android.app.ProgressDialog;  
  5. import android.content.Intent;  
  6. import android.support.v7.app.AppCompatActivity;  
  7. import android.os.Bundle;  
  8. import android.util.Log;  
  9. import android.view.View;  
  10. import android.widget.Button;  
  11. import android.widget.EditText;  
  12. import android.widget.Toast;  
  13.   
  14. import com.hyphenate.EMCallBack;  
  15. import com.hyphenate.EMError;  
  16. import com.hyphenate.chat.EMClient;  
  17. import com.hyphenate.exceptions.HyphenateException;  
  18.   
  19. public class LoginActivity extends Activity {  
  20.   
  21.     // 弹出框  
  22.     private ProgressDialog mDialog;  
  23.   
  24.     // username 输入框  
  25.     private EditText mUsernameEdit;  
  26.     // 密码输入框  
  27.     private EditText mPasswordEdit;  
  28.   
  29.     // 注册按钮  
  30.     private Button mSignUpBtn;  
  31.     // 登录按钮  
  32.     private Button mSignInBtn;  
  33.   
  34.   
  35.     @Override  
  36.     protected void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.         setContentView(R.layout.activity_login);  
  39.   
  40.         initView();  
  41.     }  
  42.   
  43.     /** 
  44.      * 初始化界面控件 
  45.      */  
  46.     private void initView() {  
  47.         mUsernameEdit = (EditText) findViewById(R.id.ec_edit_username);  
  48.         mPasswordEdit = (EditText) findViewById(R.id.ec_edit_password);  
  49.   
  50.         mSignUpBtn = (Button) findViewById(R.id.ec_btn_sign_up);  
  51.         mSignUpBtn.setOnClickListener(new View.OnClickListener() {  
  52.             @Override  
  53.             public void onClick(View v) {  
  54.                 signUp();  
  55.             }  
  56.         });  
  57.   
  58.         mSignInBtn = (Button) findViewById(R.id.ec_btn_sign_in);  
  59.         mSignInBtn.setOnClickListener(new View.OnClickListener() {  
  60.             @Override  
  61.             public void onClick(View v) {  
  62.                 signIn();  
  63.             }  
  64.         });  
  65.     }  
  66.   
  67.     /** 
  68.      * 注册方法 
  69.      */  
  70.     private void signUp() {  
  71.         // 注册是耗时过程,所以要显示一个dialog来提示下用户  
  72.         mDialog = new ProgressDialog(this);  
  73.         mDialog.setMessage("注册中,请稍后...");  
  74.         mDialog.show();  
  75.   
  76.         new Thread(new Runnable() {  
  77.             @Override  
  78.             public void run() {  
  79.                 try {  
  80.                     String username = mUsernameEdit.getText().toString().trim();  
  81.                     String password = mPasswordEdit.getText().toString().trim();  
  82.                     EMClient.getInstance().createAccount(username, password);  
  83.                     runOnUiThread(new Runnable() {  
  84.                         @Override  
  85.                         public void run() {  
  86.                             if (!LoginActivity.this.isFinishing()) {  
  87.                                 mDialog.dismiss();  
  88.                             }  
  89.                             Toast.makeText(LoginActivity.this"注册成功", Toast.LENGTH_LONG).show();  
  90.                         }  
  91.                     });  
  92.                 } catch (final HyphenateException e) {  
  93.                     e.printStackTrace();  
  94.                     runOnUiThread(new Runnable() {  
  95.                         @Override  
  96.                         public void run() {  
  97.                             if (!LoginActivity.this.isFinishing()) {  
  98.                                 mDialog.dismiss();  
  99.                             }  
  100.                             /** 
  101.                              * 关于错误码可以参考官方api详细说明 
  102.                              * http://www.easemob.com/apidoc/android/chat3.0/classcom_1_1hyphenate_1_1_e_m_error.html 
  103.                              */  
  104.                             int errorCode = e.getErrorCode();  
  105.                             String message = e.getMessage();  
  106.                             Log.d("lzan13", String.format("sign up - errorCode:%d, errorMsg:%s", errorCode, e.getMessage()));  
  107.                             switch (errorCode) {  
  108.                                 // 网络错误  
  109.                                 case EMError.NETWORK_ERROR:  
  110.                                     Toast.makeText(LoginActivity.this"网络错误 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();  
  111.                                     break;  
  112.                                 // 用户已存在  
  113.                                 case EMError.USER_ALREADY_EXIST:  
  114.                                     Toast.makeText(LoginActivity.this"用户已存在 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();  
  115.                                     break;  
  116.                                 // 参数不合法,一般情况是username 使用了uuid导致,不能使用uuid注册  
  117.                                 case EMError.USER_ILLEGAL_ARGUMENT:  
  118.                                     Toast.makeText(LoginActivity.this"参数不合法,一般情况是username 使用了uuid导致,不能使用uuid注册 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();  
  119.                                     break;  
  120.                                 // 服务器未知错误  
  121.                                 case EMError.SERVER_UNKNOWN_ERROR:  
  122.                                     Toast.makeText(LoginActivity.this"服务器未知错误 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();  
  123.                                     break;  
  124.                                 case EMError.USER_REG_FAILED:  
  125.                                     Toast.makeText(LoginActivity.this"账户注册失败 code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();  
  126.                                     break;  
  127.                                 default:  
  128.                                     Toast.makeText(LoginActivity.this"ml_sign_up_failed code: " + errorCode + ", message:" + message, Toast.LENGTH_LONG).show();  
  129.                                     break;  
  130.                             }  
  131.                         }  
  132.                     });  
  133.                 } catch (Exception e) {  
  134.                     e.printStackTrace();  
  135.                 }  
  136.             }  
  137.         }).start();  
  138.     }  
  139.   
  140.     /** 
  141.      * 登录方法 
  142.      */  
  143.     private void signIn() {  
  144.         mDialog = new ProgressDialog(this);  
  145.         mDialog.setMessage("正在登陆,请稍后...");  
  146.         mDialog.show();  
  147.         String username = mUsernameEdit.getText().toString().trim();  
  148.         String password = mPasswordEdit.getText().toString().trim();  
  149.         EMClient.getInstance().login(username, password, new EMCallBack() {  
  150.             /** 
  151.              * 登陆成功的回调 
  152.              */  
  153.             @Override  
  154.             public void onSuccess() {  
  155.                 runOnUiThread(new Runnable() {  
  156.                     @Override  
  157.                     public void run() {  
  158.                         mDialog.dismiss();  
  159.   
  160.                         // 加载所有会话到内存  
  161.                         EMClient.getInstance().chatManager().loadAllConversations();  
  162.                         // 加载所有群组到内存,如果使用了群组的话  
  163.                         // EMClient.getInstance().groupManager().loadAllGroups();  
  164.   
  165.                         // 登录成功跳转界面  
  166.                         Intent intent = new Intent(LoginActivity.this, MainActivity.class);  
  167.                         startActivity(intent);  
  168.                         finish();  
  169.                     }  
  170.                 });  
  171.             }  
  172.   
  173.             /** 
  174.              * 登陆错误的回调 
  175.              * @param i 
  176.              * @param s 
  177.              */  
  178.             @Override  
  179.             public void onError(final int i, final String s) {  
  180.                 runOnUiThread(new Runnable() {  
  181.                     @Override  
  182.                     public void run() {  
  183.                         mDialog.dismiss();  
  184.                         Log.d("lzan13""登录失败 Error code:" + i + ", message:" + s);  
  185.                         /** 
  186.                          * 关于错误码可以参考官方api详细说明 
  187.                          * http://www.easemob.com/apidoc/android/chat3.0/classcom_1_1hyphenate_1_1_e_m_error.html 
  188.                          */  
  189.                         switch (i) {  
  190.                             // 网络异常 2  
  191.                             case EMError.NETWORK_ERROR:  
  192.                                 Toast.makeText(LoginActivity.this"网络错误 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  193.                                 break;  
  194.                             // 无效的用户名 101  
  195.                             case EMError.INVALID_USER_NAME:  
  196.                                 Toast.makeText(LoginActivity.this"无效的用户名 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  197.                                 break;  
  198.                             // 无效的密码 102  
  199.                             case EMError.INVALID_PASSWORD:  
  200.                                 Toast.makeText(LoginActivity.this"无效的密码 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  201.                                 break;  
  202.                             // 用户认证失败,用户名或密码错误 202  
  203.                             case EMError.USER_AUTHENTICATION_FAILED:  
  204.                                 Toast.makeText(LoginActivity.this"用户认证失败,用户名或密码错误 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  205.                                 break;  
  206.                             // 用户不存在 204  
  207.                             case EMError.USER_NOT_FOUND:  
  208.                                 Toast.makeText(LoginActivity.this"用户不存在 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  209.                                 break;  
  210.                             // 无法访问到服务器 300  
  211.                             case EMError.SERVER_NOT_REACHABLE:  
  212.                                 Toast.makeText(LoginActivity.this"无法访问到服务器 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  213.                                 break;  
  214.                             // 等待服务器响应超时 301  
  215.                             case EMError.SERVER_TIMEOUT:  
  216.                                 Toast.makeText(LoginActivity.this"等待服务器响应超时 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  217.                                 break;  
  218.                             // 服务器繁忙 302  
  219.                             case EMError.SERVER_BUSY:  
  220.                                 Toast.makeText(LoginActivity.this"服务器繁忙 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  221.                                 break;  
  222.                             // 未知 Server 异常 303 一般断网会出现这个错误  
  223.                             case EMError.SERVER_UNKNOWN_ERROR:  
  224.                                 Toast.makeText(LoginActivity.this"未知的服务器异常 code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  225.                                 break;  
  226.                             default:  
  227.                                 Toast.makeText(LoginActivity.this"ml_sign_in_failed code: " + i + ", message:" + s, Toast.LENGTH_LONG).show();  
  228.                                 break;  
  229.                         }  
  230.                     }  
  231.                 });  
  232.             }  
  233.   
  234.             @Override  
  235.             public void onProgress(int i, String s) {  
  236.   
  237.             }  
  238.         });  
  239.     }  
  240. }  

界面布局

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

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     xmlns:tools="http://schemas.android.com/tools"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     android:paddingBottom="@dimen/activity_vertical_margin"  
  8.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  9.     android:paddingRight="@dimen/activity_horizontal_margin"  
  10.     android:paddingTop="@dimen/activity_vertical_margin"  
  11.     >  
  12.   
  13.     <LinearLayout  
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="match_parent"  
  16.         android:orientation="vertical">  
  17.   
  18.         <EditText  
  19.             android:id="@+id/ec_edit_chat_id"  
  20.             android:layout_width="match_parent"  
  21.             android:layout_height="wrap_content"  
  22.             android:hint="对方的username"/>  
  23.   
  24.         <Button  
  25.             android:id="@+id/ec_btn_start_chat"  
  26.             android:layout_width="match_parent"  
  27.             android:layout_height="wrap_content"  
  28.             android:text="发起聊天"/>  
  29.   
  30.         <Button  
  31.             android:id="@+id/ec_btn_sign_out"  
  32.             android:layout_width="match_parent"  
  33.             android:layout_height="wrap_content"  
  34.             android:text="退出登录"/>  
  35.     </LinearLayout>  
  36. </RelativeLayout>  

activity_login.xml

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     xmlns:tools="http://schemas.android.com/tools"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     android:paddingBottom="@dimen/activity_vertical_margin"  
  8.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  9.     android:paddingRight="@dimen/activity_horizontal_margin"  
  10.     android:paddingTop="@dimen/activity_vertical_margin"  
  11.     >  
  12.   
  13.     <LinearLayout  
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="match_parent"  
  16.         android:orientation="vertical">  
  17.   
  18.         <EditText  
  19.             android:id="@+id/ec_edit_username"  
  20.             android:layout_width="match_parent"  
  21.             android:layout_height="wrap_content"  
  22.             android:hint="username"/>  
  23.   
  24.         <EditText  
  25.             android:id="@+id/ec_edit_password"  
  26.             android:layout_width="match_parent"  
  27.             android:layout_height="wrap_content"  
  28.             android:hint="password"/>  
  29.   
  30.         <Button  
  31.             android:id="@+id/ec_btn_sign_up"  
  32.             android:layout_width="match_parent"  
  33.             android:layout_height="wrap_content"  
  34.             android:text="注册"/>  
  35.   
  36.         <Button  
  37.             android:id="@+id/ec_btn_sign_in"  
  38.             android:layout_width="match_parent"  
  39.             android:layout_height="wrap_content"  
  40.             android:text="登录"/>  
  41.     </LinearLayout>  
  42. </RelativeLayout>  
activity_chat.xml
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     xmlns:tools="http://schemas.android.com/tools"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     android:paddingBottom="@dimen/activity_vertical_margin"  
  8.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  9.     android:paddingRight="@dimen/activity_horizontal_margin"  
  10.     android:paddingTop="@dimen/activity_vertical_margin"  
  11.     >  
  12.   
  13.     <!--输入框-->  
  14.     <RelativeLayout  
  15.         android:id="@+id/ec_layout_input"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_alignParentBottom="true">  
  19.   
  20.         <Button  
  21.             android:id="@+id/ec_btn_send"  
  22.             android:layout_width="wrap_content"  
  23.             android:layout_height="wrap_content"  
  24.             android:layout_alignParentRight="true"  
  25.             android:text="Send"/>  
  26.   
  27.         <EditText  
  28.             android:id="@+id/ec_edit_message_input"  
  29.             android:layout_width="match_parent"  
  30.             android:layout_height="wrap_content"  
  31.             android:layout_alignParentLeft="true"  
  32.             android:layout_toLeftOf="@id/ec_btn_send"/>  
  33.     </RelativeLayout>  
  34.   
  35.     <!--展示消息内容-->  
  36.     <TextView  
  37.         android:id="@+id/ec_text_content"  
  38.         android:layout_width="match_parent"  
  39.         android:layout_height="match_parent"  
  40.         android:layout_above="@id/ec_layout_input"  
  41.         android:maxLines="15"  
  42.         android:scrollbars="vertical"/>  
  43. </RelativeLayout>  

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

补上ChatActivity的代码

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package us.mifeng.guaju.huanxin;  
  2.   
  3. import android.os.Bundle;  
  4. import android.os.Handler;  
  5. import android.os.Message;  
  6. import android.support.v7.app.AppCompatActivity;  
  7. import android.text.TextUtils;  
  8. import android.text.method.ScrollingMovementMethod;  
  9. import android.util.Log;  
  10. import android.view.View;  
  11. import android.widget.Button;  
  12. import android.widget.EditText;  
  13. import android.widget.TextView;  
  14.   
  15. import com.hyphenate.EMCallBack;  
  16. import com.hyphenate.EMMessageListener;  
  17. import com.hyphenate.chat.EMClient;  
  18. import com.hyphenate.chat.EMCmdMessageBody;  
  19. import com.hyphenate.chat.EMConversation;  
  20. import com.hyphenate.chat.EMMessage;  
  21. import com.hyphenate.chat.EMTextMessageBody;  
  22.   
  23. import java.util.List;  
  24.   
  25. /** 
  26.  * Created by guaju on 2016/9/12. 
  27.  */  
  28. public class ChatActivity extends AppCompatActivity implements EMMessageListener {  
  29.   
  30.     // 聊天信息输入框  
  31.     private EditText mInputEdit;  
  32.     // 发送按钮  
  33.     private Button mSendBtn;  
  34.   
  35.     // 显示内容的 TextView  
  36.     private TextView mContentText;  
  37.   
  38.     // 消息监听器  
  39.     private EMMessageListener mMessageListener;  
  40.     // 当前聊天的 ID  
  41.     private String mChatId;  
  42.     // 当前会话对象  
  43.     private EMConversation mConversation;  
  44.   
  45.   
  46.     @Override  
  47.     protected void onCreate(Bundle savedInstanceState) {  
  48.         super.onCreate(savedInstanceState);  
  49.         setContentView(R.layout.activity_chat);  
  50.   
  51.         // 获取当前会话的username(如果是群聊就是群id)  
  52.         mChatId = getIntent().getStringExtra("ec_chat_id");  
  53.         mMessageListener = this;  
  54.   
  55.         initView();  
  56.         initConversation();  
  57.     }  
  58.   
  59.     /** 
  60.      * 初始化界面 
  61.      */  
  62.     private void initView() {  
  63.         mInputEdit = (EditText) findViewById(R.id.ec_edit_message_input);  
  64.         mSendBtn = (Button) findViewById(R.id.ec_btn_send);  
  65.         mContentText = (TextView) findViewById(R.id.ec_text_content);  
  66.         // 设置textview可滚动,需配合xml布局设置  
  67.         mContentText.setMovementMethod(new ScrollingMovementMethod());  
  68.   
  69.         // 设置发送按钮的点击事件  
  70.         mSendBtn.setOnClickListener(new View.OnClickListener() {  
  71.             @Override  
  72.             public void onClick(View v) {  
  73.                 String content = mInputEdit.getText().toString().trim();  
  74.                 if (!TextUtils.isEmpty(content)) {  
  75.                     mInputEdit.setText("");  
  76.                     // 创建一条新消息,第一个参数为消息内容,第二个为接受者username  
  77.                     EMMessage message = EMMessage.createTxtSendMessage(content, mChatId);  
  78.                     // 将新的消息内容和时间加入到下边  
  79.                     mContentText.setText(mContentText.getText() + "\n" + content + " -> " + message.getMsgTime());  
  80.                     // 调用发送消息的方法  
  81.                     EMClient.getInstance().chatManager().sendMessage(message);  
  82.                     // 为消息设置回调  
  83.                     message.setMessageStatusCallback(new EMCallBack() {  
  84.                         @Override  
  85.                         public void onSuccess() {  
  86.                             // 消息发送成功,打印下日志,正常操作应该去刷新ui  
  87.                             Log.i("lzan13""send message on success");  
  88.                         }  
  89.   
  90.                         @Override  
  91.                         public void onError(int i, String s) {  
  92.                             // 消息发送失败,打印下失败的信息,正常操作应该去刷新ui  
  93.                             Log.i("lzan13""send message on error " + i + " - " + s);  
  94.                         }  
  95.   
  96.                         @Override  
  97.                         public void onProgress(int i, String s) {  
  98.                             // 消息发送进度,一般只有在发送图片和文件等消息才会有回调,txt不回调  
  99.                         }  
  100.                     });  
  101.                 }  
  102.             }  
  103.         });  
  104.     }  
  105.   
  106.     /** 
  107.      * 初始化会话对象,并且根据需要加载更多消息 
  108.      */  
  109.     private void initConversation() {  
  110.   
  111.         /** 
  112.          * 初始化会话对象,这里有三个参数么, 
  113.          * 第一个表示会话的当前聊天的 useranme 或者 groupid 
  114.          * 第二个是绘画类型可以为空 
  115.          * 第三个表示如果会话不存在是否创建 
  116.          */  
  117.         mConversation = EMClient.getInstance().chatManager().getConversation(mChatId, nulltrue);  
  118.         // 设置当前会话未读数为 0  
  119.         mConversation.markAllMessagesAsRead();  
  120.         int count = mConversation.getAllMessages().size();  
  121.         if (count < mConversation.getAllMsgCount() && count < 20) {  
  122.             // 获取已经在列表中的最上边的一条消息id  
  123.             String msgId = mConversation.getAllMessages().get(0).getMsgId();  
  124.             // 分页加载更多消息,需要传递已经加载的消息的最上边一条消息的id,以及需要加载的消息的条数  
  125.             mConversation.loadMoreMsgFromDB(msgId, 20 - count);  
  126.         }  
  127.         // 打开聊天界面获取最后一条消息内容并显示  
  128.         if (mConversation.getAllMessages().size() > 0) {  
  129.             EMMessage messge = mConversation.getLastMessage();  
  130.             EMTextMessageBody body = (EMTextMessageBody) messge.getBody();  
  131.             // 将消息内容和时间显示出来  
  132.             mContentText.setText(body.getMessage() + " - " + mConversation.getLastMessage().getMsgTime());  
  133.         }  
  134.     }  
  135.   
  136.     /** 
  137.      * 自定义实现Handler,主要用于刷新UI操作 
  138.      */  
  139.     Handler mHandler = new Handler() {  
  140.         @Override  
  141.         public void handleMessage(Message msg) {  
  142.             switch (msg.what) {  
  143.                 case 0:  
  144.                     EMMessage message = (EMMessage) msg.obj;  
  145.                     // 这里只是简单的demo,也只是测试文字消息的收发,所以直接将body转为EMTextMessageBody去获取内容  
  146.                     EMTextMessageBody body = (EMTextMessageBody) message.getBody();  
  147.                     // 将新的消息内容和时间加入到下边  
  148.                     mContentText.setText(mContentText.getText() + "\n" + body.getMessage() + " <- " + message.getMsgTime());  
  149.                     break;  
  150.             }  
  151.         }  
  152.     };  
  153.   
  154.     @Override  
  155.     protected void onResume() {  
  156.         super.onResume();  
  157.         // 添加消息监听  
  158.         EMClient.getInstance().chatManager().addMessageListener(mMessageListener);  
  159.     }  
  160.   
  161.     @Override  
  162.     protected void onStop() {  
  163.         super.onStop();  
  164.         // 移除消息监听  
  165.         EMClient.getInstance().chatManager().removeMessageListener(mMessageListener);  
  166.     }  
  167.     /** 
  168.      * --------------------------------- Message Listener ------------------------------------- 
  169.      * 环信消息监听主要方法 
  170.      */  
  171.     /** 
  172.      * 收到新消息 
  173.      * 
  174.      * @param list 收到的新消息集合 
  175.      */  
  176.     @Override  
  177.     public void onMessageReceived(List<EMMessage> list) {  
  178.         // 循环遍历当前收到的消息  
  179.         for (EMMessage message : list) {  
  180.             if (message.getFrom().equals(mChatId)) {  
  181.                 // 设置消息为已读  
  182.                 mConversation.markMessageAsRead(message.getMsgId());  
  183.   
  184.                 // 因为消息监听回调这里是非ui线程,所以要用handler去更新ui  
  185.                 Message msg = mHandler.obtainMessage();  
  186.                 msg.what = 0;  
  187.                 msg.obj = message;  
  188.                 mHandler.sendMessage(msg);  
  189.             } else {  
  190.                 // 如果消息不是当前会话的消息发送通知栏通知  
  191.             }  
  192.         }  
  193.     }  
  194.   
  195.     /** 
  196.      * 收到新的 CMD 消息 
  197.      * 
  198.      * @param list 
  199.      */  
  200.     @Override  
  201.     public void onCmdMessageReceived(List<EMMessage> list) {  
  202.         for (int i = 0; i < list.size(); i++) {  
  203.             // 透传消息  
  204.             EMMessage cmdMessage = list.get(i);  
  205.             EMCmdMessageBody body = (EMCmdMessageBody) cmdMessage.getBody();  
  206.             Log.i("lzan13", body.action());  
  207.         }  
  208.     }  
  209.   
  210.     /** 
  211.      * 收到新的已读回执 
  212.      * 
  213.      * @param list 收到消息已读回执 
  214.      */  
  215.     @Override  
  216.     public void onMessageReadAckReceived(List<EMMessage> list) {  
  217.     }  
  218.   
  219.     /** 
  220.      * 收到新的发送回执 
  221.      * TODO 无效 暂时有bug 
  222.      * 
  223.      * @param list 收到发送回执的消息集合 
  224.      */  
  225.     @Override  
  226.     public void onMessageDeliveryAckReceived(List<EMMessage> list) {  
  227.     }  
  228.   
  229.     /** 
  230.      * 消息的状态改变 
  231.      * 
  232.      * @param message 发生改变的消息 
  233.      * @param object  包含改变的消息 
  234.      */  
  235.     @Override  
  236.     public void onMessageChanged(EMMessage message, Object object) {  
  237.     }  
0 0
原创粉丝点击