一、标题栏控件 EaseTitleBar 使用

在 xml 中声明标题栏控件,可以在 xml 直接设置标题内容,左右图片,在 Java 文件中亦可以设置这些属性以及相关的点击事件。

android聊天界面源码 android 聊天界面_android聊天界面源码

<com.hyphenate.easeui.widget.EaseTitleBar
    android:id="@+id/title_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:titleBarLeftImage="@drawable/ease_mm_title_back" 
    //该控件在xml中也有很多属性(图片、文本、toolbar)
/> 

titleBar = (EaseTitleBar) findViewById(R.id.title_bar);
titleBar.setTitle("张建国");
titleBar.setRightImageResource(R.drawable.ease_mm_title_remove);

可以调用 fragment 里的 hideTitleBar() 隐藏标题栏

限定符和类型

方法和说明

static float

dip2px(android.content.Context context, float value)

dip to px

android.widget.RelativeLayout

getLeftLayout() 

android.widget.ImageView

getRightImage() 

android.widget.RelativeLayout

getRightLayout() 

android.widget.TextView

getRightText() 

android.widget.TextView

getTitle() 

Toolbar

getToolbar() 

void

onClick(android.view.View v) 

protected void

onSizeChanged(int w, int h, int oldw, int oldh) 

void

setBackgroundColor(int color) 

void

setLeftImageResource(int resId) 

void

setLeftLayoutClickListener(android.view.View.OnClickListener listener) 

void

setLeftLayoutVisibility(int visibility) 

void

setOnBackPressListener(EaseTitleBar.OnBackPressListener

设置返回按钮的点击事件

void

setOnRightClickListener(EaseTitleBar.OnRightClickListener

设置右侧更多的点击事件

void

setRightImageResource(int resId) 

void

setRightLayoutClickListener(android.view.View.OnClickListener listener) 

void

setRightLayoutVisibility(int visibility) 

void

setRightTitle(java.lang.String title) 

void

setRightTitleResource(int title) 

void

setTitle(java.lang.String title) 

void

setTitlePosition(EaseTitleBar.TitlePosition

设置标题位置

void

setToolbarCustomColor(int colorId) 

void

setToolbarCustomColorDefault(int colorId) 

static float

sp2px(android.content.Context context, float value)

sp to px

二、环信异常的错误码

本文介绍环信即时通讯 Android SDK 中接口调用或者回调中的错误码。可以根据具体错误码判断具体错误原因。

Android 中错误码的类为 EMError。

错误码

错误信息

描述

可能原因

0

EM_NO_ERROR

操作成功

提示操作成功。

1

GENERAL_ERROR

默认未区分类型的错误

提示 SDK 内部未正确初始化,或者请求服务器时未识别出具体原因的错误。

2

NETWORK_ERROR

网络错误

无网络服务时会回调此错误,表示 SDK 与服务器的连接已断开。

4

EXCEED_SERVICE_LIMIT

超过服务限制

超过服务版本的数量限制,比如创建的用户 ID 数量超过购买服务的限制时提示该错误。

5

SERVICE_ARREARAGES

服务欠费

该错误码已废弃。

100

INVALID_APP_KEY

App Key 不合法

用户的 App Key 格式不正确。

101

INVALID_USER_NAME

用户 ID 不正确

一般是用户 ID 为空时提示该错误,比如使用邀请好友 API 时 username 参数为空字符。

102

INVALID_PASSWORD

用户密码不正确

登录时提供的密码为空或不正确。

103

INVALID_URL

URL 不正确

该错误码已废弃。

104

INVALID_TOKEN

用户 token 不正确

登录时提供的 token 为空或不正确。

105

USER_NAME_TOO_LONG

用户名过长

用户名长度限制 64 个字节。

108

TOKEN_EXPIRED

声网 token 已过期

超出声网 token 有效期时间。

109

TOKEN_WILL_EXPIRE

声网 token 即将过期

超出声网 token 有效期一半时间时会开始回调此错误码。

200

USER_ALREADY_LOGIN

用户已经登录

同一个用户 ID 已经登录。

201

USER_NOT_LOGIN

用户未登录

如果未登录成功时发送消息,或者使用群组操作的 API,SDK 会提示该错误。

202

USER_AUTHENTICATION_FAILED

用户鉴权失败

一般是 token 鉴权失败或者 token 已经过期。

203

USER_ALREADY_EXIST

用户已经存在

注册用户 ID 时如果该 ID 已经存在会提示该错误。

204

USER_NOT_FOUND

用户不存在

比如登录或者获取用户会话列表时用户 ID 不存在。

205

USER_ILLEGAL_ARGUMENT

用户参数不正确

比如创建用户 ID 时不符合格式要求, 或者更新用户属性时用户参数为空等。

206

USER_LOGIN_ANOTHER_DEVICE

用户在其他设备登录

如果未开启多设备登录,则在其他设备登录会将当前登录的设备踢下线,用户会收到此错误。

207

USER_REMOVED

用户已经被注销

如果登录用户被从管理后台删除 ID 则会收到此错误。

208

USER_REG_FAILED

用户注册失败

注册用户 ID 时失败,比如未开启开放注册功能等原因。

209

PUSH_UPDATECONFIGS_FAILED

更新推送配置错误

用户更新推送昵称,设置免推送配置时失败。

210

USER_PERMISSION_DENIED

用户无权限

例如如果用户被封禁,发送消息时会提示该错误。

211

USER_BINDDEVICETOKEN_FAILED

用户更新推送 token 错误

该错误码已废弃。

212

USER_UNBIND_DEVICETOKEN_FAILED

用户更新推送 token 错误

该错误码已废弃。

213

USER_BIND_ANOTHER_DEVICE

用户已经在另外设备登录

如果用户设置为先登录的设备优先,则后登录设备登录失败并提示该错误。

214

USER_LOGIN_TOO_MANY_DEVICES

用户登录设备数超过限制

用户同一 ID 登录设备数量超过限制提示该错误。

215

USER_MUTED

用户在群组聊天室中被禁言

用户被禁言后发送消息时提示该错误。

216

USER_KICKED_BY_CHANGE_PASSWORD

用户密码更新

当前登录的用户密码被修改后,当前登录会断开并提示该错误。

217

USER_KICKED_BY_OTHER_DEVICE

用户被踢下线

开启多设备后,如果用户在其他设备上通过调用 API 或者管理后台将当前设备登录的 ID 强制退出登录,SDK 会提示该错误。

218

USER_ALREADY_LOGIN_ANOTHER

其他用户已登录

SDK 未退出登录前又被使用不同的账户登录。

219

USER_MUTED_BY_ADMIN

用户被禁言

用户在当前 app key 被禁言后发送消息时提示该错误。

220

USER_DEVICE_CHANGED

用户登录设备与上次不一致

用户登录设备与上次登录设备不一致,需要用户重新登录,注意:默认会允许用户登录,踢掉另一个设备上的登录,此 error 在打开不踢掉另外设备上的登录开关后才会生效。

221

USER_NOT_ON_ROSTER

非好友禁止发消息

开通非好友禁止发消息后,非好友间发消息提示此错误。若要开通该功能,请联系商务咨询。

300

SERVER_NOT_REACHABLE

请求服务失败

发送或撤回消息时,如果 SDK 与消息服务器未保持连接,会返回该错误;操作群组、好友等请求时,如果因网络连接太差而不成功,也会返回该错误。

301

SERVER_TIMEOUT

请求服务超时

如果调用 API 在特定时间内服务器未响应则返回该错误,一般是 30 秒或者 60 秒。

302

SERVER_BUSY

服务器忙碌

服务器当前忙碌会返回该错误,建议稍后再尝试请求。

303

SERVER_UNKNOWN_ERROR

服务请求的通用错误码

当请求服务器未成功时的默认错误,该错误发生情况较多,需要根据日志进一步排查。

304

SERVER_GET_DNSLIST_FAILED

获取服务器配置信息错误

SDK 获取当前应用的服务器配置时失败。

305

SERVER_SERVICE_RESTRICTED

当前 app 被禁用

如果 app 因为某种原因被禁用时会返回该错误。

400

FILE_NOT_FOUND

文件未找到

当用户获取不到日志文件,或者下载附件失败时提示该错误。

401

FILE_INVALID

文件异常

当上传消息附件或者群组共享文件时可能会提示该错误。

402

FILE_UPLOAD_FAILED

上传文件错误

上传消息附件失败时提示该错误。

403

FILE_DOWNLOAD_FAILED

下载文件错误

下载消息附件失败时提示该错误。

404

FILE_DELETE_FAILED

删除文件错误

通过 API 获取日志文件时会将旧的日志文件删除,如果删除失败提示该错误。

405

FILE_TOO_LARGE

文件太大

消息附件或群共享文件超过文件大小限制时提示该错误。

406

FILE_CONTENT_IMPROPER

文件内容不合规

消息附件或群共享文件内容不合规时提示该错误。

500

MESSAGE_INVALID

消息异常错误

如果要发送的消息为空,或者消息 ID 为空,或者消息的发送方 ID 与当前登录 ID 不同则会提示该错误。

501

MESSAGE_INCLUDE_ILLEGAL_CONTENT

消息含有非法内容

如果消息被过滤系统识别为非法消息时返回该错误。

502

MESSAGE_SEND_TRAFFIC_LIMIT

消息限流

发送消息过快时提示该错误,建议降低频率或者减少消息内容的大小。

503

MESSAGE_ENCRYPTION_ERROR

消息加密错误

该错误码已废弃。

504

MESSAGE_RECALL_TIME_LIMIT

消息撤回超时错误

如果超过消息撤回允许的时间尝试撤回时提示该错误。

505

SERVICE_NOT_ENABLED

服务未开启

尝试使用某些未开通的功能时提示该错误。

506

MESSAGE_EXPIRED

消息已过期

发送群组回执时如果已经超过时间限制 (默认 3 天) 会提示该错误。

507

MESSAGE_ILLEGAL_WHITELIST

用户未在白名单中

如果群组聊天室开启全员禁言,且用户未在白名单中发送消息时提示该错误。

508

MESSAGE_EXTERNAL_LOGIC_BLOCKED

消息执行发送前回调,被用户自己的逻辑拦截

发送的消息被用户自己的服务器定义的规则拦截掉时提示该错误。

600

GROUP_INVALID_ID

群组 ID 异常

使用群组相关 API,提供的群组 ID 为空时提示该错误。

601

GROUP_ALREADY_JOINED

已在该群组中

调用加入群组的 API 时如果已经在该群组中则提示该错误。

602

GROUP_NOT_JOINED

未加入该群组

尝试在未加入的群组中发送消息或进行群组操作时提示该错误。

603

GROUP_PERMISSION_DENIED

无权限的群组操作

没有权限进行群组操作,比如群组成员不能设置群组管理员。

604

GROUP_MEMBERS_FULL

群组已满

群组已经达到人数上限。

605

GROUP_NOT_EXIST

群组不存在

尝试对不存在的群组进行操作时提示该错误。

700

CHATROOM_INVALID_ID

聊天室 ID 异常

使用聊天室相关 API,提供的聊天室 ID 为空时提示该错误。

701

CHATROOM_ALREADY_JOINED

已在该聊天室中

调用加入聊天室的 API 时如果已经在该聊天室中则提示该错误。

702

CHATROOM_NOT_JOINED

未加入该聊天室

尝试在未加入的聊天室中发送消息或进行聊天室操作时提示该错误。

703

CHATROOM_PERMISSION_DENIED

无权限的聊天室操作

没有权限进行聊天室操作,比如聊天室成员不能设置聊天室管理员。

704

CHATROOM_MEMBERS_FULL

聊天室已满

聊天室已经达到人数上限。

705

CHATROOM_NOT_EXIST

聊天室不存在

尝试对不存在的聊天室进行操作时提示该错误。

900

PUSH_NOT_SUPPORT

第三方推送不支持

如果用户配置的第三方推送在当前设备上不支持,会提示该错误。

901

PUSH_BIND_FAILED

绑定第三方推送 token 失败

如果将第三方推送 token 上传到服务器失败时会返回该错误。

902

PUSH_UNBIND_FAILED

解绑第三方推送 token 失败

如果解绑第三方推送 token 失败会提示该错误。

三、登录注册界面

效果演示:

android聊天界面源码 android 聊天界面_android studio_02

 

登录界面主要分为四个步骤:

  • 页面布局
  • 环信注册
  • 创建用户账号信息数据库
  • 环信登录

3.1 登录界面布局:activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".controller.activity.LoginActivity">

    <com.hyphenate.easeui.widget.EaseTitleBar
        android:id="@+id/login_titleBar"
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:background="@color/blue"
        app:titleBarTitleTextSize="30dp"
        app:titleBarTitleTextColor="@color/black"
        app:titleBarTitle="登录"
        >
    </com.hyphenate.easeui.widget.EaseTitleBar>

    <TextView
        android:layout_marginTop="40dp"
        android:layout_marginBottom="40dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="环信 SDK"
        android:textSize="40sp"
        android:layout_gravity="center"
        />

     <LinearLayout
         android:layout_margin="20dp"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal">
         <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textSize="25sp"
             android:text="用户名:"/>

         <EditText
             android:id="@+id/login_name"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"/>

     </LinearLayout>

    <LinearLayout
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="25sp"
            android:text="密    码:"/>

        <EditText
            android:id="@+id/login_password"
            android:inputType="textPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    </LinearLayout>


    <CheckBox
        android:id="@+id/checkbox_password"
        android:layout_marginEnd="20dp"
        android:layout_gravity="end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="显示密码"/>

    <LinearLayout
        android:layout_margin="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/bt_register"
            android:text="注册"
            android:layout_marginEnd="10dp"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@+id/bt_login"
            android:text="登录"
            android:layout_marginStart="10dp"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>

    </LinearLayout>

</LinearLayout>

一些简单的说明: 

  1. EaseTitleBar 在最开始就有讲解,就是一个简单的标题列使用。
  2. 如何设置密码的 EditText 显示加密:
  • 早期:使用android:password="true"  已经弃用
  • 目前:使用android:inputType="textPassword"
//EditText控件inputType的使用

//文本类型,多为大写、小写和数字符号。  
android:inputType="none"//输入普通字符 
android:inputType="text"//输入普通字符 
android:inputType="textCapCharacters"//输入普通字符 
android:inputType="textCapWords"//单词首字母大小 
android:inputType="textCapSentences"//仅第一个字母大小 
android:inputType="textAutoCorrect"//前两个自动完成 
android:inputType="textAutoComplete"//前两个自动完成 
android:inputType="textMultiLine"//多行输入 
android:inputType="textImeMultiLine"//输入法多行(不一定支持) 
android:inputType="textNoSuggestions"//不提示 
android:inputType="textUri"//URI格式 
android:inputType="textEmailAddress"//电子邮件地址格式 
android:inputType="textEmailSubject"//邮件主题格式 
android:inputType="textShortMessage"//短消息格式 
android:inputType="textLongMessage"//长消息格式 
android:inputType="textPersonName"//人名格式 
android:inputType="textPostalAddress"//邮政格式 
android:inputType="textPassword"//密码格式 
android:inputType="textVisiblePassword"//密码可见格式 
android:inputType="textWebEditText"//作为网页表单的文本格式 
android:inputType="textFilter"//文本筛选格式 
android:inputType="textPhonetic"//拼音输入格式 

//数值类型 
android:inputType="number"//数字格式 
android:inputType="numberSigned"//有符号数字格式 
android:inputType="numberDecimal"//可以带小数点的浮点格式 
android:inputType="phone"//拨号键盘 
android:inputType="datetime"//日期+时间格式 
android:inputType="date"//日期键盘 
android:inputType="time"//时间键盘

3.2 登录注册功能实现:LoginActivity.java

主要实现了一下四个功能:

  • 浅试了一下EaseTitleBar
  • 实现点击ChecBox显示密码的功能
  • 注册的业务逻辑
  • 登录的业务逻辑
public class LoginActivity extends Activity {

    private EaseTitleBar easeTitleBar;
    private EditText et_name,et_pwd;
    private CheckBox checkBox;
    private Button bt_register,bt_login;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        //初始化控件
        initView();
        //初始化监听
        initListener();
        //尝试玩弄一下EaseTitleBar
        initEaseTitleBar();
        //实现点击显示密码功能
        initPwdShow();
    }

    //实现点击显示密码功能
    private void initPwdShow() {

        checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if(checkBox.isChecked()){
                et_pwd.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); //如果被选中则显示密码
            }else {

                et_pwd.setTransformationMethod(PasswordTransformationMethod.getInstance()); //如果没选中CheckBox则隐藏密码
            }
            et_pwd.setSelection(et_pwd.getText().length());   //TextView默认光标在最左端,这里控制光标在最右端
        });

    }

    //尝试玩弄一下EaseTitleBar
    private void initEaseTitleBar() {
        //可以看具体的文档
        easeTitleBar.setTitle("杨文杰");
    }

    //初始化控件
    private void initView() {
        easeTitleBar = (EaseTitleBar) findViewById(R.id.login_titleBar);
        et_name = (EditText) findViewById(R.id.login_name);
        et_pwd = (EditText) findViewById(R.id.login_password);
        checkBox = (CheckBox) findViewById(R.id.checkbox_password);
        bt_register = (Button) findViewById(R.id.bt_register);
        bt_login = (Button) findViewById(R.id.bt_login);
    }

    //初始化监听
    private void initListener() {
        bt_register.setOnClickListener(v -> {
            //注册的业务逻辑
            regist();
        });


        bt_login.setOnClickListener(v->{
            //登录的业务逻辑
            login();
        });
    }


    //登录的业务逻辑
    private void login() {
        // 1.获取输入的用户名和密码
        String loginName = et_name.getText().toString();
        String loginPwd = et_pwd.getText().toString();


        // 2.校验输入的用户名和密码
        if(TextUtils.isEmpty(loginName)||TextUtils.isEmpty(loginPwd)){
            Toast.makeText(LoginActivity.this,"输入的用户名和密码不可以为空",Toast.LENGTH_SHORT).show();
            return;
        }
        // 3.登录逻辑处理
        Model.getInstance().getGlobalThreadPool().execute(() -> {
            //去环信服务器登录
            EMClient.getInstance().login(loginName, loginPwd, new EMCallBack() {
                //登录成功后的处理

                @Override
                public void onSuccess() {
                    //对模型层数据的处理
                    Model.getInstance().loginSuccess();
                    //保存用户账户信息到本地数据库
                    Model.getInstance().getUserAccountDao().addAccount(new UserInfo(loginName));

                    runOnUiThread(() -> {
                        //提示登录成功
                        Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
                        //跳转到主界面
                        Intent intent = new Intent(LoginActivity.this,MainActivity.class);
                        startActivity(intent);
                        //登录成功后,登录界面就可以销毁了。
                        finish();
                    });
                    
                }

                //登录失败的处理
                @Override
                public void onError(int code, String error) {
                    runOnUiThread(() -> {
                        //提示登录失败
                        Toast.makeText(LoginActivity.this, "登录失败"+error+code, Toast.LENGTH_SHORT).show();

                    });

                }

                //登录过程中的处理
                @Override
                public void onProgress(int progress, String status) {

                }
            });
        });
    }

    //注册的业务逻辑
    private void regist() {
        // 1.获取输入的用户名和密码
        String registName = et_name.getText().toString();
        String registPwd = et_pwd.getText().toString();
        // 2.校验输入的用户名和密码
        if(TextUtils.isEmpty(registName)||TextUtils.isEmpty(registPwd)){
            Toast.makeText(LoginActivity.this,"输入的用户名和密码不可以为空",Toast.LENGTH_SHORT).show();
            //防止进行以下逻辑
            return;
        }

        // 3.去服务器去注册账号(目前直接去环信的服务器,后期会使用app的服务器)
        Model.getInstance().getGlobalThreadPool().execute(() -> {
            try {
                //去环信服务器注册账号
                EMClient.getInstance().createAccount(registName,registPwd);
                //注册成功,更新UI弹出吐司(显然要去子线程中更新UI)
                runOnUiThread(() -> {
                    Toast.makeText(LoginActivity.this, "注册成功", Toast.LENGTH_SHORT).show();
                });
            } catch (HyphenateException e) {
                e.printStackTrace();
                runOnUiThread(() -> {
                    Toast.makeText(LoginActivity.this, "注册失败"+e, Toast.LENGTH_SHORT).show();
                });
            }
        });
    }
}

上面的注释细节说的清楚,说点其他需要了解的。

  1. 注册失败后:通过返回的异常 HyphenateException e 来进行相应的提醒操作
  2. 登录失败后:会返回一个 int 的状态码和一个 String 的错误信息(详情看本章第二节)

3.3 创建用户账号信息数据库

目的是为了:用户登录成功后将用户信息保存到本地

主要分为以下四个步骤:

  1. 创建用户bean类
  2. 创建用户账号数据库
  3. 创建表类
  4. 创建数据库操作类

3.3.1 创建用户bean类 UserInfo.java

//用户账号信息的bean
public class UserInfo {

    private String name;// 用户名称
    private String huanxingID;// 环信ID
    private String nick;// 用户的名称
    private String photo;// 用户头像

    //无参构造器
    public UserInfo() {
    }

    //构造器
    public UserInfo(String name) {
        this.name = name;
        this.huanxingID = name;
        this.nick = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHuanxingID() {
        return huanxingID;
    }

    public void setHuanxingID(String huanxingID) {
        this.huanxingID = huanxingID;
    }

    public String getNick() {
        return nick;
    }

    public void setNick(String nick) {
        this.nick = nick;
    }

    public String getPhoto() {
        return photo;
    }

    public void setPhoto(String photo) {
        this.photo = photo;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "name='" + name + '\'' +
                ", huanxingID='" + huanxingID + '\'' +
                ", nick='" + nick + '\'' +
                ", photo='" + photo + '\'' +
                '}';
    }
}

这里很粗糙的传入了一个name参数的构造器,是为了方便之后的操作。

3.3.2 创建用户账号数据库 UserAccountDB.java

public class UserAccountDB extends SQLiteOpenHelper {
    //构造
    public UserAccountDB(@Nullable Context context) {
        super(context, "account.db", null, 1);
    }

    //数据库创建的时候调用
    @Override
    public void onCreate(SQLiteDatabase db) {
        //创建创建数据库表的语句
        db.execSQL(UserAccountTable.CREATE_TAB);
    }

    //数据库更新的时候调用(版本号)
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

3.3.3 创建表类 UserAccountTable.java

这里创建一个表类:在后面你就会发现有大大地好处。

public class UserAccountTable {
    public static final String TAB_NAME = "tab_account";
    public static final String COL_NAME = "name";
    public static final String COL_HXID = "huanxingID";
    public static final String COL_NICK = "nick";
    public static final String COL_PHOTO = "photo";

    public static final String CREATE_TAB = "create table "
            + TAB_NAME +" ("
            + COL_HXID +" text primary key,"
            + COL_NAME +" text,"
            + COL_NICK +" text,"
            + COL_PHOTO +" text);";

}

注意这里的CREATE_TAB代表的是一个sql语句,不要在写的时候出错。

3.3.3 创建数据库操作类 UserAccountDao.java

//用户账号数据的操作类
public class UserAccountDao {

    private final UserAccountDB mHelper;

    public UserAccountDao(Context context) {
        mHelper =  new UserAccountDB(context);
    }

    //添加用户到数据库
    public void addAccount(UserInfo user){
        //获取数据库对象
        SQLiteDatabase db = mHelper.getWritableDatabase();
        //执行添加操作
        ContentValues values=new ContentValues();
        values.put(UserAccountTable.COL_HXID,user.getHuanxingID());
        values.put(UserAccountTable.COL_NAME,user.getName());
        values.put(UserAccountTable.COL_NICK,user.getNick());
        values.put(UserAccountTable.COL_PHOTO,user.getPhoto());

        db.replace(UserAccountTable.TAB_NAME,null,values);
    }

    //根据环信id获取所有用户信息
    public UserInfo getAccountByHxId(String huanxingID){
        //获取数据库对象
        SQLiteDatabase db= mHelper.getReadableDatabase();
        //执行查询语句
        String sql = "select * from " + UserAccountTable.TAB_NAME+" where "+UserAccountTable.COL_HXID+"=?";
        Cursor cursor = db.rawQuery(sql, new String[]{huanxingID});

        UserInfo  userInfo=null;
        if(cursor.moveToNext()){
            userInfo = new UserInfo();

            //封装对象
            userInfo.setHuanxingID(cursor.getString(cursor.getColumnIndex(UserAccountTable.COL_HXID)));
            userInfo.setName(cursor.getString(cursor.getColumnIndex(UserAccountTable.COL_NAME)));
            userInfo.setNick(cursor.getString(cursor.getColumnIndex(UserAccountTable.COL_NICK)));
            userInfo.setPhoto(cursor.getString(cursor.getColumnIndex(UserAccountTable.COL_PHOTO)));
        }

        //关闭资源
        cursor.close();
        //返回数据
        return userInfo;
    }

}