├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── release
│ └── app-release.apk
├── src
│ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── king
│ │ │ └── easychat
│ │ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── ic_launcher-web.png
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── king
│ │ │ │ └── easychat
│ │ │ │ ├── App.kt
│ │ │ │ ├── api
│ │ │ │ └── ApiService.kt
│ │ │ │ ├── app
│ │ │ │ ├── Constants.kt
│ │ │ │ ├── account
│ │ │ │ │ ├── LoginActivity.kt
│ │ │ │ │ ├── LoginViewModel.kt
│ │ │ │ │ ├── RegisterActivity.kt
│ │ │ │ │ ├── RegisterViewModel.kt
│ │ │ │ │ ├── UpdatePwdActivity.kt
│ │ │ │ │ └── UpdatePwdViewModel.kt
│ │ │ │ ├── adapter
│ │ │ │ │ ├── BindingAdapter.kt
│ │ │ │ │ ├── BindingHolder.kt
│ │ │ │ │ ├── ChatAdapter.kt
│ │ │ │ │ ├── GroupChatAdapter.kt
│ │ │ │ │ └── MessageAdapter.kt
│ │ │ │ ├── base
│ │ │ │ │ ├── BaseActivity.kt
│ │ │ │ │ ├── BaseFragment.kt
│ │ │ │ │ ├── MessageModel.kt
│ │ │ │ │ └── MessageViewModel.kt
│ │ │ │ ├── chat
│ │ │ │ │ ├── ChatActivity.kt
│ │ │ │ │ ├── ChatModel.kt
│ │ │ │ │ ├── ChatViewModel.kt
│ │ │ │ │ ├── GroupChatActivity.kt
│ │ │ │ │ ├── GroupChatModel.kt
│ │ │ │ │ └── GroupChatViewModel.kt
│ │ │ │ ├── code
│ │ │ │ │ ├── CodeActivity.kt
│ │ │ │ │ ├── CodeViewModel.kt
│ │ │ │ │ └── ScanCodeActivity.kt
│ │ │ │ ├── friend
│ │ │ │ │ ├── FriendFragment.kt
│ │ │ │ │ ├── FriendModel.kt
│ │ │ │ │ ├── FriendViewModel.kt
│ │ │ │ │ ├── UserProfileActivity.kt
│ │ │ │ │ └── UserProfileViewModel.kt
│ │ │ │ ├── group
│ │ │ │ │ ├── GroupFragment.kt
│ │ │ │ │ ├── GroupMemberActivity.kt
│ │ │ │ │ ├── GroupMemberViewModel.kt
│ │ │ │ │ ├── GroupModel.kt
│ │ │ │ │ ├── GroupProfileActivity.kt
│ │ │ │ │ ├── GroupProfileViewModel.kt
│ │ │ │ │ └── GroupViewModel.kt
│ │ │ │ ├── home
│ │ │ │ │ ├── HomeActivity.kt
│ │ │ │ │ ├── HomeFragment.kt
│ │ │ │ │ ├── HomeModel.kt
│ │ │ │ │ └── HomeViewModel.kt
│ │ │ │ ├── me
│ │ │ │ │ ├── MeFragment.kt
│ │ │ │ │ ├── MeViewModel.kt
│ │ │ │ │ ├── about
│ │ │ │ │ │ └── AboutActivity.kt
│ │ │ │ │ └── user
│ │ │ │ │ │ ├── ChangeUserInfoActivity.kt
│ │ │ │ │ │ ├── ChangeUserInfoViewModel.kt
│ │ │ │ │ │ ├── UserInfoActivity.kt
│ │ │ │ │ │ └── UserInfoViewModel.kt
│ │ │ │ ├── photo
│ │ │ │ │ └── PhotoViewActivity.kt
│ │ │ │ ├── search
│ │ │ │ │ ├── SearchActivity.kt
│ │ │ │ │ └── SearchViewModel.kt
│ │ │ │ ├── service
│ │ │ │ │ └── HeartBeatService.kt
│ │ │ │ ├── splash
│ │ │ │ │ ├── SplashActivity.kt
│ │ │ │ │ └── SplashViewModel.kt
│ │ │ │ └── web
│ │ │ │ │ └── WebActivity.kt
│ │ │ │ ├── bean
│ │ │ │ ├── AppVersion.kt
│ │ │ │ ├── Group.kt
│ │ │ │ ├── GroupMessageDbo.kt
│ │ │ │ ├── Message.kt
│ │ │ │ ├── MessageDbo.kt
│ │ │ │ ├── Operator.kt
│ │ │ │ ├── RecentChat.kt
│ │ │ │ ├── RecentGroupChat.kt
│ │ │ │ ├── Result.kt
│ │ │ │ ├── Search.kt
│ │ │ │ └── User.kt
│ │ │ │ ├── binding
│ │ │ │ └── BindingAdapter.kt
│ │ │ │ ├── config
│ │ │ │ └── ConfigModule.kt
│ │ │ │ ├── dao
│ │ │ │ ├── AppDatabase.kt
│ │ │ │ ├── GroupDao.kt
│ │ │ │ ├── GroupMessageDao.kt
│ │ │ │ ├── MessageDao.kt
│ │ │ │ ├── RecentChatDao.kt
│ │ │ │ ├── RecentGroupChatDao.kt
│ │ │ │ └── UserDao.kt
│ │ │ │ ├── di
│ │ │ │ ├── component
│ │ │ │ │ └── ApplicationComponent.kt
│ │ │ │ └── module
│ │ │ │ │ ├── ActivityModule.kt
│ │ │ │ │ ├── ApplicationModule.kt
│ │ │ │ │ ├── FragmentModule.kt
│ │ │ │ │ └── ViewModelModule.kt
│ │ │ │ ├── glide
│ │ │ │ ├── GlideEngine.kt
│ │ │ │ ├── GlideModule.kt
│ │ │ │ └── ImageLoader.kt
│ │ │ │ ├── netty
│ │ │ │ ├── ChannelInitial.kt
│ │ │ │ ├── NettyClient.kt
│ │ │ │ ├── codec
│ │ │ │ │ ├── PacketDecoder.kt
│ │ │ │ │ ├── PacketEncoder.kt
│ │ │ │ │ ├── PacketHelper.kt
│ │ │ │ │ └── Spliter.kt
│ │ │ │ ├── handle
│ │ │ │ │ ├── AcceptGroupRespHandler.kt
│ │ │ │ │ ├── AcceptRespHandler.kt
│ │ │ │ │ ├── AddUserRespHandler.kt
│ │ │ │ │ ├── AddUserSelfRespHandler.kt
│ │ │ │ │ ├── AllowGroupRespHandler.kt
│ │ │ │ │ ├── ApplyGroupRespHandler.kt
│ │ │ │ │ ├── ApplyGroupSelfRespHandler.kt
│ │ │ │ │ ├── CreateGroupRespHandler.kt
│ │ │ │ │ ├── GroupMessageRespHandler.kt
│ │ │ │ │ ├── HeartBeatRespHandler.kt
│ │ │ │ │ ├── InviteGroupRespHandler.kt
│ │ │ │ │ ├── InviteGroupSelfRespHandler.kt
│ │ │ │ │ ├── LoginRespHandler.kt
│ │ │ │ │ ├── MessageRespHandler.kt
│ │ │ │ │ ├── MessageSelfRespHandler.kt
│ │ │ │ │ ├── RegisterRespHandler.kt
│ │ │ │ │ └── RespHandler.kt
│ │ │ │ └── packet
│ │ │ │ │ ├── MessageType.kt
│ │ │ │ │ ├── Packet.kt
│ │ │ │ │ ├── PacketType.kt
│ │ │ │ │ ├── req
│ │ │ │ │ ├── AcceptGroupReq.kt
│ │ │ │ │ ├── AcceptReq.kt
│ │ │ │ │ ├── AddUserReq.kt
│ │ │ │ │ ├── AllowGroupReq.kt
│ │ │ │ │ ├── ApplyGroupReq.kt
│ │ │ │ │ ├── CreateGroupReq.kt
│ │ │ │ │ ├── GroupMessageReq.kt
│ │ │ │ │ ├── HeartBeatReq.kt
│ │ │ │ │ ├── InviteGroupReq.kt
│ │ │ │ │ ├── LoginReq.kt
│ │ │ │ │ ├── LogoutReq.kt
│ │ │ │ │ ├── MessageReq.kt
│ │ │ │ │ ├── RegisterReq.kt
│ │ │ │ │ ├── SyncMessageReq.kt
│ │ │ │ │ └── UpdatePasswdReq.kt
│ │ │ │ │ └── resp
│ │ │ │ │ ├── AcceptGroupResp.kt
│ │ │ │ │ ├── AcceptResp.kt
│ │ │ │ │ ├── AddUserResp.kt
│ │ │ │ │ ├── AddUserSelfResp.kt
│ │ │ │ │ ├── AllowGroupResp.kt
│ │ │ │ │ ├── ApplyGroupResp.kt
│ │ │ │ │ ├── ApplyGroupSelfResp.kt
│ │ │ │ │ ├── CreateGroupResp.kt
│ │ │ │ │ ├── GroupMessageResp.kt
│ │ │ │ │ ├── HeartBeatResp.kt
│ │ │ │ │ ├── InviteGroupResp.kt
│ │ │ │ │ ├── InviteGroupSelfResp.kt
│ │ │ │ │ ├── LoginResp.kt
│ │ │ │ │ ├── LogoutResp.kt
│ │ │ │ │ ├── MessageResp.kt
│ │ │ │ │ ├── MessageSelfResp.kt
│ │ │ │ │ ├── RegisterResp.kt
│ │ │ │ │ └── UpdatePasswdResp.kt
│ │ │ │ ├── temp
│ │ │ │ ├── TempActivity.kt
│ │ │ │ ├── TempFragment.kt
│ │ │ │ └── TempViewModel.kt
│ │ │ │ ├── util
│ │ │ │ ├── AES.kt
│ │ │ │ ├── BitmapUtil.kt
│ │ │ │ ├── Cache.kt
│ │ │ │ ├── CheckUtil.kt
│ │ │ │ ├── Event.kt
│ │ │ │ ├── FileUtil.kt
│ │ │ │ ├── JsonUtil.kt
│ │ │ │ ├── KeyboardUtils.java
│ │ │ │ └── SystemBarHelper.java
│ │ │ │ └── view
│ │ │ │ ├── DragBubbleView.java
│ │ │ │ └── EasySwipeMenuLayout.java
│ │ └── res
│ │ │ ├── anim
│ │ │ ├── anim_in.xml
│ │ │ ├── anim_out.xml
│ │ │ ├── splash_in.xml
│ │ │ ├── translate_left_in.xml
│ │ │ ├── translate_left_out.xml
│ │ │ ├── translate_right_in.xml
│ │ │ └── translate_right_out.xml
│ │ │ ├── color
│ │ │ └── bottom_menu_selector.xml
│ │ │ ├── drawable-v21
│ │ │ └── white_selector.xml
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable-xhdpi
│ │ │ └── ec_welcome.9.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── btn_back_normal.png
│ │ │ ├── btn_back_pressed.png
│ │ │ ├── btn_bg_normal.9.png
│ │ │ ├── btn_bg_pressed.9.png
│ │ │ ├── btn_black_back_normal.png
│ │ │ ├── btn_black_back_pressed.png
│ │ │ ├── btn_clear.png
│ │ │ ├── btn_close_normal.png
│ │ │ ├── btn_close_pressed.png
│ │ │ ├── btn_delete_normal.png
│ │ │ ├── btn_delete_pressed.png
│ │ │ ├── btn_menu_normal.png
│ │ │ ├── btn_menu_pressed.png
│ │ │ ├── btn_more_normal.png
│ │ │ ├── btn_more_pressed.png
│ │ │ ├── btn_none.png
│ │ │ ├── btn_scan_normal.png
│ │ │ ├── btn_scan_pressed.png
│ │ │ ├── btn_search_normal.png
│ │ │ ├── btn_search_pressed.png
│ │ │ ├── default_avatar.png
│ │ │ ├── ec_about.png
│ │ │ ├── ec_about_line.png
│ │ │ ├── ec_add.png
│ │ │ ├── ec_chat_bubble_left.9.png
│ │ │ ├── ec_chat_bubble_right.9.png
│ │ │ ├── ec_create_group_normal.png
│ │ │ ├── ec_create_group_pressed.png
│ │ │ ├── ec_delete.png
│ │ │ ├── ec_detail_normal.png
│ │ │ ├── ec_detail_pressed.png
│ │ │ ├── ec_edit_box_bg.9.png
│ │ │ ├── ec_empty.png
│ │ │ ├── ec_heart.png
│ │ │ ├── ec_keyboard.png
│ │ │ ├── ec_modify_password.png
│ │ │ ├── ec_next.png
│ │ │ ├── ec_next_white.png
│ │ │ ├── ec_off.png
│ │ │ ├── ec_on.png
│ │ │ ├── ec_qrcode.png
│ │ │ ├── ec_save_normal.png
│ │ │ ├── ec_save_pressed.png
│ │ │ ├── ec_smile.png
│ │ │ ├── ec_version.png
│ │ │ ├── explosion_five.png
│ │ │ ├── explosion_four.png
│ │ │ ├── explosion_one.png
│ │ │ ├── explosion_three.png
│ │ │ ├── explosion_two.png
│ │ │ ├── ic_about_image.png
│ │ │ ├── ic_close.png
│ │ │ ├── ic_github.png
│ │ │ ├── ic_hide.png
│ │ │ ├── ic_menu_about.png
│ │ │ ├── ic_menu_logout.png
│ │ │ ├── ic_none.png
│ │ │ ├── ic_password.png
│ │ │ ├── ic_search.png
│ │ │ ├── ic_show.png
│ │ │ ├── ic_user.png
│ │ │ ├── input_bg_focus.9.png
│ │ │ ├── input_bg_normal.9.png
│ │ │ ├── login_slogan.png
│ │ │ ├── logo.png
│ │ │ ├── menu_friend_normal.png
│ │ │ ├── menu_friend_selected.png
│ │ │ ├── menu_group_normal.png
│ │ │ ├── menu_group_selected.png
│ │ │ ├── menu_me_normal.png
│ │ │ ├── menu_me_selected.png
│ │ │ ├── menu_message_normal.png
│ │ │ └── menu_message_selected.png
│ │ │ ├── drawable
│ │ │ ├── btn_back_selector.xml
│ │ │ ├── btn_bg_selector.xml
│ │ │ ├── btn_black_back_selector.xml
│ │ │ ├── btn_clear_selector.xml
│ │ │ ├── btn_close_selector.xml
│ │ │ ├── btn_create_group_selector.xml
│ │ │ ├── btn_delete_selector.xml
│ │ │ ├── btn_detail_selector.xml
│ │ │ ├── btn_flash_selector.xml
│ │ │ ├── btn_menu_selector.xml
│ │ │ ├── btn_password_eye_selector.xml
│ │ │ ├── btn_save_selector.xml
│ │ │ ├── btn_scan_selector.xml
│ │ │ ├── btn_search_selector.xml
│ │ │ ├── edit_bg_line_normal.xml
│ │ │ ├── edit_bg_line_pressed.xml
│ │ │ ├── edit_bg_line_selector.xml
│ │ │ ├── ic_clear_selector.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── line_drawable.xml
│ │ │ ├── line_drawable_8.xml
│ │ │ ├── line_drawable_xh_none.xml
│ │ │ ├── logo_layer.xml
│ │ │ ├── menu_friend_selector.xml
│ │ │ ├── menu_group_selector.xml
│ │ │ ├── menu_me_selector.xml
│ │ │ ├── menu_message_selector.xml
│ │ │ ├── search_bg.xml
│ │ │ ├── splash_layer.xml
│ │ │ ├── web_progress_bar.xml
│ │ │ ├── white_bottom_layer.xml
│ │ │ ├── white_layer.xml
│ │ │ └── white_selector.xml
│ │ │ ├── layout
│ │ │ ├── about_activity.xml
│ │ │ ├── change_user_info_activity.xml
│ │ │ ├── chat_activity.xml
│ │ │ ├── code_activity.xml
│ │ │ ├── create_group_dialog.xml
│ │ │ ├── friend_fragment.xml
│ │ │ ├── group_chat_activity.xml
│ │ │ ├── group_fragment.xml
│ │ │ ├── group_member_activity.xml
│ │ │ ├── group_profile_activity.xml
│ │ │ ├── home_activity.xml
│ │ │ ├── home_fragment.xml
│ │ │ ├── home_toolbar.xml
│ │ │ ├── layout_empty.xml
│ │ │ ├── login_activity.xml
│ │ │ ├── me_fragment.xml
│ │ │ ├── photo_view_activity.xml
│ │ │ ├── register_activity.xml
│ │ │ ├── rv_chat_item.xml
│ │ │ ├── rv_chat_right_item.xml
│ │ │ ├── rv_friend_item.xml
│ │ │ ├── rv_group_chat_item.xml
│ │ │ ├── rv_group_chat_right_item.xml
│ │ │ ├── rv_group_item.xml
│ │ │ ├── rv_item.xml
│ │ │ ├── rv_message_item.xml
│ │ │ ├── rv_search_user_item.xml
│ │ │ ├── rv_user_item.xml
│ │ │ ├── scan_code_activity.xml
│ │ │ ├── scan_toolbar.xml
│ │ │ ├── search_user_activity.xml
│ │ │ ├── splash_activity.xml
│ │ │ ├── toolbar.xml
│ │ │ ├── update_pwd_activity.xml
│ │ │ ├── user_info_activity.xml
│ │ │ ├── user_profile_activity.xml
│ │ │ ├── vp_photo_item.xml
│ │ │ └── web_activity.xml
│ │ │ ├── menu
│ │ │ └── about_me.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_foreground.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── values-v21
│ │ │ ├── dimens.xml
│ │ │ └── styles.xml
│ │ │ ├── values
│ │ │ ├── attrs.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── ids.xml
│ │ │ ├── integers.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ │ └── xml
│ │ │ └── network_security_config.xml
│ └── test
│ │ └── java
│ │ └── com
│ │ └── king
│ │ └── easychat
│ │ └── ExampleUnitTest.kt
└── tinker-support.gradle
├── art
├── GIF.gif
├── GIF2.gif
└── QR_EasyChat.png
├── build.gradle
├── doc
└── 接口文档.docx
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── versions.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | dist: trusty
3 | jdk: oraclejdk8
4 | sudo: false
5 |
6 | env:
7 | global:
8 | - ANDROID_API_LEVEL=29
9 | - ANDROID_BUILD_TOOLS_VERSION=29.0.2
10 | - TRAVIS_SECURE_ENV_VARS=true
11 |
12 | before_install:
13 | - chmod +x gradlew
14 | - mkdir "$ANDROID_HOME/licenses" || true
15 | # Hack to accept Android licenses
16 | - yes | sdkmanager "platforms;android-$ANDROID_API_LEVEL"
17 |
18 |
19 | android:
20 | components:
21 | # The BuildTools version used by your project
22 | - tools
23 | - platform-tools
24 | - build-tools-$ANDROID_BUILD_TOOLS_VERSION
25 | # The SDK version used to compile your project
26 | - android-$ANDROID_API_LEVEL
27 | - extra-android-m2repository
28 | - extra-google-android-support
29 |
30 | script:
31 | - ./gradlew clean
32 | - ./gradlew assembleRelease
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## EasyChat
2 |
3 | 
4 |
5 | [](https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/master/app/release/app-release.apk)
6 | [](https://android-arsenal.com/api?level=16)
7 | [](http://www.apache.org/licenses/LICENSE-2.0)
8 | [](http://shang.qq.com/wpa/qunwpa?idkey=8fcc6a2f88552ea44b1411582c94fd124f7bb3ec227e2a400dbbfaad3dc2f5ad)
9 |
10 |
11 | EasyChat for Android 是一个开源的社交类的App。主要包含消息、好友、群组等相关的社交核心功能。部分界面参照了QQ、微信等相关社交APP。更多精彩详情,请直接[下载App](https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/master/app/release/app-release.apk)进行体验吧。
12 |
13 | > App整体架构主要采用MVVM模式, 基于 [MVVMFrame](https://github.com/jenly1314/MVVMFrame) 框架搭建。
14 |
15 | ### 核心技术点
16 |
17 | * JetPack(Lifecycle,LiveData,ViewModel,Room)
18 | * Dagger
19 | * DataBinding
20 | * Netty
21 |
22 | ## Gif 展示
23 | 
24 | 
25 |
26 | > 你也可以直接 [下载App](https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/master/app/release/app-release.apk) 体验效果
27 |
28 |
29 | ## 版本记录
30 |
31 | #### 2019-10-31 v1.0.0 初始版本
32 | * EasyChat完成主要核心功能
33 |
34 | ## EasyChat相关开源项目
35 |
36 | ##### 服务端:[EasyChatServer](https://github.com/yetel/EasyChatServer)
37 | ##### JavaFX客户端:[EasyChatJavaFXClient](https://github.com/yetel/EasyChatJavaFXClient)
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/release/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/release/app-release.apk
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/king/easychat/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.runner.AndroidJUnit4
5 | import com.king.easychat.netty.packet.Packet
6 |
7 | import org.junit.Test
8 | import org.junit.runner.RunWith
9 |
10 | import org.junit.Assert.*
11 | import java.io.File
12 | import java.io.IOException
13 |
14 | /**
15 | * Instrumented test, which will execute on an Android device.
16 | *
17 | * See [testing documentation](http://d.android.com/tools/testing).
18 | */
19 | @RunWith(AndroidJUnit4::class)
20 | class ExampleInstrumentedTest {
21 | @Test
22 | fun useAppContext() {
23 | // Context of the app under test.
24 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
25 | assertEquals("com.king.easychat", appContext.packageName)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/api/ApiService.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.api
2 |
3 | import com.king.easychat.bean.*
4 | import retrofit2.Call
5 | import retrofit2.http.*
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | interface ApiService {
11 |
12 | /**
13 | * 获取用户信息
14 | */
15 | @GET("user/{userId}")
16 | fun getUser(@Header("token")token : String,@Path("userId")userId: String): Call>
17 |
18 | /**
19 | * 获取好友列表
20 | */
21 | @GET("users")
22 | fun getFriends(@Header("token")token : String): Call>>
23 |
24 | /**
25 | * 获取群组信息
26 | */
27 | @GET("group/{groupId}")
28 | fun getGroup(@Header("token")token : String,@Path("groupId")groupId: String): Call>
29 |
30 |
31 | /**
32 | * 获取群列表
33 | */
34 | @GET("groups")
35 | fun getGroups(@Header("token")token : String): Call>>
36 |
37 | /**
38 | * 获取群用户列表
39 | */
40 | @GET("query/member/{groupId}")
41 | fun getGroupMembers(@Header("token")token : String,@Path("groupId")groupId : String): Call>>
42 |
43 | /**
44 | * 上传图片
45 | */
46 | @POST("image/upload")
47 | fun uploadImage(@Header("token")token : String,@Body params: Map): Call>
48 |
49 | /**
50 | * 修改用户信息
51 | */
52 | @PUT("user/update")
53 | fun updateUserInfo(@Header("token")token : String,@Body params: Map): Call>
54 |
55 | /**
56 | * 修改用户密码
57 | */
58 | @FormUrlEncoded
59 | @PUT("update/password")
60 | fun updateUserPassword(@Header("token")token : String,@Field("oldPassword")oldPassword: String,@Field("newPassword")newPassword: String): Call>
61 |
62 | /**
63 | * 搜索
64 | */
65 | @GET("fuzzy/allQuery")
66 | fun search(@Header("token")token : String,@Query("key")keyword: String,@Query("currentPage")currentPage : Int, @Query("pageSize")pageSize: Int): Call>>
67 |
68 | /**
69 | * 修改好友备注名称
70 | */
71 | @FormUrlEncoded
72 | @PUT("update/friend/remark")
73 | fun updateFriendRemark(@Header("token")token : String,@Field("friendId")friendId : String,@Field("remark")remark : String): Call>
74 |
75 |
76 | /**
77 | * 版本检测
78 | */
79 | @GET("system/checkVersion")
80 | fun checkVersion(@Query("versionCode")versionCode : String): Call>
81 |
82 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/account/LoginViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.account
2 |
3 | import android.app.Application
4 | import com.king.anetty.Netty
5 | import com.king.easychat.app.Constants
6 | import com.king.easychat.netty.NettyClient
7 | import com.king.easychat.netty.packet.req.LoginReq
8 | import com.king.frame.mvvmframe.base.BaseModel
9 | import com.king.frame.mvvmframe.base.DataViewModel
10 | import javax.inject.Inject
11 |
12 | /**
13 | * @author Jenly
14 | */
15 | class LoginViewModel @Inject constructor(application: Application, model: BaseModel?) : DataViewModel(application, model){
16 |
17 | var loginReq: LoginReq? = null
18 |
19 | val onSendMessageListener = Netty.OnSendMessageListener { msg, success ->
20 | hideLoading()
21 | if(success){
22 | sendSingleLiveEvent(Constants.EVENT_SUCCESS)
23 | }
24 | }
25 |
26 | override fun onCreate() {
27 | super.onCreate()
28 |
29 |
30 | NettyClient.INSTANCE.setOnConnectListener(object: Netty.OnConnectListener{
31 | override fun onSuccess() {
32 |
33 | }
34 |
35 | override fun onFailed() {
36 | hideLoading()
37 | }
38 |
39 | override fun onError(e: Exception?) {
40 | hideLoading()
41 | }
42 |
43 | })
44 | NettyClient.INSTANCE.setOnSendMessageListener(onSendMessageListener)
45 |
46 | }
47 |
48 | override fun onDestroy() {
49 | NettyClient.INSTANCE.setOnSendMessageListener(null)
50 | super.onDestroy()
51 | }
52 |
53 | fun login(username: String,password: String){
54 | showLoading()
55 | loginReq = LoginReq(null,username,password)
56 | if(!NettyClient.INSTANCE.isConnected()){
57 | NettyClient.INSTANCE.setOnConnectListener(object: Netty.OnConnectListener{
58 | override fun onSuccess() {
59 | NettyClient.INSTANCE.sendMessage(loginReq!!)
60 | hideLoading()
61 | }
62 |
63 | override fun onFailed() {
64 | hideLoading()
65 | }
66 |
67 | override fun onError(e: Exception?) {
68 | hideLoading()
69 | }
70 |
71 | })
72 | NettyClient.INSTANCE.connect()
73 |
74 | }else{
75 | NettyClient.INSTANCE.sendMessage(loginReq!!)
76 | }
77 |
78 |
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/account/UpdatePwdViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.account
2 |
3 | import android.app.Application
4 | import com.king.easychat.App
5 | import com.king.easychat.R
6 | import com.king.easychat.api.ApiService
7 | import com.king.easychat.bean.Result
8 | import com.king.easychat.bean.User
9 | import com.king.frame.mvvmframe.base.BaseModel
10 | import com.king.frame.mvvmframe.base.DataViewModel
11 | import com.king.frame.mvvmframe.base.livedata.StatusEvent
12 | import com.king.frame.mvvmframe.http.callback.ApiCallback
13 | import retrofit2.Call
14 | import timber.log.Timber
15 | import javax.inject.Inject
16 |
17 | /**
18 | * @author Jenly
19 | */
20 | class UpdatePwdViewModel @Inject constructor(application: Application, model: BaseModel?) : DataViewModel(application, model){
21 |
22 | /**
23 | * 更新用户信息
24 | */
25 | fun updateUserPassword(oldPassword: String, newPassword: String){
26 |
27 | val app = getApplication()
28 | val token = app.getToken()
29 | updateStatus(StatusEvent.Status.LOADING)
30 | getRetrofitService(ApiService::class.java)
31 | .updateUserPassword(token,oldPassword,newPassword)
32 | .enqueue(object: ApiCallback>(){
33 | override fun onResponse(call: Call>?, result: Result?) {
34 | result?.let {
35 | if(it.isSuccess()){
36 | updateStatus(StatusEvent.Status.SUCCESS)
37 | }else{
38 | sendMessage(it.desc)
39 | Timber.d(it.desc)
40 | updateStatus(StatusEvent.Status.FAILURE)
41 | }
42 | } ?: run {
43 | updateStatus(StatusEvent.Status.FAILURE)
44 | sendMessage(R.string.result_failure)
45 | }
46 |
47 | }
48 |
49 | override fun onError(call: Call>?, t: Throwable) {
50 | updateStatus(StatusEvent.Status.ERROR)
51 | sendMessage(t.message)
52 | }
53 |
54 | })
55 | }
56 |
57 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/adapter/BindingAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.adapter
2 |
3 | import androidx.annotation.Nullable
4 | import com.chad.library.adapter.base.BaseQuickAdapter
5 | import com.king.easychat.BR
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | open class BindingAdapter : BaseQuickAdapter {
11 |
12 | constructor(layoutResId: Int, @Nullable data: List) : super(layoutResId, data)
13 |
14 | constructor(@Nullable data: List) : super(data)
15 |
16 | constructor(layoutResId: Int) : super(layoutResId)
17 |
18 | override fun convert(helper: BindingHolder, item: T) {
19 | helper.mBinding?.let {
20 | it.setVariable(BR.data,item)
21 | it.executePendingBindings()
22 | }
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/adapter/BindingHolder.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.adapter
2 |
3 | import android.view.View
4 | import androidx.databinding.DataBindingUtil
5 | import androidx.databinding.ViewDataBinding
6 | import com.chad.library.adapter.base.BaseViewHolder
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | class BindingHolder(view: View) : BaseViewHolder(view) {
12 |
13 | var mBinding: ViewDataBinding? = null
14 | init {
15 | try {
16 | mBinding = DataBindingUtil.bind(view)!!
17 | } catch (e: Exception) {
18 |
19 | }
20 |
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/adapter/ChatAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.adapter
2 |
3 | import com.chad.library.adapter.base.BaseMultiItemQuickAdapter
4 | import com.king.easychat.BR
5 | import com.king.easychat.R
6 | import com.king.easychat.glide.ImageLoader
7 | import com.king.easychat.netty.packet.resp.MessageResp
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | class ChatAdapter(var friendImageUrl : String?,var myImageUrl : String?): BaseMultiItemQuickAdapter(null) {
13 |
14 | var curTime = System.currentTimeMillis()
15 |
16 | init {
17 |
18 | addItemType(MessageResp.Left, R.layout.rv_chat_item)
19 | addItemType(MessageResp.Right, R.layout.rv_chat_right_item)
20 | }
21 |
22 | override fun convert(helper: BindingHolder, item: MessageResp?) {
23 | helper.mBinding?.let {
24 | when(item?.itemType){
25 | MessageResp.Left -> ImageLoader.displayImage(mContext,helper.getView(R.id.ivAvatar),friendImageUrl,R.drawable.default_avatar)
26 | MessageResp.Right -> ImageLoader.displayImage(mContext,helper.getView(R.id.ivAvatar),myImageUrl,R.drawable.default_avatar)
27 | }
28 | helper.addOnClickListener(R.id.ivContent)
29 | helper.addOnClickListener(R.id.ivAvatar)
30 | it.setVariable(BR.curTime,curTime)
31 | it.setVariable(BR.data,item)
32 | it.executePendingBindings()
33 | }
34 | }
35 |
36 |
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/adapter/GroupChatAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.adapter
2 |
3 | import com.chad.library.adapter.base.BaseMultiItemQuickAdapter
4 | import com.king.easychat.BR
5 | import com.king.easychat.R
6 | import com.king.easychat.glide.ImageLoader
7 | import com.king.easychat.netty.packet.resp.GroupMessageResp
8 | import com.king.easychat.netty.packet.resp.MessageResp
9 |
10 | /**
11 | * @author Jenly
12 | */
13 | class GroupChatAdapter: BaseMultiItemQuickAdapter {
14 |
15 | var curTime = System.currentTimeMillis()
16 |
17 | constructor() : super(null){
18 | addItemType(GroupMessageResp.Left, R.layout.rv_group_chat_item)
19 | addItemType(GroupMessageResp.Right, R.layout.rv_group_chat_right_item)
20 | }
21 |
22 | override fun convert(helper: BindingHolder, item: GroupMessageResp?) {
23 | helper.mBinding?.let {
24 | when(item?.itemType){
25 | MessageResp.Left -> ImageLoader.displayImage(mContext,helper.getView(R.id.ivAvatar),null,R.drawable.default_avatar)
26 | MessageResp.Right -> ImageLoader.displayImage(mContext,helper.getView(R.id.ivAvatar),null,R.drawable.default_avatar)
27 | }
28 | helper.addOnClickListener(R.id.ivContent)
29 | helper.addOnClickListener(R.id.ivAvatar)
30 | it.setVariable(BR.data,item)
31 | it.setVariable(BR.curTime,curTime)
32 | it.executePendingBindings()
33 | }
34 | }
35 |
36 |
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/adapter/MessageAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.adapter
2 |
3 | import com.king.easychat.BR
4 | import com.king.easychat.R
5 | import com.king.easychat.app.home.HomeViewModel
6 | import com.king.easychat.bean.Message
7 | import com.king.easychat.view.DragBubbleView
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | class MessageAdapter(val userId: String,val viewModel: HomeViewModel) : BindingAdapter(R.layout.rv_message_item) {
13 |
14 | var curTime = System.currentTimeMillis()
15 |
16 | override fun convert(helper: BindingHolder, item: Message) {
17 | helper.getView(R.id.dbvCount).setOnBubbleStateListener(object : DragBubbleView.OnBubbleStateListener{
18 | override fun onDrag() {
19 | }
20 |
21 | override fun onMove() {
22 | }
23 |
24 | override fun onRestore() {
25 | }
26 |
27 | override fun onDismiss() {
28 | when(item.messageMode){
29 | Message.userMode -> viewModel.updateMessageRead(userId,item.id!!)
30 | Message.groupMode -> viewModel.updateGroupMessageRead(userId,item.id!!)
31 | }
32 | }
33 |
34 | })
35 |
36 | helper.addOnClickListener(R.id.clContent)
37 | helper.addOnClickListener(R.id.llDelete)
38 |
39 |
40 | helper.mBinding?.let {
41 | it.setVariable(BR.curTime,curTime)
42 | it.setVariable(BR.data,item)
43 | it.executePendingBindings()
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/chat/ChatModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.chat
2 |
3 | import com.king.easychat.app.base.MessageModel
4 | import com.king.easychat.bean.MessageDbo
5 | import com.king.frame.mvvmframe.data.IDataRepository
6 | import javax.inject.Inject
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | class ChatModel @Inject constructor(repository: IDataRepository?) : MessageModel(repository){
12 |
13 | /**
14 | * 根据好友id获取聊天记录
15 | */
16 | fun queryMessageByFriendId(userId : String, friendId : String, currentPage : Int, pageSize: Int) : List {
17 | return getMessageDao().getMessageBySenderId(userId, friendId,friendId, (currentPage-1) * pageSize, pageSize).sortedBy { it.dateTime }
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/chat/ChatViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.chat
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.MutableLiveData
5 | import com.king.easychat.app.Constants
6 | import com.king.easychat.app.base.MessageViewModel
7 | import com.king.easychat.netty.NettyClient
8 | import com.king.easychat.netty.packet.MessageType
9 | import com.king.easychat.netty.packet.req.MessageReq
10 | import com.king.easychat.netty.packet.resp.MessageResp
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.GlobalScope
13 | import kotlinx.coroutines.launch
14 | import timber.log.Timber
15 | import javax.inject.Inject
16 |
17 | /**
18 | * @author Jenly
19 | */
20 | class ChatViewModel @Inject constructor(application: Application, model: ChatModel?) : MessageViewModel(application, model){
21 |
22 | var messageLiveData = MutableLiveData>()
23 |
24 | override fun onCreate() {
25 | super.onCreate()
26 | }
27 |
28 |
29 | /**
30 | * 根据好友id获取聊天记录
31 | */
32 | fun queryMessageByFriendId(userId : String, friendId : String, currentPage : Int, pageSize: Int) {
33 |
34 | GlobalScope.launch(Dispatchers.IO) {
35 | var list = mModel.queryMessageByFriendId(userId,friendId,currentPage,pageSize)
36 | Timber.d("message:$list")
37 | messageLiveData.postValue(list.map { it.toMessageResp() })
38 | }
39 | sendSingleLiveEvent(Constants.REFRESH_SUCCESS)
40 |
41 | }
42 |
43 | /**
44 | * 发送桃心
45 | */
46 | fun sendHeart(receiver: String){
47 | NettyClient.INSTANCE.sendMessage(MessageReq(receiver,MessageType.HEART.toString(),MessageType.HEART))
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/chat/GroupChatModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.chat
2 |
3 | import com.king.easychat.app.base.MessageModel
4 | import com.king.easychat.bean.GroupMessageDbo
5 | import com.king.frame.mvvmframe.data.IDataRepository
6 | import javax.inject.Inject
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | class GroupChatModel @Inject constructor(repository: IDataRepository?) : MessageModel(repository){
12 |
13 | /**
14 | * 根据群聊id获取聊天记录
15 | */
16 | fun queryMessageByGroupId(userId : String, groupId : String, currentPage : Int, pageSize : Int) : List {
17 | return getGroupMessageDao().getGroupMessageByGroupId(userId, groupId, (currentPage-1) * pageSize, pageSize).sortedBy { it.dateTime }
18 | }
19 |
20 |
21 |
22 |
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/chat/GroupChatViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.chat
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.MutableLiveData
5 | import com.king.easychat.app.Constants
6 | import com.king.easychat.app.base.MessageViewModel
7 | import com.king.easychat.netty.NettyClient
8 | import com.king.easychat.netty.packet.MessageType
9 | import com.king.easychat.netty.packet.req.GroupMessageReq
10 | import com.king.easychat.netty.packet.resp.GroupMessageResp
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.GlobalScope
13 | import kotlinx.coroutines.launch
14 | import javax.inject.Inject
15 |
16 | /**
17 | * @author Jenly
18 | */
19 | class GroupChatViewModel @Inject constructor(application: Application, model: GroupChatModel?) : MessageViewModel(application, model){
20 |
21 | var groupMessageLiveData = MutableLiveData>()
22 |
23 | /**
24 | * 查询群组聊天记录
25 | */
26 | fun queryMessageByGroupId(userId : String, groupId : String, currentPage : Int, pageSize : Int){
27 | GlobalScope.launch(Dispatchers.IO) {
28 | var list = mModel.queryMessageByGroupId(userId,groupId,currentPage,pageSize)
29 | groupMessageLiveData.postValue(list.map { it.toGroupMessageResp() })
30 | }
31 | sendSingleLiveEvent(Constants.REFRESH_SUCCESS)
32 | }
33 |
34 | /**
35 | * 发送桃心
36 | */
37 | fun sendHeart(receiver: String){
38 | NettyClient.INSTANCE.sendMessage(GroupMessageReq(receiver,MessageType.HEART.toString(),MessageType.HEART))
39 | }
40 |
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/code/CodeActivity.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.code
2 |
3 | import android.os.Bundle
4 | import com.king.easychat.R
5 | import com.king.easychat.app.Constants
6 | import com.king.easychat.app.base.BaseActivity
7 | import com.king.easychat.databinding.CodeActivityBinding
8 | import kotlinx.android.synthetic.main.code_activity.*
9 | import kotlinx.android.synthetic.main.toolbar.*
10 |
11 | /**
12 | * @author Jenly
13 | */
14 | class CodeActivity : BaseActivity(){
15 |
16 | override fun initData(savedInstanceState: Bundle?) {
17 | tvTitle.setText(R.string.qrcode)
18 |
19 | var userId = intent.getStringExtra(Constants.KEY_ID)
20 | var avatar = intent.getStringExtra(Constants.KEY_IMAGE_URL)
21 | val type = intent.getIntExtra(Constants.KEY_TYPE,Constants.USER_TYPE)
22 | mViewModel.updateQRCode(context,userId,avatar,type,ivCode)
23 |
24 | tvTips.setText(if(type == Constants.GROUP_TYPE) R.string.tips_group_qrcode else R.string.tips_user_qrcode )
25 | }
26 |
27 | override fun getLayoutId(): Int {
28 | return R.layout.code_activity
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/code/CodeViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.code
2 |
3 | import android.app.Application
4 | import android.content.Context
5 | import android.graphics.Bitmap
6 | import android.graphics.BitmapFactory
7 | import android.widget.ImageView
8 | import com.king.easychat.R
9 | import com.king.easychat.app.Constants
10 | import com.king.easychat.glide.GlideApp
11 | import com.king.easychat.util.BitmapUtil
12 | import com.king.frame.mvvmframe.base.BaseModel
13 | import com.king.frame.mvvmframe.base.DataViewModel
14 | import com.king.zxing.util.CodeUtils
15 | import kotlinx.coroutines.Dispatchers
16 | import kotlinx.coroutines.GlobalScope
17 | import kotlinx.coroutines.launch
18 | import kotlinx.coroutines.withContext
19 | import javax.inject.Inject
20 |
21 | /**
22 | * @author Jenly
23 | */
24 | class CodeViewModel @Inject constructor(application: Application, model: BaseModel?) : DataViewModel(application, model){
25 |
26 | fun updateQRCode(context: Context,id: String,avatar: String?,type: Int,iv: ImageView){
27 | GlobalScope.launch(Dispatchers.Main) {
28 | var codeContent = ""
29 | if(type == Constants.GROUP_TYPE){
30 | codeContent = Constants.GROUP_CODE_PREFIX + id
31 | } else{
32 | codeContent = Constants.USER_CODE_PREFIX + id
33 | }
34 | val code = withContext(Dispatchers.IO){
35 | var logo : Bitmap? = null
36 | if(avatar != null){
37 | var bmp: Bitmap? = null
38 | var file = GlideApp.with(context).load(avatar).downloadOnly(100,100).get()
39 | if(file != null){
40 | bmp = BitmapFactory.decodeFile(file.absolutePath)
41 | }else{
42 | bmp = BitmapFactory.decodeResource(context.resources, R.drawable.logo)
43 | }
44 |
45 | logo = BitmapUtil.getOvalBitmap(bmp)
46 | }
47 |
48 | CodeUtils.createQRCode(codeContent,400,logo)
49 | }
50 |
51 | GlideApp.with(context).load(code).into(iv)
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/friend/FriendModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.friend
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import com.king.easychat.api.ApiService
5 | import com.king.easychat.app.base.MessageModel
6 | import com.king.easychat.bean.Result
7 | import com.king.easychat.bean.User
8 | import com.king.frame.mvvmframe.bean.Resource
9 | import com.king.frame.mvvmframe.data.IDataRepository
10 | import com.king.frame.mvvmframe.http.callback.ApiCallback
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.GlobalScope
13 | import kotlinx.coroutines.launch
14 | import retrofit2.Call
15 | import javax.inject.Inject
16 |
17 | /**
18 | * @author Jenly
19 | */
20 | class FriendModel @Inject constructor(repository: IDataRepository?) : MessageModel(repository){
21 |
22 | val friendResource = MutableLiveData>>()
23 |
24 |
25 | fun getFriends(token: String){
26 | friendResource.value = Resource.loading()
27 | getRetrofitService(ApiService::class.java)
28 | .getFriends(token)
29 | .enqueue(object : ApiCallback>>(){
30 | override fun onResponse(call: Call>>?, result: Result>?) {
31 | result?.let {
32 | if(it.isSuccess()){
33 | friendResource.value = Resource.success(it.data)
34 | saveUsers(it.data)
35 | return
36 | }else{
37 | friendResource.value = Resource.failure(result.desc)
38 | }
39 |
40 | } ?: run {
41 | friendResource.value = Resource.failure(null)
42 | }
43 |
44 |
45 | }
46 |
47 | override fun onError(call: Call>>?, t: Throwable?) {
48 | friendResource.value = Resource.error(t)
49 | }
50 |
51 | })
52 |
53 | }
54 |
55 | fun saveUsers(users: List?){
56 | users?.let {
57 | GlobalScope.launch(Dispatchers.IO) {
58 | with(getUserDao()){
59 | deleteAll()
60 | insert(it)
61 | }
62 | }
63 | }
64 |
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/friend/FriendViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.friend
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.LiveData
5 | import androidx.lifecycle.MediatorLiveData
6 | import com.king.easychat.App
7 | import com.king.easychat.bean.User
8 | import com.king.frame.mvvmframe.base.BaseViewModel
9 | import com.king.frame.mvvmframe.bean.Resource
10 | import javax.inject.Inject
11 |
12 | /**
13 | * @author Jenly
14 | */
15 | class FriendViewModel @Inject constructor(application: Application, model: FriendModel?) : BaseViewModel(application, model){
16 |
17 | var friendsLiveData = MediatorLiveData>()
18 |
19 | var source : LiveData>>? = null
20 |
21 | override fun onCreate() {
22 | super.onCreate()
23 | getFriends()
24 | }
25 |
26 | fun retry(){
27 | getFriends()
28 | }
29 |
30 | /**
31 | * 获取好友列表
32 | */
33 | fun getFriends(){
34 | val token = getApplication().getToken()
35 | mModel.getFriends(token!!)
36 | source?.let {
37 | friendsLiveData.removeSource(it)
38 | }
39 | source = mModel.friendResource
40 | friendsLiveData.addSource(source!!) {
41 | updateStatus(it.status)
42 | if(it.isSuccess){
43 | friendsLiveData.postValue(it.data)
44 | }else {
45 | if(it.isFailure){
46 | sendMessage(it.message)
47 | }
48 | friendsLiveData.addSource(mModel.getUsers()) {friendsLiveData::postValue}
49 | }
50 |
51 | }
52 |
53 | }
54 |
55 |
56 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/group/GroupMemberViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.group
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.MutableLiveData
5 | import com.king.easychat.App
6 | import com.king.easychat.R
7 | import com.king.easychat.api.ApiService
8 | import com.king.easychat.bean.Result
9 | import com.king.easychat.bean.User
10 | import com.king.frame.mvvmframe.base.BaseModel
11 | import com.king.frame.mvvmframe.base.DataViewModel
12 | import com.king.frame.mvvmframe.base.livedata.StatusEvent
13 | import com.king.frame.mvvmframe.http.callback.ApiCallback
14 | import retrofit2.Call
15 | import javax.inject.Inject
16 |
17 | /**
18 | * @author Jenly
19 | */
20 | class GroupMemberViewModel @Inject constructor(application: Application, model: BaseModel?) : DataViewModel(application, model){
21 |
22 |
23 | val usersLiveData = MutableLiveData>()
24 | lateinit var groupId : String
25 |
26 | fun retry(){
27 | getGroupMembers(groupId)
28 | }
29 |
30 | /**
31 | * 获取群成员信息
32 | */
33 | fun getGroupMembers(groupId: String){
34 | updateStatus(StatusEvent.Status.LOADING)
35 | val token = getApplication().getToken()
36 | mModel.getRetrofitService(ApiService::class.java)
37 | .getGroupMembers(token,groupId)
38 | .enqueue(object : ApiCallback>>(){
39 | override fun onResponse(call: Call>>?, result: Result>?) {
40 | result?.let {
41 | if(it.isSuccess()){
42 | updateStatus(StatusEvent.Status.SUCCESS)
43 | usersLiveData.value = it.data
44 | }else{
45 | sendMessage(it.desc)
46 | updateStatus(StatusEvent.Status.FAILURE)
47 | }
48 |
49 | } ?: run{
50 | updateStatus(StatusEvent.Status.FAILURE)
51 | sendMessage(R.string.result_failure)
52 | }
53 | }
54 |
55 | override fun onError(call: Call>>?, t: Throwable?) {
56 | updateStatus(StatusEvent.Status.ERROR)
57 | sendMessage(t?.message)
58 | }
59 |
60 | })
61 |
62 | }
63 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/group/GroupModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.group
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import com.king.easychat.api.ApiService
5 | import com.king.easychat.app.base.MessageModel
6 | import com.king.easychat.bean.Group
7 | import com.king.easychat.bean.Result
8 | import com.king.frame.mvvmframe.bean.Resource
9 | import com.king.frame.mvvmframe.data.IDataRepository
10 | import com.king.frame.mvvmframe.http.callback.ApiCallback
11 | import kotlinx.coroutines.Dispatchers
12 | import kotlinx.coroutines.GlobalScope
13 | import kotlinx.coroutines.launch
14 | import retrofit2.Call
15 | import javax.inject.Inject
16 |
17 | /**
18 | * @author Jenly
19 | */
20 | class GroupModel @Inject constructor(repository: IDataRepository?): MessageModel(repository){
21 |
22 |
23 | val groupResource = MutableLiveData>>()
24 |
25 | /**
26 | * 获取群组列表
27 | */
28 | fun getGroups(token: String){
29 | groupResource.value = Resource.loading()
30 | getRetrofitService(ApiService::class.java)
31 | .getGroups(token)
32 | .enqueue(object : ApiCallback>>(){
33 | override fun onResponse(call: Call>>?, result: Result>?) {
34 | result?.let {
35 | if(it.isSuccess()){
36 | groupResource.value = Resource.success(it.data)
37 | saveGroups(it.data)
38 | return
39 | }else{
40 | groupResource.value = Resource.failure(result.desc)
41 | }
42 |
43 | } ?: run {
44 | groupResource.value = Resource.failure(null)
45 | }
46 |
47 |
48 | }
49 |
50 | override fun onError(call: Call>>?, t: Throwable?) {
51 | groupResource.value = Resource.error(t)
52 | }
53 |
54 | })
55 |
56 | }
57 |
58 | fun saveGroups(users: List?){
59 | users?.let {
60 | GlobalScope.launch(Dispatchers.IO) {
61 | with(getGroupDao()){
62 | deleteAll()
63 | insert(it)
64 | }
65 | }
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/group/GroupViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.group
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.LiveData
5 | import androidx.lifecycle.MediatorLiveData
6 | import com.king.easychat.App
7 | import com.king.easychat.bean.Group
8 | import com.king.easychat.netty.NettyClient
9 | import com.king.easychat.netty.packet.req.CreateGroupReq
10 | import com.king.frame.mvvmframe.base.BaseViewModel
11 | import com.king.frame.mvvmframe.bean.Resource
12 | import javax.inject.Inject
13 |
14 | /**
15 | * @author Jenly
16 | */
17 | class GroupViewModel @Inject constructor(application: Application, model: GroupModel?) : BaseViewModel(application, model){
18 |
19 | var groupsLiveData = MediatorLiveData>()
20 |
21 | var source : LiveData>>? = null
22 |
23 | override fun onCreate() {
24 | super.onCreate()
25 | getGroups()
26 | }
27 |
28 | fun retry(){
29 | getGroups()
30 | }
31 |
32 | /**
33 | * 获取群组列表
34 | */
35 | fun getGroups(){
36 | val token = getApplication().getToken()
37 | mModel.getGroups(token!!)
38 | source?.let {
39 | groupsLiveData.removeSource(it)
40 | }
41 | source = mModel.groupResource
42 | groupsLiveData.addSource(source!!){
43 | updateStatus(it.status)
44 | if(it.isSuccess){
45 | groupsLiveData.postValue(it.data)
46 | }else {
47 | if(it.isFailure){
48 | sendMessage(it.message)
49 | }
50 | groupsLiveData.addSource(mModel.getGroups()){groupsLiveData::postValue}
51 | }
52 | }
53 |
54 | }
55 |
56 | fun createGroup(groupName: String){
57 | NettyClient.INSTANCE.sendMessage(CreateGroupReq(groupName,null))
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/photo/PhotoViewActivity.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.photo
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import androidx.core.view.ViewCompat
6 | import androidx.viewpager2.widget.ViewPager2
7 | import com.chad.library.adapter.base.BaseQuickAdapter
8 | import com.king.easychat.R
9 | import com.king.easychat.app.Constants
10 | import com.king.easychat.app.adapter.BindingAdapter
11 | import com.king.easychat.app.base.BaseActivity
12 | import com.king.easychat.databinding.PhotoViewActivityBinding
13 | import com.king.frame.mvvmframe.base.DataViewModel
14 | import kotlinx.android.synthetic.main.photo_view_activity.*
15 |
16 | /**
17 | * @author Jenly
18 | */
19 | class PhotoViewActivity : BaseActivity() {
20 |
21 | var size = 0
22 |
23 | companion object{
24 | const val IMAGE = "image"
25 | }
26 |
27 | val mAdapter by lazy { BindingAdapter(R.layout.vp_photo_item) }
28 |
29 | override fun initData(savedInstanceState: Bundle?) {
30 | ViewCompat.setTransitionName(vp, IMAGE)
31 | val list = intent.getStringArrayListExtra(Constants.KEY_LIST)
32 | list?.let {
33 | size = it.size
34 | if(it.size>1){
35 | tvPage.visibility = View.VISIBLE
36 | }else{
37 | tvPage.visibility = View.GONE
38 | }
39 |
40 | }
41 | vp.adapter = mAdapter
42 | vp.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback(){
43 | override fun onPageSelected(position: Int) {
44 | super.onPageSelected(position)
45 | updatePage(position+1,size)
46 | }
47 | })
48 | mAdapter.onItemClickListener = BaseQuickAdapter.OnItemClickListener { adapter, view, position -> onBackPressed() }
49 | mAdapter.replaceData(list)
50 |
51 | }
52 |
53 |
54 | override fun getLayoutId(): Int {
55 | return R.layout.photo_view_activity
56 | }
57 |
58 | private fun updatePage(position: Int,size: Int){
59 | tvPage.text = "$position/$size"
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/search/SearchViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.search
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.MutableLiveData
5 | import com.king.easychat.App
6 | import com.king.easychat.R
7 | import com.king.easychat.api.ApiService
8 | import com.king.easychat.bean.Result
9 | import com.king.easychat.bean.Search
10 | import com.king.frame.mvvmframe.base.BaseModel
11 | import com.king.frame.mvvmframe.base.DataViewModel
12 | import com.king.frame.mvvmframe.base.livedata.StatusEvent
13 | import com.king.frame.mvvmframe.http.callback.ApiCallback
14 | import retrofit2.Call
15 | import timber.log.Timber
16 | import javax.inject.Inject
17 |
18 | /**
19 | * @author Jenly
20 | */
21 | class SearchViewModel @Inject constructor(application: Application, model: BaseModel?) : DataViewModel(application,model){
22 |
23 | val searchsLiveData = MutableLiveData>()
24 |
25 | /**
26 | * 搜索
27 | */
28 | fun search(keyword: String,curPage: Int,pageSize: Int){
29 | val token = getApplication().getToken()
30 | updateStatus(StatusEvent.Status.LOADING)
31 | getRetrofitService(ApiService::class.java)
32 | .search(token,keyword,curPage,pageSize)
33 | .enqueue(object : ApiCallback>>(){
34 | override fun onResponse(call: Call>>?, result: Result>?) {
35 | result?.let {
36 | if(it.isSuccess()){
37 | updateStatus(StatusEvent.Status.SUCCESS)
38 | searchsLiveData.value = it.data
39 | }else{
40 | sendMessage(it.desc)
41 | Timber.d(it.desc)
42 | updateStatus(StatusEvent.Status.FAILURE)
43 | }
44 | } ?: run {
45 | updateStatus(StatusEvent.Status.FAILURE)
46 | sendMessage(R.string.result_failure)
47 | }
48 | }
49 |
50 | override fun onError(call: Call>>?, t: Throwable) {
51 | updateStatus(StatusEvent.Status.ERROR)
52 | sendMessage(t.message)
53 | }
54 |
55 | })
56 |
57 | }
58 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/app/splash/SplashViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.app.splash
2 |
3 | import android.app.Application
4 | import com.king.easychat.netty.NettyClient
5 | import com.king.easychat.netty.packet.req.LoginReq
6 | import com.king.frame.mvvmframe.base.BaseModel
7 | import com.king.frame.mvvmframe.base.DataViewModel
8 | import javax.inject.Inject
9 |
10 | /**
11 | * @author Jenly
12 | */
13 | class SplashViewModel @Inject constructor(application: Application, model: BaseModel?) : DataViewModel(application, model){
14 |
15 |
16 | override fun onCreate() {
17 | super.onCreate()
18 |
19 | }
20 |
21 | fun login(loginReq: LoginReq){
22 | NettyClient.INSTANCE.sendMessage(loginReq)
23 | }
24 |
25 |
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/AppVersion.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | /**
4 | * @author Jenly
5 | */
6 | class AppVersion {
7 | /** 版本码 */
8 | val versionCode: Int? = null
9 | /** 版本名称 */
10 | val versionName: String? = null
11 | /** 版本更新描述 */
12 | val versionDesc: String? = null
13 | /** 下载链接 */
14 | val downloadUrl: String? = null
15 | /** 是否强制升级 */
16 | val isForcedUpgrade: Boolean = false
17 |
18 | /** 发布时间 */
19 | val releaseTime: String? = null
20 |
21 | override fun toString(): String {
22 | return "AppVersion(versionCode=$versionCode, versionName=$versionName, versionDesc=$versionDesc, downloadUrl=$downloadUrl, isForcedUpgrade=$isForcedUpgrade, releaseTime=$releaseTime)"
23 | }
24 |
25 |
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/Group.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import android.os.Parcelable
4 | import androidx.room.Entity
5 | import androidx.room.Ignore
6 | import androidx.room.Index
7 | import androidx.room.PrimaryKey
8 | import kotlinx.android.parcel.Parcelize
9 |
10 |
11 | /**
12 | * @author: Zed
13 | * date: 2019/08/22.
14 | * description:
15 | */
16 | @Entity(indices = [Index(value = ["groupId"], unique = true)])
17 | @Parcelize
18 | class Group(val groupId: String,var groupName: String,var avatar: String?,var mainUserId: String?) : Parcelable {
19 |
20 | @PrimaryKey(autoGenerate = true)
21 | var id: Int = 0
22 |
23 | @Ignore var memberNum: Int = 0
24 |
25 | fun getMemberNumber(): String{
26 | return memberNum.toString()
27 | }
28 |
29 | override fun equals(other: Any?): Boolean {
30 | if (this === other) return true
31 | if (javaClass != other?.javaClass) return false
32 |
33 | other as Group
34 |
35 | if (groupId != other.groupId) return false
36 |
37 | return true
38 | }
39 |
40 | override fun hashCode(): Int {
41 | return groupId.hashCode()
42 | }
43 |
44 | override fun toString(): String {
45 | return "Group(groupId='$groupId', groupName='$groupName', avatar=$avatar, mainUserId=$mainUserId, memberNum=$memberNum, id=$id)"
46 | }
47 |
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/GroupMessageDbo.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import android.os.Parcelable
4 | import androidx.room.Entity
5 | import androidx.room.Index
6 | import androidx.room.PrimaryKey
7 | import com.king.easychat.netty.packet.resp.GroupMessageResp
8 | import kotlinx.android.parcel.Parcelize
9 |
10 | /**
11 | * @author Zed
12 | * date: 2019/10/14.
13 | * description:
14 | */
15 | @Entity(indices = [Index(value = ["groupId"])])
16 | @Parcelize
17 | class GroupMessageDbo(val userId : String, val groupId: String, val sender : String, val senderName : String?,var avatar: String?,val message : String,
18 | val send: Boolean = false, val messageType : Int, var dateTime : String,var read: Boolean = false) : Parcelable {
19 | @PrimaryKey(autoGenerate = true)
20 | var id: Long = 0
21 |
22 | fun toGroupMessageResp(): GroupMessageResp {
23 | val resp = GroupMessageResp(sender,senderName,avatar,message,groupId,messageType,userId == sender)
24 | resp.dateTime = dateTime
25 | return resp
26 | }
27 |
28 | override fun toString(): String {
29 | return "GroupMessageDbo(userId='$userId', groupId='$groupId', sender='$sender', senderName=$senderName, avatar=$avatar, message='$message', send=$send, messageType=$messageType, dateTime='$dateTime', read=$read, id=$id)"
30 | }
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/Message.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import com.king.base.util.StringUtils
4 | import com.king.easychat.util.AES
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description: 消息列表
10 | */
11 | class Message {
12 |
13 | companion object{
14 | var userMode = 0
15 | var groupMode = 1
16 | }
17 |
18 | /** 用户id 或者群聊id*/
19 | var id : String?=null
20 | /** 消息时间 用于排序*/
21 | var dateTime : String?=null
22 | /** 0 单聊消息 1 群聊消息*/
23 | var messageMode : Int?=null
24 |
25 | /** 单聊为好友id 群聊为发送者id*/
26 | var senderId : String?=null
27 | /** 发送的消息内容*/
28 | var message : String?=null
29 |
30 | /** 0 普通消息 1 图片消息*/
31 | var messageType : Int?=null
32 |
33 | var name : String? = null
34 |
35 | var avatar: String? = null
36 |
37 | /**
38 | * 未读消息数
39 | */
40 | var count = 0
41 |
42 | fun getMsg() : String? {
43 | if(messageType ==1){
44 | return "[图片消息]"
45 | }
46 | message?.let {
47 | return AES.decrypt(it, "${dateTime}ab")
48 | }
49 | return null
50 | }
51 |
52 | fun getShowName(): String?{
53 | return if(StringUtils.isNotBlank(name)) name else id
54 | }
55 |
56 | override fun toString(): String {
57 | return "Message(id=$id, dateTime=$dateTime, messageMode=$messageMode, senderId=$senderId, message=$message, messageType=$messageType, name=$name, avatar=$avatar, count=$count)"
58 | }
59 |
60 |
61 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/MessageDbo.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import android.os.Parcelable
4 | import androidx.room.Entity
5 | import androidx.room.Index
6 | import androidx.room.PrimaryKey
7 | import com.king.easychat.netty.packet.resp.MessageResp
8 | import kotlinx.android.parcel.Parcelize
9 |
10 | /**
11 | * @author Zed
12 | * date: 2019/10/14.
13 | * description:
14 | */
15 | @Entity(indices = [Index(value = ["sender"]), Index(value = ["receiver"])])
16 | @Parcelize
17 | open class MessageDbo(var userId : String, val sender : String?, val receiver: String?
18 | ,val message : String, val send: Boolean = false
19 | , val messageType : Int, var dateTime : String
20 | ,val senderName : String?,var read: Boolean = false) : Parcelable {
21 | @PrimaryKey(autoGenerate = true)
22 | var id: Long = 0
23 |
24 | fun toMessageResp(): MessageResp{
25 | var resp = MessageResp(sender,senderName,message,send,messageType)
26 | resp.dateTime = dateTime
27 | return resp
28 | }
29 |
30 | override fun toString(): String {
31 | return "MessageDbo(userId='$userId', sender=$sender, receiver=$receiver, message='$message', send=$send, messageType=$messageType, dateTime='$dateTime', senderName=$senderName, read=$read, id=$id)"
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/Operator.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import android.os.Parcelable
4 | import kotlinx.android.parcel.Parcelize
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @Parcelize
10 | class Operator(val event: Int): Parcelable
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/RecentChat.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import androidx.room.Entity
4 | import androidx.room.Index
5 | import androidx.room.PrimaryKey
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | @Entity(indices = [Index(value = ["chatId"], unique = true)])
11 | class RecentChat(val userId: String,val chatId: String,var showName: String?,var avatar: String?,var dateTime: String){
12 |
13 | @PrimaryKey(autoGenerate = true)
14 | var id: Int = 0
15 |
16 | override fun toString(): String {
17 | return "RecentChat(userId='$userId', chatId='$chatId', showName=$showName, avatar=$avatar, dateTime='$dateTime', id=$id)"
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/RecentGroupChat.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import androidx.room.Entity
4 | import androidx.room.Index
5 | import androidx.room.PrimaryKey
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | @Entity(indices = [Index(value = ["groupChatId"], unique = true)])
11 | class RecentGroupChat(val userId: String, var groupChatId: String, var showName: String?, var avatar: String?, var dateTime: String){
12 |
13 | @PrimaryKey(autoGenerate = true)
14 | var id: Int = 0
15 |
16 | override fun toString(): String {
17 | return "RecentGroupChat(userId='$userId', groupChatId='$groupChatId', showName=$showName, avatar=$avatar, dateTime='$dateTime', id=$id)"
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/Result.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | /**
4 | * @author Jenly
5 | */
6 | class Result {
7 |
8 | var code : String? = null
9 |
10 | var desc : String? = null
11 |
12 | var data : T? = null
13 |
14 | fun isSuccess(): Boolean{
15 | return "0" == code
16 | }
17 |
18 | override fun toString(): String {
19 | return "Result(code=$code, desc=$desc, data=$data)"
20 | }
21 |
22 |
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/Search.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import com.king.base.util.StringUtils
4 |
5 | /**
6 | * @author Jenly
7 | */
8 | class Search {
9 |
10 | companion object{
11 | const val USER_TYPE = 0
12 | const val GROUP_TYPE = 1
13 | }
14 |
15 | /** 用户id 或者群id */
16 | var id: String? = null
17 | /** 用户名称或者群名称 */
18 | var name: String? = null
19 | /** 用户 昵称 */
20 | var nickName: String? = null
21 | /** 用户图像或者群头像 */
22 | var avatar: String? = null
23 | /** 类型 0 用户类型 1 群类型 */
24 | var type: Int = USER_TYPE
25 |
26 | fun getShowName(): String?{
27 | if(StringUtils.isNotBlank(nickName)){
28 | return nickName
29 | }
30 |
31 | return name
32 | }
33 |
34 | fun getTypeName(): String?{
35 | when(type){
36 | USER_TYPE -> return "用户"
37 | GROUP_TYPE -> return "群组"
38 | }
39 | return "未知"
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/bean/User.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.bean
2 |
3 | import android.os.Parcelable
4 | import androidx.room.Entity
5 | import androidx.room.Index
6 | import kotlinx.android.parcel.Parcelize
7 | import androidx.room.PrimaryKey
8 |
9 |
10 |
11 |
12 | /**
13 | * @author Zed
14 | * date: 2019/10/09.
15 | * description:
16 | */
17 | @Entity(indices = [Index(value = ["userId"], unique = true)])
18 | @Parcelize
19 | class User(val userId: String,val userName: String,var nickName: String?,var avatar: String?,var signature: String?,
20 | var remark: String? = null) : Parcelable {
21 |
22 | @PrimaryKey(autoGenerate = true)
23 | var id: Int = 0
24 |
25 | fun getShowName(): String {
26 | remark?.let {
27 | return it
28 | }
29 | nickName?.let {
30 | return it
31 | }
32 |
33 | return userName
34 | }
35 |
36 | override fun toString(): String {
37 | return "User(userId=$userId, userName=$userName, nickName=$nickName, avatar=$avatar, signature=$signature)"
38 | }
39 |
40 | override fun equals(other: Any?): Boolean {
41 | if (this === other) return true
42 | if (javaClass != other?.javaClass) return false
43 |
44 | other as User
45 |
46 | if (userId != other.userId) return false
47 |
48 | return true
49 | }
50 |
51 | override fun hashCode(): Int {
52 | return userId.hashCode()
53 | }
54 |
55 |
56 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/config/ConfigModule.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.config
2 |
3 | import android.content.Context
4 | import com.king.base.baseurlmanager.BaseUrlManager
5 | import com.king.easychat.app.Constants
6 | import com.king.frame.mvvmframe.config.FrameConfigModule
7 | import com.king.frame.mvvmframe.di.module.ConfigModule
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | class ConfigModule : FrameConfigModule() {
13 | override fun applyOptions(context: Context, builder: ConfigModule.Builder?) {
14 | if(Constants.isDomain){
15 | val manager = BaseUrlManager(context)
16 | builder?.baseUrl(Constants.getBaseUrl(manager.baseUrl))
17 | }else{
18 | builder?.baseUrl(Constants.BASE_URL)
19 | }
20 |
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/dao/AppDatabase.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.dao
2 |
3 | import androidx.room.Database
4 | import androidx.room.RoomDatabase
5 | import com.king.easychat.bean.*
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | @Database(entities = [User::class, Group::class, MessageDbo::class,GroupMessageDbo::class, RecentChat::class,RecentGroupChat::class], version = 1,exportSchema = false)
11 | abstract class AppDatabase : RoomDatabase() {
12 |
13 | abstract fun userDao(): UserDao
14 | abstract fun groupDao(): GroupDao
15 | abstract fun groupMessageDao(): GroupMessageDao
16 | abstract fun messageDao(): MessageDao
17 |
18 | abstract fun recentChatDao(): RecentChatDao
19 | abstract fun recentGroupChatDao(): RecentGroupChatDao
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/dao/GroupDao.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.dao
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.room.*
5 | import com.king.easychat.bean.Group
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | @Dao
11 | interface GroupDao {
12 |
13 | /**
14 | * 插入并去重
15 | */
16 | @Insert(onConflict = OnConflictStrategy.REPLACE)
17 | fun insert(group: Group)
18 |
19 | @Insert(onConflict = OnConflictStrategy.REPLACE)
20 | fun insert(groups: List)
21 |
22 | @Delete
23 | fun delete(group: Group)
24 |
25 | /**
26 | * 删除所有
27 | */
28 | @Query("DELETE FROM `group`")
29 | fun deleteAll()
30 |
31 | @Query("DELETE FROM `group` WHERE groupId = :groupId")
32 | fun delete(groupId: String)
33 |
34 | /**
35 | * 查询所有群组列表
36 | */
37 | @Query("SELECT * FROM `group`")
38 | fun getAllGroups(): LiveData>
39 |
40 | @Query("SELECT * FROM `group`")
41 | fun getGroups(): List
42 |
43 | /**
44 | * 查询群组列表
45 | */
46 | @Query("SELECT * FROM `group` ORDER BY groupId DESC LIMIT :count")
47 | fun getGroups(count: Int): LiveData>
48 |
49 | /**
50 | * 修改群组
51 | */
52 | // @Update
53 | // fun updateGroup(group: Group)
54 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/dao/GroupMessageDao.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.dao
2 |
3 | import androidx.room.*
4 | import com.king.easychat.bean.GroupMessageDbo
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @Dao
10 | interface GroupMessageDao {
11 | /**
12 | * 插入并去重
13 | */
14 | @Insert(onConflict = OnConflictStrategy.REPLACE)
15 | fun insert(message: GroupMessageDbo)
16 |
17 | @Delete
18 | fun delete(message: GroupMessageDbo)
19 |
20 | /**
21 | * 删除所有
22 | */
23 | @Query("DELETE FROM GroupMessageDbo")
24 | fun deleteAll()
25 |
26 | /**
27 | * 获取所有的群聊id
28 | */
29 | @Query("SELECT groupId FROM GroupMessageDbo WHERE userId = :userId GROUP BY groupId")
30 | fun queryAllGroups(userId : String) : List
31 |
32 | /**
33 | * 根据时间倒序查询最近聊天的几个用户
34 | */
35 | @Query("SELECT * FROM GroupMessageDbo WHERE userId = :userId AND groupId = :groupId order by dateTime desc limit 1")
36 | fun getLastMessageByGroupId(userId : String, groupId: String): GroupMessageDbo?
37 |
38 | /**
39 | * 根据群id获取好友的最近几条聊天记录
40 | */
41 | @Query("SELECT * FROM GroupMessageDbo WHERE userId = :userId AND groupId = :groupId order by dateTime desc limit :start, :pageSize")
42 | fun getGroupMessageByGroupId(userId : String, groupId : String, start : Int, pageSize : Int) : List
43 |
44 | /**
45 | * 查询未读消息记录数
46 | */
47 | @Query("SELECT COUNT(*) FROM GroupMessageDbo WHERE userId = :userId AND groupId = :groupId AND read = '0'")
48 | fun getUnreadNumByGroupId(userId : String, groupId : String) : Int
49 |
50 | /**
51 | * 查询未读消息记录数
52 | */
53 | @Query("SELECT id FROM GroupMessageDbo WHERE userId = :userId AND groupId = :groupId AND read = '0'")
54 | fun getUnreadList(userId : String, groupId : String) : List
55 |
56 | /**
57 | * 更新为已读消息
58 | */
59 | @Query("UPDATE GroupMessageDbo SET read = '1' WHERE userId =:userId AND groupId = :groupId")
60 | fun updateRead(userId : String, groupId : String) : Int
61 |
62 | /**
63 | * 更新为已读消息
64 | */
65 | @Query("UPDATE GroupMessageDbo SET read = '1' WHERE userId =:userId")
66 | fun updateRead(userId : String) : Int
67 |
68 |
69 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/dao/MessageDao.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.dao
2 |
3 | import androidx.room.*
4 | import com.king.easychat.bean.MessageDbo
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @Dao
10 | interface MessageDao {
11 | /**
12 | * 插入并去重
13 | */
14 | @Insert(onConflict = OnConflictStrategy.REPLACE)
15 | fun insert(message: MessageDbo)
16 |
17 | @Delete
18 | fun delete(message: MessageDbo)
19 |
20 | /**
21 | * 删除所有
22 | */
23 | @Query("DELETE FROM MessageDbo")
24 | fun deleteAll()
25 |
26 | /**
27 | * 获取所有的聊天好友id
28 | */
29 | @Query("SELECT sender FROM MessageDbo WHERE userId = :userId GROUP BY sender")
30 | fun queryAllFriends(userId : String) : List
31 |
32 | /**
33 | * 根据时间倒序查询最近聊天的几个用户
34 | */
35 | @Query("SELECT * FROM MessageDbo WHERE userId = :userId AND (sender = :sender OR receiver = :receiver) ORDER BY dateTime DESC LIMIT 1")
36 | fun getLastMessageBySenderId(userId : String, sender: String,receiver: String): MessageDbo?
37 |
38 | /**
39 | * 根据好友id获取好友的最近几条聊天记录
40 | */
41 | @Query("SELECT * FROM MessageDbo WHERE userId = :userId AND (sender = :senderId OR receiver = :receiver) ORDER BY dateTime DESC LIMIT :start, :pageSize")
42 | fun getMessageBySenderId(userId : String,senderId : String,receiver : String, start : Int, pageSize : Int) : List
43 |
44 | /**
45 | * 查询未读消息记录数
46 | */
47 | @Query("SELECT COUNT(*) FROM MessageDbo WHERE userId = :userId AND sender = :senderId AND read = '0'")
48 | fun getUnreadNumBySenderId(userId : String, senderId : String) : Int
49 |
50 | /**
51 | * 查询未读消息记录数
52 | */
53 | @Query("SELECT id FROM MessageDbo WHERE userId = :userId AND sender = :senderId AND read = '0' GROUP BY id")
54 | fun getUnreadList(userId : String, senderId : String) : List
55 |
56 | /**
57 | * 更新为已读消息
58 | */
59 | @Query("UPDATE MessageDbo SET read = '1' WHERE userId =:userId AND (sender = :senderId OR receiver = :receiver)")
60 | fun updateRead(userId : String, senderId : String,receiver : String) : Int
61 |
62 | /**
63 | * 更新为已读消息
64 | */
65 | @Query("UPDATE MessageDbo SET read = '1' WHERE userId =:userId")
66 | fun updateRead(userId : String) : Int
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/dao/RecentChatDao.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.dao
2 |
3 | import androidx.room.*
4 | import com.king.easychat.bean.RecentChat
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @Dao
10 | interface RecentChatDao {
11 |
12 | @Insert(onConflict = OnConflictStrategy.REPLACE)
13 | fun insert(data: RecentChat)
14 |
15 | @Query("DELETE FROM RecentChat WHERE userId = :userId AND chatId = :chatId")
16 | fun delete(userId: String,chatId: String)
17 |
18 | @Query("DELETE FROM RecentChat WHERE userId = :userId")
19 | fun delete(userId: String)
20 |
21 |
22 | @Query("SELECT * FROM RecentChat WHERE userId = :userId")
23 | fun getRecentChats(userId: String): List
24 |
25 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/dao/RecentGroupChatDao.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.dao
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy
6 | import androidx.room.Query
7 | import com.king.easychat.bean.RecentGroupChat
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | @Dao
13 | interface RecentGroupChatDao {
14 |
15 | @Insert(onConflict = OnConflictStrategy.REPLACE)
16 | fun insert(data: RecentGroupChat)
17 |
18 | @Query("DELETE FROM RecentGroupChat WHERE userId = :userId AND groupChatId = :groupChatId")
19 | fun delete(userId: String,groupChatId: String)
20 |
21 | @Query("DELETE FROM RecentGroupChat WHERE userId = :userId")
22 | fun delete(userId: String)
23 |
24 | @Query("SELECT * FROM RecentGroupChat WHERE userId = :userId")
25 | fun getRecentGroupChats(userId: String): List
26 |
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/dao/UserDao.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.dao
2 |
3 | import androidx.room.*
4 | import com.king.easychat.bean.User
5 | import androidx.lifecycle.LiveData
6 |
7 |
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | @Dao
13 | interface UserDao {
14 |
15 | /**
16 | * 插入并去重
17 | */
18 | @Insert(onConflict = OnConflictStrategy.REPLACE)
19 | fun insert(user: User)
20 |
21 | @Insert(onConflict = OnConflictStrategy.REPLACE)
22 | fun insert(users: List)
23 |
24 | @Delete
25 | fun delete(user: User)
26 |
27 | /**
28 | * 删除所有
29 | */
30 | @Query("DELETE FROM User")
31 | fun deleteAll()
32 |
33 | @Query("DELETE FROM User WHERE userId = :userId")
34 | fun delete(userId: String)
35 |
36 | /**
37 | * 查询所有用户列表
38 | */
39 | @Query("SELECT * FROM User")
40 | fun getAllUsers(): LiveData>
41 |
42 | @Query("SELECT * FROM User")
43 | fun getUsers(): List
44 |
45 | /**
46 | * 查询用户列表
47 | */
48 | @Query("SELECT * FROM User ORDER BY userId DESC LIMIT :count")
49 | fun getUsers(count: Int): LiveData>
50 |
51 | /**
52 | * 修改用户
53 | */
54 | // @Update
55 | // fun updateUser(user: User)
56 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/di/component/ApplicationComponent.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.di.component
2 |
3 | import com.king.easychat.App
4 | import com.king.easychat.di.module.ApplicationModule
5 | import com.king.frame.mvvmframe.di.component.AppComponent
6 | import com.king.frame.mvvmframe.di.scope.ApplicationScope
7 | import dagger.Component
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | @ApplicationScope
13 | @Component(dependencies = [AppComponent::class], modules = [ApplicationModule::class])
14 | interface ApplicationComponent {
15 |
16 | fun inject(app: App)
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/di/module/ApplicationModule.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.di.module
2 |
3 | import com.king.frame.mvvmframe.di.module.ViewModelFactoryModule
4 | import dagger.Module
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @Module(includes = [ViewModelFactoryModule::class,ViewModelModule::class,ActivityModule::class,FragmentModule::class])
10 | class ApplicationModule {
11 |
12 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/di/module/FragmentModule.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.di.module
2 |
3 | import com.king.easychat.app.friend.FriendFragment
4 | import com.king.easychat.app.group.GroupFragment
5 | import com.king.easychat.app.home.HomeFragment
6 | import com.king.easychat.app.me.MeFragment
7 | import com.king.easychat.temp.TempFragment
8 | import com.king.frame.mvvmframe.di.component.BaseFragmentSubcomponent
9 | import dagger.Module
10 | import dagger.android.ContributesAndroidInjector
11 |
12 | /**
13 | * @author Jenly
14 | */
15 | @Module(subcomponents = [BaseFragmentSubcomponent::class])
16 | abstract class FragmentModule {
17 |
18 | @ContributesAndroidInjector
19 | abstract fun contributeTempFragment(): TempFragment
20 |
21 | @ContributesAndroidInjector
22 | abstract fun contributeHomeFragment(): HomeFragment
23 |
24 | @ContributesAndroidInjector
25 | abstract fun contributeFriendFragment(): FriendFragment
26 |
27 | @ContributesAndroidInjector
28 | abstract fun contributeGroupFragment(): GroupFragment
29 |
30 | @ContributesAndroidInjector
31 | abstract fun contributeMeFragment(): MeFragment
32 |
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/glide/GlideModule.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.glide
2 |
3 | import android.content.Context
4 | import com.bumptech.glide.GlideBuilder
5 | import com.bumptech.glide.annotation.GlideModule
6 | import com.bumptech.glide.load.engine.DiskCacheStrategy
7 | import com.bumptech.glide.module.AppGlideModule
8 | import com.bumptech.glide.request.RequestOptions
9 |
10 | /**
11 | * @author Jenly
12 | */
13 | @GlideModule
14 | class GlideModule : AppGlideModule(){
15 |
16 | override fun applyOptions(context: Context, builder: GlideBuilder) {
17 | super.applyOptions(context, builder)
18 | builder.setDefaultRequestOptions(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.RESOURCE))
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/glide/ImageLoader.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.glide
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.widget.ImageView
6 | import androidx.fragment.app.Fragment
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | object ImageLoader {
12 |
13 |
14 | fun displayImage(iv: ImageView,url: String?,defaultImage: Int){
15 | url?.let {
16 | GlideApp.with(iv).load(url).error(defaultImage).into(iv)
17 | } ?: run {
18 | iv.setImageResource(defaultImage)
19 | }
20 | }
21 |
22 | fun displayImage(context: Context,iv: ImageView,url: String?,defaultImage: Int){
23 | url?.let {
24 | GlideApp.with(context).load(url).error(defaultImage).into(iv)
25 | } ?: run {
26 | iv.setImageResource(defaultImage)
27 | }
28 | }
29 |
30 | fun displayImage(fragment: Fragment,iv: ImageView,url: String?,defaultImage: Int){
31 | url?.let {
32 | GlideApp.with(fragment).load(url).error(defaultImage).into(iv)
33 | } ?: run {
34 | iv.setImageResource(defaultImage)
35 | }
36 | }
37 |
38 | fun displayImage(activity: Activity,iv: ImageView,url: String?,defaultImage: Int){
39 | url?.let {
40 | GlideApp.with(activity).load(url).error(defaultImage).into(iv)
41 | } ?: run {
42 | iv.setImageResource(defaultImage)
43 | }
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/ChannelInitial.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty
2 |
3 | import com.king.easychat.netty.codec.PacketDecoder
4 | import com.king.easychat.netty.codec.PacketEncoder
5 | import com.king.easychat.netty.codec.Spliter
6 | import com.king.easychat.netty.handle.*
7 | import io.netty.channel.ChannelInitializer
8 | import io.netty.channel.socket.SocketChannel
9 |
10 | /**
11 | * @author Jenly
12 | */
13 | class ChannelInitial : ChannelInitializer(){
14 |
15 | override fun initChannel(ch: SocketChannel?) {
16 | ch?.pipeline()?.let {
17 | it.addLast(Spliter())
18 | .addLast(PacketDecoder())
19 | .addLast(PacketEncoder())
20 | .addLast(LoginRespHandler())
21 | .addLast(MessageRespHandler())
22 | .addLast(MessageSelfRespHandler())
23 | .addLast(GroupMessageRespHandler())
24 | .addLast(HeartBeatRespHandler())
25 | .addLast(AddUserRespHandler())
26 | .addLast(AddUserSelfRespHandler())
27 | .addLast(AcceptRespHandler())
28 | .addLast(CreateGroupRespHandler())
29 | .addLast(InviteGroupRespHandler())
30 | .addLast(InviteGroupSelfRespHandler())
31 | .addLast(AcceptGroupRespHandler())
32 | .addLast(ApplyGroupRespHandler())
33 | .addLast(ApplyGroupSelfRespHandler())
34 | .addLast(AllowGroupRespHandler())
35 | }
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/codec/PacketDecoder.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.codec
2 |
3 | import io.netty.buffer.ByteBuf
4 | import io.netty.channel.ChannelHandlerContext
5 | import io.netty.handler.codec.ByteToMessageDecoder
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | class PacketDecoder : ByteToMessageDecoder() {
11 |
12 | override fun decode(ctx: ChannelHandlerContext?, byteBuf: ByteBuf?, out: MutableList?) {
13 |
14 | byteBuf?.let {
15 | out?.add(PacketHelper.decode(it))
16 | }
17 |
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/codec/PacketEncoder.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.codec
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import io.netty.buffer.ByteBuf
5 | import io.netty.channel.ChannelHandlerContext
6 | import io.netty.handler.codec.MessageToByteEncoder
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | class PacketEncoder : MessageToByteEncoder() {
12 |
13 | @ExperimentalStdlibApi
14 | override fun encode(ctx: ChannelHandlerContext?, msg: Packet?, out: ByteBuf?) {
15 | out?.let {
16 | msg?.run {
17 | PacketHelper.encode(it,this)
18 | }
19 | }
20 |
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/codec/Spliter.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.codec
2 |
3 | import io.netty.buffer.ByteBuf
4 | import io.netty.channel.ChannelHandlerContext
5 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | class Spliter : LengthFieldBasedFrameDecoder(Int.MAX_VALUE,LENGTH_FIELD_OFFSET,LENGTH_FIELD_LENGTH) {
11 |
12 | companion object{
13 | const val LENGTH_FIELD_OFFSET = 7
14 | const val LENGTH_FIELD_LENGTH = 4
15 | }
16 |
17 | override fun decode(ctx: ChannelHandlerContext?, byteBuf: ByteBuf): Any {
18 |
19 | val magicNumber = byteBuf.getInt(byteBuf.readerIndex())
20 | //如果魔数不匹配则直接关闭通道
21 | if(magicNumber != PacketHelper.MAGIC_NUMBER){
22 | ctx?.channel()?.close()
23 | }
24 |
25 | return super.decode(ctx, byteBuf)
26 |
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/AcceptGroupRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.AcceptGroupResp
4 | import com.king.easychat.netty.packet.resp.GroupMessageResp
5 | import com.king.easychat.netty.packet.resp.MessageResp
6 | import io.netty.channel.ChannelHandler
7 |
8 | /**
9 | * @author Zed
10 | * date: 2019/10/12.
11 | * description:
12 | */
13 | @ChannelHandler.Sharable
14 | class AcceptGroupRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/AcceptRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.AcceptResp
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class AcceptRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/AddUserRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.*
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class AddUserRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/AddUserSelfRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.*
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class AddUserSelfRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/AllowGroupRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.AllowGroupResp
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @ChannelHandler.Sharable
10 | class AllowGroupRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/ApplyGroupRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.ApplyGroupResp
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @ChannelHandler.Sharable
10 | class ApplyGroupRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/ApplyGroupSelfRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.ApplyGroupSelfResp
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @ChannelHandler.Sharable
10 | class ApplyGroupSelfRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/CreateGroupRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.*
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class CreateGroupRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/GroupMessageRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.GroupMessageResp
4 | import com.king.easychat.netty.packet.resp.MessageResp
5 | import io.netty.channel.ChannelHandler
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | @ChannelHandler.Sharable
11 | class GroupMessageRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/HeartBeatRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.HeartBeatResp
4 | import com.king.easychat.netty.packet.resp.MessageResp
5 | import io.netty.channel.ChannelHandler
6 | import io.netty.channel.ChannelHandlerContext
7 | import timber.log.Timber
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | @ChannelHandler.Sharable
13 | class HeartBeatRespHandler : RespHandler(){
14 | // override fun channelRead0(ctx: ChannelHandlerContext?, msg: HeartBeatResp) {
15 | // Timber.d(msg.toString())
16 | // }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/InviteGroupRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.*
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class InviteGroupRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/InviteGroupSelfRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.*
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class InviteGroupSelfRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/LoginRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.LoginResp
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @ChannelHandler.Sharable
10 | class LoginRespHandler : RespHandler()
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/MessageRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.MessageResp
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | @ChannelHandler.Sharable
10 | class MessageRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/MessageSelfRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.*
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class MessageSelfRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/RegisterRespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.netty.packet.resp.*
4 | import io.netty.channel.ChannelHandler
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/12.
9 | * description:
10 | */
11 | @ChannelHandler.Sharable
12 | class RegisterRespHandler : RespHandler()
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/handle/RespHandler.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.handle
2 |
3 | import com.king.easychat.app.Constants
4 | import com.king.easychat.bean.Operator
5 | import com.king.easychat.util.Event
6 | import io.netty.channel.ChannelHandlerContext
7 | import io.netty.channel.SimpleChannelInboundHandler
8 | import timber.log.Timber
9 |
10 | /**
11 | * @author Jenly
12 | */
13 | open class RespHandler : SimpleChannelInboundHandler(){
14 | override fun channelRead0(ctx: ChannelHandlerContext?, msg: T) {
15 | Timber.d(msg.toString())
16 | Event.sendEvent(msg)
17 |
18 | if(!ctx?.channel()!!.isActive){
19 | Event.sendEvent(Operator(Constants.EVENT_NETTY_DISCONNECT))
20 | }
21 | }
22 |
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/MessageType.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet
2 |
3 | /**
4 | * @author Jenly
5 | */
6 | object MessageType {
7 | const val TEXT = 0
8 | const val IMAGE = 1
9 |
10 |
11 | const val NORMAL = 100
12 |
13 | const val HEART = 101
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/Packet.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet
2 |
3 | import com.king.base.util.TimeUtils
4 |
5 | /**
6 | * @author Jenly
7 | */
8 | abstract class Packet {
9 |
10 | constructor(): this(TimeUtils.formatDate(System.currentTimeMillis(),TimeUtils.FORMAT_Y_TO_S))
11 |
12 | constructor(dateTime: String){
13 | this.dateTime = dateTime
14 | }
15 |
16 | var version = 1
17 |
18 | var dateTime : String
19 |
20 | abstract fun packetType(): Int
21 |
22 |
23 | override fun toString(): String {
24 | return "Packet(version=$version, dateTime='$dateTime')"
25 | }
26 |
27 |
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/PacketType.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet
2 |
3 | /**
4 | * @author Jenly
5 | */
6 | object PacketType {
7 |
8 | const val LOGIN_REQ = 1
9 | const val LOGIN_RESP = 2
10 |
11 | const val LOGOUT_REQ = 3
12 | const val LOGOUT_RESP = 4
13 |
14 | const val SEND_MESSAGE_REQ = 5
15 | const val SEND_MESSAGE_RESP = 6
16 |
17 | const val ADD_FRIEND_REQ = 7
18 | const val ADD_FRIEND_RESP = 8
19 | const val ADD_USER_SELF_RESP = 9
20 | const val CREATE_GROUP_REQ = 10
21 | const val CREATE_GROUP_RESP = 11
22 | const val INVITE_GROUP_REQ = 12
23 | const val INVITE_GROUP_RESP = 13
24 | const val INVITE_GROUP_SELF_RESP = 14
25 | const val GROUP_MESSAGE_REQ = 15
26 | const val GROUP_MESSAGE_RESP = 16
27 | const val ACCEPT_GROUP_REQ = 17
28 | const val ACCEPT_GROUP_RESP = 18
29 | const val ACCEPT_REQ = 19
30 | const val ACCEPT_RESP = 20
31 | const val REGISTER_REQ = 21
32 | const val REGISTER_RESP = 22
33 | const val UPDATE_PASSWD_REQ = 23
34 | const val UPDATE_PASSWD_RESP = 24
35 | const val MESSAGE_SELF_RESP = 25
36 | const val HEART_BEAT_REQ = 26
37 | const val HEART_BEAT_RESP = 27
38 | const val SYNC_MESSAGE_REQ = 28
39 | const val APPLY_GROUP_REQ = 29
40 | const val APPLY_GROUP_RESP = 30
41 | const val APPLY_GROUP_SELF_RESP = 31
42 | const val ALLOW_GROUP_REQ = 32
43 | const val ALLOW_GROUP_RESP = 33
44 |
45 |
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/AcceptGroupReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class AcceptGroupReq(val groupId : String, val inviterId : String, val accept : Boolean) : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.ACCEPT_GROUP_REQ
14 | }
15 |
16 | override fun toString(): String {
17 | return "AcceptGroupReq(groupId='$groupId', inviterId='$inviterId', accept=$accept)"
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/AcceptReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class AcceptReq(val receiver : String, val accept : Boolean) : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.ACCEPT_REQ
14 | }
15 |
16 | override fun toString(): String {
17 | return "AcceptReq(receiver='$receiver', accept=$accept)"
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/AddUserReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class AddUserReq(val addUserId : String) : Packet(){
12 | override fun packetType(): Int {
13 | return PacketType.ADD_FRIEND_REQ
14 | }
15 |
16 | override fun toString(): String {
17 | return "AddUserReq(addUserId='$addUserId')"
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/AllowGroupReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | class AllowGroupReq(val groupId: String,val userId: String,val allow: Boolean) : Packet(){
10 |
11 | override fun packetType(): Int {
12 | return PacketType.ALLOW_GROUP_REQ
13 | }
14 |
15 | override fun toString(): String {
16 | return "AllowGroupReq(groupId='$groupId', userId='$userId', allow=$allow)"
17 | }
18 |
19 |
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/ApplyGroupReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | class ApplyGroupReq(val groupId: String) : Packet(){
10 | override fun packetType(): Int {
11 | return PacketType.APPLY_GROUP_REQ
12 | }
13 |
14 | override fun toString(): String {
15 | return "ApplyGroupReq(groupId='$groupId')"
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/CreateGroupReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class CreateGroupReq(val groupName : String, val users : List?) : Packet(){
12 | override fun packetType(): Int {
13 | return PacketType.CREATE_GROUP_REQ
14 | }
15 |
16 | override fun toString(): String {
17 | return "CreateGroupReq(groupName='$groupName', users=$users)"
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/GroupMessageReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.google.gson.annotations.Expose
4 | import com.king.easychat.netty.packet.Packet
5 | import com.king.easychat.netty.packet.PacketType
6 | import com.king.easychat.netty.packet.resp.GroupMessageResp
7 | import com.king.easychat.netty.packet.resp.LoginResp
8 | import com.king.easychat.util.AES
9 |
10 | /**
11 | * @author Zed
12 | * date: 2019/10/09.
13 | * description:
14 | */
15 | class GroupMessageReq(val groupId : String, @Expose val msg : String, var messageType : Int) : Packet(){
16 |
17 | val message = AES.encrypt(msg,"${dateTime}ab").toString()
18 |
19 | override fun packetType(): Int {
20 | return PacketType.GROUP_MESSAGE_REQ
21 | }
22 |
23 | fun toGroupMessageResp(userId: String,userName: String?,avatar: String?, isSender: Boolean): GroupMessageResp {
24 | val data = GroupMessageResp(userId,userName,avatar,message,groupId,messageType,isSender)
25 | data.dateTime = dateTime
26 | return data
27 | }
28 |
29 | fun toGroupMessageResp(loginResp: LoginResp?,avatar: String?, isSender: Boolean): GroupMessageResp {
30 | val data = GroupMessageResp(loginResp?.userId!!,loginResp?.userName,avatar,message,groupId,messageType,isSender)
31 | data.dateTime = dateTime
32 | return data
33 | }
34 |
35 | override fun toString(): String {
36 | return "GroupMessageReq(groupId='$groupId', msg='$msg', messageType=$messageType, message='$message')"
37 | }
38 |
39 |
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/HeartBeatReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class HeartBeatReq : Packet(){
12 | override fun packetType(): Int {
13 | return PacketType.HEART_BEAT_REQ
14 | }
15 |
16 | override fun toString(): String {
17 | return "HeartBeatReq(packetType=PacketType.HEART_BEAT_REQ) ${super.toString()}"
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/InviteGroupReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class InviteGroupReq(val groupId : String, val users : List) : Packet(){
12 | override fun packetType(): Int {
13 | return PacketType.INVITE_GROUP_REQ
14 | }
15 |
16 | override fun toString(): String {
17 | return "InviteGroupReq(groupId='$groupId', users=$users)"
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/LoginReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import android.os.Parcelable
4 | import com.king.easychat.netty.packet.Packet
5 | import com.king.easychat.netty.packet.PacketType
6 | import kotlinx.android.parcel.Parcelize
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | @Parcelize
12 | data class LoginReq(var token: String?,val userName: String?,val password: String?, val sendCacheMessage: Boolean = false) : Packet(), Parcelable {
13 |
14 |
15 | override fun packetType(): Int {
16 | return PacketType.LOGIN_REQ
17 | }
18 |
19 | override fun toString(): String {
20 | return "LoginReq(token='$token', userName='$userName', password='$password', sendCacheMessage=$sendCacheMessage)"
21 | }
22 |
23 |
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/LogoutReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class LogoutReq : Packet() {
12 |
13 | override fun packetType(): Int {
14 | return PacketType.LOGOUT_REQ
15 | }
16 |
17 | override fun toString(): String {
18 | return "LogoutReq(PacketType.LOGOUT_REQ)"
19 | }
20 |
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/MessageReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.google.gson.annotations.Expose
4 | import com.king.easychat.netty.packet.Packet
5 | import com.king.easychat.netty.packet.PacketType
6 | import com.king.easychat.netty.packet.resp.LoginResp
7 | import com.king.easychat.netty.packet.resp.MessageResp
8 | import com.king.easychat.util.AES
9 |
10 | /**
11 | * @author Zed
12 | * date: 2019/10/09.
13 | * description:
14 | */
15 | class MessageReq(val receiver : String,@Expose val msg : String, val messageType : Int = 0) : Packet(){
16 |
17 | val message = AES.encrypt(msg,"${dateTime}ab").toString()
18 |
19 | override fun packetType(): Int {
20 | return PacketType.SEND_MESSAGE_REQ
21 | }
22 |
23 | fun toMessageResp(userId: String?,userName: String?,isSender: Boolean): MessageResp{
24 | val data = MessageResp(userId,userName,message,isSender,messageType)
25 | data.dateTime = dateTime
26 | return data
27 | }
28 |
29 | fun toMessageResp(loginResp: LoginResp?,isSender: Boolean): MessageResp{
30 | val data = MessageResp(loginResp?.userId,loginResp?.userName,message,isSender,messageType)
31 | data.dateTime = dateTime
32 | return data
33 | }
34 |
35 |
36 | override fun toString(): String {
37 | return "MessageReq(receiver='$receiver', msg='$msg', message='$message') ${super.toString()}"
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/RegisterReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class RegisterReq(val userName: String, val password: String,val login: Boolean = true) : Packet() {
12 |
13 | override fun packetType(): Int {
14 | return PacketType.REGISTER_REQ
15 | }
16 |
17 | override fun toString(): String {
18 | return "RegisterReq(userName='$userName', password='$password', login=$login)"
19 | }
20 |
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/SyncMessageReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | class SyncMessageReq : Packet(){
10 |
11 | override fun packetType(): Int {
12 | return PacketType.SYNC_MESSAGE_REQ
13 | }
14 |
15 | override fun toString(): String {
16 | return "SyncMessageReq(PacketType.SYNC_MESSAGE_REQ)"
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/req/UpdatePasswdReq.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.req
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/10/09.
9 | * description:
10 | */
11 | class UpdatePasswdReq(val oldPassword: String, val newPassword: String) : Packet() {
12 |
13 | override fun packetType(): Int {
14 | return PacketType.UPDATE_PASSWD_REQ
15 | }
16 |
17 | override fun toString(): String {
18 | return "UpdatePasswdReq(oldPassword='$oldPassword', newPassword='$newPassword')"
19 | }
20 |
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/AcceptGroupResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class AcceptGroupResp(val acceptUser: String, val groupId: String, val success: Boolean) : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.ACCEPT_GROUP_RESP
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/AcceptResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class AcceptResp(val inviterId: String, val invitedId: String,val invitedName: String, val success: Boolean) : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.ACCEPT_RESP
14 | }
15 |
16 | override fun toString(): String {
17 | return "AcceptResp(inviterId='$inviterId', invitedId='$invitedId', invitedName='$invitedName', success=$success)"
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/AddUserResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class AddUserResp(val inviterId: String,val inviterName: String) : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.ADD_FRIEND_RESP
14 | }
15 |
16 | override fun toString(): String {
17 | return "AddUserResp(inviterId='$inviterId', inviterName='$inviterName')"
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/AddUserSelfResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class AddUserSelfResp(val inviterId: String, val reason: String, val success: Boolean) : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.ADD_USER_SELF_RESP
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/AllowGroupResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | class AllowGroupResp(val groupId: String,val allow: Boolean) : Packet(){
10 |
11 | override fun packetType(): Int {
12 | return PacketType.ALLOW_GROUP_RESP
13 | }
14 |
15 | override fun toString(): String {
16 | return "AllowGroupResp(groupId='$groupId', allow=$allow)"
17 | }
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/ApplyGroupResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | class ApplyGroupResp(val applyUserId: String,val applyUserName: String,val groupId: String,val groupName: String) : Packet(){
10 |
11 | override fun packetType(): Int {
12 | return PacketType.APPLY_GROUP_RESP
13 | }
14 |
15 | override fun toString(): String {
16 | return "ApplyGroupResp(applyUserId='$applyUserId', applyUserName='$applyUserName', groupId='$groupId')"
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/ApplyGroupSelfResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | class ApplyGroupSelfResp(val groupId: String,var reason: String?,val success: Boolean) : Packet(){
10 |
11 | override fun packetType(): Int {
12 | return PacketType.APPLY_GROUP_SELF_RESP
13 | }
14 |
15 | override fun toString(): String {
16 | return "ApplyGroupSelfResp(groupId='$groupId', reason=$reason, success=$success)"
17 | }
18 |
19 |
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/CreateGroupResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class CreateGroupResp(val groupName : String, val groupId: String, val reason: String, val success: Boolean) : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.CREATE_GROUP_RESP
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/GroupMessageResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import android.os.Parcelable
4 | import androidx.room.Entity
5 | import androidx.room.Ignore
6 | import androidx.room.Index
7 | import androidx.room.PrimaryKey
8 | import com.chad.library.adapter.base.entity.MultiItemEntity
9 | import com.king.easychat.bean.GroupMessageDbo
10 | import com.king.easychat.bean.MessageDbo
11 | import com.king.easychat.netty.packet.MessageType
12 | import com.king.easychat.netty.packet.Packet
13 | import com.king.easychat.netty.packet.PacketType
14 | import com.king.easychat.util.AES
15 | import kotlinx.android.parcel.Parcelize
16 |
17 | /**
18 | * @author Zed
19 | * date: 2019/08/19.
20 | * description:
21 | */
22 | @Parcelize
23 | class GroupMessageResp(val senderId : String,val senderName : String?,var avatar: String?,val message : String,val groupId: String, val messageType : Int, val isSender: Boolean = false) : Packet(), MultiItemEntity,
24 | Parcelable {
25 |
26 | @PrimaryKey(autoGenerate = true)
27 | var id: Int = 0
28 |
29 | companion object{
30 | const val Left = 1
31 | const val Right = 2
32 | }
33 |
34 | @Ignore
35 | override fun getItemType(): Int {
36 | return if(isSender) Right else Left
37 | }
38 |
39 | // @Expose val msg = AES.decrypt(message,dateTime + "ab").toString()
40 |
41 | override fun packetType(): Int {
42 | return PacketType.GROUP_MESSAGE_RESP
43 | }
44 |
45 | fun getMsg(): String?{
46 | return AES.decrypt(message,"${dateTime}ab")
47 | }
48 |
49 | override fun toString(): String {
50 | return "GroupMessageResp(senderId='$senderId', senderName='$senderName', message='$message', msg='${getMsg()}', groupId='$groupId') ${super.toString()}"
51 | }
52 |
53 | fun isSelf(self: String): Boolean{
54 | return self == senderId
55 | }
56 |
57 |
58 | fun toGroupMessageDbo(userId: String,read: Boolean): GroupMessageDbo{
59 | val data = GroupMessageDbo(userId,groupId,senderId,senderName,avatar,message,isSender,messageType,dateTime,read)
60 | data.dateTime = dateTime
61 | return data
62 | }
63 |
64 | fun isImage():Boolean{
65 | return messageType == MessageType.IMAGE
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/HeartBeatResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class HeartBeatResp : Packet() {
12 | override fun packetType(): Int {
13 | return PacketType.HEART_BEAT_RESP
14 | }
15 |
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/InviteGroupResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class InviteGroupResp : Packet() {
12 | /** 群名 */
13 | val groupName: String? = null
14 | /** 群Id */
15 | val groupId: String? = null
16 | /** 邀请方id */
17 | val inviteId: String? = null
18 |
19 | override fun packetType(): Int {
20 | return PacketType.INVITE_GROUP_RESP
21 | }
22 |
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/InviteGroupSelfResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class InviteGroupSelfResp : Packet() {
12 | /** 发出邀请成功用户 */
13 | val successUser: List? = null
14 | val failedUser: List? = null
15 | /** 群名 */
16 | val groupName: String? = null
17 | /** 群Id */
18 | val groupId: String? = null
19 |
20 | override fun packetType(): Int {
21 | return PacketType.INVITE_GROUP_SELF_RESP
22 | }
23 |
24 |
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/LoginResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | open class LoginResp(val userId: String,val userName: String,val token: String,val success: Boolean,val reason: String = "") : Packet() {
10 |
11 |
12 | override fun packetType(): Int {
13 | return PacketType.LOGIN_RESP
14 | }
15 |
16 | override fun toString(): String {
17 | return "LoginResp(userId='$userId', userName='$userName', token='$token', success=$success, reason='$reason')"
18 | }
19 |
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/LogoutResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class LogoutResp : Packet() {
12 |
13 | override fun packetType(): Int {
14 | return PacketType.LOGOUT_RESP
15 | }
16 |
17 |
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/MessageResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import android.os.Parcelable
4 | import androidx.room.Entity
5 | import androidx.room.Index
6 | import androidx.room.PrimaryKey
7 | import com.chad.library.adapter.base.entity.MultiItemEntity
8 | import com.king.easychat.bean.MessageDbo
9 | import com.king.easychat.bean.RecentChat
10 | import com.king.easychat.netty.packet.MessageType
11 | import com.king.easychat.netty.packet.Packet
12 | import com.king.easychat.netty.packet.PacketType
13 | import com.king.easychat.util.AES
14 | import kotlinx.android.parcel.IgnoredOnParcel
15 | import kotlinx.android.parcel.Parcelize
16 |
17 | /**
18 | * @author Zed
19 | * date: 2019/08/19.
20 | * description:
21 | */
22 | @Parcelize
23 | class MessageResp(val sender : String?,val senderName : String?,val message : String, val isSender: Boolean = false, val messageType : Int) : Packet(), MultiItemEntity,
24 | Parcelable {
25 |
26 | @PrimaryKey(autoGenerate = true)
27 | var id: Int = 0
28 |
29 | companion object{
30 | const val Left = 1
31 | const val Right = 2
32 | }
33 |
34 | override fun getItemType(): Int {
35 | return if(isSender) Right else Left
36 | }
37 |
38 | // @Expose val msg = AES.decrypt(message,dateTime + "ab").toString()
39 |
40 | override fun packetType(): Int {
41 | return PacketType.SEND_MESSAGE_RESP
42 | }
43 |
44 | fun getMsg(): String?{
45 | return AES.decrypt(message,"${dateTime}ab")
46 | }
47 |
48 | override fun toString(): String {
49 | return "MessageResp(sender='$sender', senderName='$senderName', message='$message', msg='${getMsg()}') ${super.toString()}"
50 | }
51 |
52 | fun isSelf(self: String): Boolean{
53 | return self == sender
54 | }
55 |
56 |
57 | fun toMessageDbo(userId: String,friendId: String?,read: Boolean): MessageDbo{
58 | var receiver = if(isSender) friendId else sender
59 | var data = MessageDbo(userId,sender,receiver,message,isSender,messageType,dateTime,senderName,read)
60 | data.dateTime = dateTime
61 | return data
62 | }
63 |
64 |
65 | fun isImage():Boolean{
66 | return messageType == MessageType.IMAGE
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/MessageSelfResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class MessageSelfResp : Packet() {
12 | var receiverId: String? = null
13 | var groupId: String? = null
14 | var success: Boolean = false
15 | var reason: String? = null
16 |
17 | override fun packetType(): Int {
18 | return PacketType.MESSAGE_SELF_RESP
19 | }
20 |
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/RegisterResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.PacketType
4 |
5 | /**
6 | * @author Zed
7 | * date: 2019/08/19.
8 | * description:
9 | */
10 | class RegisterResp constructor(userId: String,userName: String,token: String,success: Boolean,reason: String = "") : LoginResp(userId,userName,token,success,reason) {
11 |
12 |
13 | override fun packetType(): Int {
14 | return PacketType.REGISTER_RESP
15 | }
16 |
17 |
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/netty/packet/resp/UpdatePasswdResp.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.netty.packet.resp
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.PacketType
5 |
6 | /**
7 | * @author Zed
8 | * date: 2019/08/19.
9 | * description:
10 | */
11 | class UpdatePasswdResp : Packet() {
12 | var password: String? = null
13 | var success: Boolean = false
14 | var reason: String? = null
15 |
16 | override fun packetType(): Int {
17 | return PacketType.UPDATE_PASSWD_RESP
18 | }
19 |
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/temp/TempActivity.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.temp
2 |
3 | import android.os.Bundle
4 | import androidx.databinding.ViewDataBinding
5 | import com.king.easychat.app.base.BaseActivity
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | class TempActivity : BaseActivity(){
11 |
12 | override fun initData(savedInstanceState: Bundle?) {
13 |
14 | }
15 |
16 | override fun getLayoutId(): Int {
17 | return 0
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/temp/TempFragment.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.temp
2 |
3 | import android.os.Bundle
4 | import androidx.databinding.ViewDataBinding
5 | import com.king.easychat.app.account.RegisterViewModel
6 | import com.king.easychat.app.base.BaseFragment
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | class TempFragment : BaseFragment(){
12 |
13 | companion object{
14 | fun newInstance(): TempFragment{
15 | return TempFragment()
16 | }
17 | }
18 |
19 | override fun initData(savedInstanceState: Bundle?) {
20 | }
21 |
22 | override fun getLayoutId(): Int {
23 | return 0
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/temp/TempViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.temp
2 |
3 | import android.app.Application
4 | import com.king.frame.mvvmframe.base.BaseModel
5 | import com.king.frame.mvvmframe.base.DataViewModel
6 | import javax.inject.Inject
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | class TempViewModel @Inject constructor(application: Application, model: BaseModel?) : DataViewModel(application, model){
12 |
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/util/AES.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.util
2 | import android.util.Base64
3 | import javax.crypto.Cipher
4 | import javax.crypto.spec.IvParameterSpec
5 | import javax.crypto.spec.SecretKeySpec
6 |
7 |
8 | /**
9 | * @author Jenly
10 | */
11 | object AES {
12 | private const val IV_STRING = "ABCD1234EFGH5678"
13 | private const val charset = "UTF-8"
14 |
15 | fun encrypt(content: String, key: String): String? {
16 | try {
17 | val contentBytes = content.toByteArray(charset(charset))
18 | val keyBytes = key.toByteArray(charset(charset))
19 | val encryptedBytes = encrypt(contentBytes, keyBytes)
20 | return Base64.encodeToString(encryptedBytes,Base64.DEFAULT)
21 | } catch (e: Exception) {
22 | return null
23 | }
24 |
25 | }
26 |
27 | fun decrypt(content: String, key: String): String? {
28 | try {
29 | val encryptedBytes = Base64.decode(content,Base64.DEFAULT)
30 | val keyBytes = key.toByteArray(charset(charset))
31 | val decryptedBytes = decrypt(encryptedBytes, keyBytes)
32 | return String(decryptedBytes)
33 | } catch (e: Exception) {
34 | return null
35 | }
36 |
37 | }
38 |
39 | @Throws(Exception::class)
40 | private fun encrypt(contentBytes: ByteArray, keyBytes: ByteArray): ByteArray {
41 | return cipherOperation(contentBytes, keyBytes, Cipher.ENCRYPT_MODE)
42 | }
43 |
44 | @Throws(Exception::class)
45 | private fun decrypt(contentBytes: ByteArray, keyBytes: ByteArray): ByteArray {
46 | return cipherOperation(contentBytes, keyBytes, Cipher.DECRYPT_MODE)
47 | }
48 |
49 | @Throws(Exception::class)
50 | private fun cipherOperation(
51 | contentBytes: ByteArray,
52 | keyBytes: ByteArray,
53 | mode: Int
54 | ): ByteArray {
55 | val secretKey = SecretKeySpec(keyBytes, "AES")
56 |
57 | val initParam = IV_STRING.toByteArray(charset(charset))
58 | val ivParameterSpec = IvParameterSpec(initParam)
59 |
60 | val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
61 | cipher.init(mode, secretKey, ivParameterSpec)
62 |
63 | return cipher.doFinal(contentBytes)
64 | }
65 |
66 |
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/util/BitmapUtil.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.util
2 |
3 | import android.graphics.*
4 |
5 | /**
6 | * @author Jenly
7 | */
8 | object BitmapUtil {
9 |
10 | /**
11 | * 通过PorterDuff模式获取圆角图片
12 | */
13 | fun getOvalBitmap(bitmap: Bitmap): Bitmap{
14 | val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
15 | val canvas = Canvas(output)
16 |
17 | val color = Color.WHITE
18 | val paint = Paint()
19 | paint.isAntiAlias = true
20 | paint.isFilterBitmap = true
21 | val rect = Rect(0, 0, bitmap.width, bitmap.height)
22 |
23 | val rectF = RectF(rect)
24 | paint.isAntiAlias = true
25 | canvas.drawARGB(0, 0, 0, 0)
26 | paint.color = color
27 | canvas.drawOval(rectF, paint)
28 | paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
29 | canvas.drawBitmap(bitmap, rect, rect, paint)
30 |
31 | return output
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/util/Cache.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.util
2 |
3 | import com.king.base.util.StringUtils
4 | import com.king.easychat.app.Constants
5 | import com.king.easychat.netty.packet.req.LoginReq
6 | import com.king.easychat.netty.packet.req.RegisterReq
7 | import com.tencent.mmkv.MMKV
8 |
9 | /**
10 | * @author Jenly
11 | */
12 | object Cache {
13 |
14 | fun put(data: RegisterReq?,token: String){
15 | data?.let {
16 | MMKV.defaultMMKV().encode(Constants.KEY_USERNAME,it.userName)
17 | }
18 | putToken(token)
19 |
20 | }
21 |
22 | fun put(data: LoginReq?,token: String){
23 | data?.let {
24 | MMKV.defaultMMKV().encode(Constants.KEY_USERNAME,it.userName)
25 | }
26 | putToken(token)
27 |
28 | }
29 |
30 | fun put(key: String,value: String){
31 | MMKV.defaultMMKV().encode(key,value)
32 |
33 | }
34 |
35 | fun putToken(token : String?){
36 | token?.let {
37 | put(Constants.KEY_TOKEN,it)
38 | }
39 |
40 | }
41 |
42 | fun clearToken(){
43 | MMKV.defaultMMKV().reKey(Constants.KEY_TOKEN)
44 | }
45 |
46 | fun getUsername(): String?{
47 | return MMKV.defaultMMKV().decodeString(Constants.KEY_USERNAME)
48 | }
49 |
50 | fun getToken(): String?{
51 | return MMKV.defaultMMKV().decodeString(Constants.KEY_TOKEN)
52 | }
53 |
54 | fun getLoginReq(): LoginReq?{
55 | var loginReq : LoginReq? = null
56 | MMKV.defaultMMKV().run {
57 | var username: String? = decodeString(Constants.KEY_USERNAME)
58 | var token: String? = decodeString(Constants.KEY_TOKEN)
59 |
60 | if(StringUtils.isNotBlank(token)){
61 | loginReq = LoginReq(token,username,null)
62 | }
63 | }
64 |
65 | return loginReq
66 | }
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/util/CheckUtil.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.util
2 |
3 | import java.util.regex.Pattern
4 |
5 | /**
6 | * @author Jenly
7 | */
8 | object CheckUtil {
9 |
10 |
11 | /**
12 | * 密码验证 6-20位数字,不允许有空格
13 | *
14 | * @param password
15 | * @return
16 | */
17 | fun isPassword(password: String): Boolean {
18 | val regex = "^(?![0-9]+\$)(?![a-zA-Z]+\$)[0-9A-Za-z]{6,20}\$"
19 | return matcher(password,regex)
20 | }
21 |
22 | fun isUrl(url: String): Boolean{
23 | val regex = "[hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://"
24 | return matcher(url,regex)
25 | }
26 |
27 | fun matcher(content: String,regex: String): Boolean{
28 | val p = Pattern.compile(regex)
29 | val m = p.matcher(content)
30 | return m.matches()
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/util/Event.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.util
2 |
3 | import org.greenrobot.eventbus.EventBus
4 |
5 | /**
6 | * @author Jenly
7 | */
8 | object Event {
9 |
10 | private val event = EventBus.getDefault()
11 |
12 | fun sendEvent(msg: Any,isSticky: Boolean = false){
13 | if(isSticky){
14 | event.postSticky(msg)
15 | }else{
16 | event.post(msg)
17 | }
18 |
19 | }
20 |
21 | fun registerEvent(obj: Any){
22 | event.register(obj)
23 | }
24 |
25 | fun unregisterEvent(obj: Any){
26 | event.unregister(obj)
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/util/FileUtil.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.util
2 |
3 | import android.util.Base64
4 | import java.io.*
5 |
6 | /**
7 | * @author Jenly
8 | */
9 | object FileUtil {
10 |
11 |
12 | fun imageToBase64(filename: String): String{
13 | return imageToBase64(File(filename))
14 | }
15 |
16 | fun imageToBase64(file: File): String{
17 | var bytes = file.toBytes()
18 | bytes?.let {
19 | return Base64.encodeToString(it,Base64.NO_WRAP)
20 | }
21 |
22 | return ""
23 | }
24 |
25 | fun File.toBytes(): ByteArray?{
26 | val length = length().toInt()
27 | var baos = ByteArrayOutputStream(length)
28 | var ins : InputStream? = null
29 | try {
30 | ins = BufferedInputStream(FileInputStream(this))
31 | ins?.let {
32 | var buffer = ByteArray(8192)
33 | var read = it.read(buffer)
34 | while (read > 0 ){
35 | baos.write(buffer,0 ,read)
36 | read = it.read(buffer)
37 | }
38 | }
39 |
40 | }catch (e: Exception){
41 |
42 | }finally {
43 | try{
44 | ins?.close()
45 | }catch (e1: Exception){
46 |
47 | }
48 | }
49 |
50 | return baos.toByteArray()
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/king/easychat/util/JsonUtil.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat.util
2 |
3 | import com.google.gson.Gson
4 | import org.json.JSONObject
5 |
6 |
7 | /**
8 | * @author Jenly
9 | */
10 | object JsonUtil{
11 |
12 | private val gson = Gson()
13 |
14 | fun toJson(obj: Any): String{
15 | return gson.toJson(obj)
16 | }
17 |
18 | @ExperimentalStdlibApi
19 | fun toJsonBytes(obj: Any): ByteArray{
20 | return toJson(obj).encodeToByteArray()
21 | }
22 |
23 | fun fromJson(json: String,clazz: Class): T{
24 | return gson.fromJson(json,clazz)
25 | }
26 |
27 |
28 | fun getPacketType(json: String): Int {
29 | val jsonObject = JSONObject(json)
30 | return jsonObject.getInt("command")
31 | }
32 |
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/splash_in.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/translate_left_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/translate_left_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/translate_right_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/translate_right_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/color/bottom_menu_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/white_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ec_welcome.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xhdpi/ec_welcome.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_back_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_back_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_back_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_back_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_bg_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_bg_normal.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_bg_pressed.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_bg_pressed.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_black_back_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_black_back_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_black_back_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_black_back_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_clear.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_close_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_close_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_close_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_close_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_delete_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_delete_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_delete_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_delete_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_menu_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_menu_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_menu_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_menu_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_more_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_more_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_more_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_more_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_none.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_none.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_scan_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_scan_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_scan_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_scan_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_search_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_search_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/btn_search_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/btn_search_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/default_avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/default_avatar.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_about.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_about_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_about_line.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_chat_bubble_left.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_chat_bubble_left.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_chat_bubble_right.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_chat_bubble_right.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_create_group_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_create_group_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_create_group_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_create_group_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_detail_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_detail_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_detail_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_detail_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_edit_box_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_edit_box_bg.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_empty.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_heart.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_keyboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_keyboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_modify_password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_modify_password.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_next.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_next_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_next_white.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_off.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_on.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_qrcode.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_save_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_save_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_save_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_save_pressed.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_smile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_smile.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ec_version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ec_version.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/explosion_five.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/explosion_five.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/explosion_four.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/explosion_four.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/explosion_one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/explosion_one.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/explosion_three.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/explosion_three.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/explosion_two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/explosion_two.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_about_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_about_image.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_github.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_hide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_hide.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_menu_about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_menu_about.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_menu_logout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_menu_logout.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_none.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_none.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_password.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_search.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_show.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/ic_user.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/input_bg_focus.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/input_bg_focus.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/input_bg_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/input_bg_normal.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/login_slogan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/login_slogan.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/logo.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_friend_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_friend_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_friend_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_friend_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_group_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_group_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_group_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_group_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_me_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_me_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_me_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_me_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_message_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_message_normal.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/menu_message_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/drawable-xxhdpi/menu_message_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_back_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_bg_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_black_back_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_clear_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_close_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_create_group_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_delete_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_detail_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_flash_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_menu_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_password_eye_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_save_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_scan_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_search_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edit_bg_line_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 | -
11 |
12 |
13 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edit_bg_line_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 | -
11 |
12 |
13 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edit_bg_line_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_clear_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/line_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/line_drawable_8.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/line_drawable_xh_none.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/logo_layer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_friend_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_group_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_me_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_message_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/search_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/splash_layer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/web_progress_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 | -
35 |
36 |
37 |
38 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/white_bottom_layer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 | -
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/white_layer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 | -
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/white_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/change_user_info_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
15 |
24 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/code_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
11 |
12 |
17 |
26 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/friend_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
13 |
14 |
19 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/group_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
13 |
14 |
19 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/group_member_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
13 |
14 |
19 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/home_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
13 |
14 |
19 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/home_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
17 |
25 |
36 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_empty.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/photo_view_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
11 |
16 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rv_group_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
19 |
30 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rv_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/scan_code_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
13 |
26 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/scan_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
16 |
24 |
35 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/splash_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
17 |
25 |
36 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/vp_photo_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/web_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
16 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/about_me.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #4587f0
5 | #4587f0
6 | #4587f0
7 |
8 | #1298ed
9 |
10 | #d0d0d0
11 |
12 | #4587f0
13 | #f2f3f6
14 |
15 | #f2f3f6
16 |
17 | #cccccc
18 |
19 | #333333
20 | #666666
21 | #999999
22 | #808080
23 | #ffffff
24 |
25 | #7fffffff
26 |
27 | #4587f0
28 |
29 | #7fffffff
30 |
31 | #7f000000
32 |
33 | #D93F3C
34 |
35 | #4587f0
36 | #999999
37 |
38 | #f2f3f6
39 |
40 | #ddffffff
41 |
42 | #ffffff
43 | #000000
44 |
45 | #00000000
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4587F0
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 20
4 | 30
5 | 26
6 | 20
7 | 20
8 | 30
9 | 20
10 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/test/java/com/king/easychat/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.king.easychat
2 |
3 | import com.king.easychat.netty.packet.Packet
4 | import com.king.easychat.netty.packet.req.GroupMessageReq
5 | import org.junit.Test
6 |
7 | import org.junit.Assert.*
8 | import java.nio.file.Files.isDirectory
9 | import io.netty.util.internal.ResourcesUtil.getFile
10 | import java.io.File
11 | import java.io.IOException
12 |
13 |
14 | /**
15 | * Example local unit test, which will execute on the development machine (host).
16 | *
17 | * See [testing documentation](http://d.android.com/tools/testing).
18 | */
19 | class ExampleUnitTest {
20 | @Test
21 | fun addition_isCorrect() {
22 | assertEquals(4, 2 + 2)
23 | }
24 |
25 | @Test
26 | fun testPacket() {
27 | var req = GroupMessageReq("123", "456", 1)
28 | println(req.messageType)
29 | println(req.packetType())
30 | }
31 | @Test
32 | fun testClass() {
33 | val clazz = Packet::class.java
34 | val classes = getClasses(clazz)
35 | println(classes)
36 | }
37 |
38 | /**
39 | * 取得当前类路径下的所有类
40 | *
41 | * @param cls
42 | * @return
43 | * @throws IOException
44 | * @throws ClassNotFoundException
45 | */
46 | @Throws(IOException::class, ClassNotFoundException::class)
47 | fun getClasses(cls: Class<*>): List> {
48 | val pk = cls.getPackage()!!.name
49 | val path = pk.replace('.', '/')
50 | val classloader = Thread.currentThread().contextClassLoader
51 | val url = classloader!!.getResource(path)
52 | return getClasses(File(url.file), pk)
53 | }
54 |
55 | /**
56 | * 迭代查找类
57 | *
58 | * @param dir
59 | * @param pk
60 | * @return
61 | * @throws ClassNotFoundException
62 | */
63 | @Throws(ClassNotFoundException::class)
64 | private fun getClasses(dir: File, pk: String): List> {
65 | val classes = ArrayList>()
66 | if (!dir.exists()) {
67 | return classes
68 | }
69 | for (f in dir.listFiles()) {
70 | if (f.isDirectory()) {
71 | classes.addAll(getClasses(f, pk + "." + f.getName()))
72 | }
73 | val name = f.getName()
74 | if (name.endsWith(".class")) {
75 | classes.add(Class.forName(pk + "." + name.substring(0, name.length - 6)))
76 | }
77 | }
78 | return classes
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/art/GIF.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/art/GIF.gif
--------------------------------------------------------------------------------
/art/GIF2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/art/GIF2.gif
--------------------------------------------------------------------------------
/art/QR_EasyChat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/art/QR_EasyChat.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | apply from: 'versions.gradle'
5 | repositories {
6 | google()
7 | jcenter()
8 |
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.5.1'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin"
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | classpath 'com.tencent.bugly:tinker-support:1.1.5'
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 | maven { url 'https://jitpack.io' }
24 | maven { url 'https://dl.bintray.com/jenly/maven' }
25 |
26 | }
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
33 | ext {
34 | signingEnabled = false
35 |
36 | tinkerEnabled = false
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/doc/接口文档.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/doc/接口文档.docx
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs = -Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX = true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier = true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style = official
22 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yetel/EasyChatAndroidClient/393e334c8bb3a14e9d554e5187fbc88a0afc3d43/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Sep 24 14:25:09 CST 2019
2 | distributionBase = GRADLE_USER_HOME
3 | distributionPath = wrapper/dists
4 | zipStoreBase = GRADLE_USER_HOME
5 | zipStorePath = wrapper/dists
6 | distributionUrl = https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name='EasyChat'
3 |
--------------------------------------------------------------------------------
/versions.gradle:
--------------------------------------------------------------------------------
1 | //App
2 | def app_version = [:]
3 | app_version.versionCode = 1
4 | app_version.versionName = "1.0.0"
5 | ext.app_version = app_version
6 |
7 | //build version
8 | def build_versions = [:]
9 | build_versions.minSdk = 16
10 | build_versions.targetSdk = 29
11 | build_versions.compileSdk = 29
12 | build_versions.buildTools = "29.0.2"
13 | ext.build_versions = build_versions
14 |
15 | // App dependencies
16 | def versions = [:]
17 |
18 | versions.kotlin = "1.3.50"
19 | versions.appcompat = "1.0.2"
20 | versions.coreKtx = "1.0.2"
21 | versions.material = "1.0.0"
22 | versions.constraintlayout = "1.1.3"
23 | versions.junit = "4.12"
24 | versions.runner = "1.1.1"
25 | versions.espressoCore = "3.1.1"
26 | versions.recyclerview = "1.1.0-beta05"
27 | versions.viewpager2 = "1.0.0-beta05"
28 | versions.debugDb = "1.0.6"
29 | versions.kotlinxCoroutines = "1.3.2"
30 | versions.room = "2.2.0-alpha01"
31 | versions.dagger = "2.23.2"
32 |
33 | versions.mvvmframe = "1.1.0"
34 | versions.nevercrash = "1.0.0"
35 | versions.base = "3.2.1-androidx"
36 | versions.anetty = "1.0.2"
37 | versions.appUpdater = "1.0.5-androidx"
38 | versions.flutteringlayout = "1.1.1"
39 | versions.zxingLite = "1.1.3-androidx"
40 | versions.baseUrlManager = "1.0.1-androidx"
41 | versions.logger = "2.2.0"
42 | versions.eventbus = "3.1.1"
43 | versions.brvah = "2.9.49-androidx"
44 | versions.circleimageview = "3.0.1"
45 | versions.glide = "4.10.0"
46 | versions.matisse = "0.5.3-beta2"
47 | versions.Luban = "1.1.8"
48 | versions.ucrop = "2.2.4"
49 | versions.PhotoView = "2.0.0"
50 | versions.rxpermissions = "0.10.2"
51 | versions.jsbridge = "1.0.4"
52 | versions.mmkv = "1.0.23"
53 | versions.bugly = "1.3.6"
54 | versions.tinker = "1.9.9"
55 |
56 | ext.versions = versions
57 |
--------------------------------------------------------------------------------