Skip to content

泛聊,一个IM示例项目,使用MVP模式,集成了环信SDK和Bmob后端云。

Notifications You must be signed in to change notification settings

uncleleonfan/FanChat

Repository files navigation

项目简介

本项目是即时通讯的示例项目,使用了MVP模式,集成了环信SDK和Bmob后端云,展示了即时通讯基本的功能的实现,包括注册登录,退出登录,联系人列表,添加好友,删除好友,收发消息,消息提醒等功能。

使用的开源项目

学习目标

  • 环信SDK的集成与使用
  • MVP模式的运用
  • ORM数据库的集成与使用
  • 模块化思想的运用

即时通讯 IM(Instant Messaging)#

允许两人或多人使用网路即时的传递文字讯息、档案、语音与视频交流。

相关产品

  • 鼻祖 ICQ
  • 国内主流 QQ 微信 陌陌 YY等
  • 国外主流 Facebook Messenger WhatsApp Skype Instagram Line

第三方服务平台

环信

官网

即时通信云3.x文档

环信业务逻辑

环信集成

  1. 注册并创建应用
  2. 下载SDK
  3. SDK的导入
  4. SDK的初始化

.so文件夹

  1. 放在jniLibs

  2. 也可以放在libs目录下,不过需要在模块下的配置文件中配置

     android {
     	sourceSets {
             main {
                 jniLibs.srcDirs = ['libs']
             }
         }
     }
    

巨坑

运行出错:Didn't find class "com.hyphenate.chat.adapter.EMACallSession",原因是hyphenatechat_3.2.0.jar包内没有该类。

解决办法:导入Demo源码中EaseUI库里面的hyphenatechat_3.2.0.jar替换。

软件架构

MVC

MVC应用于Ruby on Rails, Spring Framework, iOS开发和 ASP.NET等。

  • Model: 获取数据的业务逻辑,网络操作,数据库操作
  • View: UI
  • Controller: 操作Model层获取数据传递给UI

MVC依赖关系

服务器端的MVC

服务器端MVC

Android中MVC

Android中并没有清晰的MVC框架,如果把Activity当做Controller,根据我们实际开发经验,里面会有大量的UI操作,所以V和C就傻傻分不清了。

  • Model:Java Bean, NetworkManager, DataBaseHelper
  • View: xml res
  • Controller: Activity Fragment
  • ArrayList-ListView-Adapter(MVC)

MVP

MVP主要应用于ASP.NET等。MVP与MVC主要区别是View和Model不再耦合。

  • Model: 获取数据的业务逻辑,网络操作,数据库操作
  • View: UI
  • Presenter: 操作Model层获取数据传递给UI MVP依赖关系

MVVM

MVVM主要应用于WPF, Silverlight, Caliburn, nRoute等。

  • Model: 获取数据的业务逻辑,网络操作,数据库操作
  • View: UI
  • ViewModel: 将View和Model绑定

MVVM依赖关系

Android中MVVM

Data Binding Library 中文翻译

软件架构的核心思想

分层分模块

架构

参考

android architecture

MVC,MVP和MVVM模式如何选择

Understanding MVC, MVP and MVVM Design Patterns

教你认清MVC,MVP和MVVM

Android Data Binding

Clean Architecture

准备好了么? 开车啦!!!

包的创建

  • adapter 存放适配器
  • app 存放常量类,Application类以及一些app层级的全局类
  • database 数据库相关类
  • event EventBus使用的事件类
  • factory 工厂类
  • model 数据模型
  • presenter MVP模型中的Presenter类
  • ui 存放activity和fragment
  • utils 工具类
  • view MVP模型中的View类
  • widget 自定义控件

基类的创建

  • BaseActivity
  • BaseFragment

Git初始化

Splash界面

Splash界面

功能需求

  1. 如果没有登录,延时2s, 跳转到登录界面
  2. 如果已经登录,则跳转到主界面

MVP实现

  • SplashView
  • SplashPresenter

登录界面

登录界面

功能需求

  1. 有两种情况都可以发起登录操作,一是点击登录按钮,而是点击虚拟键盘上的Action键。
  2. 点击新用户,跳转到注册界面。

IME Options##

注意配置EditText的imeOptions属性时,需要配合inputType才能起作用。

android:imeOptions="actionNext"//下一个
android:imeOptions="actionGo"//启动
android:imeOptions="actionDone"//完成
android:imeOptions="actionPrevious"//上一个
android:imeOptions="actionSearch"//搜索
android:imeOptions="actionSend"//发送

MVP实现

  • LoginView
  • LoginPresenter

EMCallBack的适配器

public class EMCallBackAdapter implements EMCallBack{

    @Override
    public void onSuccess() {

    }

    @Override
    public void onError(int i, String s) {

    }

    @Override
    public void onProgress(int i, String s) {

    }
}

Android6.0动态权限管理

介绍

举个栗子:高德地图 百度地图等

/**
 * 是否有写磁盘权限
 */
private boolean hasWriteExternalStoragePermission() {
    int result = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    return result == PermissionChecker.PERMISSION_GRANTED;
}

/**
 * 申请权限
 */
private void applyPermission() {
    String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
    ActivityCompat.requestPermissions(this, permissions, REQUEST_WRITE_EXTERNAL_STORAGE);
}

/**
 * 申请权限回调
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_WRITE_EXTERNAL_STORAGE:
            if (grantResults[0] == PermissionChecker.PERMISSION_GRANTED) {
                login();
            } else {
                toast(getString(R.string.not_get_permission));
            }
            break;
    }
}

注册界面

注册界面

功能需求

  1. 用户名的长度必须是3-20位,首字母必须为英文字符,其他字符则除了英文外还可以是数字或者下划线。
  2. 密码必须是3-20位的数字。
  3. 密码和确认密码一致

正则表达式

正则表达式-元字符

private static final String USER_NAME_REGEX = "^[a-zA-Z]\\w{2,19}$";
private static final String PASSWORD_REGEX = "^[0-9]{3,20}$";
  • \w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。

MVP实现

  • RegisterView
  • RegisterPresenter

注册流程

  1. 实际项目中,注册会将用户名和密码注册到APP的服务器,然后APP的服务器再通过REST API方式注册到环信服务器。
  2. 由于本项目没有APP服务器,会将用户数据注册到第三方云数据库Bmob,注册成功后,在客户端发送请求注册到环信服务器。

注册流程

云数据库

Bmob集成

开发文档

  1. 注册创建应用
  2. 下载SDK
  3. 导入SDK
  4. 初始化SDk

隐藏软键盘

protected void hideSoftKeyboard() {
    if (mInputMethodManager == null) {
        mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
    }
    mInputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

软键盘Action处理

private TextView.OnEditorActionListener mOnEditorActionListener = new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_GO) {
            reigister();//注册
            return true;
        }
        return false;
    }
};

用户名已注册的处理

Bmob错误码

主界面

主界面

底部导航条

RadioGroup, TabHost, FragmentTabHost, 自定义

第三方底部条

BottomBar AHBottomNavigation BottomNavigation

Fragment的切换

动态界面

退出登录

联系人界面

联系人1 联系人2

MVP实现

  • ContactView
  • ContactPresenter

RecyclerView的使用

Creating Lists and Cards

联系人是否在同一个组

private boolean itemInSameGroup(int i, ContactItem item) {
    return i > 0 && (item.getFirstLetter() == mContactItems.get(i - 1).getFirstLetter());
}

CardView的使用

SwipeRefreshLayout的使用

mSwipeRefreshLayout.setColorSchemeResources(R.color.qq_blue, R.color.qq_red);
mSwipeRefreshLayout.setOnRefreshListener(mOnRefreshListener);

自定义控件SlideBar

分类字符数组(供拷贝)

private static final String[] SECTIONS = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"
        , "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

绘制居中文本

http://www.cnblogs.com/tianzhijiexian/p/4297664.html

在ContactFragment里面监听SlideBar的事件

private SlideBar.OnSlideBarChangeListener mOnSlideBarChangeListener = new SlideBar.OnSlideBarChangeListener() {
    @Override
    public void onSectionChange(int index, String section) {
        mSection.setVisibility(View.VISIBLE);
        mSection.setText(section);
        scrollToSection(section);
    }

    @Override
    public void onSlidingFinish() {
        mSection.setVisibility(View.GONE);
    }
};

/**
 * RecyclerView滚动直到界面出现对应section的联系人
 * 
 * @param section 首字符
 */
private void scrollToSection(String section) {
    int sectionPosition = getSectionPosition(section);
    if (sectionPosition != POSITION_NOT_FOUND) {
        mRecyclerView.smoothScrollToPosition(sectionPosition);
    }
}


/**
 * 
 * @param section 首字符
 * @return 在联系人列表中首字符是section的第一个联系人在联系人列表中的位置
 */
private int getSectionPosition(String section) {
    List<ContactItem> contactItems = mContactListAdapter.getContactItems();
    for (int i = 0; i < contactItems.size(); i++) {
        if (section.equals(contactItems.get(i).getFirstLetterString())) {
            return i;
        }
    }
    return POSITION_NOT_FOUND;
}

添加好友界面

添加好友

GreenDAO

Github

官网

AppBrain

使用文档

中文使用文档

  1. 保存联系人
  2. 查询联系人
  3. 删除联系人

聊天界面

聊天界面 聊天界面

通信过程及聊天记录保存

发送一条消息

动画文件

anim文件夹:补间动画

animator文件夹:属性动画

drawable文件夹:帧动画

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/loading1" android:duration="100"/>
    <item android:drawable="@mipmap/loading2" android:duration="100"/>
    <item android:drawable="@mipmap/loading3" android:duration="100"/>
    <item android:drawable="@mipmap/loading4" android:duration="100"/>
    <item android:drawable="@mipmap/loading5" android:duration="100"/>
    <item android:drawable="@mipmap/loading6" android:duration="100"/>
    <item android:drawable="@mipmap/loading7" android:duration="100"/>
    <item android:drawable="@mipmap/loading8" android:duration="100"/>
</animation-list>

.9文件制作

接收一条消息

初始化聊天记录

官方文档

加载更多聊天记录

会话界面

icon

会话界面的MVP实现

未读消息的更新

官方文档

标记消息已读

消息通知

声音

通知

多设备登录

官方文档

About

泛聊,一个IM示例项目,使用MVP模式,集成了环信SDK和Bmob后端云。

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages