├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── TigerLibrary ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── ittiger │ │ ├── app │ │ └── AppContext.java │ │ ├── base │ │ ├── BaseActivity.java │ │ └── BaseFragment.java │ │ ├── ui │ │ ├── BaseKeyboardLayout.java │ │ ├── LoadingView.java │ │ └── NoHorizontalScrollViewPager.java │ │ └── util │ │ ├── ActivityUtil.java │ │ ├── AppInfo.java │ │ ├── AppUtil.java │ │ ├── BitmapUtil.java │ │ ├── ByteUtil.java │ │ ├── DateUtil.java │ │ ├── DisplayUtils.java │ │ ├── FileUtil.java │ │ ├── HexUtil.java │ │ ├── KeyboardUtil.java │ │ ├── PageLoadingHelper.java │ │ ├── PreferenceHelper.java │ │ ├── SdCardUtil.java │ │ ├── UIUtil.java │ │ ├── UnCaughtCrashExceptionHandler.java │ │ ├── ValueUtil.java │ │ └── cipher │ │ ├── Base64Cipher.java │ │ ├── Cipher.java │ │ ├── Decrypt.java │ │ └── Encrypt.java │ └── res │ ├── layout │ ├── base_layout.xml │ └── loading_failed_layout.xml │ └── values │ ├── ids.xml │ └── strings.xml ├── app ├── .gitignore ├── build.gradle ├── libs │ └── TigerDB.jar ├── problem.md ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── ittiger │ │ └── im │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ └── ittiger │ │ │ └── im │ │ │ ├── activity │ │ │ ├── AboutActivity.java │ │ │ ├── AccountMngActivity.java │ │ │ ├── AddFriendActivity.java │ │ │ ├── ChatActivity.java │ │ │ ├── CreateMultiChatActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MultiChatActivity.java │ │ │ ├── RegisterActivity.java │ │ │ ├── WebPageActivity.java │ │ │ └── base │ │ │ │ ├── BaseChatActivity.java │ │ │ │ └── IMBaseActivity.java │ │ │ ├── adapter │ │ │ ├── BaseViewAdapter.java │ │ │ ├── ChatAdapter.java │ │ │ ├── ChatRecordAdapter.java │ │ │ ├── CheckableContactAdapter.java │ │ │ ├── ContactAdapter.java │ │ │ ├── EmotionAdapter.java │ │ │ ├── EmotionViewPagerAdapter.java │ │ │ └── viewholder │ │ │ │ ├── ChatRecordViewHolder.java │ │ │ │ ├── ContactIndexViewHolder.java │ │ │ │ ├── ContactViewHolder.java │ │ │ │ └── CreateMultiChatViewHolder.java │ │ │ ├── app │ │ │ ├── App.java │ │ │ └── IDbApplication.java │ │ │ ├── bean │ │ │ ├── ChatMessage.java │ │ │ ├── ChatRecord.java │ │ │ ├── ChatUser.java │ │ │ ├── CheckableContactEntity.java │ │ │ ├── ContactEntity.java │ │ │ ├── ContactMenuEntity.java │ │ │ ├── LoginResult.java │ │ │ ├── MultiChatRoom.java │ │ │ └── User.java │ │ │ ├── constant │ │ │ ├── Constant.java │ │ │ ├── EmotionType.java │ │ │ ├── FileLoadState.java │ │ │ ├── KeyBoardMoreFunType.java │ │ │ └── MessageType.java │ │ │ ├── decoration │ │ │ ├── CommonItemDecoration.java │ │ │ ├── CommonVerticalItemDecoration.java │ │ │ └── ContactItemDecoration.java │ │ │ ├── fragment │ │ │ ├── BaseEmotionFragment.java │ │ │ ├── ContactFragment.java │ │ │ ├── EmotionFragment.java │ │ │ └── MessageFragment.java │ │ │ ├── smack │ │ │ ├── MultiChatInvitationListener.java │ │ │ ├── MultiChatMessageListener.java │ │ │ ├── SmackChatManagerListener.java │ │ │ ├── SmackConnectionListener.java │ │ │ ├── SmackListenerManager.java │ │ │ ├── SmackManager.java │ │ │ └── SmackMultiChatManager.java │ │ │ ├── ui │ │ │ ├── ChatPromptDialog.java │ │ │ ├── CircleImageView.java │ │ │ ├── ClearEditText.java │ │ │ ├── FragmentSaveStateTabHost.java │ │ │ ├── RecordingVoiceView.java │ │ │ ├── keyboard │ │ │ │ ├── ChatKeyboard.java │ │ │ │ ├── KeyBoardMoreFunView.java │ │ │ │ ├── KeyBoardToolBoxView.java │ │ │ │ └── emotion │ │ │ │ │ ├── EmotionIndicatorView.java │ │ │ │ │ ├── EmotionItemClickListener.java │ │ │ │ │ └── KeyBoardEmotionView.java │ │ │ └── recyclerview │ │ │ │ ├── CommonRecyclerView.java │ │ │ │ ├── HeaderAndFooterAdapter.java │ │ │ │ └── ViewHolder.java │ │ │ └── util │ │ │ ├── AppFileHelper.java │ │ │ ├── ChatTimeUtil.java │ │ │ ├── DBHelper.java │ │ │ ├── DBQueryHelper.java │ │ │ ├── EmotionDataHelper.java │ │ │ ├── EmotionUtil.java │ │ │ ├── IMUtil.java │ │ │ ├── ImageLoaderHelper.java │ │ │ ├── IntentHelper.java │ │ │ ├── LoginHelper.java │ │ │ ├── RecordVoiceManager.java │ │ │ └── ShareHelper.java │ └── res │ │ ├── color │ │ └── tabbar_text_color.xml │ │ ├── drawable-hdpi │ │ ├── avatar.png │ │ ├── bg_launcher.jpeg │ │ ├── pic_default.png │ │ ├── tigerframe_edittext_clear.png │ │ ├── tigerframe_icon_back_btn_normal.png │ │ └── tigerframe_icon_back_btn_pressed.png │ │ ├── drawable-xxhdpi │ │ ├── about_img.jpg │ │ ├── avatar.png │ │ ├── chat_from_bg_normal.9.png │ │ ├── chat_from_bg_pressed.9.png │ │ ├── chat_to_bg_normal.9.png │ │ ├── chat_to_bg_pressed.9.png │ │ ├── d_aini.png │ │ ├── d_aoteman.png │ │ ├── d_baibai.png │ │ ├── d_beishang.png │ │ ├── d_bishi.png │ │ ├── d_bizui.png │ │ ├── d_chanzui.png │ │ ├── d_chijing.png │ │ ├── d_dahaqi.png │ │ ├── d_dalian.png │ │ ├── d_ding.png │ │ ├── d_doge.png │ │ ├── d_fangdumianju.png │ │ ├── d_feizao.png │ │ ├── d_ganmao.png │ │ ├── d_guzhang.png │ │ ├── d_haha.png │ │ ├── d_haixiu.png │ │ ├── d_han.png │ │ ├── d_hehe.png │ │ ├── d_heixian.png │ │ ├── d_heng.png │ │ ├── d_huaxin.png │ │ ├── d_jiyan.png │ │ ├── d_keai.png │ │ ├── d_kelian.png │ │ ├── d_ku.png │ │ ├── d_kun.png │ │ ├── d_landelini.png │ │ ├── d_lang.png │ │ ├── d_lei.png │ │ ├── d_miao.png │ │ ├── d_nanhaier.png │ │ ├── d_nu.png │ │ ├── d_numa.png │ │ ├── d_nvhaier.png │ │ ├── d_qian.png │ │ ├── d_qinqin.png │ │ ├── d_shayan.png │ │ ├── d_shengbing.png │ │ ├── d_shenshou.png │ │ ├── d_shiwang.png │ │ ├── d_shuai.png │ │ ├── d_shuijiao.png │ │ ├── d_sikao.png │ │ ├── d_taikaixin.png │ │ ├── d_touxiao.png │ │ ├── d_travel.png │ │ ├── d_tu.png │ │ ├── d_tuzi.png │ │ ├── d_wabishi.png │ │ ├── d_weiqu.png │ │ ├── d_xiaoku.png │ │ ├── d_xiongmao.png │ │ ├── d_xixi.png │ │ ├── d_xu.png │ │ ├── d_yinxian.png │ │ ├── d_yiwen.png │ │ ├── d_youhengheng.png │ │ ├── d_yun.png │ │ ├── d_zhuakuang.png │ │ ├── d_zhutou.png │ │ ├── d_zuiyou.png │ │ ├── d_zuohengheng.png │ │ ├── file_load_fail.png │ │ ├── gxu.png │ │ ├── gxv.png │ │ ├── gxw.png │ │ ├── gxx.png │ │ ├── gxy.png │ │ ├── gxz.png │ │ ├── icon_chat_image.png │ │ ├── icon_chat_take_photo.png │ │ ├── loading1.png │ │ ├── loading2.png │ │ └── loading3.png │ │ ├── drawable │ │ ├── anim_chat_voice_left.xml │ │ ├── anim_chat_voice_right.xml │ │ ├── bg_chat_time_tag.xml │ │ ├── chat_file_content_loading_anim.xml │ │ ├── chat_from_bg_selector.xml │ │ ├── chat_to_bg_selector.xml │ │ ├── ic_keyboard_emotion.xml │ │ ├── ic_keyboard_more.xml │ │ ├── ic_keyboard_voice.xml │ │ ├── ic_tabbar_contact.xml │ │ ├── ic_tabbar_message.xml │ │ ├── ic_toolbar_add.xml │ │ ├── ic_toolbar_avatar.xml │ │ ├── keyboard_emotion_indicator_nomal_bg.xml │ │ ├── keyboard_emotion_indicator_select_bg.xml │ │ ├── keyboard_input_edittext_bg.xml │ │ ├── keyboard_record_voice_button_bg.xml │ │ ├── main_bg.xml │ │ ├── main_button_bg.xml │ │ ├── recording_vocie_view_bg.xml │ │ ├── recording_voice_cancel_text_bg.xml │ │ ├── tigerframe_icon_back_btn_selector.xml │ │ ├── vector_about.xml │ │ ├── vector_add.xml │ │ ├── vector_add_focus.xml │ │ ├── vector_avatar.xml │ │ ├── vector_avatar_focus.xml │ │ ├── vector_chat_avatar.xml │ │ ├── vector_checked.xml │ │ ├── vector_contact.xml │ │ ├── vector_contact_focus.xml │ │ ├── vector_contact_group.xml │ │ ├── vector_default_image.xml │ │ ├── vector_emotion_more.xml │ │ ├── vector_keyboard_emotion.xml │ │ ├── vector_keyboard_emotion_delete.xml │ │ ├── vector_keyboard_emotion_focus.xml │ │ ├── vector_keyboard_more.xml │ │ ├── vector_keyboard_more_focus.xml │ │ ├── vector_keyboard_normal.xml │ │ ├── vector_keyboard_pressed.xml │ │ ├── vector_keyboard_text.xml │ │ ├── vector_keyboard_text_focus.xml │ │ ├── vector_keyboard_voice.xml │ │ ├── vector_keyboard_voice_focus.xml │ │ ├── vector_message.xml │ │ ├── vector_message_focus.xml │ │ ├── vector_multi_chat.xml │ │ ├── vector_recording_cancel.xml │ │ ├── vector_recording_voice.xml │ │ ├── vector_share.xml │ │ └── vector_uncheck.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_account_mng_layout.xml │ │ ├── activity_addfriend_layout.xml │ │ ├── activity_chat_layout.xml │ │ ├── activity_create_multi_chat.xml │ │ ├── activity_login_layout.xml │ │ ├── activity_main.xml │ │ ├── activity_main_bar.xml │ │ ├── activity_main_content.xml │ │ ├── activity_main_nav_header.xml │ │ ├── activity_multichat_layout.xml │ │ ├── activity_register_layout.xml │ │ ├── activity_webpage.xml │ │ ├── chat_keyboard_emotion_layout.xml │ │ ├── chat_keyboard_emotion_tab_item_layout.xml │ │ ├── chat_keyboard_layout.xml │ │ ├── chat_keyboard_more_item_layout.xml │ │ ├── chat_keyboard_more_layout.xml │ │ ├── chat_keyboard_toolbox_layout.xml │ │ ├── chat_messgae_item_left_layout.xml │ │ ├── chat_messgae_item_right_layout.xml │ │ ├── chat_record_item_layout.xml │ │ ├── checkable_contact_item_view.xml │ │ ├── contact_item_index_view.xml │ │ ├── contact_item_view.xml │ │ ├── divider_horizontal_view.xml │ │ ├── fragment_contact.xml │ │ ├── fragment_emotion_layout.xml │ │ ├── fragment_message.xml │ │ ├── keyboard_recording_voice_layout.xml │ │ ├── tabbar_item_view.xml │ │ └── toolbar_layout.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ ├── create_multi_chat_toolbar_menu.xml │ │ └── main_toolbar_menu.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ └── values │ │ ├── arrays.xml │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── ittiger │ └── im │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── projectFilesBackup └── .idea │ └── workspace.xml ├── screenshots ├── 1.jpg ├── 2.jpg └── 3.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TigerIM 2 | 基于Openfire+Smack实现的简单即时通信客户端,界面仿照QQ实现。 3 | 实现了简单的登陆、注册、点对点聊天,发送文本、语音、图片消息,同时程序中实现了多人之间的聊天,但是没写界面,后面有时间之后再完善吧。 4 | 目前程序完全可以独立运行,程序里面配置了服务器。 5 | 6 | Smack与openfire服务之间的通信关键代码和实现可以参考我的[博客文章](http://ittiger.cn/tags/smack/) 7 | 8 | 此Demo已停止维护 9 | 10 | 个人微信公众号,欢迎扫码关注交流: 11 | ![](https://img-blog.csdnimg.cn/2019052410035231.jpg) 12 | 13 | # 实现效果如如下: 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /TigerLibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /TigerLibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "24.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile 'com.android.support:appcompat-v7:24.2.1' 23 | } 24 | -------------------------------------------------------------------------------- /TigerLibrary/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/baina/ylhu/program/android-sdk-linux/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/app/AppContext.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.app; 2 | 3 | import android.content.Context; 4 | import android.content.ContextWrapper; 5 | import android.content.pm.PackageManager.NameNotFoundException; 6 | 7 | public class AppContext extends ContextWrapper { 8 | 9 | private static AppContext sInstance; 10 | 11 | public static void init(Context context) { 12 | 13 | if (sInstance == null) { 14 | try { 15 | sInstance = new AppContext(context.createPackageContext(context.getPackageName(), 16 | Context.CONTEXT_INCLUDE_CODE)); 17 | } catch (NameNotFoundException e) { 18 | throw new RuntimeException(e); 19 | } 20 | } 21 | } 22 | 23 | public static AppContext getInstance() { 24 | 25 | return sInstance; 26 | } 27 | 28 | private AppContext(Context context) { 29 | 30 | super(context); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.base; 2 | 3 | import cn.ittiger.R; 4 | import cn.ittiger.util.PageLoadingHelper; 5 | 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.content.Context; 8 | import android.os.Bundle; 9 | import android.support.annotation.Nullable; 10 | import android.support.v4.app.Fragment; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | /** 16 | * @author laohu 17 | * @site http://ittiger.cn 18 | */ 19 | public abstract class BaseFragment extends Fragment { 20 | 21 | protected AppCompatActivity mContext; 22 | private PageLoadingHelper mPageLoadingHelper; 23 | 24 | @Override 25 | public void onAttach(Context context) { 26 | 27 | super.onAttach(context); 28 | mContext = (AppCompatActivity) context; 29 | } 30 | 31 | @Nullable 32 | @Override 33 | public final View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 34 | 35 | ViewGroup view = (ViewGroup) inflater.inflate(R.layout.base_layout, container, false); 36 | 37 | view.addView(getContentView(inflater, savedInstanceState), 0); 38 | 39 | mPageLoadingHelper = new PageLoadingHelper(view); 40 | mPageLoadingHelper.setOnLoadingClickListener(new View.OnClickListener() { 41 | 42 | @Override 43 | public void onClick(View v) { 44 | 45 | clickToRefresh(); 46 | } 47 | }); 48 | clickToRefresh(); 49 | 50 | return view; 51 | } 52 | 53 | /** 54 | * 点击刷新加载 55 | */ 56 | private void clickToRefresh() { 57 | 58 | startRefresh(); 59 | refreshData(); 60 | } 61 | 62 | /** 63 | * 初始化数据 64 | * 主线程 65 | */ 66 | public abstract void refreshData(); 67 | 68 | /** 69 | * 开始加载数据 70 | */ 71 | public void startRefresh() { 72 | 73 | mPageLoadingHelper.startRefresh(); 74 | } 75 | 76 | /** 77 | * 加载失败 78 | */ 79 | public void refreshFailed() { 80 | 81 | mPageLoadingHelper.refreshFailed(); 82 | } 83 | 84 | /** 85 | * 加载成功 86 | */ 87 | public void refreshSuccess() { 88 | 89 | mPageLoadingHelper.refreshSuccess(); 90 | } 91 | 92 | /** 93 | * Fragment数据视图 94 | * @param inflater 95 | * @param savedInstanceState 96 | * @return 97 | */ 98 | public abstract View getContentView(LayoutInflater inflater, @Nullable Bundle savedInstanceState); 99 | 100 | public abstract String getTitle(); 101 | } 102 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/ui/NoHorizontalScrollViewPager.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.ui; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | * 不能横向滑动的ViewPager 10 | * 11 | * @author: laohu on 2017/2/6 12 | * @site: http://ittiger.cn 13 | */ 14 | public class NoHorizontalScrollViewPager extends ViewPager { 15 | 16 | public NoHorizontalScrollViewPager(Context context) { 17 | super(context); 18 | } 19 | 20 | public NoHorizontalScrollViewPager(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | /** 25 | * 重写拦截事件,返回值设置为false,这时便不会横向滑动了。 26 | * @param ev 27 | * @return 28 | */ 29 | @Override 30 | public boolean onInterceptTouchEvent(MotionEvent ev) { 31 | 32 | return false; 33 | } 34 | 35 | /** 36 | * 重写拦截事件,返回值设置为false,这时便不会横向滑动了。 37 | * @param ev 38 | * @return 39 | */ 40 | @Override 41 | public boolean onTouchEvent(MotionEvent ev) { 42 | 43 | return false; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/ActivityUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | 8 | /** 9 | * Created by laohu on 16-12-14. 10 | */ 11 | public class ActivityUtil { 12 | 13 | public static void startActivity(Context context, Intent intent) { 14 | 15 | context.startActivity(intent); 16 | } 17 | 18 | public static void startActivity(Context context, Class claxx) { 19 | 20 | startActivity(context, new Intent(context, claxx)); 21 | } 22 | 23 | public static void startActivity(Context context, Class claxx, Bundle bundle) { 24 | 25 | Intent intent = new Intent(context, claxx); 26 | intent.putExtras(bundle); 27 | startActivity(context, intent); 28 | } 29 | 30 | public static void skipActivity(Context context, Class claxx) { 31 | 32 | startActivity(context, claxx); 33 | finishActivity((Activity) context); 34 | } 35 | 36 | public static void finishActivity(Activity activity) { 37 | 38 | activity.finish(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/AppInfo.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import android.graphics.drawable.Drawable; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 系统内安装的应用信息 9 | * @auther: hyl 10 | * @time: 2015-10-26上午9:51:32 11 | */ 12 | public class AppInfo implements Serializable { 13 | /** 14 | * 15 | */ 16 | private static final long serialVersionUID = 1L; 17 | 18 | /** 19 | * 应用名称 20 | */ 21 | private String mAppLable; 22 | /** 23 | * 应用图标 24 | */ 25 | private Drawable mAppIcon; 26 | /** 27 | * 应用包名 28 | */ 29 | private String mAppPackage; 30 | /** 31 | * 应用class 32 | */ 33 | private String mAppClass; 34 | 35 | public String getAppLable() { 36 | return mAppLable; 37 | } 38 | public void setAppLable(String appLable) { 39 | this.mAppLable = appLable; 40 | } 41 | public Drawable getAppIcon() { 42 | return mAppIcon; 43 | } 44 | public void setAppIcon(Drawable appIcon) { 45 | this.mAppIcon = appIcon; 46 | } 47 | public String getAppPackage() { 48 | return mAppPackage; 49 | } 50 | public void setAppPackage(String appPackage) { 51 | this.mAppPackage = appPackage; 52 | } 53 | public String getAppClass() { 54 | return mAppClass; 55 | } 56 | public void setAppClass(String appClass) { 57 | this.mAppClass = appClass; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/BitmapUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | 9 | public class BitmapUtil { 10 | /** 11 | * 获取缩放图 12 | * @param file 13 | * @param width 14 | * @return 15 | */ 16 | public static Bitmap createBitmapWithFile(String filePath, int width) { 17 | BitmapFactory.Options options = new BitmapFactory.Options(); 18 | options.inJustDecodeBounds = true; 19 | BitmapFactory.decodeFile(filePath, options); 20 | options.inSampleSize = options.outWidth / width; 21 | if(options.outWidth == 0) { 22 | //避免图片还没有保存成功 23 | options.outWidth = width; 24 | options.outHeight = width * 4 / 3; 25 | }else { 26 | options.outHeight = options.outHeight * width / options.outWidth; 27 | options.outWidth = width; 28 | } 29 | options.inDither = false; //图片不抖动 30 | options.inJustDecodeBounds = false; 31 | options.inPreferredConfig = Bitmap.Config.ARGB_4444; 32 | options.inPurgeable = true; 33 | options.inInputShareable = true; 34 | Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); 35 | return bitmap; 36 | } 37 | 38 | /*** 39 | * 通过bitmap获取图片 40 | * @param filePath 41 | * @param bitmap 42 | */ 43 | public static void createPictureWithBitmap(String filePath, Bitmap bitmap) { 44 | File file = new File(filePath); 45 | if(file.exists()) { 46 | file.delete(); 47 | } 48 | try { 49 | FileOutputStream outputStream = new FileOutputStream(file); 50 | bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); 51 | outputStream.flush(); 52 | outputStream.close(); 53 | } catch (Exception e) { 54 | } 55 | } 56 | 57 | /** 58 | * 通过bitmap获取图片 59 | * @param filePath 60 | * @param bitmap 61 | * @param percent 获取图片质量 62 | */ 63 | public static void createPictureWithBitmap(String filePath, Bitmap bitmap, int percent) { 64 | File file = new File(filePath); 65 | if(file.exists()) { 66 | file.delete(); 67 | } 68 | try { 69 | FileOutputStream outputStream = new FileOutputStream(file); 70 | bitmap.compress(Bitmap.CompressFormat.JPEG, percent, outputStream); 71 | outputStream.flush(); 72 | outputStream.close(); 73 | } catch (Exception e) { 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/ByteUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | 8 | public class ByteUtil { 9 | /** 10 | * byte[] 转为 对象 11 | * 12 | * @param bytes 13 | * @return 14 | */ 15 | public static Object byteToObject(byte[] bytes) throws Exception { 16 | ObjectInputStream ois = null; 17 | try { 18 | ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); 19 | return ois.readObject(); 20 | } finally { 21 | if (ois != null) ois.close(); 22 | } 23 | } 24 | 25 | /** 26 | * 对象 转为 byte[] 27 | * 28 | * @param obj 29 | * @return 30 | */ 31 | public static byte[] objectToByte(Object obj) throws Exception { 32 | ObjectOutputStream oos = null; 33 | try { 34 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 35 | oos = new ObjectOutputStream(bos); 36 | oos.writeObject(obj); 37 | return bos.toByteArray(); 38 | } finally { 39 | if (oos != null) oos.close(); 40 | } 41 | } 42 | 43 | public static void byteToBit(byte[] bytes, StringBuilder sb) { 44 | for (int i = 0; i < Byte.SIZE * bytes.length; i++) 45 | sb.append((bytes[i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1'); 46 | } 47 | 48 | public static String byteToBit(byte[] bytes) { 49 | StringBuilder sb = new StringBuilder(); 50 | for (int i = 0; i < Byte.SIZE * bytes.length; i++) 51 | sb.append((bytes[i / Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1'); 52 | return sb.toString(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/DisplayUtils.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.util.DisplayMetrics; 6 | 7 | public class DisplayUtils { 8 | /** 9 | * 将px值转换为dp值 10 | */ 11 | public static int px2dp(Context context, float pxValue) { 12 | final float scale = context.getResources().getDisplayMetrics().density; 13 | return (int) (pxValue / scale + 0.5f); 14 | } 15 | 16 | /** 17 | * 将dp值转换为px值 18 | */ 19 | public static int dp2px(Context context, float dpValue) { 20 | final float scale = context.getResources().getDisplayMetrics().density; 21 | return (int) (dpValue * scale + 0.5f); 22 | } 23 | 24 | /** 25 | * 将px值转换为sp值 26 | */ 27 | public static int px2sp(Context context, float pxValue) { 28 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 29 | return (int) (pxValue / fontScale + 0.5f); 30 | } 31 | 32 | /** 33 | * 将sp值转换为px值 34 | */ 35 | public static int sp2px(Context context, float spValue) { 36 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 37 | return (int) (spValue * fontScale + 0.5f); 38 | } 39 | 40 | /** 41 | * 获取屏幕宽度 42 | */ 43 | public static int getScreenWidthPixels(Activity context) { 44 | DisplayMetrics metric = new DisplayMetrics(); 45 | context.getWindowManager().getDefaultDisplay().getMetrics(metric); 46 | return metric.widthPixels; 47 | } 48 | 49 | /** 50 | * 获取屏幕高度 51 | */ 52 | public static int getScreenHeightPixels(Activity context) { 53 | DisplayMetrics metric = new DisplayMetrics(); 54 | context.getWindowManager().getDefaultDisplay().getMetrics(metric); 55 | return metric.heightPixels; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/KeyboardUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.inputmethod.InputMethodManager; 6 | 7 | /** 8 | * @author: laohu on 2017/2/5 9 | * @site: http://ittiger.cn 10 | */ 11 | public class KeyboardUtil { 12 | 13 | /** 14 | * 隐藏软键盘 15 | */ 16 | public static void hideKeyboard(Context context) { 17 | 18 | Activity activity = (Activity) context; 19 | if (activity != null) { 20 | InputMethodManager imm = (InputMethodManager) activity 21 | .getSystemService(Context.INPUT_METHOD_SERVICE); 22 | if (imm.isActive() && activity.getCurrentFocus() != null) { 23 | imm.hideSoftInputFromWindow(activity.getCurrentFocus() 24 | .getWindowToken(), 0); 25 | } 26 | } 27 | } 28 | 29 | /** 30 | * 显示软键盘 31 | */ 32 | public static void showKeyboard(Context context) { 33 | 34 | Activity activity = (Activity) context; 35 | if (activity != null) { 36 | InputMethodManager imm = (InputMethodManager) activity 37 | .getSystemService(Context.INPUT_METHOD_SERVICE); 38 | imm.showSoftInputFromInputMethod(activity.getCurrentFocus() 39 | .getWindowToken(), 0); 40 | imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/PageLoadingHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import cn.ittiger.R; 4 | import cn.ittiger.ui.LoadingView; 5 | 6 | import android.view.View; 7 | import android.widget.FrameLayout; 8 | import android.widget.TextView; 9 | 10 | /** 11 | * 页面加载的时候,页面加载进度条及加载失败后的处理 12 | * @author: laohu on 2016/7/3 13 | * @site: http://ittiger.cn 14 | */ 15 | public class PageLoadingHelper { 16 | private FrameLayout mLoadingFailedLayout; 17 | private LoadingView mLoadingView; 18 | private TextView mLoadingFailedText; 19 | 20 | public PageLoadingHelper(View rootView) { 21 | 22 | mLoadingFailedLayout = (FrameLayout) rootView.findViewById(R.id.loading_failed_layout); 23 | mLoadingView = (LoadingView) rootView.findViewById(R.id.loadingView); 24 | mLoadingFailedText = (TextView) rootView.findViewById(R.id.errorView); 25 | } 26 | 27 | public void setOnLoadingClickListener(final View.OnClickListener onClickListener) { 28 | 29 | this.mLoadingFailedText.setOnClickListener(new View.OnClickListener() { 30 | 31 | @Override 32 | public void onClick(View v) { 33 | 34 | if(onClickListener != null) { 35 | mLoadingFailedText.setVisibility(View.GONE); 36 | onClickListener.onClick(v); 37 | } 38 | } 39 | }); 40 | } 41 | 42 | public void setLoadingFailedText(String failedText) { 43 | 44 | mLoadingFailedText.setText(failedText); 45 | } 46 | 47 | /** 48 | * 开始加载数据 49 | */ 50 | public void startRefresh() { 51 | 52 | if(mLoadingView.getVisibility() == View.GONE) { 53 | mLoadingFailedLayout.setVisibility(View.VISIBLE); 54 | mLoadingView.setVisibility(View.VISIBLE); 55 | mLoadingView.start(); 56 | mLoadingFailedText.setVisibility(View.GONE); 57 | } 58 | } 59 | 60 | /** 61 | * 加载失败 62 | */ 63 | public void refreshFailed() { 64 | 65 | if(mLoadingView.getVisibility() == View.VISIBLE) { 66 | mLoadingView.stop(); 67 | mLoadingView.setVisibility(View.GONE); 68 | mLoadingFailedText.setVisibility(View.VISIBLE); 69 | } 70 | } 71 | 72 | /** 73 | * 加载成功 74 | */ 75 | public void refreshSuccess() { 76 | 77 | if(mLoadingFailedLayout.getVisibility() == View.VISIBLE) { 78 | mLoadingView.stop(); 79 | mLoadingFailedLayout.setVisibility(View.GONE); 80 | mLoadingView.setVisibility(View.GONE); 81 | mLoadingFailedText.setVisibility(View.GONE); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/SdCardUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.os.Environment; 7 | import android.os.StatFs; 8 | 9 | import java.io.File; 10 | 11 | /** 12 | * SDCard帮助类 13 | * @author: huylee 14 | * @time: 2015-8-13下午10:13:31 15 | */ 16 | public class SdCardUtil { 17 | 18 | /** 19 | * 是否存在SD卡 20 | * @return 21 | */ 22 | public static boolean isHasSDCard() { 23 | return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); 24 | } 25 | 26 | /** 27 | * 获取手机SD卡根目录路径 28 | * @return 29 | */ 30 | public static String getSDCardDir() { 31 | return Environment.getExternalStorageDirectory().getPath(); 32 | } 33 | 34 | /** 35 | * 获取手机自身根目录 36 | * @return 37 | */ 38 | public static String getMobileDir() { 39 | return Environment.getDataDirectory().getAbsolutePath(); 40 | } 41 | 42 | /** 43 | * 获取手机数据根目录,有Sdcard则返回Sdcard根目录,没有则返回手机自身根目录 44 | * @return 45 | */ 46 | public static String getRootPath() { 47 | return isHasSDCard() ? getSDCardDir() : getMobileDir(); 48 | } 49 | 50 | /** 51 | * 应用缓存目录,可以通过手机中的清除缓存把数据清除掉 52 | * @param context 53 | * @return 54 | */ 55 | public static String getCacheDir(Context context) { 56 | return context.getCacheDir().getAbsolutePath(); 57 | } 58 | 59 | /** 60 | * 获取当前应用的文件目录 61 | * @param context 62 | * @return 63 | */ 64 | public static String getFilesDir(Context context) { 65 | return context.getFilesDir().getAbsolutePath(); 66 | } 67 | 68 | /** 69 | * 获取当前路径,可用空间 70 | */ 71 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 72 | public static long getAvailableSize(String path) { 73 | try { 74 | File base = new File(path); 75 | StatFs stat = new StatFs(base.getPath()); 76 | return stat.getBlockSizeLong() * stat.getAvailableBlocksLong(); 77 | } catch (Exception e) { 78 | e.printStackTrace(); 79 | } 80 | return 0; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/UIUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.widget.Toast; 7 | 8 | /** 9 | * Created by laohu on 16-12-14. 10 | */ 11 | public class UIUtil { 12 | 13 | private static Handler sHandler = new Handler(Looper.getMainLooper()); 14 | 15 | public static Thread getUIThread() { 16 | 17 | return Looper.getMainLooper().getThread(); 18 | } 19 | 20 | public static boolean isOnUIThread() { 21 | 22 | return Thread.currentThread() == getUIThread(); 23 | } 24 | 25 | /** 26 | * 在UI线程执行 27 | * 28 | * @param action 29 | */ 30 | public static void runOnUIThread(Runnable action) { 31 | 32 | if (!isOnUIThread()) { 33 | getHandler().post(action); 34 | } else { 35 | action.run(); 36 | } 37 | } 38 | 39 | public static Handler getHandler() { 40 | 41 | return sHandler; 42 | } 43 | 44 | public static void showToast(Context context, String msg) { 45 | 46 | Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); 47 | } 48 | 49 | public static void showToast(Context context, int resId) { 50 | 51 | Toast.makeText(context, context.getString(resId), Toast.LENGTH_SHORT).show(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/ValueUtil.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util; 2 | 3 | import java.util.Collection; 4 | 5 | public class ValueUtil { 6 | /** 7 | * 判断字符串是否为空,Null或空白字符串均返回true 8 | * Author: hyl 9 | * Time: 2015-8-13下午1:18:26 10 | * @param value 11 | * @return 12 | */ 13 | public static boolean isEmpty(String value) { 14 | if(value == null) { 15 | return true; 16 | } 17 | if(value.trim().length() == 0) { 18 | return true; 19 | } 20 | return false; 21 | } 22 | 23 | /** 24 | * 判断集合是否为空,Null或集合没有元素均返回true 25 | * Author: hyl 26 | * Time: 2015-8-17下午9:30:24 27 | * @param collection 28 | * @return 29 | */ 30 | public static boolean isEmpty(Collection collection) { 31 | if(collection == null || collection.size() <= 0) { 32 | return true; 33 | } 34 | return false; 35 | } 36 | 37 | /** 38 | * 判断Object是否为空 39 | * Author: hyl 40 | * Time: 2015-8-17下午9:42:29 41 | * @param object 42 | * @return 43 | */ 44 | public static boolean isEmpty(Object object) { 45 | if(object == null) { 46 | return true; 47 | } 48 | return false; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/cipher/Base64Cipher.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util.cipher; 2 | 3 | import android.util.Base64; 4 | 5 | public class Base64Cipher extends Cipher { 6 | private Cipher cipher; 7 | 8 | public Base64Cipher() { 9 | } 10 | 11 | public Base64Cipher(Cipher cipher) { 12 | this.cipher = cipher; 13 | } 14 | 15 | @Override 16 | public byte[] decrypt(byte[] res) { 17 | if(cipher != null) res = cipher.decrypt(res); 18 | return Base64.decode(res, Base64.DEFAULT); 19 | } 20 | 21 | @Override 22 | public byte[] encrypt(byte[] res) { 23 | if(cipher != null) res = cipher.encrypt(res); 24 | return Base64.encode(res, Base64.DEFAULT); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/cipher/Cipher.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util.cipher; 2 | 3 | /** 4 | * @author MaTianyu 5 | * @date 14-7-31 6 | */ 7 | public abstract class Cipher implements Encrypt,Decrypt{ 8 | 9 | } 10 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/cipher/Decrypt.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util.cipher; 2 | 3 | /** 4 | * @author MaTianyu 5 | * @date 14-7-31 6 | */ 7 | public interface Decrypt { 8 | public byte[] decrypt(byte[] res); 9 | } 10 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/java/cn/ittiger/util/cipher/Encrypt.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.util.cipher; 2 | 3 | /** 4 | * @author MaTianyu 5 | * @date 14-7-31 6 | */ 7 | public interface Encrypt { 8 | public byte[] encrypt(byte[] res); 9 | } 10 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/res/layout/base_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/res/layout/loading_failed_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 20 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /TigerLibrary/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 加载失败,点击重试 3 | 再按一次退出程序 4 | 5 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | //butterknife 3 | apply plugin: 'android-apt' 4 | 5 | android { 6 | compileSdkVersion 24 7 | buildToolsVersion "24.0.2" 8 | 9 | defaultConfig { 10 | applicationId "cn.ittiger.im" 11 | minSdkVersion 14 12 | targetSdkVersion 24 13 | versionCode 2 14 | versionName "2.0" 15 | vectorDrawables.useSupportLibrary=true 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | testCompile 'junit:junit:4.12' 28 | compile project(':TigerLibrary') 29 | compile 'com.android.support:design:24.2.1' 30 | compile 'com.android.support:cardview-v7:24.2.1' 31 | compile 'cn.ittiger:indexstickyview:1.1.0' 32 | 33 | //smack-core为核心库 34 | compile 'org.igniterealtime.smack:smack-core:4.1.9' 35 | //Smack IM.Classes and methods for XMPP-IM (RFC 6121): Roster, Chat and other functionality 36 | compile "org.igniterealtime.smack:smack-im:4.1.9" 37 | //Smack for Android. All the required dependencies to run Smack on Android. 38 | //smack-android依赖smack-extensions和smack-experimental和smack-tcp 39 | compile "org.igniterealtime.smack:smack-android:4.1.9" 40 | compile "org.igniterealtime.smack:smack-android-extensions:4.1.9" 41 | //XMPP connections 42 | compile "org.igniterealtime.smack:smack-tcp:4.1.9" 43 | //support for the various XMPP XEPs (Multi-User Chat, PubSub, …) and other XMPP extensions. 44 | compile "org.igniterealtime.smack:smack-extensions:4.1.9" 45 | compile "org.igniterealtime.smack:smack-experimental:4.1.9" 46 | 47 | //UIL 48 | compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' 49 | //Logger 50 | compile 'com.orhanobut:logger:1.15' 51 | 52 | //butterknife 53 | compile 'com.jakewharton:butterknife:8.4.0' 54 | apt 'com.jakewharton:butterknife-compiler:8.4.0' 55 | 56 | //rxjava 57 | compile 'io.reactivex:rxjava:1.1.6' 58 | compile 'io.reactivex:rxandroid:1.2.1' 59 | 60 | //eventbus 61 | compile 'org.greenrobot:eventbus:3.0.0' 62 | } 63 | -------------------------------------------------------------------------------- /app/libs/TigerDB.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/libs/TigerDB.jar -------------------------------------------------------------------------------- /app/problem.md: -------------------------------------------------------------------------------- 1 | ### java.lang.VerifyError: org/jivesoftware/smack/sasl/javax/SASLJavaXMechanism 2 | 在初始化`XMPPTCPConnectionConfiguration.builder()`的时候出现上述异常,移除smack-java7相关jar包即可 3 | 4 | ### org.jivesoftware.smack.smackexception$noresponseexception no response received within reply timeout 5 | 登陆的时候出现这个异常信息,一直以为是代码出现了问题,然后各种google,结果依然无效,最后发现将手机的网络代理去掉就ok了,我擦嘞~~~ -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/baina/ylhu/program/android-sdk-linux/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/ittiger/im/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | 12 | super(Application.class); 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 34 | 35 | 38 | 39 | 42 | 43 | 47 | 48 | 51 | 52 | 55 | 56 | 59 | 60 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/activity/AccountMngActivity.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.activity; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.widget.Button; 6 | import android.widget.RadioGroup; 7 | import android.widget.RadioGroup.OnCheckedChangeListener; 8 | 9 | import butterknife.BindView; 10 | import butterknife.OnClick; 11 | import cn.ittiger.base.BaseActivity; 12 | import cn.ittiger.im.R; 13 | import cn.ittiger.im.smack.SmackManager; 14 | import cn.ittiger.util.ActivityUtil; 15 | import cn.ittiger.util.UIUtil; 16 | 17 | /** 18 | * 账号管理 19 | * @auther: hyl 20 | * @time: 2015-10-23下午3:11:11 21 | */ 22 | public class AccountMngActivity extends BaseActivity { 23 | /** 24 | * 注销登陆 25 | */ 26 | @BindView(R.id.btn_logout) 27 | Button mBtnLogout; 28 | /** 29 | * 用户状态修改 30 | */ 31 | @BindView(R.id.rg_user_state) 32 | RadioGroup mUserState; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_account_mng_layout); 38 | 39 | mUserState.setOnCheckedChangeListener(new OnCheckedChangeListener() { 40 | @Override 41 | public void onCheckedChanged(RadioGroup group, int checkedId) { 42 | switch(checkedId) { 43 | case R.id.rb_user_online://在线 44 | changeState(0); 45 | break; 46 | case R.id.rb_user_busy://忙碌 47 | changeState(2); 48 | break; 49 | case R.id.rb_disconnect://断开连接 50 | disconnect(); 51 | break; 52 | } 53 | } 54 | }); 55 | } 56 | 57 | public void changeState(int code) { 58 | if(SmackManager.getInstance().updateUserState(code)) { 59 | UIUtil.showToast(this, "修改状态成功"); 60 | } else { 61 | UIUtil.showToast(this, "修改状态失败"); 62 | } 63 | } 64 | 65 | public void disconnect() { 66 | if(SmackManager.getInstance().disconnect()) { 67 | ActivityUtil.finishActivity(this); 68 | } else { 69 | UIUtil.showToast(this, "断开连接失败"); 70 | } 71 | } 72 | 73 | /** 74 | * 注销登陆 75 | * @param v 76 | */ 77 | @OnClick(R.id.btn_logout) 78 | public void onLogoutClick(View v) { 79 | if(SmackManager.getInstance().logout()) { 80 | ActivityUtil.finishActivity(this); 81 | } else { 82 | UIUtil.showToast(this, "注销失败"); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/activity/MultiChatActivity.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.activity; 2 | 3 | import org.greenrobot.eventbus.Subscribe; 4 | import org.greenrobot.eventbus.ThreadMode; 5 | import org.jivesoftware.smackx.muc.MultiUserChat; 6 | import org.json.JSONObject; 7 | 8 | import android.os.Bundle; 9 | 10 | import cn.ittiger.im.R; 11 | import cn.ittiger.im.activity.base.BaseChatActivity; 12 | import cn.ittiger.im.bean.ChatMessage; 13 | import cn.ittiger.im.constant.KeyBoardMoreFunType; 14 | import cn.ittiger.im.smack.SmackManager; 15 | import cn.ittiger.util.ValueUtil; 16 | import rx.Observable; 17 | import rx.functions.Action1; 18 | import rx.schedulers.Schedulers; 19 | 20 | import com.orhanobut.logger.Logger; 21 | 22 | import java.io.File; 23 | 24 | /** 25 | * 多人聊天 26 | * 27 | * @author: laohu on 2017/2/3 28 | * @site: http://ittiger.cn 29 | */ 30 | public class MultiChatActivity extends BaseChatActivity { 31 | /** 32 | * 多人聊天对象 33 | */ 34 | private MultiUserChat mMultiUserChat; 35 | 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.activity_multichat_layout); 41 | mMultiUserChat = SmackManager.getInstance().getMultiChat(mChatUser.getFriendUsername()); 42 | } 43 | 44 | @Subscribe(threadMode = ThreadMode.MAIN) 45 | public void onReceiveChatMessageEvent(ChatMessage message) { 46 | 47 | if(mChatUser.getFriendUsername().equals(message.getFriendUsername()) && message.isMulti()) { 48 | addChatMessageView(message); 49 | } 50 | } 51 | 52 | @Override 53 | public void send(String message) { 54 | 55 | if (ValueUtil.isEmpty(message)) { 56 | return; 57 | } 58 | Observable.just(message) 59 | .observeOn(Schedulers.io()) 60 | .subscribe(new Action1() { 61 | @Override 62 | public void call(String message) { 63 | try { 64 | JSONObject json = new JSONObject(); 65 | json.put(ChatMessage.KEY_MESSAGE_CONTENT, message); 66 | json.put(ChatMessage.KEY_MULTI_CHAT_SEND_USER, mChatUser.getMeUsername()); 67 | mMultiUserChat.sendMessage(json.toString()); 68 | } catch (Exception e) { 69 | Logger.e(e, "send message failure"); 70 | } 71 | } 72 | }); 73 | } 74 | 75 | @Override 76 | public void sendVoice(File audioFile) { 77 | 78 | } 79 | 80 | @Override 81 | public void functionClick(KeyBoardMoreFunType funType) { 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/activity/base/IMBaseActivity.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.activity.base; 2 | 3 | import cn.ittiger.base.BaseActivity; 4 | import cn.ittiger.im.R; 5 | 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | 9 | /** 10 | * @author: laohu on 2017/1/1 11 | * @site: http://ittiger.cn 12 | */ 13 | public class IMBaseActivity extends BaseActivity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | 18 | super.onCreate(savedInstanceState); 19 | initNavigationBarColor(); 20 | } 21 | 22 | private void initNavigationBarColor() { 23 | 24 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 25 | getWindow().setNavigationBarColor(getResources().getColor(R.color.main_color)); 26 | } 27 | } 28 | 29 | @Override 30 | public boolean isLceActivity() { 31 | 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/ChatRecordAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter; 2 | 3 | import cn.ittiger.im.R; 4 | import cn.ittiger.im.adapter.viewholder.ChatRecordViewHolder; 5 | import cn.ittiger.im.bean.ChatRecord; 6 | import cn.ittiger.im.constant.EmotionType; 7 | import cn.ittiger.im.ui.recyclerview.HeaderAndFooterAdapter; 8 | import cn.ittiger.im.ui.recyclerview.ViewHolder; 9 | import cn.ittiger.im.util.ChatTimeUtil; 10 | import cn.ittiger.im.util.EmotionUtil; 11 | import cn.ittiger.im.util.ImageLoaderHelper; 12 | import cn.ittiger.util.ValueUtil; 13 | 14 | import android.content.Context; 15 | import android.text.SpannableString; 16 | import android.view.LayoutInflater; 17 | import android.view.View; 18 | import android.view.ViewGroup; 19 | 20 | import java.util.List; 21 | 22 | import static android.R.id.message; 23 | 24 | /** 25 | * 聊天记录列表适配器 26 | * @author: laohu on 2017/1/22 27 | * @site: http://ittiger.cn 28 | */ 29 | public class ChatRecordAdapter extends HeaderAndFooterAdapter { 30 | private Context mContext; 31 | 32 | public ChatRecordAdapter(Context context, List list) { 33 | 34 | super(list); 35 | this.mContext = context; 36 | } 37 | 38 | @Override 39 | public ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { 40 | 41 | View view = LayoutInflater.from(mContext).inflate(R.layout.chat_record_item_layout, parent, false); 42 | return new ChatRecordViewHolder(view); 43 | } 44 | 45 | @Override 46 | public void onBindItemViewHolder(ViewHolder holder, int position, ChatRecord item) { 47 | 48 | ChatRecordViewHolder viewHolder = (ChatRecordViewHolder) holder; 49 | 50 | if(!ValueUtil.isEmpty(item.getFriendAvatar())) { 51 | ImageLoaderHelper.displayImage(viewHolder.avatar, item.getFriendAvatar()); 52 | } 53 | viewHolder.nickName.setText(item.getFriendNickname()); 54 | if(!ValueUtil.isEmpty(item.getLastMessage())) { 55 | if(viewHolder.message.getVisibility() == View.GONE) { 56 | viewHolder.message.setVisibility(View.VISIBLE); 57 | } 58 | SpannableString content = EmotionUtil.getInputEmotionContent(mContext, EmotionType.EMOTION_TYPE_CLASSIC, viewHolder.message, item.getLastMessage()); 59 | viewHolder.message.setText(content); 60 | } 61 | viewHolder.chatTime.setText(ChatTimeUtil.getFriendlyTimeSpanByNow(item.getChatTime())); 62 | String messageCount = item.getUnReadMessageCount() > 0 ? String.valueOf(item.getUnReadMessageCount()) : ""; 63 | viewHolder.messageCount.setText(messageCount); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/CheckableContactAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter; 2 | 3 | import cn.ittiger.im.R; 4 | import cn.ittiger.im.adapter.viewholder.ContactIndexViewHolder; 5 | import cn.ittiger.im.adapter.viewholder.CreateMultiChatViewHolder; 6 | import cn.ittiger.im.bean.CheckableContactEntity; 7 | import cn.ittiger.indexlist.adapter.IndexStickyViewAdapter; 8 | 9 | import android.content.Context; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * 可选联系人列表适配器 19 | * @author: laohu on 2017/1/24 20 | * @site: http://ittiger.cn 21 | */ 22 | public class CheckableContactAdapter extends IndexStickyViewAdapter { 23 | private Context mContext; 24 | 25 | public CheckableContactAdapter(Context context, List originalList) { 26 | 27 | super(originalList); 28 | mContext = context; 29 | } 30 | 31 | @Override 32 | public RecyclerView.ViewHolder onCreateIndexViewHolder(ViewGroup parent) { 33 | 34 | View view = LayoutInflater.from(mContext).inflate(R.layout.contact_item_index_view, parent, false); 35 | return new ContactIndexViewHolder(view); 36 | } 37 | 38 | @Override 39 | public RecyclerView.ViewHolder onCreateContentViewHolder(ViewGroup parent) { 40 | 41 | View view = LayoutInflater.from(mContext).inflate(R.layout.checkable_contact_item_view, parent, false); 42 | return new CreateMultiChatViewHolder(view); 43 | } 44 | 45 | @Override 46 | public void onBindIndexViewHolder(RecyclerView.ViewHolder holder, int position, String indexName) { 47 | 48 | ContactIndexViewHolder viewHolder = (ContactIndexViewHolder) holder; 49 | viewHolder.getTextView().setText(indexName); 50 | } 51 | 52 | @Override 53 | public void onBindContentViewHolder(RecyclerView.ViewHolder holder, int position, CheckableContactEntity itemData) { 54 | 55 | CreateMultiChatViewHolder viewHolder = (CreateMultiChatViewHolder) holder; 56 | if(itemData.isChecked()) { 57 | viewHolder.getCheckImageView().setImageResource(R.drawable.vector_checked); 58 | } else { 59 | viewHolder.getCheckImageView().setImageResource(R.drawable.vector_uncheck); 60 | } 61 | viewHolder.getImageView().setImageResource(R.drawable.vector_contact_focus); 62 | viewHolder.getTextView().setText(itemData.getRosterEntry().getName()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/ContactAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter; 2 | 3 | import cn.ittiger.im.R; 4 | import cn.ittiger.im.adapter.viewholder.ContactIndexViewHolder; 5 | import cn.ittiger.im.adapter.viewholder.ContactViewHolder; 6 | import cn.ittiger.im.bean.ContactEntity; 7 | import cn.ittiger.indexlist.adapter.IndexStickyViewAdapter; 8 | 9 | import android.content.Context; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * 联系人列表数据适配器 19 | * @author: laohu on 2016/12/27 20 | * @site: http://ittiger.cn 21 | */ 22 | public class ContactAdapter extends IndexStickyViewAdapter { 23 | private Context mContext; 24 | public ContactAdapter(Context context, List originalList) { 25 | 26 | super(originalList); 27 | mContext = context; 28 | } 29 | 30 | @Override 31 | public RecyclerView.ViewHolder onCreateIndexViewHolder(ViewGroup parent) { 32 | 33 | View view = LayoutInflater.from(mContext).inflate(R.layout.contact_item_index_view, parent, false); 34 | return new ContactIndexViewHolder(view); 35 | } 36 | 37 | @Override 38 | public RecyclerView.ViewHolder onCreateContentViewHolder(ViewGroup parent) { 39 | 40 | View view = LayoutInflater.from(mContext).inflate(R.layout.contact_item_view, parent, false); 41 | return new ContactViewHolder(view); 42 | } 43 | 44 | @Override 45 | public void onBindIndexViewHolder(RecyclerView.ViewHolder holder, int position, String indexName) { 46 | 47 | ContactIndexViewHolder viewHolder = (ContactIndexViewHolder) holder; 48 | viewHolder.getTextView().setText(indexName); 49 | } 50 | 51 | @Override 52 | public void onBindContentViewHolder(RecyclerView.ViewHolder holder, int position, ContactEntity itemData) { 53 | 54 | ContactViewHolder viewHolder = (ContactViewHolder) holder; 55 | viewHolder.getImageView().setImageResource(R.drawable.vector_contact_focus); 56 | viewHolder.getTextView().setText(itemData.getRosterEntry().getName()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/EmotionViewPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter; 2 | 3 | import android.support.v4.view.PagerAdapter; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author: laohu on 2017/2/6 11 | * @site: http://ittiger.cn 12 | */ 13 | public class EmotionViewPagerAdapter extends PagerAdapter { 14 | private List mViewList; 15 | 16 | public EmotionViewPagerAdapter(List viewList) { 17 | 18 | mViewList = viewList; 19 | } 20 | 21 | @Override 22 | public Object instantiateItem(ViewGroup container, int position) { 23 | 24 | View view = mViewList.get(position); 25 | container.addView(view); 26 | return view; 27 | } 28 | 29 | @Override 30 | public void destroyItem(ViewGroup container, int position, Object object) { 31 | 32 | container.removeView(mViewList.get(position)); 33 | } 34 | 35 | @Override 36 | public int getCount() { 37 | 38 | return mViewList.size(); 39 | } 40 | 41 | @Override 42 | public boolean isViewFromObject(View view, Object object) { 43 | 44 | return view == object; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/viewholder/ChatRecordViewHolder.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter.viewholder; 2 | 3 | import butterknife.BindView; 4 | import butterknife.ButterKnife; 5 | import cn.ittiger.im.R; 6 | import cn.ittiger.im.ui.recyclerview.ViewHolder; 7 | 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | /** 13 | * @author: laohu on 2017/1/22 14 | * @site: http://ittiger.cn 15 | */ 16 | public class ChatRecordViewHolder extends ViewHolder { 17 | @BindView(R.id.chat_friend_avatar) 18 | public ImageView avatar; 19 | @BindView(R.id.chat_friend_nickname) 20 | public TextView nickName; 21 | @BindView(R.id.chat_message) 22 | public TextView message; 23 | @BindView(R.id.chat_time) 24 | public TextView chatTime; 25 | @BindView(R.id.chat_message_count) 26 | public TextView messageCount; 27 | 28 | public ChatRecordViewHolder(View itemView) { 29 | 30 | super(itemView); 31 | ButterKnife.bind(this, itemView); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/viewholder/ContactIndexViewHolder.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter.viewholder; 2 | 3 | import butterknife.BindView; 4 | import butterknife.ButterKnife; 5 | import cn.ittiger.im.R; 6 | 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | 11 | /** 12 | * Created by ylhu on 16-12-27. 13 | */ 14 | public class ContactIndexViewHolder extends RecyclerView.ViewHolder { 15 | @BindView(R.id.contact_index_name) 16 | TextView mTextView; 17 | 18 | public ContactIndexViewHolder(View itemView) { 19 | 20 | super(itemView); 21 | ButterKnife.bind(this, itemView); 22 | } 23 | 24 | public TextView getTextView() { 25 | 26 | return mTextView; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/viewholder/ContactViewHolder.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter.viewholder; 2 | 3 | import butterknife.BindView; 4 | import butterknife.ButterKnife; 5 | import cn.ittiger.im.R; 6 | 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | /** 13 | * 联系人列表Item项ViewHolder 14 | * @author: laohu on 2016/12/24 15 | * @site: http://ittiger.cn 16 | */ 17 | public class ContactViewHolder extends RecyclerView.ViewHolder { 18 | @BindView(R.id.contact_avatar) 19 | ImageView avatar; 20 | @BindView(R.id.contact_name) 21 | TextView name; 22 | 23 | public ContactViewHolder(View itemView) { 24 | 25 | super(itemView); 26 | ButterKnife.bind(this, itemView); 27 | } 28 | 29 | public ImageView getImageView() { 30 | 31 | return avatar; 32 | } 33 | 34 | public TextView getTextView() { 35 | 36 | return name; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/adapter/viewholder/CreateMultiChatViewHolder.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.adapter.viewholder; 2 | 3 | import butterknife.BindView; 4 | import butterknife.ButterKnife; 5 | import cn.ittiger.im.R; 6 | 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | /** 13 | * @author: laohu on 2017/1/24 14 | * @site: http://ittiger.cn 15 | */ 16 | public class CreateMultiChatViewHolder extends RecyclerView.ViewHolder { 17 | @BindView(R.id.contact_check) 18 | ImageView checkImageView; 19 | @BindView(R.id.contact_avatar) 20 | ImageView avatar; 21 | @BindView(R.id.contact_name) 22 | TextView name; 23 | 24 | public CreateMultiChatViewHolder(View itemView) { 25 | 26 | super(itemView); 27 | ButterKnife.bind(this, itemView); 28 | } 29 | 30 | public ImageView getCheckImageView() { 31 | 32 | return checkImageView; 33 | } 34 | 35 | public ImageView getImageView() { 36 | 37 | return avatar; 38 | } 39 | 40 | public TextView getTextView() { 41 | 42 | return name; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/app/IDbApplication.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.app; 2 | 3 | import cn.ittiger.database.SQLiteDBConfig; 4 | 5 | /** 6 | * 本地数据库接口 7 | * @author: laohu on 2017/1/18 8 | * @site: http://ittiger.cn 9 | */ 10 | public interface IDbApplication { 11 | /** 12 | * 系统全局数据库配置 13 | * @return 14 | */ 15 | SQLiteDBConfig getGlobalDbConfig(); 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/bean/CheckableContactEntity.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.bean; 2 | 3 | import cn.ittiger.indexlist.entity.BaseEntity; 4 | 5 | import org.jivesoftware.smack.roster.RosterEntry; 6 | 7 | /** 8 | * 创建群聊时可选联系人实体 9 | * @author: laohu on 2017/1/24 10 | * @site: http://ittiger.cn 11 | */ 12 | public class CheckableContactEntity implements BaseEntity { 13 | private RosterEntry mRosterEntry; 14 | private boolean mChecked = false; 15 | 16 | public CheckableContactEntity(RosterEntry rosterEntry) { 17 | 18 | mRosterEntry = rosterEntry; 19 | } 20 | 21 | @Override 22 | public String getIndexField() { 23 | 24 | return mRosterEntry.getName(); 25 | } 26 | 27 | public RosterEntry getRosterEntry() { 28 | 29 | return mRosterEntry; 30 | } 31 | 32 | public boolean isChecked() { 33 | 34 | return mChecked; 35 | } 36 | 37 | public void setChecked(boolean checked) { 38 | 39 | mChecked = checked; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object obj) { 44 | 45 | if(obj == null) { 46 | return false; 47 | } 48 | if(obj instanceof CheckableContactEntity) { 49 | return mRosterEntry.getUser().equals(((CheckableContactEntity) obj).getRosterEntry().getUser()) && 50 | mRosterEntry.getName().equals(((CheckableContactEntity) obj).getRosterEntry().getName()); 51 | } 52 | 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/bean/ContactEntity.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.bean; 2 | 3 | import cn.ittiger.indexlist.entity.BaseEntity; 4 | 5 | import org.jivesoftware.smack.roster.RosterEntry; 6 | 7 | /** 8 | * 联系人实体 9 | * @author: laohu on 2016/12/26 10 | * @site: http://ittiger.cn 11 | */ 12 | public class ContactEntity implements BaseEntity { 13 | private RosterEntry mRosterEntry; 14 | 15 | public ContactEntity(RosterEntry rosterEntry) { 16 | 17 | mRosterEntry = rosterEntry; 18 | } 19 | 20 | @Override 21 | public String getIndexField() { 22 | 23 | return mRosterEntry.getName(); 24 | } 25 | 26 | public RosterEntry getRosterEntry() { 27 | 28 | return mRosterEntry; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/bean/ContactMenuEntity.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.bean; 2 | 3 | import cn.ittiger.im.R; 4 | import cn.ittiger.indexlist.entity.BaseEntity; 5 | 6 | /** 7 | * 联系人列表头部的菜单项 8 | * @author: laohu on 2016/12/26 9 | * @site: http://ittiger.cn 10 | */ 11 | public class ContactMenuEntity implements BaseEntity { 12 | private String mMenuName; 13 | private int mAvatar; 14 | private MenuType mMenuType; 15 | 16 | public ContactMenuEntity(String menuName, MenuType menuType) { 17 | 18 | mMenuName = menuName; 19 | mMenuType = menuType; 20 | mAvatar = menuType.getAvatar(); 21 | } 22 | 23 | @Override 24 | public String getIndexField() { 25 | 26 | return mMenuName; 27 | } 28 | 29 | public String getMenuName() { 30 | 31 | return mMenuName; 32 | } 33 | 34 | public MenuType getMenuType() { 35 | 36 | return mMenuType; 37 | } 38 | 39 | public int getAvatar() { 40 | 41 | return mAvatar; 42 | } 43 | 44 | public enum MenuType { 45 | GROUP(R.drawable.vector_contact_group), //分组 46 | MULTI_CHAT(R.drawable.vector_multi_chat); //群聊 47 | 48 | private int mAvatar; 49 | 50 | MenuType(int avatar) { 51 | 52 | mAvatar = avatar; 53 | } 54 | 55 | public int getAvatar() { 56 | 57 | return mAvatar; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/bean/LoginResult.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.bean; 2 | 3 | /** 4 | * Created by ylhu on 16-12-14. 5 | */ 6 | public class LoginResult { 7 | 8 | private User mUser; 9 | private boolean mSuccess; 10 | private String mErrorMsg; 11 | 12 | public LoginResult(User user, boolean success) { 13 | 14 | mUser = user; 15 | mSuccess = success; 16 | } 17 | 18 | public LoginResult(boolean success, String errorMsg) { 19 | 20 | mSuccess = success; 21 | mErrorMsg = errorMsg; 22 | } 23 | 24 | public boolean isSuccess() { 25 | 26 | return mSuccess; 27 | } 28 | 29 | public String getErrorMsg() { 30 | 31 | return mErrorMsg; 32 | } 33 | 34 | public User getUser() { 35 | 36 | return mUser; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/bean/MultiChatRoom.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.bean; 2 | 3 | import cn.ittiger.database.annotation.Column; 4 | import cn.ittiger.database.annotation.PrimaryKey; 5 | import cn.ittiger.database.annotation.Table; 6 | 7 | import org.jivesoftware.smackx.disco.packet.DiscoverItems; 8 | 9 | /** 10 | * 当前用户加入过的群聊 11 | * 12 | * @author: laohu on 2017/2/3 13 | * @site: http://ittiger.cn 14 | */ 15 | @Table(name = "MultiChatRoom") 16 | public class MultiChatRoom { 17 | @PrimaryKey(isAutoGenerate = true) 18 | private long mId; 19 | @Column(columnName = "roomJid") 20 | private String mRoomJid; 21 | 22 | public MultiChatRoom() { 23 | 24 | } 25 | 26 | public MultiChatRoom(String roomJid) { 27 | 28 | mRoomJid = roomJid; 29 | } 30 | 31 | public String getRoomJid() { 32 | 33 | return mRoomJid; 34 | } 35 | 36 | public void setRoomJid(String roomJid) { 37 | 38 | mRoomJid = roomJid; 39 | } 40 | 41 | @Override 42 | public boolean equals(Object obj) { 43 | 44 | if(obj instanceof DiscoverItems.Item) { 45 | return ((DiscoverItems.Item) obj).getEntityID().equals(mRoomJid); 46 | } 47 | if(obj instanceof MultiChatRoom) { 48 | return ((MultiChatRoom) obj).mRoomJid.equals(mRoomJid); 49 | } 50 | return false; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/bean/User.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by laohu on 16-12-14. 7 | */ 8 | public class User implements Serializable { 9 | 10 | private String mUsername; 11 | private String mNickname; 12 | private String mPassword; 13 | 14 | public User() { 15 | 16 | } 17 | 18 | public User(String username, String password) { 19 | 20 | mUsername = username; 21 | mPassword = password; 22 | } 23 | 24 | public String getUsername() { 25 | 26 | return mUsername; 27 | } 28 | 29 | public void setUsername(String username) { 30 | 31 | mUsername = username; 32 | } 33 | 34 | public String getPassword() { 35 | 36 | return mPassword; 37 | } 38 | 39 | public void setPassword(String password) { 40 | 41 | mPassword = password; 42 | } 43 | 44 | public void setNickname(String nickname) { 45 | 46 | mNickname = nickname; 47 | } 48 | 49 | public String getNickname() { 50 | 51 | return mNickname; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/constant/Constant.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.constant; 2 | 3 | /** 4 | * @author: laohu on 2017/2/3 5 | * @site: http://ittiger.cn 6 | */ 7 | public class Constant { 8 | 9 | public static final String MULTI_CHAT_ADDRESS_SPLIT = "@conference."; 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/constant/EmotionType.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.constant; 2 | 3 | import cn.ittiger.im.R; 4 | import cn.ittiger.im.fragment.BaseEmotionFragment; 5 | import cn.ittiger.im.fragment.EmotionFragment; 6 | 7 | /** 8 | * 表情类型 9 | * 10 | * @author: laohu on 2017/2/6 11 | * @site: http://ittiger.cn 12 | */ 13 | public enum EmotionType { 14 | EMOTION_TYPE_CLASSIC(R.drawable.vector_keyboard_emotion, EmotionFragment.class), //经典表情 15 | EMOTION_TYPE_MORE(R.drawable.vector_emotion_more, BaseEmotionFragment.class); //+点击更多 16 | 17 | private int mEmotionTypeIcon; 18 | private Class mFragmentClass; 19 | 20 | EmotionType(int emotionTypeIcon, Class fragmentClass) { 21 | 22 | mEmotionTypeIcon = emotionTypeIcon; 23 | mFragmentClass = fragmentClass; 24 | } 25 | 26 | public int getEmotionTypeIcon() { 27 | 28 | return mEmotionTypeIcon; 29 | } 30 | 31 | public Class getFragmentClass() { 32 | 33 | return mFragmentClass; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/constant/FileLoadState.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.constant; 2 | 3 | /** 4 | * 消息接收过程中文件的加载状态 5 | * @author: laohu on 2017/1/17 6 | * @site: http://ittiger.cn 7 | */ 8 | public enum FileLoadState { 9 | STATE_LOAD_START(0),//加载开始 10 | STATE_LOAD_SUCCESS(1),//加载成功 11 | STATE_LOAD_ERROR(2);//加载失败 12 | 13 | int value; 14 | FileLoadState(int value) { 15 | 16 | this.value = value; 17 | } 18 | 19 | public int value() { 20 | 21 | return value; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/constant/KeyBoardMoreFunType.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.constant; 2 | 3 | /** 4 | * KeyBoard更多功能选项类型 5 | * @author: laohu on 2017/2/4 6 | * @site: http://ittiger.cn 7 | */ 8 | public enum KeyBoardMoreFunType { 9 | NONE(-1), 10 | /** 11 | * 选择图片 12 | */ 13 | FUN_TYPE_IMAGE(0), 14 | /** 15 | * 拍照 16 | */ 17 | FUN_TYPE_TAKE_PHOTO(1); 18 | 19 | int value; 20 | 21 | KeyBoardMoreFunType(int value) { 22 | 23 | this.value = value; 24 | } 25 | 26 | public int value() { 27 | 28 | return value; 29 | } 30 | 31 | public static KeyBoardMoreFunType getFunType(int value) { 32 | 33 | if (value == FUN_TYPE_IMAGE.value()) { 34 | return FUN_TYPE_IMAGE; 35 | } else if(value == FUN_TYPE_TAKE_PHOTO.value()) { 36 | return FUN_TYPE_TAKE_PHOTO; 37 | } else { 38 | return NONE; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/constant/MessageType.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.constant; 2 | 3 | /** 4 | * 消息类型 5 | * @author: laohu on 2017/1/12 6 | * @site: http://ittiger.cn 7 | */ 8 | public enum MessageType { 9 | /** 10 | * 文本消息类型 11 | */ 12 | MESSAGE_TYPE_TEXT(0), 13 | /** 14 | * 图片消息类型 15 | */ 16 | MESSAGE_TYPE_IMAGE(1), 17 | /** 18 | * 语音消息类型 19 | */ 20 | MESSAGE_TYPE_VOICE(2); 21 | 22 | int value; 23 | MessageType(int value) { 24 | 25 | this.value = value; 26 | } 27 | 28 | public int value() { 29 | 30 | return value; 31 | } 32 | 33 | public static MessageType getMessageType(int value) { 34 | 35 | if (value == MESSAGE_TYPE_IMAGE.value()) { 36 | return MESSAGE_TYPE_IMAGE; 37 | } else if(value == MESSAGE_TYPE_TEXT.value()) { 38 | return MESSAGE_TYPE_TEXT; 39 | } else { 40 | return MESSAGE_TYPE_VOICE; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/decoration/CommonItemDecoration.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.decoration; 2 | 3 | import cn.ittiger.app.AppContext; 4 | import cn.ittiger.im.R; 5 | 6 | import android.graphics.Canvas; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.ColorDrawable; 9 | import android.graphics.drawable.Drawable; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.view.View; 12 | 13 | /** 14 | * 聊天记录列表分割线 15 | * @author: laohu on 2016/12/27 16 | * @site: http://ittiger.cn 17 | */ 18 | public class CommonItemDecoration extends RecyclerView.ItemDecoration { 19 | 20 | private final Drawable mDivider; 21 | private final int mSize; 22 | 23 | public CommonItemDecoration() { 24 | 25 | mDivider = new ColorDrawable(AppContext.getInstance().getResources().getColor(R.color.divider_color)); 26 | mSize = AppContext.getInstance().getResources().getDimensionPixelSize(R.dimen.global_divider_size); 27 | } 28 | 29 | @Override 30 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 31 | 32 | outRect.set(0, 0, 0, mSize); 33 | } 34 | 35 | @Override 36 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 37 | 38 | super.onDraw(c, parent, state); 39 | int top; 40 | int bottom; 41 | int left = parent.getPaddingLeft(); 42 | int right = parent.getWidth() - parent.getPaddingRight(); 43 | final int childCount = parent.getChildCount(); 44 | for (int i = 0; i < childCount; i++) { 45 | final View child = parent.getChildAt(i); 46 | //获得child的布局信息 47 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams(); 48 | top = child.getBottom() + params.bottomMargin; 49 | bottom = top + mSize; 50 | mDivider.setBounds(left, top, right, bottom); 51 | mDivider.draw(c); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/decoration/CommonVerticalItemDecoration.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.decoration; 2 | 3 | import cn.ittiger.app.AppContext; 4 | import cn.ittiger.im.R; 5 | 6 | import android.graphics.Canvas; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.ColorDrawable; 9 | import android.graphics.drawable.Drawable; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.view.View; 12 | 13 | /** 14 | * 列表垂直分割线 15 | * @author: laohu on 2017/2/6 16 | * @site: http://ittiger.cn 17 | */ 18 | public class CommonVerticalItemDecoration extends RecyclerView.ItemDecoration { 19 | 20 | private final Drawable mDivider; 21 | private final int mSize; 22 | 23 | public CommonVerticalItemDecoration() { 24 | 25 | mDivider = new ColorDrawable(AppContext.getInstance().getResources().getColor(R.color.divider_color)); 26 | mSize = AppContext.getInstance().getResources().getDimensionPixelSize(R.dimen.global_divider_size); 27 | } 28 | 29 | @Override 30 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 31 | 32 | outRect.set(0, 0, mSize, 0); 33 | } 34 | 35 | @Override 36 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 37 | 38 | super.onDraw(c, parent, state); 39 | int top = parent.getPaddingTop(); 40 | int bottom = parent.getHeight() - parent.getPaddingTop(); 41 | int left; 42 | int right; 43 | final int childCount = parent.getChildCount(); 44 | for (int i = 0; i < childCount; i++) { 45 | final View child = parent.getChildAt(i); 46 | //获得child的布局信息 47 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams(); 48 | left = child.getRight() + params.rightMargin; 49 | right = left + mSize; 50 | mDivider.setBounds(left, top, right, bottom); 51 | mDivider.draw(c); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/fragment/BaseEmotionFragment.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.fragment; 2 | 3 | import cn.ittiger.im.constant.EmotionType; 4 | 5 | import android.support.v4.app.Fragment; 6 | import android.widget.EditText; 7 | 8 | /** 9 | * @author: laohu on 2017/2/6 10 | * @site: http://ittiger.cn 11 | */ 12 | public class BaseEmotionFragment extends Fragment { 13 | protected EmotionType mEmotionType; 14 | protected EditText mEditText; 15 | 16 | public BaseEmotionFragment() { 17 | 18 | } 19 | 20 | public void setEmotionType(EmotionType emotionType) { 21 | 22 | mEmotionType = emotionType; 23 | } 24 | 25 | public void bindToEditText(EditText editText) { 26 | 27 | mEditText = editText; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/smack/MultiChatInvitationListener.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.smack; 2 | 3 | import cn.ittiger.im.bean.ChatUser; 4 | import cn.ittiger.im.constant.Constant; 5 | import cn.ittiger.im.util.DBHelper; 6 | import cn.ittiger.im.util.LoginHelper; 7 | 8 | import com.orhanobut.logger.Logger; 9 | 10 | import org.jivesoftware.smack.XMPPConnection; 11 | import org.jivesoftware.smack.packet.Message; 12 | import org.jivesoftware.smackx.muc.InvitationListener; 13 | import org.jivesoftware.smackx.muc.MultiUserChat; 14 | 15 | /** 16 | * 多人聊天邀请监听 17 | * @author: laohu on 2017/1/24 18 | * @site: http://ittiger.cn 19 | */ 20 | public class MultiChatInvitationListener implements InvitationListener { 21 | 22 | @Override 23 | public void invitationReceived(XMPPConnection conn, MultiUserChat room, String inviter, 24 | String reason, String password, Message message) { 25 | 26 | try { 27 | room.join(LoginHelper.getUser().getNickname()); 28 | SmackMultiChatManager.saveMultiChat(room); 29 | SmackListenerManager.addMultiChatMessageListener(room); 30 | 31 | String friendUserName = room.getRoom(); 32 | int idx = friendUserName.indexOf(Constant.MULTI_CHAT_ADDRESS_SPLIT); 33 | String friendNickName = friendUserName.substring(0, idx); 34 | ChatUser chatUser = new ChatUser(friendUserName, friendNickName, true); 35 | DBHelper.getInstance().getSQLiteDB().save(chatUser); 36 | } catch (Exception e) { 37 | Logger.e(e, "join multiChat failure on invitationReceived"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/smack/MultiChatMessageListener.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.smack; 2 | 3 | import cn.ittiger.im.bean.ChatMessage; 4 | import cn.ittiger.im.constant.MessageType; 5 | import cn.ittiger.im.util.DBHelper; 6 | import cn.ittiger.im.util.LoginHelper; 7 | 8 | import com.orhanobut.logger.Logger; 9 | 10 | import org.greenrobot.eventbus.EventBus; 11 | import org.jivesoftware.smack.MessageListener; 12 | import org.jivesoftware.smack.packet.Message; 13 | import org.json.JSONObject; 14 | 15 | import java.util.regex.Matcher; 16 | import java.util.regex.Pattern; 17 | 18 | /** 19 | * 多人聊天消息监听 20 | * @author: laohu on 2017/1/24 21 | * @site: http://ittiger.cn 22 | */ 23 | public class MultiChatMessageListener implements MessageListener { 24 | private static final String PATTERN = "[a-zA-Z0-9_]+@"; 25 | private String mMeNickName = LoginHelper.getUser().getNickname(); 26 | private String mMeUserName = LoginHelper.getUser().getUsername(); 27 | 28 | @Override 29 | public void processMessage(Message message) { 30 | 31 | //不会收到自己发送过来的消息 32 | Logger.d(message.toString()); 33 | String from = message.getFrom();//消息发送人,格式:老胡创建的群@conference.121.42.13.79/老胡 --> 老胡发送的 34 | String to = message.getTo();//消息接收人(当前登陆用户),格式:zhangsan@121.42.13.79/Smack 35 | Matcher matcherTo = Pattern.compile(PATTERN).matcher(to); 36 | 37 | if(matcherTo.find()) { 38 | try { 39 | String[] fromUsers = from.split("/"); 40 | String friendUserName = fromUsers[0];//老胡创建的群@conference.121.42.13.79 41 | String friendNickName = fromUsers[1];//发送人的昵称,用于聊天窗口中显示 42 | 43 | JSONObject json = new JSONObject(message.getBody()); 44 | 45 | ChatMessage chatMessage = new ChatMessage(MessageType.MESSAGE_TYPE_TEXT.value(), false); 46 | chatMessage.setFriendUsername(friendUserName); 47 | chatMessage.setFriendNickname(friendNickName); 48 | chatMessage.setMeUsername(mMeUserName); 49 | chatMessage.setMeNickname(mMeNickName); 50 | chatMessage.setContent(json.optString(ChatMessage.KEY_MESSAGE_CONTENT)); 51 | 52 | String sendUser = json.optString(ChatMessage.KEY_MULTI_CHAT_SEND_USER); 53 | chatMessage.setMeSend(mMeUserName.equals(sendUser)); 54 | chatMessage.setMulti(true); 55 | 56 | DBHelper.getInstance().getSQLiteDB().save(chatMessage); 57 | EventBus.getDefault().post(chatMessage); 58 | } catch (Exception e) { 59 | Logger.e(e, "发送的消息格式不正确"); 60 | } 61 | } else { 62 | Logger.e("发送人格式不正确"); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/smack/SmackConnectionListener.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.smack; 2 | 3 | import com.orhanobut.logger.Logger; 4 | 5 | import org.jivesoftware.smack.ConnectionListener; 6 | import org.jivesoftware.smack.XMPPConnection; 7 | 8 | /** 9 | * 服务器连接监听 10 | * @author: laohu on 2017/1/18 11 | * @site: http://ittiger.cn 12 | */ 13 | public class SmackConnectionListener implements ConnectionListener { 14 | 15 | @Override 16 | public void connected(XMPPConnection connection) { 17 | 18 | Logger.d("connection connected"); 19 | } 20 | 21 | @Override 22 | public void authenticated(XMPPConnection connection, boolean resumed) { 23 | 24 | Logger.d("connection authenticated"); 25 | } 26 | 27 | @Override 28 | public void connectionClosed() { 29 | 30 | Logger.d("connection connectionClosed"); 31 | } 32 | 33 | @Override 34 | public void connectionClosedOnError(Exception e) { 35 | 36 | Logger.d("connectionClosedOnError"); 37 | } 38 | 39 | @Override 40 | public void reconnectingIn(int seconds) { 41 | 42 | Logger.d("connection reconnectingIn " + seconds + " second"); 43 | } 44 | 45 | @Override 46 | public void reconnectionFailed(Exception e) { 47 | 48 | Logger.d("reconnectionFailed"); 49 | } 50 | 51 | @Override 52 | public void reconnectionSuccessful() { 53 | 54 | Logger.d("reconnectionSuccessful"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/ui/ChatPromptDialog.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.ui; 2 | 3 | import cn.ittiger.im.R; 4 | import cn.ittiger.im.bean.ContactEntity; 5 | import cn.ittiger.im.util.IMUtil; 6 | import cn.ittiger.im.util.IntentHelper; 7 | 8 | import org.greenrobot.eventbus.EventBus; 9 | 10 | import android.content.Context; 11 | import android.content.DialogInterface; 12 | import android.support.v7.app.AlertDialog; 13 | 14 | /** 15 | * 联系人列表 16 | * @author: laohu on 2016/12/24 17 | * @site: http://ittiger.cn 18 | */ 19 | public class ChatPromptDialog implements DialogInterface.OnClickListener { 20 | 21 | private AlertDialog mDialog; 22 | private Context mContext; 23 | private ContactEntity mContactEntity; 24 | 25 | public ChatPromptDialog(Context context) { 26 | 27 | mContext = context; 28 | } 29 | 30 | public void show(ContactEntity contactEntity) { 31 | 32 | mContactEntity = contactEntity; 33 | String message = String.format(mContext.getString(R.string.chat_dialog_message), contactEntity.getRosterEntry().getName()); 34 | 35 | if(mDialog == null) { 36 | AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 37 | builder.setTitle(mContext.getString(R.string.chat_dialog_title)) 38 | .setCancelable(true) 39 | .setNegativeButton(mContext.getString(R.string.cancel), this) 40 | .setPositiveButton(mContext.getString(R.string.ok), this); 41 | mDialog = builder.create(); 42 | } 43 | mDialog.setMessage(message); 44 | mDialog.show(); 45 | } 46 | 47 | @Override 48 | public void onClick(DialogInterface dialog, int which) { 49 | 50 | if(which == DialogInterface.BUTTON_POSITIVE) { 51 | dialog.dismiss(); 52 | IMUtil.startChatActivity(mContext, mContactEntity.getRosterEntry()); 53 | EventBus.getDefault().post(Integer.valueOf(IntentHelper.MESSAGE_TAB_INDEX)); 54 | mContactEntity = null; 55 | } else if(which == DialogInterface.BUTTON_NEGATIVE) { 56 | dialog.dismiss(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/ui/ClearEditText.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.ui; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.drawable.Drawable; 6 | import android.text.Editable; 7 | import android.text.TextWatcher; 8 | import android.util.AttributeSet; 9 | import android.view.MotionEvent; 10 | import android.widget.EditText; 11 | import cn.ittiger.im.R; 12 | 13 | /** 14 | * 可清除的EditText 15 | * @auther: hyl 16 | * @time: 2015-10-20下午3:02:42 17 | */ 18 | public class ClearEditText extends EditText { 19 | /** 20 | * 清除图标是否显示 21 | */ 22 | private boolean mClearIconVisible = false; 23 | /** 24 | * 清除图标 25 | */ 26 | private Drawable mClearIcon; 27 | 28 | public ClearEditText(Context context, AttributeSet attrs, int defStyle) { 29 | super(context, attrs, defStyle); 30 | initView(context); 31 | } 32 | 33 | public ClearEditText(Context context, AttributeSet attrs) { 34 | super(context, attrs); 35 | initView(context); 36 | } 37 | 38 | public ClearEditText(Context context) { 39 | super(context); 40 | initView(context); 41 | } 42 | 43 | private void initView(Context context) { 44 | mClearIcon = getResources().getDrawable(R.drawable.tigerframe_edittext_clear); 45 | mClearIcon.setBounds(0, 0, mClearIcon.getMinimumWidth(), mClearIcon.getMinimumHeight()); 46 | 47 | addTextChangedListener(new TextWatcher() { 48 | @Override 49 | public void onTextChanged(CharSequence s, int start, int before, int count) { 50 | 51 | } 52 | 53 | @Override 54 | public void beforeTextChanged(CharSequence s, int start, int count, 55 | int after) { 56 | 57 | } 58 | 59 | @Override 60 | public void afterTextChanged(Editable s) { 61 | String text = getText().toString(); 62 | if(isFocused() && text != null && !text.isEmpty()) { 63 | if(!mClearIconVisible) { 64 | setCompoundDrawables(null, null, mClearIcon, null); 65 | mClearIconVisible = true; 66 | } 67 | } else { 68 | setCompoundDrawables(null, null, null, null); 69 | mClearIconVisible = false; 70 | } 71 | } 72 | }); 73 | } 74 | 75 | /** 76 | * 添加触摸事件 点击之后 出现 清空editText的效果 77 | */ 78 | @SuppressLint("ClickableViewAccessibility") 79 | @Override 80 | public boolean onTouchEvent(MotionEvent motionEvent) { 81 | if(mClearIconVisible && mClearIcon != null && motionEvent.getAction() == MotionEvent.ACTION_UP) { 82 | if(motionEvent.getX() > getWidth() - getPaddingRight() - mClearIcon.getIntrinsicWidth()) { 83 | setText(""); 84 | motionEvent.setAction(MotionEvent.ACTION_CANCEL); 85 | } 86 | } 87 | return super.onTouchEvent(motionEvent); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/ui/RecordingVoiceView.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.ui; 2 | 3 | import butterknife.BindView; 4 | import butterknife.ButterKnife; 5 | import cn.ittiger.im.R; 6 | 7 | import android.content.Context; 8 | import android.os.Build; 9 | import android.support.annotation.RequiresApi; 10 | import android.util.AttributeSet; 11 | import android.view.View; 12 | import android.widget.FrameLayout; 13 | 14 | /** 15 | * Created by ylhu on 17-2-7. 16 | */ 17 | public class RecordingVoiceView extends FrameLayout { 18 | @BindView(R.id.recording_voice_container) 19 | View mRecordingContainer; 20 | @BindView(R.id.cancel_recording_voice_container) 21 | View mCancelRecordingContainer; 22 | 23 | public RecordingVoiceView(Context context) { 24 | 25 | super(context); 26 | initView(context); 27 | } 28 | 29 | public RecordingVoiceView(Context context, AttributeSet attrs) { 30 | 31 | super(context, attrs); 32 | initView(context); 33 | } 34 | 35 | public RecordingVoiceView(Context context, AttributeSet attrs, int defStyleAttr) { 36 | 37 | super(context, attrs, defStyleAttr); 38 | initView(context); 39 | } 40 | 41 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 42 | public RecordingVoiceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 43 | 44 | super(context, attrs, defStyleAttr, defStyleRes); 45 | initView(context); 46 | } 47 | 48 | private void initView(Context context) { 49 | 50 | inflate(context, R.layout.keyboard_recording_voice_layout, this); 51 | ButterKnife.bind(this); 52 | setBackgroundResource(R.drawable.recording_vocie_view_bg); 53 | setAlpha(0.6f); 54 | } 55 | 56 | public void showStartRecordingView() { 57 | 58 | if(getVisibility() == GONE) { 59 | setVisibility(VISIBLE); 60 | } 61 | if(mRecordingContainer.getVisibility() == GONE) { 62 | mRecordingContainer.setVisibility(VISIBLE); 63 | } 64 | if(mCancelRecordingContainer.getVisibility() == VISIBLE) { 65 | mCancelRecordingContainer.setVisibility(GONE); 66 | } 67 | } 68 | 69 | public void showCancelRecordingView() { 70 | 71 | if(getVisibility() == GONE) { 72 | setVisibility(VISIBLE); 73 | } 74 | if(mRecordingContainer.getVisibility() == VISIBLE) { 75 | mRecordingContainer.setVisibility(GONE); 76 | } 77 | if(mCancelRecordingContainer.getVisibility() == GONE) { 78 | mCancelRecordingContainer.setVisibility(VISIBLE); 79 | } 80 | } 81 | 82 | public void hide() { 83 | 84 | setVisibility(GONE); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/ui/keyboard/emotion/EmotionItemClickListener.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.ui.keyboard.emotion; 2 | 3 | import cn.ittiger.im.adapter.EmotionAdapter; 4 | import cn.ittiger.im.constant.EmotionType; 5 | import cn.ittiger.im.util.EmotionUtil; 6 | 7 | import android.content.Context; 8 | import android.view.KeyEvent; 9 | import android.view.View; 10 | import android.widget.AdapterView; 11 | import android.widget.EditText; 12 | import android.widget.GridView; 13 | 14 | /** 15 | * @author: laohu on 2017/2/6 16 | * @site: http://ittiger.cn 17 | */ 18 | public class EmotionItemClickListener implements GridView.OnItemClickListener { 19 | private Context mContext; 20 | private EditText mEditText; 21 | private EmotionType mEmotionType; 22 | 23 | public EmotionItemClickListener(Context context, EditText editText, EmotionType emotionType) { 24 | 25 | mContext = context; 26 | mEditText = editText; 27 | mEmotionType = emotionType; 28 | } 29 | 30 | @Override 31 | public void onItemClick(AdapterView parent, View view, int position, long id) { 32 | 33 | if(!(parent.getAdapter() instanceof EmotionAdapter)) { 34 | return; 35 | } 36 | EmotionAdapter adapter = (EmotionAdapter) parent.getAdapter(); 37 | if(position == adapter.getCount() - 1) {//点击了最后一个,即删除表情按钮 38 | //发送一个删除事件交给系统进行删除操作 39 | mEditText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); 40 | } else {//点击了表情,则添加到输入框 41 | String emotionName = adapter.getItem(position);//得到点击表情的名称 42 | 43 | // 获取输入框当前光标位置,在指定位置上添加表情图片文本 44 | int curPosition = mEditText.getSelectionStart(); 45 | StringBuilder sb = new StringBuilder(mEditText.getText().toString()); 46 | sb.insert(curPosition, emotionName); 47 | 48 | // 特殊文字处理,将表情等转换一下 49 | mEditText.setText(EmotionUtil.getInputEmotionContent(mContext, mEmotionType, mEditText, sb.toString())); 50 | 51 | // 将光标设置到新增完表情的右侧 52 | mEditText.setSelection(curPosition + emotionName.length()); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/ui/recyclerview/ViewHolder.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.ui.recyclerview; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by laohu on 16-7-19. 8 | */ 9 | public class ViewHolder extends RecyclerView.ViewHolder { 10 | 11 | public ViewHolder(View itemView) { 12 | 13 | super(itemView); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/util/AppFileHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.util; 2 | 3 | import cn.ittiger.app.AppContext; 4 | import cn.ittiger.im.constant.MessageType; 5 | import cn.ittiger.util.ValueUtil; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * 应用相关文件帮助类 11 | * @author: laohu on 2017/1/18 12 | * @site: http://ittiger.cn 13 | */ 14 | public class AppFileHelper { 15 | 16 | public static String getAppRoot() { 17 | 18 | return AppContext.getInstance().getExternalCacheDir().getAbsolutePath(); 19 | } 20 | 21 | public static String getAppImageCacheDir() { 22 | 23 | return getAppRoot() + "/image"; 24 | } 25 | 26 | public static String getAppDBDir() { 27 | 28 | return getAppRoot() + "/db"; 29 | } 30 | 31 | public static String getAppCrashDir() { 32 | 33 | return getAppRoot() + "/crash"; 34 | } 35 | 36 | public static String getAppChatDir() { 37 | 38 | return getAppRoot() + "/chat"; 39 | } 40 | 41 | public static File getAppChatMessageDir(int type) { 42 | 43 | String root = getAppChatDir(); 44 | String child = ""; 45 | if(type == MessageType.MESSAGE_TYPE_IMAGE.value()) { 46 | child = "recv_image"; 47 | } else if(type == MessageType.MESSAGE_TYPE_VOICE.value()) { 48 | child = "recv_voice"; 49 | } 50 | File file; 51 | if(ValueUtil.isEmpty(child)) { 52 | file = new File(root); 53 | } else { 54 | file = new File(root, child); 55 | } 56 | if(!file.exists()) { 57 | file.mkdirs(); 58 | } 59 | return file; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/util/DBHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.util; 2 | 3 | import cn.ittiger.app.AppContext; 4 | import cn.ittiger.database.SQLiteDB; 5 | import cn.ittiger.database.SQLiteDBConfig; 6 | import cn.ittiger.database.SQLiteDBFactory; 7 | import cn.ittiger.im.app.App; 8 | import cn.ittiger.im.app.IDbApplication; 9 | 10 | /** 11 | * 本地数据库管理类 12 | * @author laohu 13 | */ 14 | public class DBHelper { 15 | /** 16 | * 管理器单例 17 | */ 18 | private static DBHelper sDBInstance; 19 | /** 20 | * 数据库配置上下文 21 | */ 22 | private IDbApplication mDbApplication; 23 | /** 24 | * 全局数据库 25 | */ 26 | private SQLiteDB mDB; 27 | 28 | 29 | private DBHelper() { 30 | 31 | mDbApplication = ((App) AppContext.getInstance().getApplicationContext()); 32 | } 33 | 34 | public static DBHelper getInstance() { 35 | 36 | if(sDBInstance == null) { 37 | synchronized (DBHelper.class) { 38 | if(sDBInstance == null) { 39 | sDBInstance = new DBHelper(); 40 | } 41 | } 42 | } 43 | return sDBInstance; 44 | } 45 | 46 | /** 47 | * 获取全局数据库操作对象 48 | * @return 49 | */ 50 | public SQLiteDB getSQLiteDB() { 51 | 52 | if(mDB == null) { 53 | synchronized (this) { 54 | if(mDB == null) { 55 | SQLiteDBConfig config = mDbApplication.getGlobalDbConfig(); 56 | mDB = SQLiteDBFactory.createSQLiteDB(config); 57 | } 58 | } 59 | } 60 | return mDB; 61 | } 62 | 63 | /** 64 | * 关闭数据库 65 | */ 66 | public void closeSQLiteDB() { 67 | if(this.mDB != null) { 68 | this.mDB.close(); 69 | } 70 | this.mDB = null; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/util/ImageLoaderHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.util; 2 | 3 | import cn.ittiger.im.R; 4 | 5 | import com.nostra13.universalimageloader.core.DisplayImageOptions; 6 | import com.nostra13.universalimageloader.core.ImageLoader; 7 | import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; 8 | 9 | import android.graphics.Bitmap; 10 | import android.widget.ImageView; 11 | 12 | /** 13 | * 图片参数帮助类 14 | * @author: laohu on 2016/12/24 15 | * @site: http://ittiger.cn 16 | */ 17 | public class ImageLoaderHelper { 18 | 19 | /* 20 | String imageUri = "http://site.com/image.png"; // 网络图片 21 | String imageUri = "file:///mnt/sdcard/image.png"; // sd卡图片 22 | String imageUri = "content://media/external/audio/albumart/13"; // content provider 23 | String imageUri = "assets://image.png"; // assets文件夹图片 24 | String imageUri = "drawable://" + R.drawable.image; // drawable图片 25 | */ 26 | private static volatile DisplayImageOptions sImageOptions; 27 | 28 | public static DisplayImageOptions getChatImageOptions() { 29 | 30 | if(sImageOptions == null) { 31 | synchronized (ImageLoaderHelper.class) { 32 | if(sImageOptions == null) { 33 | sImageOptions = new DisplayImageOptions.Builder() 34 | .cacheOnDisk(true)//图片下载后是否缓存到SDCard 35 | .cacheInMemory(true)//图片下载后是否缓存到内存 36 | .bitmapConfig(Bitmap.Config.RGB_565)//图片解码类型,推荐此种方式,减少OOM 37 | .considerExifParams(true)//是否考虑JPEG图像EXIF参数(旋转,翻转) 38 | .resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位 39 | .showImageOnFail(R.drawable.vector_default_image)//图片加载失败后显示的图片 40 | .showImageOnLoading(R.drawable.vector_default_image) 41 | .build(); 42 | } 43 | } 44 | } 45 | return sImageOptions; 46 | } 47 | 48 | public static void displayImage(ImageView imageView, String url) { 49 | 50 | displayImage(imageView, url, null); 51 | } 52 | 53 | public static void displayImage(ImageView imageView, String url, ImageLoadingListener imageLoadingListener) { 54 | 55 | ImageLoader.getInstance().displayImage(url, imageView, getChatImageOptions(), imageLoadingListener); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/util/IntentHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.util; 2 | 3 | /** 4 | * Intent间传递参数的帮助类 5 | * @author: laohu on 2017/1/12 6 | * @site: http://ittiger.cn 7 | */ 8 | public class IntentHelper { 9 | public static final String KEY_CHAT_DIALOG = "key_chat_dialog";//从联系人中发起聊天时传递参数的key 10 | public static final int MESSAGE_TAB_INDEX = 0;//主界面中消息Fragment的索引 11 | public static final int CONTACT_TAB_INDEX = 1;//主界面中联系人Fragment的索引 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/util/LoginHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.util; 2 | 3 | import cn.ittiger.im.bean.User; 4 | import cn.ittiger.util.PreferenceHelper; 5 | 6 | /** 7 | * Created by laohu on 16-12-14. 8 | */ 9 | public class LoginHelper { 10 | 11 | private static final String KEY_REMEMBER_PASSWORD = "pre_key_remember_password"; 12 | private static final String KEY_USER = "pre_key_user"; 13 | 14 | /** 15 | * 是否记住密码 16 | * 17 | * @return 18 | */ 19 | public static boolean isRememberPassword() { 20 | 21 | return PreferenceHelper.getBoolean(KEY_REMEMBER_PASSWORD, false); 22 | } 23 | 24 | public static void rememberRassword(boolean isRemember) { 25 | 26 | PreferenceHelper.putBoolean(KEY_REMEMBER_PASSWORD, isRemember); 27 | } 28 | 29 | public static User getUser() { 30 | 31 | User user = (User) PreferenceHelper.get(KEY_USER); 32 | if(user == null) { 33 | user = new User("", ""); 34 | } 35 | return user; 36 | } 37 | 38 | public static void saveUser(User user) { 39 | 40 | PreferenceHelper.put(KEY_USER, user); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/cn/ittiger/im/util/ShareHelper.java: -------------------------------------------------------------------------------- 1 | package cn.ittiger.im.util; 2 | 3 | import cn.ittiger.im.R; 4 | import cn.ittiger.util.UIUtil; 5 | 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.PackageInfo; 9 | import android.content.pm.PackageManager; 10 | import android.net.Uri; 11 | 12 | import java.io.File; 13 | 14 | /** 15 | * @author laohu 16 | * @site http://ittiger.cn 17 | */ 18 | public class ShareHelper { 19 | 20 | public static void shareApp(Context context) { 21 | 22 | String packageName = context.getPackageName(); 23 | try { 24 | PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_ACTIVITIES); 25 | File sourceFile=new File(packageInfo.applicationInfo.sourceDir); 26 | //调用android系统的分享窗口 27 | Intent intent = new Intent(Intent.ACTION_SEND); 28 | intent.setType("*/*"); 29 | intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(sourceFile)); 30 | context.startActivity(Intent.createChooser(intent, context.getString(R.string.share_app_title))); 31 | } catch (PackageManager.NameNotFoundException e) { 32 | UIUtil.showToast(context, "分享失败"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/res/color/tabbar_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-hdpi/avatar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bg_launcher.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-hdpi/bg_launcher.jpeg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/pic_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-hdpi/pic_default.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/tigerframe_edittext_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-hdpi/tigerframe_edittext_clear.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/tigerframe_icon_back_btn_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-hdpi/tigerframe_icon_back_btn_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/tigerframe_icon_back_btn_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-hdpi/tigerframe_icon_back_btn_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/about_img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/about_img.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/avatar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/chat_from_bg_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/chat_from_bg_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/chat_from_bg_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/chat_from_bg_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/chat_to_bg_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/chat_to_bg_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/chat_to_bg_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/chat_to_bg_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_aini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_aini.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_aoteman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_aoteman.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_baibai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_baibai.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_beishang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_beishang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_bishi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_bishi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_bizui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_bizui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_chanzui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_chanzui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_chijing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_chijing.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_dahaqi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_dahaqi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_dalian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_dalian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_ding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_ding.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_doge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_doge.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_fangdumianju.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_fangdumianju.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_feizao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_feizao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_ganmao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_ganmao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_guzhang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_guzhang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_haha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_haha.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_haixiu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_haixiu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_han.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_han.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_hehe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_hehe.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_heixian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_heixian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_heng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_heng.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_huaxin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_huaxin.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_jiyan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_jiyan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_keai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_keai.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_kelian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_kelian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_ku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_ku.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_kun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_kun.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_landelini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_landelini.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_lang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_lang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_lei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_lei.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_miao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_miao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_nanhaier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_nanhaier.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_nu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_nu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_numa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_numa.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_nvhaier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_nvhaier.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_qian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_qian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_qinqin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_qinqin.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_shayan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_shayan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_shengbing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_shengbing.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_shenshou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_shenshou.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_shiwang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_shiwang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_shuai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_shuai.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_shuijiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_shuijiao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_sikao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_sikao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_taikaixin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_taikaixin.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_touxiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_touxiao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_travel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_travel.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_tu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_tu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_tuzi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_tuzi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_wabishi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_wabishi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_weiqu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_weiqu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_xiaoku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_xiaoku.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_xiongmao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_xiongmao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_xixi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_xixi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_xu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_xu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_yinxian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_yinxian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_yiwen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_yiwen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_youhengheng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_youhengheng.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_yun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_yun.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_zhuakuang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_zhuakuang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_zhutou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_zhutou.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_zuiyou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_zuiyou.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/d_zuohengheng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/d_zuohengheng.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/file_load_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/file_load_fail.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gxu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/gxu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gxv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/gxv.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gxw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/gxw.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gxx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/gxx.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/gxy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gxz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/gxz.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_chat_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/icon_chat_image.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_chat_take_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/icon_chat_take_photo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/loading1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/loading1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/loading2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/loading2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/loading3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyongli/TigerIM/415c24a76f28f1a9952955d59dfc8e6731286e8a/app/src/main/res/drawable-xxhdpi/loading3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/anim_chat_voice_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/anim_chat_voice_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_chat_time_tag.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/chat_file_content_loading_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/chat_from_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/chat_to_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_emotion.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_more.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_voice.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tabbar_contact.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tabbar_message.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_toolbar_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_toolbar_avatar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_emotion_indicator_nomal_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_emotion_indicator_select_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_input_edittext_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_record_voice_button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/main_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/main_button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 9 | 10 | 11 | 12 | 13 | 15 | 17 | 18 | 19 | 20 | 21 | 23 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/recording_vocie_view_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/recording_voice_cancel_text_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tigerframe_icon_back_btn_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_about.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_add.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_add_focus.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_avatar.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_avatar_focus.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_chat_avatar.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_checked.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_contact.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_contact_focus.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_contact_group.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_default_image.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_emotion_more.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_emotion.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_emotion_delete.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_emotion_focus.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_more.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_more_focus.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_normal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_pressed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_text.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_text_focus.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_voice.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_keyboard_voice_focus.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_message.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_message_focus.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_multi_chat.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_recording_cancel.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_recording_voice.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vector_uncheck.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_account_mng_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 17 | 22 | 27 | 32 | 33 | 34 |