[
  {
    "path": ".gitignore",
    "content": "# Built application files\n*.apk\n*.ap_\n\n# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\nout/\n\n# Gradle files\n.gradle/\nbuild/\n.idea\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n# Android Studio captures folder\ncaptures/\n\n# Intellij\n*.iml\n# Keystore files\n*.jks\ngotye.keystore\n\n"
  },
  {
    "path": "README.md",
    "content": "# Android 项目配置#\n    public class HTConstant {\n    //IM服务器相关\n    public static final String HOST_IM = \"xxx.xxx.xxx.xxx\";//示例ip: 119.125.523.153 此IP不可用\n    //api服务器\n    public static final String HOST_API = \"http://xxx.xxx.xxx.xxx/api/\";//示例ip: 119.125.523.153 此IP不可用\n    //阿里云OSS信息配置\n    public static final String endpoint = \"oss-cn-hangzhou.aliyuncs.com\";\n    public static final String accessKeyId = \"xxxxxxxx\";\n    public static final String accessKeySecret = \"xxxxxxxxxxxx\";\n    .....\n    }\n\n\n----------\n# 相关工程 #\n----------\n#最具诚意的开源IM系统 YiChat#\n1. github地址:[https://github.com/YiChat](https://github.com/YiChat)\n2. 开源中国地址:[https://git.oschina.net/zhangfeng_tech](https://git.oschina.net/zhangfeng_tech)\n##本项目的开源内容##\n###已开源的所有源码:###\n1. IM服务器(负责即时通讯消息)-直接部署,无需修改参数\n2. api服务器(非IM模块相关的其他业务逻辑)-修改一处参数,详见工程下文档\n3. android客户端-配置参数,连接自己的服务器ip.详见工程文档\n\n###待开源的工程源码:###\n\n- iOS客户端:前面三个工程的github star数超过3000马上开源\n\n##这个开源项目的意义在于##\n1. 拥有自己的IM服务器,不再受制于第三方通讯云的限制.\n2. 提供了一个完善优化的客户端源码,具体参见体验包:\n    \n - Android:[https://www.pgyer.com/YiChatLite](https://www.pgyer.com/YiChatLite)\n - iOS:[https://www.pgyer.com/9sVQ](https://www.pgyer.com/9sVQ)\n\n##QQ:84543217 (技术相关请提交Issus,商务合作可联系QQ)\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.0\"\n\n    defaultConfig {\n        applicationId \"com.htmessage.yichatopen\"\n        minSdkVersion 16\n        targetSdkVersion 23\n        versionCode 1\n        versionName \"1.0\"\n        multiDexEnabled true\n        ndk {\n            abiFilter 'armeabi-v7a' // 例如：abiFilter 'armeabi, x86'\n        }\n        sourceSets {\n            main {\n                jniLibs.srcDir 'libs'\n\n            }\n            instrumentTest.setRoot('tests')\n            debug.setRoot('build-types/debug')\n            release.setRoot('build-types/release')\n        }\n        lintOptions {\n            abortOnError false\n        }\n\n        aaptOptions{\n            cruncherEnabled=false\n            useNewCruncher=false\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    repositories {\n        flatDir {\n            dirs 'libs'\n        }\n    }\n}\n\next {\n    smackVersion = '4.1.9'\n}\ndependencies {\n    compile 'com.android.support:multidex:1.0.1'\n    compile fileTree(include: '*.jar' , dir: 'libs')\n    compile 'com.android.support:appcompat-v7:25.0.1'\n    compile 'com.tencent.bugly:crashreport:2.2.0'\n    //\n    compile 'com.android.support:design:25.0.1'\n    compile 'com.android.support:cardview-v7:25.0.1'\n    compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.1@aar'\n     compile 'com.github.promeg:tinypinyin:1.0.0'\n     compile 'com.squareup.okhttp3:okhttp:3.3.1'\n    compile \"org.igniterealtime.smack:smack-android-extensions:$smackVersion\"\n    compile \"org.igniterealtime.smack:smack-experimental:$smackVersion\"\n    compile \"org.igniterealtime.smack:smack-tcp:$smackVersion\"\n    compile \"org.igniterealtime.smack:smack-legacy:$smackVersion\"\n    compile 'io.reactivex:rxandroid:1.2.1'\n    compile 'io.reactivex:rxjava:1.1.6'\n    compile 'com.android.support:support-v4:25.0.0'\n      compile 'com.alibaba:fastjson:1.2.24'\n    compile 'com.alibaba:fastjson:1.1.56.android'\n    compile 'top.zibin:Luban:1.0.9'\n    //图片裁剪库\n    compile 'com.soundcloud.android:android-crop:1.0.1@aar'\n    //图片处理库和毛玻璃特效\n    compile 'com.github.bumptech.glide:glide:3.7.0'\n    compile 'jp.wasabeef:glide-transformations:2.0.1'\n    compile 'com.google.android.gms:play-services-appindexing:8.4.0'\n    compile 'com.mabeijianxi:small-video-record:1.2.0'\n    //视频播放器\n    compile 'fm.jiecao:jiecaovideoplayer:5.5.4'\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in C:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.htmessage.yichatopen\">\n\n    <uses-sdk\n        android:minSdkVersion=\"16\"\n        android:targetSdkVersion=\"25\"\n        tools:overrideLibrary=\"com.htmessage.sdk\" />\n\n\n\n    <uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\" />\n    <!-- To auto-complete the email text field in the login form with the user's emails -->\n    <uses-permission android:name=\"android.permission.GET_ACCOUNTS\" />\n    <uses-permission android:name=\"android.permission.READ_PROFILE\" />\n    <uses-permission android:name=\"android.permission.READ_CONTACTS\" />\n    <uses-permission android:name=\"android.permission.VIBRATE\" />\n    <uses-permission android:name=\"android.permission.WAKE_LOCK\" />\n    <uses-permission android:name=\"android.permission.FLASHLIGHT\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n    <uses-permission android:name=\"android.permission.CAMERA\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\" />\n    <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n    <uses-permission android:name=\"android.permission.GET_TASKS\" />\n    <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\" />\n    <uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />\n    <uses-permission android:name=\"android.permission.USE_CREDENTIALS\" />\n    <uses-permission android:name=\"com.android.launcher.permission.READ_SETTINGS\" />\n    <uses-permission android:name=\"android.permission.BROADCAST_STICKY\" />\n    <uses-permission android:name=\"android.permission.WRITE_SETTINGS\" />\n    <uses-permission android:name=\"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS\" />\n    <!-- SDK2.1新增获取用户位置信息 -->\n    <uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />\n    <uses-permission android:name=\"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS\" />\n    <uses-permission\n        android:name=\"android.permission.WRITE_APN_SETTINGS\"\n        tools:ignore=\"ProtectedPermissions\" />\n    <uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\" />\n    <uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\" />\n    <!-- To auto-complete the email text field in the login form with the user's emails -->\n    <uses-permission android:name=\"android.permission.GET_ACCOUNTS\" />\n    <uses-permission android:name=\"android.permission.READ_PROFILE\" />\n    <uses-permission android:name=\"android.permission.READ_CONTACTS\" />\n    <uses-permission android:name=\"android.permission.VIBRATE\" />\n    <uses-permission android:name=\"android.permission.WAKE_LOCK\" />\n    <uses-permission android:name=\"android.permission.FLASHLIGHT\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.CAMERA\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\" />\n    <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n    <uses-permission android:name=\"android.permission.GET_TASKS\" />\n    <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\" />\n    <uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />\n    <uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\" />\n    <uses-permission android:name=\"android.permission.USE_CREDENTIALS\" />\n    <uses-permission android:name=\"com.android.launcher.permission.READ_SETTINGS\" />\n    <uses-permission android:name=\"android.permission.BROADCAST_STICKY\" />\n    <uses-permission android:name=\"android.permission.WRITE_SETTINGS\" />\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.RECORD_VIDEO\" />\n    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n\n    <application\n        android:name=\"com.htmessage.yichatopen.HTApp\"\n        android:allowBackup=\"true\"\n        android:icon=\"@drawable/app_logo\"\n        android:label=\"@string/app_name\"\n        android:persistent=\"true\"\n        >\n\n\n        <activity\n            android:name=\".activity.main.MainActivity\"\n            android:launchMode=\"singleTask\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustPan\"/>\n\n         <activity\n            android:name=\"com.htmessage.yichatopen.activity.SplashActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\"\n             >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n\n         <activity\n            android:name=\".activity.login.LoginActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n\n         <activity\n            android:name=\".activity.register.RegisterActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n\n\n         <activity\n            android:name=\".activity.chat.ChatActivity\"\n            android:launchMode=\"singleTask\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"stateVisible|adjustResize\"/>\n        <activity\n            android:name=\".activity.chat.activity.ChatSettingActivity\"\n            android:launchMode=\"singleTask\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n\n         <activity\n            android:name=\".activity.main.profile.info.profile.ProfileActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n\n         <activity\n            android:name=\".activity.main.profile.info.update.ProfileUpdateActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n\n        <activity\n            android:name=\"com.htmessage.yichatopen.activity.SettingsActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n        <activity\n            android:name=\".activity.addfriends.add.pre.AddFriendsPreActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n        <activity\n            android:name=\".activity.addfriends.add.next.AddFriendsNextActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n        <activity\n            android:name=\".activity.addfriends.add.end.AddFriendsFinalActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n\n        <activity\n            android:name=\"com.htmessage.yichatopen.activity.main.details.UserDetailsActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n        <activity\n            android:name=\".activity.addfriends.newfriend.NewFriendsActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n        <activity\n            android:name=\"com.htmessage.yichatopen.activity.ScanCaptureActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n        <activity\n            android:name=\"com.htmessage.yichatopen.activity.main.qrcode.QrCodeActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n        <activity\n            android:name=\"com.htmessage.yichatopen.activity.ShowBigImageActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"adjustResize\"/>\n\n        <activity\n            android:name=\"com.soundcloud.android.crop.CropImageActivity\"\n            android:launchMode=\"singleTask\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\" />\n\n         <activity\n            android:name=\".activity.main.password.PasswordResetActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"stateVisible|adjustResize\"/>\n\n\n         <activity\n            android:name=\".activity.main.find.recentlypeople.PeopleRecentlyActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"stateAlwaysHidden\"/>\n\n         <activity\n            android:name=\"com.htmessage.yichatopen.activity.main.region.RegionActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"stateAlwaysHidden\"/>\n\n\n         <activity\n            android:name=\".activity.chat.activity.ChooseContactActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/horizontal_slide\"\n            android:windowSoftInputMode=\"stateAlwaysHidden\"/>\n\n          <activity android:name=\"mabeijianxi.camera.MediaRecorderActivity\" />\n\n\n        <service\n            android:name=\"com.htmessage.sdk.service.AwakeService\"\n            android:permission=\"android.permission.BIND_NOTIFICATION_LISTENER_SERVICE\"\n            android:process=\":push\">\n            <intent-filter>\n                <action android:name=\"android.service.notification.NotificationListenerService\" />\n            </intent-filter>\n        </service>\n\n        <service\n            android:name=\"com.htmessage.sdk.service.KeepAliveService\"\n            android:permission=\"android.permission.BIND_JOB_SERVICE\"\n            android:process=\":push\">\n        </service>\n\n        <service\n            android:name=\"com.htmessage.sdk.service.MessageService\"\n            android:exported=\"true\" />\n        <service\n            android:name=\"com.htmessage.sdk.service.RemoteService\"\n            android:exported=\"true\"\n            android:process=\":push\" />\n\n        <receiver android:name=\"com.htmessage.sdk.receiver.NetworkStateReceiver\">\n            <intent-filter>\n                <action android:name=\"android.net.conn.CONNECTIVITY_CHANGE\" />\n                <action android:name=\"android.net.conn.BACKGROUND_DATA_SETTING_CHANGED\" />\n            </intent-filter>\n        </receiver>\n\n        <receiver\n            android:name=\"com.htmessage.sdk.receiver.SystemReceiver\"\n            android:exported=\"true\"\n            android:process=\":push\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.BOOT_COMPLETED\" />\n                <action android:name=\"android.intent.action.SCREEN_ON\" />\n                <action android:name=\"android.intent.action.USER_PRESENT\" />\n            </intent-filter>\n        </receiver>\n\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/HTApp.java",
    "content": "package com.htmessage.yichatopen;\n\nimport android.app.Activity;\nimport android.app.ActivityManager;\nimport android.app.Application;\nimport android.app.Dialog;\nimport android.content.Context;\nimport android.content.pm.PackageManager;\nimport android.support.multidex.MultiDex;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.animation.Animation;\nimport android.view.animation.AnimationUtils;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.manager.MyNotification;\nimport com.htmessage.yichatopen.manager.LocalUserManager;\nimport com.htmessage.yichatopen.manager.Manager;\nimport com.tencent.bugly.crashreport.CrashReport;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\n\npublic class HTApp extends Application {\n    private static Context applicationContext;\n    private static HTApp instance;\n    private JSONObject userJson = null;\n     private List<Activity> activities = new ArrayList<>();\n    public static boolean isCalling = false;\n\n    @Override\n    public void onCreate() {\n        //sdk采用双进程守护,因此不要在守护进程中初始Application\n        int pid = android.os.Process.myPid();\n        String processAppName = getAppName(pid, this);\n        if (processAppName == null || !processAppName.equalsIgnoreCase(this.getPackageName())) {\n            return;\n        }\n        super.onCreate();\n        applicationContext = this;\n        instance = this;\n        MyNotification.init(applicationContext);\n        LocalUserManager.init(applicationContext);\n         if (getUserJson() != null) {\n            Manager.initManagerList(applicationContext);\n        }\n        //异常上报\n        CrashReport.initCrashReport(applicationContext, \"a7b4566fd9\", false);\n        HTClientHelper.init(applicationContext);\n    }\n\n    public static Context getContext() {\n        return applicationContext;\n    }\n\n\n\n\n    public static HTApp getInstance() {\n        return instance;\n    }\n\n    public String getUsername() {\n        String username = null;\n        if (getUserJson() != null) {\n            username = getUserJson().getString(HTConstant.JSON_KEY_HXID);\n        }\n        return username;\n    }\n\n    @Override\n    protected void attachBaseContext(Context base) {\n        super.attachBaseContext(base);\n        MultiDex.install(this);\n    }\n\n    public void setUserJson(JSONObject userJson) {\n        this.userJson = userJson;\n        if (userJson != null) {\n            Manager.initManagerList(applicationContext);\n        }\n        LocalUserManager.getInstance().setUserJson(userJson);\n    }\n\n    public JSONObject getUserJson() {\n        if (userJson == null) {\n            userJson = LocalUserManager.getInstance().getUserJson();\n        }\n        return userJson;\n    }\n\n\n\n\n\n\n    public void saveActivity(Activity activity) {\n        if (activity != null) {\n            activities.add(activity);\n        }\n\n    }\n\n    public void finishActivities() {\n        for (Activity activity : activities) {\n            if (activity != null && !activity.isFinishing()) {\n                activity.finish();\n            }\n        }\n\n    }\n\n\n\n    /**\n     * check the application process name if process name is not qualified, then we think it is a service process and we will not init SDK\n     *\n     * @param pID\n     * @return\n     */\n    private static String getAppName(int pID, Context appContext) {\n        String processName = null;\n        ActivityManager am = (ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);\n        List l = am.getRunningAppProcesses();\n        Iterator i = l.iterator();\n        PackageManager pm = appContext.getPackageManager();\n        while (i.hasNext()) {\n            ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());\n            try {\n                if (info.pid == pID) {\n                    CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));\n                    processName = info.processName;\n                    return processName;\n                }\n            } catch (Exception e) {\n            }\n        }\n        return processName;\n    }\n\n    /**\n     * 得到自定义的progressDialog\n     *\n     * @param context\n     * @param msg\n     * @return\n     */\n    public Dialog createLoadingDialog(Context context, String msg) {\n        LayoutInflater inflater = LayoutInflater.from(context);\n        View v = inflater.inflate(R.layout.loading_dialog, null);// 得到加载view\n        LinearLayout layout = (LinearLayout) v.findViewById(R.id.dialog_view);// 加载布局\n        // main.xml中的ImageView\n        ImageView spaceshipImage = (ImageView) v.findViewById(R.id.img);\n        TextView tipTextView = (TextView) v.findViewById(R.id.tipTextView);// 提示文字\n        // 加载动画\n        Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(\n                context, R.anim.loading_animation);\n        // 使用ImageView显示动画\n        spaceshipImage.startAnimation(hyperspaceJumpAnimation);\n        tipTextView.setText(msg);// 设置加载信息\n        Dialog loadingDialog = new Dialog(context, R.style.loading_dialog);// 创建自定义样式dialog\n        loadingDialog.setCancelable(false);// 不可以用“返回键”取消\n        loadingDialog.setContentView(layout, new LinearLayout.LayoutParams(\n                LinearLayout.LayoutParams.MATCH_PARENT,\n                LinearLayout.LayoutParams.MATCH_PARENT));// 设置布局\n      \n        return loadingDialog;\n    }\n\n    public String getDirFilePath() {\n        File file = new File(HTConstant.DIR_AVATAR);\n        if (!file.exists()) {\n            file.getParentFile().mkdirs();\n            file.mkdir();\n        }\n        return file.getAbsolutePath() + File.separator;\n    }\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/HTClientHelper.java",
    "content": "package com.htmessage.yichatopen;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.util.Log;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.sdk.client.HTOptions;\nimport com.htmessage.sdk.manager.HTChatManager;\nimport com.htmessage.yichatopen.activity.main.MainActivity;\nimport com.htmessage.yichatopen.activity.chat.ChatActivity;\n\nimport com.htmessage.yichatopen.manager.MyNotification;\nimport com.htmessage.yichatopen.domain.InviteMessage;\nimport com.htmessage.yichatopen.domain.InviteMessgeDao;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.manager.NotifierManager;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.listener.HTConnectionListener;\nimport com.htmessage.sdk.model.CallMessage;\nimport com.htmessage.sdk.model.CmdMessage;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.utils.HTMessageUtils;\n\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/3/3.\n * qq 84543217\n */\n\npublic class HTClientHelper {\n    private NotifierManager notifierManager;\n    private static Context applicationContext;\n\n    private static HTClientHelper htClientHelper;\n\n    public static void init(Context context) {\n        htClientHelper = new HTClientHelper(context);\n    }\n\n    public HTClientHelper(Context context) {\n        this.applicationContext = context;\n        HTOptions options=new HTOptions(); //IM相关配置\n        options.setHost(HTConstant.HOST_IM); //IP地址\n        options.setOssInfo(HTConstant.endpoint,HTConstant.bucket,HTConstant.accessKeyId,HTConstant.accessKeySecret);//阿里云OSS相关\n        options.setSinglePointUrl(HTConstant.DEVICE_URL_UPDATE,HTConstant.DEVICE_URL_GET);//设置单APP端登录\n        options.setDebug(false); //是否打印log false不打印\n        options.setKeepAlive(false); //是否开启保活  false 不开启\n        HTClient.init(applicationContext,options);\n        HTClient.getInstance().setMessageLisenter(messageLisenter);\n        HTClient.getInstance().addConnectionListener(htConnectionListener);\n        notifierManager = new NotifierManager(applicationContext);\n    }\n\n    public static HTClientHelper getInstance() {\n\n        if (htClientHelper == null) {\n            throw new RuntimeException(\"please init first!\");\n        }\n        return htClientHelper;\n    }\n\n    private HTConnectionListener htConnectionListener = new HTConnectionListener() {\n        @Override\n        public void onConnected() {\n\n            //   Toast.makeText(applicationContext,\"连上啦\",Toast.LENGTH_SHORT).show();\n            notifyConnection(true);\n        }\n\n        @Override\n        public void onDisconnected() {\n            notifyConnection(false);\n            // Toast.makeText(applicationContext,\"断连啦\",Toast.LENGTH_SHORT).show();\n        }\n\n        @Override\n        public void onConflict() {\n            // Toast.makeText(applicationContext,\"被踢啦\",Toast.LENGTH_SHORT).show();\n            notifyConflict();\n        }\n    };\n    private HTClient.MessageLisenter messageLisenter = new HTClient.MessageLisenter() {\n        @Override\n        public void onHTMessage(HTMessage htMessage) {\n            handleHTMessage(htMessage);\n        }\n\n        @Override\n        public void onCMDMessgae(CmdMessage cmdMessage) {\n            handleCmdMessage(cmdMessage);\n        }\n\n        @Override\n        public void onCallMessgae(CallMessage callMessage) {\n             //lite版没有音视频消息\n        }\n    };\n    private void handleHTMessage(HTMessage htMessage){\n        Intent intent=new Intent(IMAction.ACTION_NEW_MESSAGE);\n        intent.putExtra(\"message\",htMessage);\n        LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent);\n        if (ChatActivity.activityInstance != null && htMessage.getUsername().equals(ChatActivity.activityInstance.getToChatUsername())) {\n        } else {\n            MyNotification.getInstance().onNewMessage(htMessage);\n        }\n        notifyHTMessage();\n    }\n\n\n    private void handleCmdMessage(CmdMessage cmdMessage) {\n        InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(applicationContext);\n        String data = cmdMessage.getBody();\n        if (data != null) {\n            JSONObject dataJSON = JSONObject.parseObject(data);\n            if (dataJSON != null && dataJSON.containsKey(\"action\")) {\n\n                int action = dataJSON.getInteger(\"action\");\n                if (action == 1000) {\n                    //收到好友申请的请求\n                    List<InviteMessage> msgs = inviteMessgeDao.getMessagesList();\n                    for (InviteMessage inviteMessage : msgs) {\n                        if ( inviteMessage.getFrom().equals(cmdMessage.getFrom())) {\n                            inviteMessgeDao.deleteMessage(cmdMessage.getFrom());\n                        }\n                    }\n                    InviteMessage msg = new InviteMessage();\n                    msg.setFrom(cmdMessage.getFrom());\n                    msg.setTime(System.currentTimeMillis());\n                    msg.setReason(dataJSON.getJSONObject(\"data\").toJSONString());\n                    // set invitation status\n                    msg.setStatus(InviteMessage.Status.BEINVITEED);\n                    notifyNewInviteMessage(msg,null);\n                } else if (action == 1001) {\n                    //收到好友同意的透传消息\n                    List<InviteMessage> msgs = inviteMessgeDao.getMessagesList();\n                    for (InviteMessage inviteMessage : msgs) {\n                        if (inviteMessage.getFrom().equals(cmdMessage.getFrom())) {\n                            inviteMessgeDao.deleteMessage(cmdMessage.getFrom());\n\n                        }\n                    }\n                    // save invitation as message\n                    InviteMessage msg = new InviteMessage();\n                    msg.setFrom(cmdMessage.getFrom());\n                    msg.setReason(dataJSON.getJSONObject(\"data\").toJSONString());\n                    msg.setTime(System.currentTimeMillis());\n                    //   Log.d(TAG, message.getFrom() + \"accept your request\");\n                    msg.setStatus(InviteMessage.Status.BEAGREED);\n                    notifyNewInviteMessage(msg,dataJSON.getJSONObject(\"data\"));\n                } else if (action == 1002) {\n                    //收到好友拒绝的透传消息\n                    //Lite版没有拒绝好友申请的处理\n                } else if (action == 1003) {\n                    //收到删除好友的透传消息\n                    //发送广播\n                    if (HTApp.getInstance().getUsername().equals(cmdMessage.getTo())){\n                        LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(new Intent(IMAction.CMD_DELETE_FRIEND).putExtra(HTConstant.JSON_KEY_HXID, cmdMessage.getFrom()));\n                    }\n                } else if (action == 6000) {//收到撤回消息的透传\n                    String msgId = dataJSON.getString(\"msgId\");\n                    String chatTo = cmdMessage.getTo();\n                    if (cmdMessage.getChatType() == ChatType.singleChat) {\n                        chatTo = cmdMessage.getFrom();\n                    }\n                    HTMessage htMessage = HTClient.getInstance().messageManager().getMssage(chatTo, msgId);\n                    HTMessageUtils.creatWithDrowMsg(htMessage);\n                    LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(new Intent(IMAction.ACTION_MESSAGE_WITHDROW).putExtra(\"msgId\", msgId));\n                }\n            }\n        }\n    }\n\n\n\n\n    /**\n     * user has logged into another device\n     */\n    protected void notifyConflict() {\n        Intent intent = new Intent(applicationContext, MainActivity.class);\n        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n        intent.putExtra(IMAction.ACTION_CONFLICT, true);\n        applicationContext.startActivity(intent);\n    }\n\n    /**\n     * user has logged into another device\n     */\n    protected void notifyConnection(boolean isConnected) {\n        Intent intent = new Intent(IMAction.ACTION_CONNECTION_CHANAGED);\n        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n        intent.putExtra(\"state\", isConnected);\n        LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent);\n    }\n\n    /**\n     * save and notify invitation message\n     *\n     * @param msg\n     */\n    private void notifyNewInviteMessage(final InviteMessage msg, final JSONObject jsonObject) {\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(applicationContext);\n                inviteMessgeDao.saveMessage(msg);\n                inviteMessgeDao.saveUnreadMessageCount(1);\n                LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(new Intent(IMAction.ACTION_INVITE_MESSAGE));\n                notifierManager.getNotifier().vibrateAndPlayTone(null);\n\n                if(jsonObject!=null){\n                     User user = CommonUtils.Json2User(jsonObject);\n                    ContactsManager.getInstance().saveContact(user);\n                    LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(new Intent(IMAction.ACTION_CONTACT_CHANAGED));\n                }\n            }\n        }).start();\n    }\n\n    /**\n     * save and notify invitation message\n     */\n    private void notifyHTMessage() {\n        notifierManager.getNotifier().vibrateAndPlayTone(null);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/HTConstant.java",
    "content": "package com.htmessage.yichatopen;\n\nimport android.os.Environment;\n\n/**\n * Created by ustc on 2016/6/27.\n */\npublic class HTConstant {\n//    IM服务器相关\n    public static final String HOST_IM = \"xxx.xxx.xxx.xxx\";//示例ip: 119.125.523.153 此IP不可用\n    //api服务器\n    public static final String HOST_API = \"http://xxx.xxx.xxx.xxx/api/\";//示例ip: 119.125.523.153 此IP不可用\n    //阿里云OSS信息配置\n    public static final String endpoint = \"oss-cn-hangzhou.aliyuncs.com\";\n    public static final String accessKeyId = \"xxxxxxxx\";\n    public static final String accessKeySecret = \"xxxxxxxxxxxx\";\n    public static final String bucket = \"xxxxxxxxxx\";\n    public static final String baseOssUrl = \"http://\"+ bucket+\".\"+endpoint+\"/\";\n\n    //登记设备id,实现单点登陆\n    public static final  String DEVICE_URL_UPDATE = HOST_API+\"updateDeviceId.php\";\n    public static final  String DEVICE_URL_GET = HOST_API+\"getDeviceId.php\";\n    //查询更新\n    public static final String URL_CHECK_UPDATE = HOST_API+\"version.php\";\n\n    //应用层使用到的api接口\n    public static final String URL_AVATAR= HOST_API + \"upload/\";\n    public static final String URL_REGISTER = HOST_API + \"register\";//注册\n    public static final String URL_LOGIN = HOST_API + \"login\";//登录\n     public static final String URL_FriendList = HOST_API + \"fetchFriends\";//获取好友列表\n    public static final String URL_Search_User = HOST_API + \"searchUser\";//查询好友\n    public static final String URL_Get_UserInfo = HOST_API + \"getUserInfo\";//获取详情\n    public static final String URL_UPDATE = HOST_API + \"update\";//更新\n    public static final String URL_RESETPASSWORD = HOST_API + \"resetPassword\";//更新密码\n    public static final String URL_ADD_FRIEND=HOST_API + \"addFriend\"; //添加好友\n    public static final String URL_DELETE_FRIEND=HOST_API + \"removeFriend\";//删除好友\n    public static final String URL_ADD_BLACKLIST=HOST_API +\"addBlackList\";//添加黑名单\n    public static final String URL_GET_RECENTLY_PEOPLE= HOST_API + \"getRecentlyUser\";//获取最近上线的人\n    public static final String URL_SEND_LOCAL_LOGIN_TIME= HOST_API + \"updateLocalTimestamp\";//获取最近上线的人\n\n\n    // 缩略图处理---等高宽-请查看阿里云官方文档oss图片处理文档\n    public static final String baseImgUrl_set = \"?x-oss-process=image/resize,m_fill,h_300,w_300\";\n    //jsonobject常用key值\n\n    public static final String JSON_KEY_NICK =\"nick\";\n    public static final String JSON_KEY_HXID =\"userId\";\n    public static final String JSON_KEY_FXID =\"fxid\";\n    public static final String JSON_KEY_SEX =\"sex\";\n    public static final String JSON_KEY_AVATAR =\"avatar\";\n    public static final String JSON_KEY_CITY =\"city\";\n    public static final String JSON_KEY_PASSWORD =\"password\";\n    public static final String JSON_KEY_PROVINCE =\"province\";\n    public static final String JSON_KEY_TEL =\"tel\";\n    public static final String JSON_KEY_SIGN =\"sign\";\n    public static final String JSON_KEY_ROLE =\"role\";\n\n    public static final String JSON_KEY_SESSION =\"session\";\n    //添加好友的原因\n    public static final String CMD_ADD_REASON=\"ADD_REASON\";\n\n    //进入用户详情页传递json字符串\n    public static final String KEY_USER_INFO=\"userInfo\";\n    //修改用户资料的广播\n    public static final String KEY_CHANGE_TYPE=\"type\";\n    //开源地址\n    public static final String GITHUBURL = \"https://github.com/YiChat\";\n    public static final String OSCHINAURL = \"http://git.oschina.net/zhangfeng_tech\";\n    //Pro版本体验\n    public static final String YICHATPROURL = \"https://www.pgyer.com/yichat_android\";\n    public static final String DIR_AVATAR = Environment.getExternalStorageDirectory().toString()+\"/yiChat/\";\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/IMAction.java",
    "content": "package com.htmessage.yichatopen;\n\n/**\n * Created by huangfangyi on 2017/2/10.\n * qq 84543217\n */\n\npublic class IMAction {\n    public static final String ACTION_INVITE_MESSAGE=\"action_invite_message\";\n    public static final String ACTION_NEW_MESSAGE=\"action_new_message\";\n    public static final String ACTION_REMOVED_FROM_GROUP=\"action_removed_from_group\";\n   public static final String ACTION_CONTACT_CHANAGED = \"action_contact_changed\";\n    public static final String ACTION_CONFLICT = \"action_conflict\";\n    public static final String ACTION_CONNECTION_CHANAGED=\"action_connection_changed\";\n    //消息撤回\n    public static final String ACTION_MESSAGE_WITHDROW=\"action_message_withdrow\";\n    //转发消息\n    public static final String ACTION_MESSAGE_FORWORD=\"action_message_forword\";\n    //清空消息\n    public static final String ACTION_MESSAGE_EMPTY=\"ACTION_MESSAGE_EMPTY\";\n    //删除好友通知\n    public static final String CMD_DELETE_FRIEND =\"DELETE_FRIEND\";\n    //资料更新的通知\n    public static final String ACTION_UPDATE_INFO =\"ACTION_UPDATE_INFO\";\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/BaseActivity.java",
    "content": "package com.htmessage.yichatopen.activity;\n\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\n\npublic class BaseActivity extends AppCompatActivity {\n     public String TAG=this.getClass().getName().toString();\n    @Override\n    protected void onCreate(Bundle arg0) {\n        super.onCreate(arg0);\n        HTApp.getInstance().saveActivity(this);\n    }\n\n\n\n\n    public void back(View view) {\n        finish();\n    }\n\n\n    public void setTitle(int title){\n        TextView textView= (TextView) this.findViewById(R.id.tv_title);\n//        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n//        layoutParams.addRule();\n//        imageView.setLayoutParams(layoutParams);\n\n\n\n        if(textView!=null){\n            textView.setText(title);\n        }\n\n    }\n    public void  setTitleCenter(){\n        TextView textView= (TextView) this.findViewById(R.id.tv_title);\n        textView.setGravity(Gravity.CENTER);\n    }\n    public void setTitle(String title){\n        TextView textView= (TextView) this.findViewById(R.id.tv_title);\n        if(textView!=null){\n            textView.setText(title);\n        }\n    }\n\n    public void hideBackView(){\n        ImageView iv_back= (ImageView) this.findViewById(R.id.iv_back);\n        View view=this.findViewById(R.id.view_temp);\n        if(iv_back!=null&&view!=null){\n            iv_back.setVisibility(View.GONE);\n            view.setVisibility(View.GONE);\n        }\n\n    }\n\n\n    public void showRightView(int res,View.OnClickListener onClickListener){\n        ImageView ivRight= (ImageView) this.findViewById(R.id.iv_right);\n        if(ivRight!=null ){\n            ivRight.setImageResource(res);\n            ivRight.setVisibility(View.VISIBLE);\n            if(onClickListener!=null){\n                ivRight.setOnClickListener(onClickListener);\n            }\n        }\n    }\n    public void showRightTextView(int res,View.OnClickListener onClickListener){\n        TextView ivRight= (TextView) this.findViewById(R.id.btn_rtc);\n        if(ivRight!=null ){\n            ivRight.setText(res);\n            ivRight.setVisibility(View.VISIBLE);\n            if(onClickListener!=null){\n                ivRight.setOnClickListener(onClickListener);\n            }\n        }\n    }\n    public void showRightTextView(String res,View.OnClickListener onClickListener){\n        TextView ivRight= (TextView) this.findViewById(R.id.btn_rtc);\n        if(ivRight!=null ){\n            ivRight.setText(res);\n            ivRight.setVisibility(View.VISIBLE);\n            if(onClickListener!=null){\n                ivRight.setOnClickListener(onClickListener);\n            }\n        }\n    }\n    protected boolean isCompatible(int apiLevel) {\n        return Build.VERSION.SDK_INT >= apiLevel;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/BasePresenter.java",
    "content": "package com.htmessage.yichatopen.activity;\n\n/**\n * Created by huangfangyi on 2017/6/21.\n * qq 84543217\n */\n\npublic interface BasePresenter  {\n    void start();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/BaseView.java",
    "content": "package com.htmessage.yichatopen.activity;\n\nimport android.app.Activity;\nimport android.content.Context;\n\n/**\n * Created by huangfangyi on 2017/6/21.\n * qq 84543217\n */\n\npublic interface BaseView<T> {\n    void setPresenter(T presenter);\n    Context getBaseContext();\n    Activity getBaseActivity();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/ScanCaptureActivity.java",
    "content": "package com.htmessage.yichatopen.activity;\n\nimport android.content.Intent;\nimport android.content.pm.ActivityInfo;\nimport android.graphics.Rect;\nimport android.hardware.Camera;\nimport android.hardware.Camera.AutoFocusCallback;\nimport android.hardware.Camera.PreviewCallback;\nimport android.hardware.Camera.Size;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.text.TextUtils;\nimport android.view.Display;\nimport android.view.View;\nimport android.view.View.OnClickListener;\nimport android.view.animation.Animation;\nimport android.view.animation.TranslateAnimation;\nimport android.widget.Button;\nimport android.widget.FrameLayout;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;\nimport com.htmessage.yichatopen.widget.scan.CameraManager;\nimport com.htmessage.yichatopen.widget.scan.CameraPreview;\n\nimport net.sourceforge.zbar.Config;\nimport net.sourceforge.zbar.Image;\nimport net.sourceforge.zbar.ImageScanner;\nimport net.sourceforge.zbar.Symbol;\nimport net.sourceforge.zbar.SymbolSet;\n\nimport java.io.IOException;\nimport java.lang.reflect.Field;\n\npublic class ScanCaptureActivity extends BaseActivity {\n    private Camera mCamera;\n    private CameraPreview mPreview;\n    private Handler autoFocusHandler;\n    private CameraManager mCameraManager;\n\n    private TextView scanResult;\n    private FrameLayout scanPreview;\n    private Button scanRestart;\n    private RelativeLayout scanContainer;\n    private RelativeLayout scanCropView;\n    private ImageView scanLine;\n    private TextView tv_title;\n    private Rect mCropRect = null;\n    private boolean barcodeScanned = false;\n    private boolean previewing = true;\n    private ImageScanner mImageScanner = null;\n\n    static {\n        System.loadLibrary(\"iconv\");\n    }\n\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.widget_zbar_scan_capture);\n        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);\n        findViewById();\n        addEvents();\n        initViews();\n    }\n\n    private void findViewById() {\n        scanPreview = (FrameLayout) findViewById(R.id.capture_preview);\n        scanResult = (TextView) findViewById(R.id.capture_scan_result);\n        scanRestart = (Button) findViewById(R.id.capture_restart_scan);\n        scanContainer = (RelativeLayout) findViewById(R.id.capture_container);\n        scanCropView = (RelativeLayout) findViewById(R.id.capture_crop_view);\n        scanLine = (ImageView) findViewById(R.id.capture_scan_line);\n        tv_title = (TextView) findViewById(R.id.tv_title);\n        tv_title.setText(R.string.scan_title);\n    }\n\n    private void addEvents() {\n        scanRestart.setOnClickListener(new OnClickListener() {\n            public void onClick(View v) {\n                if (barcodeScanned) {\n                    barcodeScanned = false;\n                    scanResult.setText(R.string.Scanning);\n                    mCamera.setPreviewCallback(previewCb);\n                    mCamera.startPreview();\n                    previewing = true;\n                    mCamera.autoFocus(autoFocusCB);\n                }\n            }\n        });\n    }\n\n    private void initViews() {\n        mImageScanner = new ImageScanner();\n        mImageScanner.setConfig(0, Config.X_DENSITY, 3);\n        mImageScanner.setConfig(0, Config.Y_DENSITY, 3);\n\n        autoFocusHandler = new Handler();\n        mCameraManager = new CameraManager(this);\n        try {\n            mCameraManager.openDriver();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n\n        // 调整扫描框大小,自适应屏幕\n        Display display = this.getWindowManager().getDefaultDisplay();\n        int width = display.getWidth();\n        int height = display.getHeight();\n\n        RelativeLayout.LayoutParams linearParams = (RelativeLayout.LayoutParams) scanCropView\n                .getLayoutParams();\n        linearParams.height = (int) (width * 0.8);\n        linearParams.width = (int) (width * 0.8);\n        scanCropView.setLayoutParams(linearParams);\n        // **\n\n        mCamera = mCameraManager.getCamera();\n        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);\n        scanPreview.addView(mPreview);\n\n        TranslateAnimation animation = new TranslateAnimation(\n                Animation.RELATIVE_TO_PARENT, 0.0f,\n                Animation.RELATIVE_TO_PARENT, 0.0f,\n                Animation.RELATIVE_TO_PARENT, 0.0f,\n                Animation.RELATIVE_TO_PARENT, 0.85f);\n        animation.setDuration(5000);\n        animation.setRepeatCount(-1);\n        animation.setRepeatMode(Animation.REVERSE);\n        scanLine.startAnimation(animation);\n    }\n\n    public void onPause() {\n        super.onPause();\n        releaseCamera();\n    }\n\n    private void releaseCamera() {\n        if (mCamera != null) {\n            previewing = false;\n            mCamera.setPreviewCallback(null);\n            mCamera.release();\n            mCamera = null;\n        }\n    }\n\n    private Runnable doAutoFocus = new Runnable() {\n        public void run() {\n            if (previewing)\n                mCamera.autoFocus(autoFocusCB);\n        }\n    };\n\n    PreviewCallback previewCb = new PreviewCallback() {\n        public void onPreviewFrame(byte[] data, Camera camera) {\n            Size size = camera.getParameters().getPreviewSize();\n\n            // 这里需要将获取的data翻转一下，因为相机默认拿的的横屏的数据\n            byte[] rotatedData = new byte[data.length];\n            for (int y = 0; y < size.height; y++) {\n                for (int x = 0; x < size.width; x++)\n                    rotatedData[x * size.height + size.height - y - 1] = data[x\n                            + y * size.width];\n            }\n\n            // 宽高也要调整\n            int tmp = size.width;\n            size.width = size.height;\n            size.height = tmp;\n\n            initCrop();\n\n            Image barcode = new Image(size.width, size.height, \"Y800\");\n            barcode.setData(rotatedData);\n            barcode.setCrop(mCropRect.left, mCropRect.top, mCropRect.width(),\n                    mCropRect.height());\n\n            int result = mImageScanner.scanImage(barcode);\n            String resultStr = null;\n\n            if (result != 0) {\n                SymbolSet syms = mImageScanner.getResults();\n                for (Symbol sym : syms) {\n                    resultStr = sym.getData();\n                }\n            }\n\n            if (!TextUtils.isEmpty(resultStr)) {\n                previewing = false;\n                mCamera.setPreviewCallback(null);\n                mCamera.stopPreview();\n                releaseCamera();\n                barcodeScanned = true;\n               if (resultStr.contains(\":\")) {\n                    String userType= resultStr\n                            .substring(0, resultStr.indexOf(\":\"));\n                    String value = resultStr.substring(resultStr.indexOf(\":\") + 1);\n                    System.out.println(\"type----------->>>>\" + userType);\n                    System.out.println(\"value----------->>>>\" + value);\n                    if (userType.equals(\"userInfo\")) {\n                        JSONObject object = JSONObject.parseObject(value);//.putExtra(HTConstant.JSON_KEY_HXID, object.getString(HTConstant.JSON_KEY_HXID))\n                        startActivity(new Intent(ScanCaptureActivity.this, UserDetailsActivity.class).putExtra(HTConstant.KEY_USER_INFO,object.toJSONString()));\n                    } else {\n                        Toast.makeText(getApplicationContext(), R.string.code_is_not_invlide, Toast.LENGTH_SHORT).show();\n                    }\n                } else {\n                    Toast.makeText(getApplicationContext(), R.string.code_is_not_invlide, Toast.LENGTH_SHORT).show();\n                }\n                finish();\n            }\n        }\n    };\n\n    // Mimic continuous auto-focusing\n    AutoFocusCallback autoFocusCB = new AutoFocusCallback() {\n        public void onAutoFocus(boolean success, Camera camera) {\n            autoFocusHandler.postDelayed(doAutoFocus, 1000);\n        }\n    };\n\n    /**\n     * 初始化截取的矩形区域\n     */\n    private void initCrop() {\n        int cameraWidth = mCameraManager.getCameraResolution().y;\n        int cameraHeight = mCameraManager.getCameraResolution().x;\n\n        /** 获取布局中扫描框的位置信息 */\n        int[] location = new int[2];\n        scanCropView.getLocationInWindow(location);\n\n        int cropLeft = location[0];\n        int cropTop = location[1] - getStatusBarHeight();\n\n        int cropWidth = scanCropView.getWidth();\n        int cropHeight = scanCropView.getHeight();\n\n        /** 获取布局容器的宽高 */\n        int containerWidth = scanContainer.getWidth();\n        int containerHeight = scanContainer.getHeight();\n\n        /** 计算最终截取的矩形的左上角顶点x坐标 */\n        int x = cropLeft * cameraWidth / containerWidth;\n        /** 计算最终截取的矩形的左上角顶点y坐标 */\n        int y = cropTop * cameraHeight / containerHeight;\n\n        /** 计算最终截取的矩形的宽度 */\n        int width = cropWidth * cameraWidth / containerWidth;\n        /** 计算最终截取的矩形的高度 */\n        int height = cropHeight * cameraHeight / containerHeight;\n\n        /** 生成最终的截取的矩形 */\n        mCropRect = new Rect(x, y, width + x, height + y);\n    }\n\n    private int getStatusBarHeight() {\n        try {\n            Class<?> c = Class.forName(\"com.android.internal.R$dimen\");\n            Object obj = c.newInstance();\n            Field field = c.getField(\"status_bar_height\");\n            int x = Integer.parseInt(field.get(obj).toString());\n            return getResources().getDimensionPixelSize(x);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return 0;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/SettingsActivity.java",
    "content": "package com.htmessage.yichatopen.activity;\n\nimport android.app.AlertDialog;\nimport android.app.ProgressDialog;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.provider.Settings;\nimport android.view.View;\nimport android.widget.LinearLayout;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.manager.SettingsManager;\nimport com.htmessage.yichatopen.activity.login.LoginActivity;\nimport com.htmessage.yichatopen.activity.main.password.PasswordResetActivity;\nimport com.htmessage.yichatopen.widget.SwitchButton;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.yichatopen.widget.HTAlertDialog;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\n/**\n * Created by huangfangyi on 2016/7/4.\\\n * QQ:84543217\n */\npublic class SettingsActivity extends BaseActivity implements View.OnClickListener {\n    /**\n     * new message notification\n     */\n    private RelativeLayout rl_switch_notification;\n    /**\n     * sound\n     */\n    private RelativeLayout rl_switch_sound;\n    /**\n     * vibration\n     */\n    private RelativeLayout rl_switch_vibrate;\n    /**\n     * speaker\n     */\n    private RelativeLayout rl_switch_speaker;\n\n\n    /**\n     * line between sound and vibration\n     */\n    private TextView textview1, textview2;\n\n    private LinearLayout blacklistContainer;\n\n    private LinearLayout userProfileContainer;\n\n    /**\n     * logout\n     */\n    private RelativeLayout rl_logout;\n\n    private RelativeLayout rl_switch_chatroom_leave;\n\n    private RelativeLayout rl_switch_delete_msg_when_exit_group;\n    private RelativeLayout rl_switch_auto_accept_group_invitation;\n    private RelativeLayout rl_switch_adaptive_video_encode, rl_keep_live, re_resetpassword;\n\n    private RelativeLayout rl_update, rl_about_us;//检查更新\n\n    /**\n     * Diagnose\n     */\n    private LinearLayout llDiagnose, llChange, ll_numal_set;\n    private View view_devider;\n    /**\n     * display name for APNs\n     */\n    private LinearLayout pushNick, ll_new_msg;\n\n    private SwitchButton notifiSwitch;\n    private SwitchButton soundSwitch;\n    private SwitchButton vibrateSwitch;\n    private SwitchButton speakerSwitch;\n    private SwitchButton ownerLeaveSwitch;\n    private SwitchButton switch_delete_msg_when_exit_group;\n    private SwitchButton switch_auto_accept_group_invitation;\n    private SwitchButton switch_adaptive_video_encode;\n    private SettingsManager settingsModel;\n\n    @Override\n    protected void onCreate(Bundle arg0) {\n        super.onCreate(arg0);\n        setContentView(R.layout.fragment_conversation_settings);\n        initView();\n        initData();\n        setListener();\n    }\n\n    private void setListener() {\n        blacklistContainer.setOnClickListener(this);\n        userProfileContainer.setOnClickListener(this);\n        rl_switch_notification.setOnClickListener(this);\n        rl_switch_sound.setOnClickListener(this);\n        rl_switch_vibrate.setOnClickListener(this);\n        rl_switch_speaker.setOnClickListener(this);\n        rl_logout.setOnClickListener(this);\n        llDiagnose.setOnClickListener(this);\n        pushNick.setOnClickListener(this);\n        rl_switch_chatroom_leave.setOnClickListener(this);\n        rl_switch_delete_msg_when_exit_group.setOnClickListener(this);\n        rl_switch_auto_accept_group_invitation.setOnClickListener(this);\n        rl_switch_adaptive_video_encode.setOnClickListener(this);\n        rl_update.setOnClickListener(this);\n        rl_keep_live.setOnClickListener(this);\n        re_resetpassword.setOnClickListener(this);\n        rl_about_us.setOnClickListener(this);\n        ll_new_msg.setOnClickListener(this);\n        llChange.setOnClickListener(this);\n    }\n\n    private void initData() {\n        settingsModel = SettingsManager.getInstance();\n\n        // the vibrate and sound notification are allowed or not?\n        if (settingsModel.getSettingMsgNotification()) {\n            notifiSwitch.openSwitch();\n            rl_switch_sound.setVisibility(View.VISIBLE);\n            rl_switch_vibrate.setVisibility(View.VISIBLE);\n            textview1.setVisibility(View.VISIBLE);\n            textview2.setVisibility(View.VISIBLE);\n        } else {\n            notifiSwitch.closeSwitch();\n            rl_switch_sound.setVisibility(View.GONE);\n            rl_switch_vibrate.setVisibility(View.GONE);\n            textview1.setVisibility(View.GONE);\n            textview2.setVisibility(View.GONE);\n        }\n\n        // sound notification is switched on or not?\n        if (settingsModel.getSettingMsgSound()) {\n            soundSwitch.openSwitch();\n        } else {\n            soundSwitch.closeSwitch();\n        }\n\n        // vibrate notification is switched on or not?\n        if (settingsModel.getSettingMsgVibrate()) {\n            vibrateSwitch.openSwitch();\n        } else {\n            vibrateSwitch.closeSwitch();\n        }\n\n        // the speaker is switched on or not?\n        if (settingsModel.getSettingMsgSpeaker()) {\n            speakerSwitch.openSwitch();\n        } else {\n            speakerSwitch.closeSwitch();\n        }\n\n        // if allow owner leave\n        if (settingsModel.isChatroomOwnerLeaveAllowed()) {\n            ownerLeaveSwitch.openSwitch();\n        } else {\n            ownerLeaveSwitch.closeSwitch();\n        }\n\n        // delete messages when exit group?\n        if (settingsModel.isDeleteMessagesAsExitGroup()) {\n            switch_delete_msg_when_exit_group.openSwitch();\n        } else {\n            switch_delete_msg_when_exit_group.closeSwitch();\n        }\n\n        if (settingsModel.isAutoAcceptGroupInvitation()) {\n            switch_auto_accept_group_invitation.openSwitch();\n        } else {\n            switch_auto_accept_group_invitation.closeSwitch();\n        }\n\n    }\n\n    private void initView() {\n        rl_switch_notification = (RelativeLayout) findViewById(R.id.rl_switch_notification);\n        rl_switch_sound = (RelativeLayout) findViewById(R.id.rl_switch_sound);\n        rl_switch_vibrate = (RelativeLayout) findViewById(R.id.rl_switch_vibrate);\n        rl_switch_speaker = (RelativeLayout) findViewById(R.id.rl_switch_speaker);\n        rl_switch_chatroom_leave = (RelativeLayout) findViewById(R.id.rl_switch_chatroom_owner_leave);\n        rl_switch_delete_msg_when_exit_group = (RelativeLayout) findViewById(R.id.rl_switch_delete_msg_when_exit_group);\n        rl_switch_auto_accept_group_invitation = (RelativeLayout) findViewById(R.id.rl_switch_auto_accept_group_invitation);\n        rl_switch_adaptive_video_encode = (RelativeLayout) findViewById(R.id.rl_switch_adaptive_video_encode);\n        rl_update = (RelativeLayout) findViewById(R.id.rl_update);//rl_keep_live,re_resetpassword\n        rl_keep_live = (RelativeLayout) findViewById(R.id.rl_keep_live);\n        re_resetpassword = (RelativeLayout) findViewById(R.id.re_resetpassword);\n        rl_about_us = (RelativeLayout) findViewById(R.id.rl_about_us);\n\n        notifiSwitch = (SwitchButton) findViewById(R.id.switch_notification);\n        soundSwitch = (SwitchButton) findViewById(R.id.switch_sound);\n        vibrateSwitch = (SwitchButton) findViewById(R.id.switch_vibrate);\n        speakerSwitch = (SwitchButton) findViewById(R.id.switch_speaker);\n        ownerLeaveSwitch = (SwitchButton) findViewById(R.id.switch_owner_leave);\n        switch_delete_msg_when_exit_group = (SwitchButton) findViewById(R.id.switch_delete_msg_when_exit_group);\n        switch_auto_accept_group_invitation = (SwitchButton) findViewById(R.id.switch_auto_accept_group_invitation);\n        switch_adaptive_video_encode = (SwitchButton) findViewById(R.id.switch_adaptive_video_encode);\n        llChange = (LinearLayout) findViewById(R.id.ll_change);\n        ll_new_msg = (LinearLayout) findViewById(R.id.ll_new_msg);\n        ll_numal_set = (LinearLayout) findViewById(R.id.ll_numal_set);\n        rl_logout = (RelativeLayout) findViewById(R.id.rl_logout);\n\n        textview1 = (TextView) findViewById(R.id.textview1);\n        textview2 = (TextView) findViewById(R.id.textview2);\n\n        blacklistContainer = (LinearLayout) findViewById(R.id.ll_black_list);\n        userProfileContainer = (LinearLayout) findViewById(R.id.ll_user_profile);\n        llDiagnose = (LinearLayout) findViewById(R.id.ll_diagnose);\n        pushNick = (LinearLayout) findViewById(R.id.ll_set_push_nick);\n        view_devider = findViewById(R.id.view_devider);\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.ll_change: //新消息设置\n                if (ll_new_msg.getVisibility() == View.GONE) {\n                    ll_new_msg.setVisibility(View.VISIBLE);\n                    view_devider.setVisibility(View.GONE);\n                } else {\n                    ll_new_msg.setVisibility(View.GONE);\n                    view_devider.setVisibility(View.VISIBLE);\n                }\n                break;\n            case R.id.rl_switch_notification:\n                if (notifiSwitch.isSwitchOpen()) {\n                    notifiSwitch.closeSwitch();\n                    rl_switch_sound.setVisibility(View.GONE);\n                    rl_switch_vibrate.setVisibility(View.GONE);\n                    textview1.setVisibility(View.GONE);\n                    textview2.setVisibility(View.GONE);\n                    settingsModel.setSettingMsgNotification(false);\n                } else {\n                    notifiSwitch.openSwitch();\n                    rl_switch_sound.setVisibility(View.VISIBLE);\n                    rl_switch_vibrate.setVisibility(View.VISIBLE);\n                    textview1.setVisibility(View.VISIBLE);\n                    textview2.setVisibility(View.VISIBLE);\n                    settingsModel.setSettingMsgNotification(true);\n                }\n                break;\n            case R.id.rl_switch_sound:\n                if (soundSwitch.isSwitchOpen()) {\n                    soundSwitch.closeSwitch();\n                    settingsModel.setSettingMsgSound(false);\n                } else {\n                    soundSwitch.openSwitch();\n                    settingsModel.setSettingMsgSound(true);\n                }\n                break;\n            case R.id.rl_switch_vibrate:\n                if (vibrateSwitch.isSwitchOpen()) {\n                    vibrateSwitch.closeSwitch();\n                    settingsModel.setSettingMsgVibrate(false);\n                } else {\n                    vibrateSwitch.openSwitch();\n                    settingsModel.setSettingMsgVibrate(true);\n                }\n                break;\n            case R.id.rl_switch_speaker:\n                if (speakerSwitch.isSwitchOpen()) {\n                    speakerSwitch.closeSwitch();\n                    settingsModel.setSettingMsgSpeaker(false);\n                } else {\n                    speakerSwitch.openSwitch();\n                    settingsModel.setSettingMsgSpeaker(true);\n                }\n                break;\n            case R.id.rl_switch_chatroom_owner_leave:\n                if (ownerLeaveSwitch.isSwitchOpen()) {\n                    ownerLeaveSwitch.closeSwitch();\n                    settingsModel.allowChatroomOwnerLeave(false);\n\n                } else {\n                    ownerLeaveSwitch.openSwitch();\n                    settingsModel.allowChatroomOwnerLeave(true);\n                }\n                break;\n            case R.id.rl_switch_delete_msg_when_exit_group:\n                if (switch_delete_msg_when_exit_group.isSwitchOpen()) {\n                    switch_delete_msg_when_exit_group.closeSwitch();\n                    settingsModel.setDeleteMessagesAsExitGroup(false);\n                } else {\n                    switch_delete_msg_when_exit_group.openSwitch();\n                    settingsModel.setDeleteMessagesAsExitGroup(true);\n                }\n                break;\n            case R.id.rl_switch_auto_accept_group_invitation:\n                if (switch_auto_accept_group_invitation.isSwitchOpen()) {\n                    switch_auto_accept_group_invitation.closeSwitch();\n                    settingsModel.setAutoAcceptGroupInvitation(false);\n                } else {\n                    switch_auto_accept_group_invitation.openSwitch();\n                    settingsModel.setAutoAcceptGroupInvitation(true);\n                }\n                break;\n            case R.id.rl_switch_adaptive_video_encode:\n                if (switch_adaptive_video_encode.isSwitchOpen()) {\n                    switch_adaptive_video_encode.closeSwitch();\n                    settingsModel.setAdaptiveVideoEncode(false);\n                } else {\n                    switch_adaptive_video_encode.openSwitch();\n                    settingsModel.setAdaptiveVideoEncode(true);\n                }\n                break;\n            case R.id.rl_logout:\n//                logout();\n                logOutDialog();\n                break;\n            case R.id.ll_black_list:\n                // startActivity(new Intent(SettingsActivity.this, BlacklistActivity.class));\n                break;\n            case R.id.ll_diagnose:\n                //    startActivity(new Intent(SettingsActivity.this, DiagnoseActivity.class));\n                break;\n            case R.id.ll_set_push_nick:\n                //   startActivity(new Intent(SettingsActivity.this, OfflinePushNickActivity.class));\n                break;\n            case R.id.ll_user_profile:\n//                startActivity(new Intent(SettingsActivity.this, UserProfileActivity.class).putExtra(\"setting\", true)\n//                        .putExtra(\"username\", EMClient.getInstance().getCurrentUser()));\n                break;\n            case R.id.rl_update: //检查更新\n                getAppUpdate();\n                break;\n            //rl_keep_live,re_resetpassword\n            case R.id.re_resetpassword: //重置密码\n                startActivity(new Intent(SettingsActivity.this, PasswordResetActivity.class).putExtra(\"isReset\", true));\n                break;\n            case R.id.rl_keep_live: //后台保活\n                Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);\n                startActivity(intent);\n                break;\n            case R.id.rl_about_us:\n                break;\n            default:\n                break;\n        }\n\n    }\n\n    private void logOutDialog() {\n        HTAlertDialog dialog = new HTAlertDialog(this, null, new String[]{getString(R.string.exit_this_user), getString(R.string.close_app)});\n        dialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                switch (position) {\n                    case 0:\n                        logout();\n                        break;\n                    case 1:\n                        HTApp.getInstance().finishActivities();\n                        //杀死该应用进程\n                        android.os.Process.killProcess(android.os.Process.myPid());\n                        System.exit(0);\n                        break;\n                }\n            }\n        });\n    }\n\n\n    void logout() {\n        final ProgressDialog pd = new ProgressDialog(SettingsActivity.this);\n        String st = getResources().getString(R.string.Are_logged_out);\n        pd.setMessage(st);\n        pd.setCanceledOnTouchOutside(false);\n        pd.show();\n\n        HTClient.getInstance().logout(new HTClient.HTCallBack() {\n            @Override\n            public void onSuccess() {\n                pd.dismiss();\n                HTApp.getInstance().setUserJson(null);\n                HTApp.getInstance().finishActivities();\n\n                startActivity(new Intent(SettingsActivity.this, LoginActivity.class));\n                finish();\n\n            }\n\n            @Override\n            public void onError() {\n                pd.dismiss();\n                Toast.makeText(getApplicationContext(), R.string.logout_failed, Toast.LENGTH_SHORT).show();\n            }\n        });\n\n\n//        HTClientManager.getInstance().logout(new HTClientManager.LogoutCallBack() {\n//            @Override\n//            public void onSuccess() {\n//\n//                HTApp.getInstance().finishActivities();\n//                runOnUiThread(new Runnable() {\n//                    @Override\n//                    public void run() {\n//                        pd.dismiss();\n//                        startActivity(new Intent(SettingsActivity.this, LoginActivity.class));\n//                        finish();\n//                    }\n//                });\n//\n//            }\n//\n//            @Override\n//            public void onFailure(String errorMessage) {\n//\n//            }\n//        });\n//\n//\n    }\n\n    public void back(View view) {\n        finish();\n    }\n\n    /**\n     * 获取VersionCode\n     *\n     * @return 当前应用的VersionCode\n     */\n    public String getVersionCode() {\n        try {\n            PackageManager manager = getPackageManager();\n            PackageInfo info = manager.getPackageInfo(getPackageName(), 0);\n            String version = String.valueOf(info.versionCode);\n            return version;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return null;\n        }\n    }\n\n    private void getAppUpdate() {\n        final ProgressDialog dialog = new ProgressDialog(SettingsActivity.this);\n        dialog.setMessage(getString(R.string.are_checking_update));\n        dialog.show();\n        final String version = getVersionCode();\n        List<Param> params = new ArrayList<>();\n        params.add(new Param(\"system\", \"0\"));\n        new OkHttpUtils(SettingsActivity.this).post(params, HTConstant.URL_CHECK_UPDATE, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                if (jsonObject != null) {\n                    String serviceVersion = jsonObject.getString(\"newVersion\");\n                    String url = jsonObject.getString(\"url\");\n                    String info = jsonObject.getString(\"info\");\n                    String statue = jsonObject.getString(\"statue\");\n                    if (!version.equals(serviceVersion) && (Integer.valueOf(version) < Integer.valueOf(serviceVersion))) {\n                        showUpdateDialog(SettingsActivity.this, getString(R.string.has_update), info, url);\n                    } else {\n                        Toast.makeText(SettingsActivity.this, R.string.just_new_version, Toast.LENGTH_SHORT).show();\n                    }\n                }\n                dialog.dismiss();\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                dialog.dismiss();\n            }\n        });\n    }\n\n    private void showUpdateDialog(final Context context, String title, String message, final String url) {\n        AlertDialog.Builder builder = new AlertDialog.Builder(context);\n        View dialogView = View.inflate(context, R.layout.layout_alert_dialog_delete, null);\n        TextView tv_delete_people = (TextView) dialogView.findViewById(R.id.tv_delete_people);\n        TextView tv_delete_title = (TextView) dialogView.findViewById(R.id.tv_delete_title);\n        TextView tv_cancle = (TextView) dialogView.findViewById(R.id.tv_cancle);\n        TextView tv_ok = (TextView) dialogView.findViewById(R.id.tv_ok);\n        tv_delete_title.setText(title);\n        tv_delete_people.setText(message);\n        tv_cancle.setText(R.string.update_later);\n        tv_ok.setText(R.string.update_now);\n        builder.setView(dialogView);\n        final AlertDialog dialog = builder.show();\n//        dialog.setCancelable(false);//点击屏幕外不取消  返回键也没用\n//        dialog.setCanceledOnTouchOutside(false); //点击屏幕外取消,返回键有用\n        tv_cancle.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n            }\n        });\n        tv_ok.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n                Intent intent = new Intent();\n                intent.setAction(Intent.ACTION_VIEW);\n                Uri uri = Uri.parse(url);\n                intent.setData(uri);\n                SettingsActivity.this.startActivity(intent);\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/ShowBigImageActivity.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.activity;\n\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.view.View.OnClickListener;\n\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.widget.photoview.PhotoView;\n\nimport java.io.File;\n\n/**\n * download and show original image\n * \n */\npublic class ShowBigImageActivity extends  BaseActivity {\n\n\tprivate PhotoView image;\n\t@Override\n\tprotected void onCreate(Bundle savedInstanceState) {\n\t\tsetContentView(R.layout.activity_show_big_image);\n\t\tsuper.onCreate(savedInstanceState);\n        String localPath=this.getIntent().getStringExtra(\"localPath\");\n\t\tUri uri=Uri.fromFile(new File(localPath));\n\t\timage = (PhotoView) findViewById(R.id.image);\n//\t\timage.setImageURI(uri);\n\t\tGlide.with(ShowBigImageActivity.this).load(uri.getPath()).diskCacheStrategy(DiskCacheStrategy.ALL).error(R.drawable.default_image).into(image);\n\t\timage.setOnClickListener(new OnClickListener() {\n\t\t\t@Override\n\t\t\tpublic void onClick(View v) {\n\t\t\t\tfinish();\n\t\t\t}\n\t\t});\n\t}\n\n\n\t@Override\n\tpublic void onBackPressed() {\n\t\tsetResult(RESULT_OK);\n\t\tfinish();\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/SplashActivity.java",
    "content": "package com.htmessage.yichatopen.activity;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.view.animation.AlphaAnimation;\nimport android.view.animation.Animation;\nimport android.widget.RelativeLayout;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.yichatopen.activity.login.LoginActivity;\nimport com.htmessage.yichatopen.activity.main.MainActivity;\nimport com.htmessage.yichatopen.utils.UpdateLastLoginTimeUtils;\n\n/**\n * 开屏页\n *\n */\npublic class SplashActivity extends  Activity {\n    //继承Activity是为动画启动前无白屏卡顿\n\t@Override\n\tprotected void onCreate(Bundle arg0) {\n \t\tsuper.onCreate(arg0);\n\t\tsetContentView(R.layout.activity_splash);\n\t\tRelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.splash_root);\n\t\tAlphaAnimation animation = new AlphaAnimation(0.5f, 1.0f);\n\t\tanimation.setDuration(2000);\n\t\trootLayout.startAnimation(animation);\n\t\tanimation.setAnimationListener(new Animation.AnimationListener() {\n\t\t\t@Override\n\t\t\tpublic void onAnimationStart(Animation animation) {\n\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void onAnimationEnd(Animation animation) {\n\t\t\t\tif (HTClient.getInstance().isLogined()) {\n\t\t\t\t\t//上传最近登录时间\n\t\t\t\t\tUpdateLastLoginTimeUtils.sendLocalTimeToService(SplashActivity.this);\n\t\t\t    \tIntent intent=new Intent(SplashActivity.this, MainActivity.class);\n \t\t\t\t\tstartActivity(intent);\n\t\t\t\t\tfinish();\n\t\t\t\t}else {\n\t\t\t\t\tstartActivity(new Intent(SplashActivity.this, LoginActivity.class));\n\t\t\t\t\tfinish();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void onAnimationRepeat(Animation animation) {\n\n\t\t\t}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/add/end/AddFriendsFinalActivity.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.add.end;\n\nimport android.app.ProgressDialog;\nimport android.os.Bundle;\nimport android.text.Selection;\nimport android.text.Spannable;\nimport android.view.View;\nimport android.view.View.OnClickListener;\nimport android.widget.EditText;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.manager.HTChatManager;\nimport com.htmessage.sdk.model.CmdMessage;\n\nimport java.util.UUID;\npublic class AddFriendsFinalActivity extends BaseActivity {\n     private   ProgressDialog progressDialog;\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_addfriends_final);\n        String userInfo = getIntent().getStringExtra(HTConstant.KEY_USER_INFO);\n        JSONObject jsonObject = null;\n        try {\n            jsonObject = JSONObject.parseObject(userInfo);\n        } catch (JSONException e) {\n        }\n        if (jsonObject == null) {\n            finish();\n            return;\n        }\n        initView(jsonObject);\n\n    }\n\n\n    private void initView(final JSONObject jsonObject) {\n        final EditText etReason = (EditText) this.findViewById(R.id.et_reason);\n        etReason.setText(getString(R.string.i_am)+HTApp.getInstance().getUserJson().getString(HTConstant.JSON_KEY_NICK));\n        if (etReason.getText() instanceof Spannable) {\n            Spannable spanText = (Spannable)etReason.getText();\n            Selection.setSelection(spanText, etReason.getText().length());\n        }\n        findViewById(R.id.tv_send).setOnClickListener(new OnClickListener() {\n\n            @Override\n            public void onClick(View v) {\n                addContact(jsonObject.getString(HTConstant.JSON_KEY_HXID), etReason.getText().toString().trim());\n            }\n\n        });\n    }\n\n    /**\n     * 添加contact\n     *\n     * @param\n     */\n    public void addContact(final String hxid, String reason) {\n        progressDialog = new ProgressDialog(this);\n        progressDialog.setMessage(getResources().getString(R.string.Is_sending_a_request));\n        progressDialog.setCanceledOnTouchOutside(false);\n        progressDialog.show();\n        JSONObject userJson = HTApp.getInstance().getUserJson();\n        JSONObject data = new JSONObject();\n        data.put(\"ADD_REASON\", reason);\n        data.put(\"userId\", userJson.getString(\"userId\"));\n        data.put(\"nick\",userJson.getString(\"nick\"));\n        data.put(\"avatar\", userJson.getString(\"avatar\"));\n        data.put(\"role\",userJson.getString(HTConstant.JSON_KEY_ROLE));\n        data.put(\"teamId\",userJson.getString(\"teamId\"));\n        JSONObject bodyJson = new JSONObject();\n        bodyJson.put(\"action\", 1000);\n        bodyJson.put(\"data\", data);\n\n        CmdMessage customMessage = new CmdMessage();\n        customMessage.setBody(bodyJson.toJSONString());\n        customMessage.setFrom(HTApp.getInstance().getUsername());\n        customMessage.setTime(System.currentTimeMillis());\n        customMessage.setTo(hxid);\n         customMessage.setMsgId( UUID.randomUUID().toString());\n        customMessage.setChatType(ChatType.singleChat);\n        HTClient.getInstance().chatManager().sendCmdMessage(customMessage, new HTChatManager.HTMessageCallBack() {\n            @Override\n            public void onProgress() {\n\n            }\n\n            @Override\n            public void onSuccess() {\n                runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (progressDialog != null) {\n                            progressDialog.dismiss();\n                        }\n                        Toast.makeText(AddFriendsFinalActivity.this,\n                                R.string.send_successful, Toast.LENGTH_SHORT)\n                                .show();\n                        finish();\n                    }\n                });\n            }\n\n            @Override\n            public void onFailure() {\n                runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (progressDialog != null) {\n                            progressDialog.dismiss();\n                        }\n                        Toast.makeText(AddFriendsFinalActivity.this,\n                                getResources().getString( R.string.Request_add_buddy_failure), Toast.LENGTH_SHORT)\n                                .show();\n                        finish();\n                    }\n                });\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/add/next/AddFriendNextBasePrestener.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.add.next;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * 项目名称：HTOpen\n * 类描述：AddFriendNextBasePrestener 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 17:22\n * 邮箱:814326663@qq.com\n */\npublic interface AddFriendNextBasePrestener  extends BasePresenter {\n    void searchUser();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/add/next/AddFriendNextFragment.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.add.next;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.EditText;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;\nimport com.htmessage.yichatopen.HTConstant;\n\n/**\n * 项目名称：HTOpen\n * 类描述：AddFriendNextFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 17:33\n * 邮箱:814326663@qq.com\n */\npublic class AddFriendNextFragment extends Fragment implements AddFriendNextView ,TextWatcher,View.OnClickListener{\n    private RelativeLayout re_search;\n    private TextView tv_search;\n    private EditText et_search;\n    private AddFriendNextPrestener prestener;\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View nextView = inflater.inflate(R.layout.activity_addfriends_next, container, false);\n        initView(nextView);\n        setListener();\n        return nextView;\n    }\n\n    private void initView(View nextView) {\n        re_search = (RelativeLayout) nextView.findViewById(R.id.re_search);\n        tv_search = (TextView) nextView.findViewById(R.id.tv_search);\n        et_search = (EditText) nextView.findViewById(R.id.et_search);\n    }\n\n    private void setListener() {\n        et_search.addTextChangedListener(this);\n        re_search.setOnClickListener(this);\n    }\n\n    @Override\n    public String getInputString() {\n        return et_search.getText().toString().trim();\n    }\n\n    @Override\n    public void onSearchSuccess(JSONObject object) {\n        getBaseActivity().startActivity(new Intent(getBaseActivity(), UserDetailsActivity.class).putExtra(HTConstant.KEY_USER_INFO,object.toJSONString()));\n    }\n\n    @Override\n    public void onSearchFailed(String error) {\n        Toast.makeText(getBaseContext(), error,\n                Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void setPresenter(AddFriendNextPrestener presenter) {\n        this.prestener = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n    }\n\n    @Override\n    public void onTextChanged(CharSequence s, int start, int before, int count) {\n        if (s.length() > 0) {\n            re_search.setVisibility(View.VISIBLE);\n            tv_search.setText(et_search.getText().toString().trim());\n        } else {\n            re_search.setVisibility(View.GONE);\n            tv_search.setText(\"\");\n        }\n    }\n\n    @Override\n    public void afterTextChanged(Editable s) {\n\n    }\n\n    public void back(View view) {\n        getBaseActivity().finish();\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()){\n            case R.id.re_search:\n                prestener.searchUser();\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/add/next/AddFriendNextPrestener.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.add.next;\n\nimport android.app.ProgressDialog;\nimport android.text.TextUtils;\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：HTOpen\n * 类描述：AddFriendNextPrestener 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 17:23\n * 邮箱:814326663@qq.com\n */\npublic class AddFriendNextPrestener implements AddFriendNextBasePrestener {\n    private AddFriendNextView nextView;\n\n    public AddFriendNextPrestener(AddFriendNextView nextView) {\n        this.nextView = nextView;\n        this.nextView.setPresenter(this);\n    }\n\n    @Override\n    public void searchUser() {\n        if (TextUtils.isEmpty(nextView.getInputString())){\n            return;\n        }\n        final ProgressDialog dialog = new ProgressDialog(nextView.getBaseContext());\n        dialog.setMessage(nextView.getBaseContext().getString(R.string.are_finding_contact));\n        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);\n        dialog.show();\n        List<Param> paramList=new ArrayList<>();\n        paramList.add(new Param(\"userId\", nextView.getInputString()));\n        new OkHttpUtils(nextView.getBaseContext()).post(paramList, HTConstant.URL_Search_User, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                dialog.dismiss();\n                int code = jsonObject.getInteger(\"code\");\n                if (code == 1) {\n                    JSONObject json = jsonObject.getJSONObject(\"user\");\n                    nextView.onSearchSuccess(json);\n                } else if (code == -1) {\n                    nextView.onSearchFailed(nextView.getBaseContext().getString(R.string.User_does_not_exis));\n                } else if (code == 0) {\n                    nextView.onSearchFailed(nextView.getBaseContext().getString(R.string.server_is_busy_try_again));\n                } else {\n                    nextView.onSearchFailed(nextView.getBaseContext().getString(R.string.server_is_busy_try_again));\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                nextView.onSearchFailed(errorMsg);\n            }\n        });\n    }\n\n    @Override\n    public void start() {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/add/next/AddFriendNextView.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.add.next;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * 项目名称：HTOpen\n * 类描述：AddFriendNextView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 17:24\n * 邮箱:814326663@qq.com\n */\npublic interface AddFriendNextView extends BaseView<AddFriendNextPrestener>{\n    String getInputString();\n    void onSearchSuccess(JSONObject object);\n    void onSearchFailed(String error);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/add/next/AddFriendsNextActivity.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.add.next;\n\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\n\n\npublic class AddFriendsNextActivity extends BaseActivity {\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_base_input);\n        AddFriendNextFragment fragment = (AddFriendNextFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (fragment == null){\n            fragment = new AddFriendNextFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame,fragment);\n            transaction.commit();\n        }\n        new AddFriendNextPrestener(fragment);\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/add/pre/AddFriendsPreActivity.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.add.pre;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.text.TextUtils;\nimport android.view.View;\nimport android.view.View.OnClickListener;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.activity.main.qrcode.QrCodeActivity;\nimport com.htmessage.yichatopen.activity.ScanCaptureActivity;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.activity.addfriends.add.next.AddFriendsNextActivity;\n\npublic class AddFriendsPreActivity extends BaseActivity implements OnClickListener{\n    private TextView tv_search,tv_fxid;\n    private RelativeLayout rl_leida,rl_jianqun,rl_sacn,rl_lianxiren,rl_ggh;\n    private ImageView iv_scode;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_addfriends_pre);\n        initUI();\n        setOnClick();\n    }\n\n    private void initUI() {\n        tv_search = (TextView) findViewById(R.id.tv_search);\n        tv_fxid = (TextView) findViewById(R.id.tv_fxid);\n        rl_leida = (RelativeLayout) findViewById(R.id.rl_leida);\n        rl_jianqun = (RelativeLayout) findViewById(R.id.rl_jianqun);\n        rl_sacn = (RelativeLayout) findViewById(R.id.rl_sacn);\n        rl_lianxiren = (RelativeLayout) findViewById(R.id.rl_lianxiren);\n        rl_ggh = (RelativeLayout) findViewById(R.id.rl_ggh);\n        iv_scode = (ImageView) findViewById(R.id.iv_scode);\n\n        JSONObject userJson = HTApp.getInstance().getUserJson();\n        if (userJson!=null){\n            String fxid = userJson.getString(HTConstant.JSON_KEY_FXID);\n            if (!TextUtils.isEmpty(fxid)){\n                tv_fxid.setText(getString(R.string.me_yichat_number)+fxid);\n            }else{\n                tv_fxid.setText(getString(R.string.me_yichat_number)+getString(R.string.not_set));\n            }\n        }\n    }\n    private void setOnClick() {\n        tv_search.setOnClickListener(this);\n        rl_leida.setOnClickListener(this);\n        rl_jianqun.setOnClickListener(this);\n        rl_sacn.setOnClickListener(this);\n        rl_lianxiren.setOnClickListener(this);\n        rl_ggh.setOnClickListener(this);\n        iv_scode.setOnClickListener(this);\n    }\n\n    @Override\n    public void onClick(View view) {\n        switch(view.getId()){\n            case R.id.tv_search:\n                startActivity(new Intent(AddFriendsPreActivity.this,AddFriendsNextActivity.class));\n                break;\n            case R.id.rl_leida:\n//                startActivity(new Intent(AddFriendsPreActivity.this,RadarActivity.class));\n                break;\n            case R.id.rl_jianqun:\n\n                break;\n            case R.id.rl_sacn:\n                startActivity(new Intent(AddFriendsPreActivity.this,ScanCaptureActivity.class));\n                break;\n            case R.id.rl_lianxiren:\n\n                break;\n            case R.id.rl_ggh:\n\n                break;\n            case R.id.iv_scode:\n                startActivity(new Intent(AddFriendsPreActivity.this,QrCodeActivity.class));\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/newfriend/NewFriendBasePresenter.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.newfriend;\n\nimport android.content.Context;\nimport com.htmessage.yichatopen.domain.InviteMessage;\nimport com.htmessage.yichatopen.activity.BasePresenter;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：NewFriendBasePresenter 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/4 9:40\n * 邮箱:814326663@qq.com\n */\npublic interface NewFriendBasePresenter extends BasePresenter{\n    List<InviteMessage> getAllInviteMessage();\n    void registerRecivier();\n    void startActivity(Context context, Class clazz);\n    void saveUnreadMessageCount(int count);\n    void refresh();\n    void onDestory();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/newfriend/NewFriendFragment.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.newfriend;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ListView;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.addfriends.add.next.AddFriendsNextActivity;\nimport com.htmessage.yichatopen.activity.addfriends.add.pre.AddFriendsPreActivity;\n\n/**\n * 项目名称：yichat0504\n * 类描述：NewFriendFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/4 17:17\n * 邮箱:814326663@qq.com\n */\npublic class NewFriendFragment extends Fragment implements NewFriendView,View.OnClickListener{\n    private ListView listView;\n    private TextView et_search, tv_add;\n    private NewFriendsAdapter adapter;\n    private NewFriendPrestener friendPrestener;\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View friendView = inflater.inflate(R.layout.activity_new_friends, container, false);\n        initView(friendView);\n        initData();\n        setListener();\n        return friendView;\n    }\n\n    private void initData() {\n        friendPrestener.registerRecivier();\n//         设置adapter\n        adapter = new NewFriendsAdapter(getBaseContext(),friendPrestener.getAllInviteMessage());\n        listView.setAdapter(adapter);\n        friendPrestener.saveUnreadMessageCount(0);\n    }\n\n    private void initView(View view) {\n        listView = (ListView) view.findViewById(R.id.listview);\n        et_search = (TextView) view.findViewById(R.id.et_search);\n        tv_add = (TextView) view.findViewById(R.id.tv_add);\n    }\n\n    private void setListener() {\n        et_search.setOnClickListener(this);\n        tv_add.setOnClickListener(this);\n    }\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.et_search:\n                friendPrestener.startActivity(getBaseActivity(),\n                        AddFriendsNextActivity.class);\n                break;\n            case R.id.tv_add:\n                friendPrestener.startActivity(getBaseActivity(),\n                        AddFriendsPreActivity.class);\n                break;\n        }\n    }\n\n    @Override\n    public void refresh() {\n        friendPrestener.refresh();\n        adapter.notifyDataSetChanged();\n        friendPrestener.saveUnreadMessageCount(0);\n    }\n\n    @Override\n    public void setPresenter(NewFriendPrestener presenter) {\n        this.friendPrestener = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void onDestroy() {\n        friendPrestener.onDestory();\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/newfriend/NewFriendPrestener.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.newfriend;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.support.v4.content.LocalBroadcastManager;\n\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.domain.InviteMessage;\nimport com.htmessage.yichatopen.domain.InviteMessgeDao;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：NewFriendPrestener 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/4 9:48\n * 邮箱:814326663@qq.com\n */\npublic class NewFriendPrestener implements NewFriendBasePresenter {\n    private NewFriendView newFriendView;\n    private InviteMessgeDao dao;\n    private NewFriendRecivier friendRecivier;\n    private List<InviteMessage> allInviteMessage;\n\n    public NewFriendPrestener(NewFriendView newFriendView) {\n        this.newFriendView = newFriendView;\n        this.newFriendView.setPresenter(this);\n        dao = new InviteMessgeDao(newFriendView.getBaseContext());\n        allInviteMessage = dao.getMessagesList();\n    }\n\n    @Override\n    public List<InviteMessage> getAllInviteMessage() {\n        return allInviteMessage;\n    }\n\n    @Override\n    public void registerRecivier() {\n        friendRecivier = new NewFriendRecivier();\n        IntentFilter intent = new IntentFilter(IMAction.ACTION_INVITE_MESSAGE);\n        LocalBroadcastManager.getInstance(newFriendView.getBaseContext()).registerReceiver(friendRecivier, intent);\n    }\n\n    @Override\n    public void startActivity(Context context, Class clazz) {\n        newFriendView.getBaseActivity().startActivity(new Intent(context, clazz));\n    }\n\n    private void unRegisterRecivier() {\n        if (friendRecivier != null) {\n            LocalBroadcastManager.getInstance(newFriendView.getBaseContext()).unregisterReceiver(friendRecivier);\n        }\n    }\n\n    @Override\n    public void saveUnreadMessageCount(int count) {\n        dao.saveUnreadMessageCount(count);\n    }\n\n    @Override\n    public void refresh() {\n        allInviteMessage.clear();\n        if (dao == null){\n            dao = new InviteMessgeDao(newFriendView.getBaseContext());\n        }\n        allInviteMessage.addAll(dao.getMessagesList());\n    }\n\n    @Override\n    public void onDestory() {\n        unRegisterRecivier();\n        newFriendView = null;\n    }\n\n\n    @Override\n    public void start() {\n\n    }\n    private class NewFriendRecivier extends BroadcastReceiver {\n\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            if (IMAction.ACTION_INVITE_MESSAGE.equals(intent.getAction())) {\n                newFriendView.refresh();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/newfriend/NewFriendView.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.newfriend;\n\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * 项目名称：yichat0504\n * 类描述：NewFriendView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/4 9:49\n * 邮箱:814326663@qq.com\n */\npublic interface NewFriendView extends BaseView<NewFriendPrestener> {\n        void refresh();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/newfriend/NewFriendsActivity.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.newfriend;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\nimport android.view.View;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.addfriends.add.next.AddFriendsNextActivity;\nimport com.htmessage.yichatopen.activity.BaseActivity;\n\n/**\n * 申请与通知\n */\npublic class NewFriendsActivity extends BaseActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_base);\n        setTitle(R.string.new_friend);\n        NewFriendFragment newFriendFragment =\n                (NewFriendFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (newFriendFragment == null) {\n            // Create the fragment\n            newFriendFragment =new  NewFriendFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame, newFriendFragment);\n            transaction.commit();\n        }\n        final NewFriendPrestener presenter=new NewFriendPrestener(newFriendFragment);\n        showRightView(R.drawable.add_icon, new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                startActivity(new Intent(NewFriendsActivity.this,\n                        AddFriendsNextActivity.class));\n            }\n        });\n    }\n\n    public void back(View v) {\n        setResult(Activity.RESULT_OK);\n        finish();\n    }\n\n    @Override\n    public void onBackPressed() {\n        setResult(Activity.RESULT_OK);\n        finish();\n        super.onBackPressed();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/addfriends/newfriend/NewFriendsAdapter.java",
    "content": "package com.htmessage.yichatopen.activity.addfriends.newfriend;\n\nimport android.app.Activity;\nimport android.app.ProgressDialog;\nimport android.content.ContentValues;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.View.OnClickListener;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.Button;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.domain.InviteMessgeDao;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.domain.UserDao;\nimport com.htmessage.yichatopen.domain.InviteMessage;\nimport com.htmessage.yichatopen.domain.InviteMessage.Status;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.manager.HTChatManager;\nimport com.htmessage.sdk.model.CmdMessage;\nimport com.htmessage.yichatopen.widget.HTAlertDialog;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.UUID;\n\npublic class NewFriendsAdapter extends BaseAdapter {\n    private Context context;\n    private List<InviteMessage> msgs;\n    private InviteMessgeDao messgeDao;\n    int total = 0;\n\n    public NewFriendsAdapter(Context _context, List<InviteMessage> msgs) {\n        this.context = _context;\n        this.msgs = msgs;\n        messgeDao = new InviteMessgeDao(context);\n        total = msgs.size();\n    }\n\n    @Override\n    public int getCount() {\n        return msgs.size();\n    }\n\n    @Override\n    public InviteMessage getItem(int position) {\n        return msgs.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n\n    @Override\n    public View getView(final int position, View convertView, ViewGroup parent) {\n        if (convertView == null) {\n            convertView = View.inflate(context, R.layout.item_newfriend_msg, null);\n\n        }\n        ViewHolder holder = (ViewHolder) convertView.getTag();\n        if (holder == null) {\n            holder = new ViewHolder();\n            holder.iv_avatar = (ImageView) convertView.findViewById(R.id.iv_avatar);\n            holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);\n            holder.tv_reason = (TextView) convertView.findViewById(R.id.tv_reason);\n            holder.tv_added = (TextView) convertView.findViewById(R.id.tv_added);\n            holder.btn_add = (Button) convertView.findViewById(R.id.btn_add);\n            holder.rl_item_add = (RelativeLayout) convertView.findViewById(R.id.rl_item_add);\n            convertView.setTag(holder);\n        }\n\n\n//        final InviteMessage msg = getItem(total - 1 - position);\n        final InviteMessage msg = getItem(position);\n//        String reason = context.getString(R.string.request_add_friend);\n        String reason = context.getString(R.string.Reasons);\n        String nick = msg.getFrom();\n        JSONObject userInfo = null;\n        try {\n            userInfo = JSONObject.parseObject(msg.getReason());\n            Log.d(\"slj\", \"----获取好友信息:\" + userInfo.toJSONString());\n            if (userInfo != null) {\n                nick = userInfo.getString(\"nick\");\n                String avatar = userInfo.getString(\"avatar\");\n                if (!TextUtils.isEmpty(avatar)) {\n                    if (!avatar.contains(\"http\")) {\n                        avatar = HTConstant.URL_AVATAR + avatar;\n                    }\n                }\n                Glide.with(context).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(holder.iv_avatar);\n                //TODO  在申请消息的jsonobject里面是传有申请理由的，后续开发者可以按照需求处理这个申请理由\n                String reasonTemp = userInfo.getString(HTConstant.CMD_ADD_REASON);\n                if (!TextUtils.isEmpty(reasonTemp)) {\n                    reason = reason + reasonTemp;\n                } else {\n                    reason = context.getString(R.string.Request_to_add_you_as_a_friend);\n                }\n            }\n        } catch (JSONException e) {\n            e.printStackTrace();\n        }\n        holder.tv_name.setText(nick);\n        holder.tv_reason.setText(reason);\n        if (msg.getStatus() == InviteMessage.Status.AGREED) {\n            holder.tv_added.setVisibility(View.VISIBLE);\n            holder.btn_add.setVisibility(View.GONE);\n        } else if (msg.getStatus() == InviteMessage.Status.REFUSED) {\n            holder.tv_added.setText(context.getString(R.string.Refused));\n            holder.tv_added.setVisibility(View.VISIBLE);\n            holder.btn_add.setVisibility(View.GONE);\n        } else if (msg.getStatus() == InviteMessage.Status.BEREFUSED) {\n            holder.tv_added.setText(context.getString(R.string.has_rejected));\n            holder.tv_reason.setText(context.getString(R.string.already_rejected));\n            holder.tv_added.setVisibility(View.VISIBLE);\n            holder.btn_add.setVisibility(View.GONE);\n        } else if (msg.getStatus() == InviteMessage.Status.BEAGREED) {\n            holder.tv_reason.setText(context.getString(R.string.Has_agreed_to_your_friend_request));\n            holder.tv_added.setVisibility(View.VISIBLE);\n            holder.btn_add.setVisibility(View.GONE);\n        } else {\n            holder.tv_added.setVisibility(View.GONE);\n            holder.btn_add.setVisibility(View.VISIBLE);\n            holder.btn_add.setTag(msg);\n            final ViewHolder finalHolder = holder;\n            final JSONObject finalUserInfo = userInfo;\n            if (finalUserInfo != null) {\n                holder.btn_add.setOnClickListener(new OnClickListener() {\n                    @Override\n                    public void onClick(View v) {\n                        acceptInvitation(finalHolder.btn_add, msg, finalHolder.tv_added, finalUserInfo);\n                    }\n\n                });\n            }\n        }\n        holder.rl_item_add.setOnClickListener(new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                String from = msg.getFrom();\n                context.startActivity(new Intent(context, UserDetailsActivity.class).putExtra(HTConstant.JSON_KEY_HXID,from));\n            }\n        });\n        holder.rl_item_add.setOnLongClickListener(new View.OnLongClickListener() {\n            @Override\n            public boolean onLongClick(View v) {\n                deleteInviteMessge(msg);\n                return true;\n            }\n        });\n        return convertView;\n    }\n\n    private static class ViewHolder {\n        ImageView iv_avatar;\n        TextView tv_name;\n        TextView tv_reason;\n        TextView tv_added;\n        Button btn_add;\n        RelativeLayout rl_item_add;\n    }\n\n    /**\n     * 同意好友请求\n     *\n     * @param button\n     * @param\n     */\n    private void acceptInvitation(final Button button, final InviteMessage msg,\n                                  final TextView textview, final JSONObject userInfo) {\n        final ProgressDialog pd = new ProgressDialog(context);\n        pd.setMessage(context.getString(R.string.Are_agree_with));\n        pd.setCanceledOnTouchOutside(false);\n        pd.show();\n        List<Param> params = new ArrayList<>();\n        params.add(new Param(\"userId\", msg.getFrom()));\n        new OkHttpUtils(context).post(params, HTConstant.URL_ADD_FRIEND, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                int code = jsonObject.getInteger(\"code\");\n                switch (code){\n                    case 1:\n                        User user = CommonUtils.Json2User(userInfo);\n                        // 存入内存\n                        ContactsManager.getInstance().getContactList().put(user.getUsername(), user);\n                        // 存入db\n                        UserDao dao = new UserDao(context);\n                        dao.saveContact(user);\n                        LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(IMAction.ACTION_CONTACT_CHANAGED));\n                        sendCmdAgreeMsg(button, msg, textview, pd);\n                        break;\n                    default:\n                        pd.dismiss();\n                        Toast.makeText(context,\n                                context.getString(R.string.add_friend_failed), Toast.LENGTH_SHORT)\n                                .show();\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                pd.dismiss();\n            }\n        });\n    }\n\n\n    private void sendCmdAgreeMsg(final Button button, final InviteMessage msg,\n                                 final TextView textview, final ProgressDialog pd) {\n        JSONObject userJson = HTApp.getInstance().getUserJson();\n        JSONObject jsonObject = new JSONObject();\n        jsonObject.put(\"action\", 1001);\n        JSONObject data = new JSONObject();\n        data.put(\"userId\", userJson.getString(\"userId\"));\n        data.put(\"nick\", userJson.getString(\"nick\"));\n        data.put(\"avatar\",userJson.getString(\"avatar\"));\n        data.put(\"role\",userJson.getString(HTConstant.JSON_KEY_ROLE));\n        data.put(\"teamId\",userJson.getString(\"teamId\"));\n        jsonObject.put(\"data\", data);\n        CmdMessage customMessage = new CmdMessage();\n        customMessage.setMsgId(UUID.randomUUID().toString());\n        customMessage.setFrom(HTApp.getInstance().getUsername());\n        customMessage.setTime(System.currentTimeMillis());\n        customMessage.setTo(msg.getFrom());\n        customMessage.setBody(jsonObject.toJSONString());\n        customMessage.setChatType(ChatType.singleChat);\n        HTClient.getInstance().chatManager().sendCmdMessage(customMessage, new HTChatManager.HTMessageCallBack() {\n            @Override\n            public void onProgress() {\n\n            }\n\n            @Override\n            public void onSuccess() {\n                ((Activity)context).runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (pd != null) {\n                            pd.dismiss();\n                        }\n                        Toast.makeText(context, context.getString(R.string.add_friend_success), Toast.LENGTH_SHORT)\n                                .show();\n                    }\n                });\n\n            }\n\n            @Override\n            public void onFailure() {\n                ((Activity)context).runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        if (pd != null) {\n                            pd.dismiss();\n                        }\n                        Toast.makeText(context,\n                              context.getString(R.string.add_friend_failed), Toast.LENGTH_SHORT)\n                                .show();\n                    }\n                });\n\n            }\n        });\n\n        textview.setVisibility(View.VISIBLE);\n        button.setEnabled(false);\n        button.setVisibility(View.GONE);\n        msg.setStatus(Status.AGREED);\n        // 更新db\n        ContentValues values = new ContentValues();\n        values.put(InviteMessgeDao.COLUMN_NAME_STATUS, msg\n                .getStatus().ordinal());\n        messgeDao.updateMessage(msg.getId(), values);\n\n    }\n\n    /**\n     * 删除透传消息\n     * @param msg\n     */\n    private void deleteInviteMessge(final InviteMessage msg){\n        HTAlertDialog dialog = new HTAlertDialog(context,null,new String[]{context.getString(R.string.delete)});\n        dialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                switch (position){\n                    case 0:\n                        msgs.remove(msg);\n                        messgeDao.deleteMessage(msg.getFrom());\n                        notifyDataSetChanged();\n                        break;\n                }\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/ChatActivity.java",
    "content": "package com.htmessage.yichatopen.activity.chat;\n\nimport android.app.ActivityManager;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.view.View;\nimport com.htmessage.sdk.utils.MessageUtils;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.manager.MyNotification;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.activity.chat.activity.ChatSettingActivity;\nimport com.htmessage.yichatopen.activity.main.MainActivity;\nimport java.util.List;\n\n/**\n *\n */\npublic class ChatActivity extends BaseActivity {\n    public static ChatActivity activityInstance;\n    private ChatFragment chatFragment;\n    public String toChatUsername;\n    public int chatType;\n\n    @Override\n    protected void onCreate(Bundle arg0) {\n        super.onCreate(arg0);\n        setContentView(R.layout.activity_base);\n        activityInstance = this;\n        toChatUsername = getIntent().getExtras().getString(\"userId\");\n        chatType = getIntent().getExtras().getInt(\"chatType\", MessageUtils.CHAT_SINGLE);\n        if (chatType == MessageUtils.CHAT_SINGLE) {\n            User user = ContactsManager.getInstance().getContactList().get(toChatUsername);\n            setTitle(user.getNick());\n            showRightView(R.drawable.icon_setting_single, new View.OnClickListener() {\n                @Override\n                public void onClick(View v) {\n                    startActivity(new Intent(ChatActivity.this, ChatSettingActivity.class).putExtra(\"userId\", toChatUsername));\n                }\n            });\n\n        }\n        chatFragment = new ChatFragment();\n        chatFragment.setArguments(getIntent().getExtras());\n        getSupportFragmentManager().beginTransaction().add(R.id.contentFrame, chatFragment).commit();\n        MyNotification.getInstance().cancel(Integer.parseInt(toChatUsername));\n    }\n\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        activityInstance = null;\n    }\n\n    @Override\n    protected void onNewIntent(Intent intent) {\n\n        String username = intent.getStringExtra(\"userId\");\n        if (toChatUsername.equals(username))\n            super.onNewIntent(intent);\n        else {\n            finish();\n            startActivity(intent);\n        }\n\n    }\n\n    @Override\n    public void onBackPressed() {\n        chatFragment.onBackPressed();\n        if (isSingleActivity(this)) {\n            Intent intent = new Intent(this, MainActivity.class);\n            startActivity(intent);\n        }\n    }\n\n\n    public boolean isSingleActivity(Context context) {\n        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n        List list = activityManager.getRunningTasks(1);\n        return ((ActivityManager.RunningTaskInfo) list.get(0)).numRunning == 1;\n    }\n\n    public String getToChatUsername() {\n        return toChatUsername;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/ChatAdapter.java",
    "content": "package com.htmessage.yichatopen.activity.chat;\n\nimport android.app.Activity;\nimport android.app.AlertDialog;\nimport android.app.Dialog;\nimport android.content.Intent;\nimport android.graphics.Bitmap;\nimport android.graphics.drawable.AnimationDrawable;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ImageView;\nimport android.widget.ProgressBar;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.activity.chat.weight.VoicePlayClickListener;\nimport com.htmessage.yichatopen.activity.chat.weight.emoji.SmileUtils;\nimport com.htmessage.yichatopen.utils.ACache;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.DateUtils;\n import com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.model.HTMessageBody;\nimport com.htmessage.sdk.model.HTMessageImageBody;\nimport com.htmessage.sdk.model.HTMessageTextBody;\nimport com.htmessage.sdk.model.HTMessageVoiceBody;\nimport com.htmessage.sdk.utils.MessageUtils;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.yichatopen.utils.PathUtils;\nimport com.htmessage.yichatopen.utils.ImageUtils;\nimport com.htmessage.yichatopen.activity.ShowBigImageActivity;\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\n\n/**\n * Created by huangfangyi on 2016/11/24.\n * qq 84543217\n */\n\npublic class ChatAdapter extends BaseAdapter {\n    private List<HTMessage> msgs;\n    private Activity context;\n    private LayoutInflater inflater;\n    private static final int MESSAGE_TEXT_RECEIVED = 0;\n    private static final int MESSAGE_TEXT_SEND = 1;\n    private static final int MESSAGE_IMAGE_RECEIVED = 2;\n    private static final int MESSAGE_IMAGE_SEND = 3;\n    private static final int MESSAGE_VOICE_RECEIVED = 4;\n    private static final int MESSAGE_VOICE_SEND = 5;\n\n    private String chatTo;\n    private int chatType;\n    private List<HTMessage> imageMsgs = new ArrayList<>();\n    private ChatFragment fragment;\n    public ChatAdapter(List<HTMessage> msgs, ChatFragment fragment, String chatTo, int chatType) {\n        this.msgs = msgs;\n        this.context = fragment.getActivity();\n        this.fragment=fragment;\n        inflater = LayoutInflater.from(context);\n        this.chatTo = chatTo;\n        this.chatType = chatType;\n        imageMsgs.clear();\n        for (int i = 0; i < msgs.size(); i++) {\n            HTMessage emMessage = msgs.get(i);\n            if (emMessage.getType() == HTMessage.Type.IMAGE) {\n                imageMsgs.add(emMessage);\n            }\n        }\n\n    }\n\n    @Override\n    public int getCount() {\n        return msgs.size();\n    }\n\n    @Override\n    public HTMessage getItem(int position) {\n        return msgs.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @Override\n    public int getItemViewType(int position) {\n        HTMessage message = getItem(position);\n        return getItemViewType(message);\n\n    }\n\n    @Override\n    public void notifyDataSetChanged() {\n        super.notifyDataSetChanged();\n        for (int i = 0; i < msgs.size(); i++) {\n            HTMessage emMessage = msgs.get(i);\n            if (emMessage.getType() == HTMessage.Type.IMAGE) {\n                if (!imageMsgs.contains(emMessage)) {\n                    imageMsgs.add(emMessage);\n                }\n            }\n        }\n\n    }\n\n    @Override\n    public int getViewTypeCount() {\n        return 14;\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        HTMessage message = getItem(position);\n        int viewType = getItemViewType(position);\n        if (convertView == null) {\n            convertView = getViewByType(viewType, parent);\n        }\n        ChatViewHolder holder = (ChatViewHolder) convertView.getTag();\n        if (holder == null) {\n            holder = new ChatViewHolder();\n            handleViewAndHolder(viewType, convertView, holder, message);\n        }\n        handleData(holder, viewType, message, position);\n\n        return convertView;\n    }\n\n\n    private int getItemViewType(HTMessage htMessage) {\n        HTMessage.Type type = htMessage.getType();\n        if (type == HTMessage.Type.TEXT) {\n            return htMessage.getDirect() == HTMessage.Direct.RECEIVE ? MESSAGE_TEXT_RECEIVED : MESSAGE_TEXT_SEND;\n        } else if (type == HTMessage.Type.IMAGE) {\n            return htMessage.getDirect() == HTMessage.Direct.RECEIVE ? MESSAGE_IMAGE_RECEIVED : MESSAGE_IMAGE_SEND;\n        } else if (type == HTMessage.Type.VOICE) {\n            return htMessage.getDirect() == HTMessage.Direct.RECEIVE ? MESSAGE_VOICE_RECEIVED : MESSAGE_VOICE_SEND;\n        }\n        return 0;\n\n    }\n\n\n    private View getViewByType(int viewType, ViewGroup parent) {\n        switch (viewType) {\n            case MESSAGE_TEXT_RECEIVED:\n                return inflater.inflate(R.layout.row_received_message, parent, false);\n            case MESSAGE_IMAGE_RECEIVED:\n                return inflater.inflate(R.layout.row_received_picture, parent, false);\n            case MESSAGE_VOICE_RECEIVED:\n                return inflater.inflate(R.layout.row_received_voice, parent, false);\n            case MESSAGE_TEXT_SEND:\n                return inflater.inflate(R.layout.row_sent_message, parent, false);\n            case MESSAGE_IMAGE_SEND:\n                return inflater.inflate(R.layout.row_sent_picture, parent, false);\n            case MESSAGE_VOICE_SEND:\n                return inflater.inflate(R.layout.row_sent_voice, parent, false);\n            default:\n                return inflater.inflate(R.layout.row_sent_message, parent, false);\n        }\n    }\n\n\n    private void handleViewAndHolder(int viewType, View convertView, ChatViewHolder holder, final HTMessage htMessage) {\n        holder.reBubble = (RelativeLayout) convertView.findViewById(R.id.bubble);\n        holder.reBubble.setOnLongClickListener(new View.OnLongClickListener() {\n            @Override\n            public boolean onLongClick(View v) {\n                return false;\n            }\n        });\n        holder.ivAvatar = (ImageView) convertView.findViewById(R.id.iv_userhead);\n        holder.timeStamp = (TextView) convertView.findViewById(R.id.timestamp);\n        holder.tv_ack_msg = (TextView) convertView.findViewById(R.id.tv_ack_msg);\n        holder.tv_delivered = (TextView) convertView.findViewById(R.id.tv_delivered);\n        if (htMessage.getDirect() == HTMessage.Direct.RECEIVE) {\n            //接收消息,可以显示成员名称\n            holder.tvNick = (TextView) convertView.findViewById(R.id.tv_userid);\n        } else {\n            holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar);\n            holder.ivMsgStatus = (ImageView) convertView.findViewById(R.id.msg_status);\n        }\n\n        if (htMessage.getType() == HTMessage.Type.TEXT) {\n            holder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);\n        }\n        if (viewType == MESSAGE_IMAGE_SEND || viewType == MESSAGE_IMAGE_RECEIVED) {\n            holder.ivContent = (ImageView) convertView.findViewById(R.id.image);\n        }\n        if (viewType == MESSAGE_VOICE_SEND || viewType == MESSAGE_VOICE_RECEIVED) {\n            holder.tvDuration = (TextView) convertView.findViewById(R.id.tv_length);\n            holder.ivVoice = (ImageView) convertView.findViewById(R.id.iv_voice);\n            if (viewType == MESSAGE_VOICE_RECEIVED) {\n                holder.ivUnread = (ImageView) convertView.findViewById(R.id.iv_unread_voice);\n            }\n        }\n        if (htMessage.getType() == HTMessage.Type.TEXT) {\n            holder.reMain = (RelativeLayout) convertView.findViewById(R.id.re_main);\n        }\n        holder.ivAvatar.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                JSONObject jsonObject = htMessage.getAttributes();\n                if (jsonObject!=null){\n                    context.startActivity(new Intent(context, UserDetailsActivity.class).putExtra(HTConstant.KEY_USER_INFO,jsonObject.toJSONString()));\n                }\n            }\n        });\n        convertView.setTag(holder);\n\n    }\n\n\n    private void handleData(ChatViewHolder holder, int viewType, final HTMessage message, int position) {\n\n        if (message.getDirect() == HTMessage.Direct.SEND && message.getStatus() == HTMessage.Status.FAIL) {\n            holder.ivMsgStatus.setOnClickListener(new View.OnClickListener() {\n                @Override\n                public void onClick(View v) {\n                    showReSendDialog(message);\n                }\n            });\n        }\n        HTMessageBody htMessageBody = message.getBody();\n        if (htMessageBody == null) {\n            return;\n        }\n        if (position == 0) {\n            holder.timeStamp.setText(DateUtils.getTimestampString(new Date(message\n                    .getTime())));\n            holder.timeStamp.setVisibility(View.VISIBLE);\n        } else {\n            // 两条消息时间离得如果稍长，显示时间\n            if (DateUtils.isCloseEnough(message.getTime(), getItem(position - 1).getTime())) {\n                holder.timeStamp.setVisibility(View.GONE);\n            } else {\n                holder.timeStamp.setText(DateUtils.getTimestampString(new Date(\n                        message.getTime())));\n                holder.timeStamp.setVisibility(View.VISIBLE);\n            }\n        }\n\n        if (chatType == MessageUtils.CHAT_GROUP && message.getDirect() == HTMessage.Direct.RECEIVE) {\n            holder.tvNick.setVisibility(View.VISIBLE);\n\n        } else if (chatType == MessageUtils.CHAT_SINGLE && message.getDirect() == HTMessage.Direct.RECEIVE) {\n            holder.tvNick.setVisibility(View.GONE);\n        }\n        String avatar = message.getStringAttribute(HTConstant.JSON_KEY_AVATAR);\n        if (message.getDirect() == HTMessage.Direct.SEND){\n            if (message.getFrom().equals(HTApp.getInstance().getUsername())){\n                JSONObject userJson = HTApp.getInstance().getUserJson();\n                if (userJson.containsKey(HTConstant.JSON_KEY_AVATAR)){\n                    avatar = userJson.getString(HTConstant.JSON_KEY_AVATAR);\n                }\n            }\n        }\n        Glide.with(context).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(holder.ivAvatar);\n        HTMessage.Status status = message.getStatus();\n        if (message.getDirect() == HTMessage.Direct.SEND) {\n            if (status == HTMessage.Status.CREATE) {\n                holder.progressBar.setVisibility(View.VISIBLE);\n            } else {\n                holder.progressBar.setVisibility(View.GONE);\n            }\n            if (status == HTMessage.Status.FAIL) {\n                holder.ivMsgStatus.setVisibility(View.VISIBLE);\n            } else {\n                holder.ivMsgStatus.setVisibility(View.GONE);\n            }\n//            if (status == HTMessage.Status.SUCCESS){\n//                holder.tv_delivered.setVisibility(View.VISIBLE);\n//            } else {\n//                holder.tv_delivered.setVisibility(View.INVISIBLE);\n//            }\n        }\n        if (message.getType() == HTMessage.Type.TEXT) {\n            int action = message.getIntAttribute(\"action\", 0);\n             if (action == 3000) {\n\n            } else if (action == 6001) {\n                holder.timeStamp.setVisibility(View.VISIBLE);\n                holder.reMain.setVisibility(View.GONE);\n                holder.timeStamp.setText(((HTMessageTextBody) htMessageBody).getContent());\n            } else {\n                holder.reMain.setVisibility(View.VISIBLE);\n                holder.tvContent.setText(SmileUtils.getSmiledText(context, ((HTMessageTextBody) htMessageBody).getContent()),\n                        TextView.BufferType.SPANNABLE);\n            }\n        }\n        if (message.getType() == HTMessage.Type.IMAGE) {\n            showImageView(message, holder, true, false);\n        } else if (message.getType() == HTMessage.Type.VOICE) {\n            showVoiceView(message, holder);\n        }\n    }\n\n    private void showImageView(final HTMessage htMessage, ChatViewHolder holder, boolean isReSize, boolean isLocMsg) {\n        if (!isReSize) {\n            holder.ivContent.setImageResource(R.drawable.ht_location);\n        } else {\n            holder.ivContent.setImageResource(R.drawable.default_image);\n        }\n        String localPath = null;\n        if (!isLocMsg) {\n            HTMessageImageBody htMessageImageBody = (HTMessageImageBody) htMessage.getBody();\n            localPath = htMessageImageBody.getLocalPath();\n        }\n        if (!TextUtils.isEmpty(localPath)) {\n            Bitmap bitmap = ACache.get(context.getApplicationContext()).getAsBitmap(htMessage.getMsgId());\n            if (bitmap == null) {\n                Log.d(\"bitmap3---->\", \"null\");\n                if (new File(localPath).exists()) {\n                    bitmap = ImageUtils.decodeScaleImage(localPath);\n                    if (bitmap != null) {\n                        ACache.get(context.getApplicationContext()).put(htMessage.getMsgId(), bitmap);\n                        holder.ivContent.setImageBitmap(bitmap);\n                    }\n                } else {\n                    downLoadImageFromServer(htMessage, holder.ivContent, isReSize, isLocMsg);\n                }\n\n            } else {\n                holder.ivContent.setImageBitmap(bitmap);\n            }\n        } else {\n            downLoadImageFromServer(htMessage, holder.ivContent, isReSize, isLocMsg);\n        }\n\n\n        final String finalLocalPath = localPath;\n        holder.reBubble.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (finalLocalPath == null || !new File(finalLocalPath).exists()) {\n                    downLoadBigImageAndOpen(htMessage);\n                } else {\n                    context.startActivity(new Intent(context, ShowBigImageActivity.class).putExtra(\"localPath\", finalLocalPath));\n                }\n            }\n        });\n    }\n\n\n    private void downLoadImageFromServer(final HTMessage htMessage, final ImageView imageView, boolean isReSize, final boolean isLocMsg) {\n        //下载缩略图,显示并且保存至缓存.\n        String remotePath = null;\n        String fileName = null;\n        if (!isLocMsg) {\n            HTMessageImageBody htMessageImageBody = (HTMessageImageBody) htMessage.getBody();\n            remotePath = htMessageImageBody.getRemotePath();\n            fileName = htMessageImageBody.getFileName();\n        }\n        if (!TextUtils.isEmpty(remotePath)) {\n            if (isReSize) {\n                remotePath = remotePath + HTConstant.baseImgUrl_set;\n\n            }\n\n            PathUtils pathUtils = new PathUtils(chatTo, context);\n\n            final String filePath = pathUtils.getImagePath().getAbsolutePath() + \"/mini\" + fileName;\n            new OkHttpUtils(context).loadFile(remotePath, filePath, new OkHttpUtils.DownloadCallBack() {\n                @Override\n                public void onSuccess() {\n                    if (new File(filePath).exists()) {\n\n                        final Bitmap bitmap = ImageUtils.decodeScaleImage(filePath);\n                        if (!isLocMsg) {\n\n                            HTMessageImageBody htMessageImageBody = (HTMessageImageBody) htMessage.getBody();\n                            htMessageImageBody.setLocalPath(filePath);\n                            htMessage.setBody(htMessageImageBody);\n                        }\n                        HTClient.getInstance().messageManager().saveMessage(htMessage, false);\n                        ACache.get(context.getApplicationContext()).put(htMessage.getMsgId(), bitmap);\n\n                        ((Activity) context).runOnUiThread(new Runnable() {\n                            @Override\n                            public void run() {\n                                imageView.setImageBitmap(bitmap);\n                            }\n                        });\n                    }\n                }\n\n                @Override\n                public void onFailure(String message) {\n\n                }\n            });\n        }\n    }\n\n    private void downLoadBigImageAndOpen(final HTMessage htMessage) {\n        final HTMessageImageBody htMessageImageBody = (HTMessageImageBody) htMessage.getBody();\n\n        String remotePath = htMessageImageBody.getRemotePath();\n        String fileName = htMessageImageBody.getFileName();\n        if (TextUtils.isEmpty(remotePath) || TextUtils.isEmpty(fileName)) {\n            return;\n        }\n        final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(context, context.getString(R.string.loading));\n        progressDialog.show();\n        PathUtils pathUtils = new PathUtils(chatTo, context);\n        final String filePath = pathUtils.getImagePath().getAbsolutePath() + \"/\" + fileName;\n        new OkHttpUtils(context).loadFile(remotePath, filePath, new OkHttpUtils.DownloadCallBack() {\n            @Override\n            public void onSuccess() {\n                (context).runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        progressDialog.dismiss();\n                    }\n                });\n                if (new File(filePath).exists()) {\n                    final Bitmap bitmap = ImageUtils.decodeScaleImage(filePath);\n                    ACache.get(context.getApplicationContext()).put(htMessage.getMsgId(), bitmap);\n                    htMessageImageBody.setLocalPath(filePath);\n                    htMessage.setBody(htMessageImageBody);\n                    (context).runOnUiThread(new Runnable() {\n                        @Override\n                        public void run() {\n                            notifyDataSetChanged();\n                        }\n                    });\n                    HTClient.getInstance().messageManager().saveMessage(htMessage, false);\n                    context.startActivity(new Intent(context, ShowBigImageActivity.class).putExtra(\"localPath\", filePath));\n                }\n            }\n\n            @Override\n            public void onFailure(String message) {\n                (context).runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        progressDialog.dismiss();\n                    }\n                });\n            }\n        });\n    }\n\n\n    private void showVoiceView(final HTMessage htMessage, final ChatViewHolder holder) {\n        HTMessageVoiceBody htMessageVoiceBody = (HTMessageVoiceBody) htMessage.getBody();\n\n        if (htMessageVoiceBody == null) {\n            return;\n        }\n        int len = htMessageVoiceBody.getAudioDuration();\n\n        if (len > 0) {\n            holder.tvDuration.setText(len + \"\\\"\");\n            holder.tvDuration.setVisibility(View.VISIBLE);\n        } else {\n            holder.tvDuration.setVisibility(View.INVISIBLE);\n        }\n        if (VoicePlayClickListener.playMsgId != null\n                && VoicePlayClickListener.playMsgId.equals(htMessage.getMsgId()) && VoicePlayClickListener.isPlaying) {\n            AnimationDrawable voiceAnimation;\n            if (htMessage.getDirect() == HTMessage.Direct.RECEIVE) {\n                holder.ivVoice.setImageResource(R.anim.voice_from_icon);\n            } else {\n                holder.ivVoice.setImageResource(R.anim.voice_to_icon);\n            }\n            voiceAnimation = (AnimationDrawable) holder.ivVoice.getDrawable();\n            voiceAnimation.start();\n        } else {\n            if (htMessage.getDirect() == HTMessage.Direct.RECEIVE) {\n                holder.ivVoice.setImageResource(R.drawable.chatfrom_voice_playing);\n            } else {\n                holder.ivVoice.setImageResource(R.drawable.chatto_voice_playing);\n            }\n        }\n\n        if (htMessage.getDirect() == HTMessage.Direct.RECEIVE) {\n            if (htMessage.getStatus() == HTMessage.Status.SUCCESS) {\n                holder.ivUnread.setVisibility(View.INVISIBLE);\n            } else {\n                holder.ivUnread.setVisibility(View.VISIBLE);\n            }\n        }\n\n        holder.reBubble.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                new VoicePlayClickListener(htMessage, chatTo, holder.ivVoice, holder.ivUnread, ChatAdapter.this, (context)).onClick(holder.reBubble);\n            }\n        });\n        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {\n            holder.reBubble.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {\n                @Override\n                public void onViewAttachedToWindow(View v) {\n\n                }\n\n                @Override\n                public void onViewDetachedFromWindow(View v) {\n                    if (VoicePlayClickListener.currentPlayListener != null && VoicePlayClickListener.isPlaying) {\n                        VoicePlayClickListener.currentPlayListener.stopPlayVoice();\n                    }\n                }\n            });\n        }\n    }\n\n    public static class ChatViewHolder {\n\n        public RelativeLayout reMain;\n        public RelativeLayout reBubble;\n\n        public ImageView ivAvatar;\n        public TextView tvNick;\n        public TextView timeStamp;\n        public ImageView ivMsgStatus;\n        //文本消息,位置消息,文件消息\n        public TextView tvContent;\n        //图片消息,视频消息,位置消息,文件消息\n        public ImageView ivContent;\n        //语音消息\n        public TextView tvDuration;\n        public ImageView ivUnread;\n        public ImageView ivVoice;\n        //发送消息\n        public ProgressBar progressBar;\n        //已读显示\n        public TextView tv_ack_msg;\n        //送达显示\n        public TextView tv_delivered;\n    }\n\n    /**\n     * 重新发送消息\n     *\n     * @param htMessage\n     */\n    private void showReSendDialog(final HTMessage htMessage) {\n        AlertDialog.Builder buidler = new AlertDialog.Builder(context);\n        View view = View.inflate(context, R.layout.item_diaolog_gridview, null);\n        TextView tv_forward = (TextView) view.findViewById(R.id.tv_forward);\n        TextView textView = (TextView) view.findViewById(R.id.textView);\n        TextView tv_ok = (TextView) view.findViewById(R.id.tv_ok);\n        TextView tv_cancel = (TextView) view.findViewById(R.id.tv_cancel);\n        final ImageView imageView = (ImageView) view.findViewById(R.id.imageView);\n        imageView.setVisibility(View.GONE);\n        tv_forward.setText(R.string.prompt);\n        textView.setText(R.string.resend_text);\n        buidler.setView(view);\n        final AlertDialog dialog = buidler.show();\n        tv_ok.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n                msgs.remove(htMessage);\n                notifyDataSetChanged();\n                HTClient.getInstance().messageManager().deleteMessage(htMessage.getUsername(), htMessage.getMsgId());\n                htMessage.setLocalTime(System.currentTimeMillis());\n                htMessage.setStatus(HTMessage.Status.CREATE);\n                fragment.sendMessage(htMessage);\n            }\n        });\n        tv_cancel.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n            }\n        });\n    }\n\n\n}\n\n\n\n\n \n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/ChatContract.java",
    "content": "package com.htmessage.yichatopen.activity.chat;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * Created by dell on 2017/7/1.\n */\n\npublic interface ChatContract {\n\n    interface  View extends BaseView<Presenter>{\n       //长按消息体出现的dialog\n       void showItemDialog();\n        //标题栏\n        void showTitle(String title);\n        //隐藏输入法\n        void hideKeyboard();\n        //显示输入法\n        void showKeyboard();\n        //显示录音UI\n        void showSpeakerMode();\n        //显示输入文字状态\n        void showInputMode();\n        //显示更多消息类型\n        void showExtendMenuItem();\n        //显示表情UI\n        void showEmojiView();\n    }\n\n    interface Presenter extends BasePresenter{\n\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/ChatFragment.java",
    "content": "package com.htmessage.yichatopen.activity.chat;\n\nimport android.app.Activity;\nimport android.app.AlertDialog;\nimport android.app.ProgressDialog;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.database.Cursor;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.graphics.Matrix;\nimport android.media.ExifInterface;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.provider.MediaStore;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.ImageView;\nimport android.widget.ListView;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.manager.HTChatManager;\nimport com.htmessage.sdk.model.CmdMessage;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.sdk.model.HTMessageImageBody;\nimport com.htmessage.sdk.model.HTMessageVoiceBody;\nimport com.htmessage.sdk.utils.MessageUtils;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.IMAction;\n\nimport com.htmessage.yichatopen.activity.chat.weight.emoji.Emojicon;\nimport com.htmessage.yichatopen.activity.chat.weight.ChatInputView;\nimport com.htmessage.yichatopen.activity.chat.weight.loadmore.PullToLoadMoreListView;\nimport com.htmessage.yichatopen.utils.ACache;\nimport com.htmessage.yichatopen.utils.HTMessageUtils;\nimport com.htmessage.yichatopen.utils.PathUtils;\nimport com.htmessage.yichatopen.activity.chat.weight.ChatExtendMenu;\nimport com.htmessage.yichatopen.widget.HTAlertDialog;\nimport com.htmessage.yichatopen.activity.chat.weight.VoiceRecorderView;\nimport com.htmessage.yichatopen.utils.CommonUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.List;\n\n\npublic class ChatFragment extends Fragment {\n\n    private static final int REQUEST_CODE_CAMERA = 2;\n    private static final int REQUEST_CODE_LOCAL = 3;\n    /**\n     * params to fragment\n     */\n    private Bundle fragmentArgs;\n    private int chatType;\n    private String toChatUsername;\n    private File cameraFile;\n    private ListView listView;\n    static final int ITEM_TAKE_PICTURE = 1;\n    static final int ITEM_PICTURE = 2;\n\n    private int[] itemStrings = {R.string.attach_take_pic, R.string.attach_picture};\n    private int[] itemdrawables = {R.drawable.chat_takepic_selector, R.drawable.chat_image_selector};\n    private int[] itemIds = {ITEM_TAKE_PICTURE, ITEM_PICTURE};\n    private MyItemClickListener extendMenuItemClickListener;\n\n    private List<HTMessage> htMessages;\n    private ChatAdapter adapter;\n    private PullToLoadMoreListView pullToLoadMoreListView;\n    private ChatInputView chatInputView;\n    private MyInputViewLisenter inputViewLisenter;\n    private VoiceRecorderView voiceRecorderView;\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        View root = inflater.inflate(R.layout.fragment_chat, container, false);\n        voiceRecorderView = (VoiceRecorderView) root.findViewById(R.id.voice_recorder);\n        pullToLoadMoreListView = (PullToLoadMoreListView) root.findViewById(R.id.list);\n        pullToLoadMoreListView.setOnRefreshListener(new PullToLoadMoreListView.OnRefreshListener() {\n\n            @Override\n            public void onPullDownLoadMore() {\n                new Handler().postDelayed(new Runnable() {\n                    @Override\n                    public void run() {\n\n                        HTMessage message = getLastMessage();\n                        if (message != null) {\n                            List<HTMessage> htMessages = HTClient.getInstance().messageManager().loadMoreMsgFromDB(toChatUsername, message.getTime(), 20);\n                            if (htMessages.size() == 0) {\n                                Toast.makeText(getActivity(), R.string.not_more_msg, Toast.LENGTH_SHORT).show();\n\n                            } else {\n                                Collections.reverse(htMessages);\n                                htMessages.addAll(0, htMessages);\n                                adapter.notifyDataSetChanged();\n\n                            }\n                        } else {\n                            Toast.makeText(getActivity(), R.string.not_more_msg, Toast.LENGTH_SHORT).show();\n\n                        }\n\n                        pullToLoadMoreListView.onRefreshComplete();\n\n                    }\n                }, 1000);\n            }\n        });\n\n        listView = pullToLoadMoreListView.getListView();\n        extendMenuItemClickListener = new MyItemClickListener();\n        chatInputView = (ChatInputView) root.findViewById(R.id.inputView);\n        inputViewLisenter = new MyInputViewLisenter();\n        chatInputView.initView(getActivity(), pullToLoadMoreListView, inputViewLisenter, getExtendMenuItem());\n        listView.setOnTouchListener(new View.OnTouchListener() {\n\n            @Override\n            public boolean onTouch(View v, MotionEvent event) {\n\n                chatInputView.hideSoftInput();\n                chatInputView.interceptBackPress();\n\n                return false;\n            }\n        });\n        return root;\n    }\n\n    private JSONObject extJSON = new JSONObject();\n\n    private boolean isHolder = false;\n    private MyBroadcastReciver myBroadcastReciver;\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        extJSON.put(HTConstant.JSON_KEY_HXID, HTApp.getInstance().getUserJson().getString(HTConstant.JSON_KEY_HXID));\n        extJSON.put(HTConstant.JSON_KEY_NICK, HTApp.getInstance().getUserJson().getString(HTConstant.JSON_KEY_NICK));\n        String avatar = HTApp.getInstance().getUserJson().getString(HTConstant.JSON_KEY_AVATAR);\n        if (!TextUtils.isEmpty(avatar)) {\n            if (!avatar.contains(\"http:\")) {\n                avatar = HTConstant.URL_AVATAR + avatar;\n            }\n        }\n        extJSON.put(HTConstant.JSON_KEY_AVATAR, avatar);\n        fragmentArgs = getArguments();\n        chatType = fragmentArgs.getInt(\"chatType\", MessageUtils.CHAT_SINGLE);\n        toChatUsername = fragmentArgs.getString(\"userId\");\n        super.onActivityCreated(savedInstanceState);\n        setUpView();\n        myBroadcastReciver = new MyBroadcastReciver();\n        IntentFilter intentFilter = new IntentFilter();\n        intentFilter.addAction(IMAction.ACTION_MESSAGE_WITHDROW);\n        intentFilter.addAction(IMAction.ACTION_MESSAGE_FORWORD);\n        intentFilter.addAction(IMAction.ACTION_NEW_MESSAGE);\n        intentFilter.addAction(IMAction.ACTION_MESSAGE_EMPTY);\n        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(myBroadcastReciver, intentFilter);\n    }\n\n\n    private void setUpView() {\n        getAllMessage();\n        adapter = new ChatAdapter(htMessages, this, toChatUsername, chatType);\n        listView.setAdapter(adapter);\n        listView.setSelection(listView.getCount() - 1);\n        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {\n            @Override\n            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {\n                HTMessage htMessage = adapter.getItem(i);\n                if (htMessage != null) {\n                    showMsgDialog(htMessage, i);\n                }\n\n                return true;\n            }\n        });\n\n\n    }\n\n    private void getAllMessage() {\n        htMessages = HTClient.getInstance().messageManager().getMessageList(toChatUsername);\n        HTClient.getInstance().conversationManager().markAllMessageRead(toChatUsername);\n    }\n\n    private class MyInputViewLisenter implements ChatInputView.InputViewLisenter {\n\n        @Override\n        public boolean onPressToSpeakBtnTouch(View v, MotionEvent event) {\n            return voiceRecorderView.onPressToSpeakBtnTouch(v, event, new VoiceRecorderView.EaseVoiceRecorderCallback() {\n\n                @Override\n                public void onVoiceRecordComplete(String voiceFilePath, int voiceTimeLength) {\n                    //Log.d(\"voiceFilePath--->\", voiceFilePath);\n                    sendVoiceMessage(voiceFilePath, voiceTimeLength);\n                }\n            });\n        }\n\n        @Override\n        public void onBigExpressionClicked(Emojicon emojicon) {\n\n        }\n\n        @Override\n        public void onSendButtonClicked(String content) {\n            sendTextMessage(content);\n        }\n\n        @Override\n        public boolean onEditTextLongClick() {\n            String myCopy = ACache.get(getActivity()).getAsString(\"myCopy\");\n            if (!TextUtils.isEmpty(myCopy)) {\n                JSONObject jsonObject = JSONObject.parseObject(myCopy);\n                String msgId = jsonObject.getString(\"msgId\");\n                String imagePath = jsonObject.getString(\"imagePath\");\n                HTMessage emMessage = getCopyMessage(msgId);\n                if (emMessage == null) {\n                    return true;\n                }\n                showCopyContent(jsonObject.getString(\"copyType\"), jsonObject.getString(\"localPath\"), emMessage, imagePath);\n                return true;\n            }\n            return false;\n        }\n\n        @Override\n        public void onEditTextUp() {\n            new Handler().postDelayed(new Runnable() {\n                @Override\n                public void run() {\n                    listView.smoothScrollToPosition(listView.getCount() - 1);\n                }\n            }, 400);\n        }\n    }\n\n    private HTMessage getCopyMessage(String msgId) {\n        for (HTMessage htMessage : htMessages) {\n            if (htMessage.getMsgId().equals(msgId)) {\n                return htMessage;\n            }\n        }\n        return null;\n    }\n\n    private HTMessage getLastMessage() {\n        if (htMessages != null && htMessages.size() != 0) {\n            return adapter.getItem(0);\n        }\n        return null;\n    }\n\n    private ChatExtendMenu getExtendMenuItem() {\n\n        ChatExtendMenu chatExtendMenu = new ChatExtendMenu(getContext());\n        //use the menu in base class\n        for (int i = 0; i < itemStrings.length; i++) {\n            chatExtendMenu.registerMenuItem(itemStrings[i], itemdrawables[i], itemIds[i], extendMenuItemClickListener);\n        }\n        chatExtendMenu.init();\n        return chatExtendMenu;\n    }\n\n\n    /**\n     * handle the click event for extend menu\n     */\n    class MyItemClickListener implements ChatExtendMenu.EaseChatExtendMenuItemClickListener {\n\n        @Override\n        public void onClick(int itemId, View view) {\n\n            switch (itemId) {\n                case ITEM_TAKE_PICTURE:\n                    selectPicFromCamera();\n                    isHolder = true;\n                    break;\n                case ITEM_PICTURE:\n                    selectPicFromLocal();\n                    isHolder = true;\n                    break;\n\n                default:\n                    break;\n            }\n        }\n\n    }\n\n\n    @Override\n    public void onStop() {\n        if (!isHolder) {\n            ChatActivity.activityInstance = null;\n        }\n        super.onStop();\n    }\n\n\n    @Override\n    public void onActivityResult(int requestCode, int resultCode, Intent data) {\n        super.onActivityResult(requestCode, resultCode, data);\n        isHolder = false;\n        if (resultCode == Activity.RESULT_OK) {\n            if (requestCode == REQUEST_CODE_CAMERA) { // capture new image\n                if (cameraFile != null && cameraFile.exists())\n                    sendImageMessage(cameraFile.getAbsolutePath());\n            } else if (requestCode == REQUEST_CODE_LOCAL) { // send local image\n                if (data != null) {\n                    Uri selectedImage = data.getData();\n                    if (selectedImage != null) {\n                        sendPicByUri(selectedImage);\n                    }\n                }\n            }\n        }\n    }\n\n    private void showMsgDialog(final HTMessage message, final int i) {\n\n        HTAlertDialog fxAlertDialog = new HTAlertDialog(getActivity(), null, new String[]{getActivity().getString(R.string.delete), getActivity().getString(R.string.copy), getActivity().getString(R.string.forward)});\n        if (message.getDirect() == HTMessage.Direct.SEND) {\n            fxAlertDialog = new HTAlertDialog(getActivity(), null, new String[]{getActivity().getString(R.string.delete), getActivity().getString(R.string.copy), getActivity().getString(R.string.forward), getActivity().getString(R.string.reback)});\n        }\n        fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                if (position == 0) { //删除\n                    HTClient.getInstance().messageManager().deleteMessage(toChatUsername, message.getMsgId());\n                    htMessages.remove(message);\n                    adapter.notifyDataSetChanged();\n                } else if (position == 1) { //复制\n                    HTMessageUtils.getCopyMsg(getActivity(), message, toChatUsername);\n                } else if (position == 2) {//转发\n                    HTMessageUtils.getForWordMessage(getActivity(), message, toChatUsername, extJSON);\n                } else if (position == 3) {//撤回\n                    long msgTime = message.getTime();\n                    long nowTime = System.currentTimeMillis();\n                    if ((nowTime - msgTime) / (1000 * 60) < 2) {\n                        final ProgressDialog progressDialog = new ProgressDialog(getActivity());\n                        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);\n                        progressDialog.setMessage(getString(R.string.rebacking));\n                        progressDialog.setCanceledOnTouchOutside(false);\n                        progressDialog.show();\n                        CmdMessage cmdMessage = new CmdMessage();\n                        cmdMessage.setTo(toChatUsername);\n                        JSONObject jsonObject = new JSONObject();\n                        jsonObject.put(\"action\", 6000);\n                        jsonObject.put(\"msgId\", message.getMsgId());\n                        cmdMessage.setBody(jsonObject.toString());\n                        if (chatType == MessageUtils.CHAT_GROUP) {\n                            cmdMessage.setChatType(ChatType.groupChat);\n                        }\n                        HTClient.getInstance().chatManager().sendCmdMessage(cmdMessage, new HTChatManager.HTMessageCallBack() {\n                            @Override\n                            public void onProgress() {\n\n                            }\n\n                            @Override\n                            public void onSuccess() {\n                                HTClient.getInstance().messageManager().deleteMessage(toChatUsername, message.getMsgId());\n                                getActivity().runOnUiThread(new Runnable() {\n                                    @Override\n                                    public void run() {\n                                        progressDialog.dismiss();\n                                        HTMessage htMessage = HTMessageUtils.creatWithDrowMsg(message);\n                                        htMessages.set(i, htMessage);\n                                        adapter.notifyDataSetChanged();\n                                    }\n                                });\n\n                            }\n\n                            @Override\n                            public void onFailure() {\n                                getActivity().runOnUiThread(new Runnable() {\n                                    @Override\n                                    public void run() {\n                                        progressDialog.dismiss();\n                                        Toast.makeText(getActivity(), R.string.reback_failed, Toast.LENGTH_SHORT).show();\n                                    }\n                                });\n                            }\n                        });\n\n                    } else {\n                        Toast.makeText(getActivity(), R.string.reback_not_more_than_30, Toast.LENGTH_SHORT).show();\n                    }\n                }\n            }\n        });\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n        HTClient.getInstance().conversationManager().markAllMessageRead(toChatUsername);\n        ChatActivity.activityInstance = (ChatActivity) getActivity();\n    }\n\n\n    public void onBackPressed() {\n        if (!chatInputView.interceptBackPress()) {\n            getActivity().finish();\n        }\n    }\n\n    @Override\n    public void onPause() {\n        if (chatInputView != null) {\n            chatInputView.hideSoftInput();\n            chatInputView.interceptBackPress();\n        }\n        super.onPause();\n    }\n\n    private void sendTextMessage(final String content) {\n        HTMessage htMessage = HTMessage.createTextSendMessage(toChatUsername, content);\n        sendMessage(htMessage);\n    }\n\n    public void sendMessage(final HTMessage htMessage) {\n        htMessage.setAttributes(extJSON.toJSONString());\n        if (chatType == MessageUtils.CHAT_GROUP) {\n            htMessage.setChatType(ChatType.groupChat);\n        }\n        HTClient.getInstance().chatManager().sendMessage(htMessage, new HTChatManager.HTMessageCallBack() {\n            @Override\n            public void onProgress() {\n                getActivity().runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        htMessages.add(htMessage);\n                        adapter.notifyDataSetChanged();\n                        if (htMessages.size() > 0) {\n                            listView.setSelection(listView.getCount() - 1);\n                        }\n                    }\n                });\n            }\n\n            @Override\n            public void onSuccess() {\n                htMessage.setStatus(HTMessage.Status.SUCCESS);\n                HTClient.getInstance().messageManager().saveMessage(htMessage, false);\n                getActivity().runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        adapter.notifyDataSetChanged();\n                        if (htMessages.size() > 0) {\n                            listView.setSelection(listView.getCount() - 1);\n                        }\n                    }\n                });\n\n            }\n\n            @Override\n            public void onFailure() {\n                getActivity().runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        htMessage.setStatus(HTMessage.Status.FAIL);\n                        HTClient.getInstance().messageManager().saveMessage(htMessage, false);\n                        adapter.notifyDataSetChanged();\n                        if (htMessages.size() > 0) {\n                            listView.setSelection(listView.getCount() - 1);\n                        }\n                    }\n                });\n            }\n\n        });\n\n\n    }\n\n\n    private void sendVoiceMessage(String filePath, int length) {\n        HTMessage htMessage = HTMessage.createVoiceSendMessage(toChatUsername, filePath, length);\n        sendMessage(htMessage);\n    }\n\n\n    /**\n     * 读取图片属性：旋转的角度\n     *\n     * @param path 图片绝对路径\n     * @return degree旋转的角度\n     */\n    public static int readPictureDegree(String path) {\n        int degree = 0;\n        try {\n            ExifInterface exifInterface = new ExifInterface(path);\n            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);\n            switch (orientation) {\n                case ExifInterface.ORIENTATION_ROTATE_90:\n                    degree = 90;\n                    break;\n                case ExifInterface.ORIENTATION_ROTATE_180:\n                    degree = 180;\n                    break;\n                case ExifInterface.ORIENTATION_ROTATE_270:\n                    degree = 270;\n                    break;\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n            return degree;\n        }\n        return degree;\n    }\n\n    /**\n     * 旋转图片，使图片保持正确的方向。\n     *\n     * @param bitmap  原始图片\n     * @param degrees 原始图片的角度\n     * @return Bitmap 旋转后的图片\n     */\n    public static Bitmap rotateBitmap(Bitmap bitmap, int degrees) {\n        if (degrees == 0 || null == bitmap) {\n            return bitmap;\n        }\n        Matrix matrix = new Matrix();\n        matrix.setRotate(degrees, bitmap.getWidth() / 2, bitmap.getHeight() / 2);\n        Bitmap bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);\n        if (null != bitmap) {\n            bitmap.recycle();\n        }\n        return bmp;\n    }\n\n    private void sendImageMessage(String imagePath) {\n\n        Bitmap bmp = BitmapFactory.decodeFile(imagePath);\n        Bitmap bitmap = rotateBitmap(bmp, readPictureDegree(imagePath));\n        String size = bitmap.getWidth() + \",\" + bitmap.getHeight();\n        Log.d(\"size---->\", size);\n        HTMessage htMessage = HTMessage.createImageSendMessage(toChatUsername, imagePath, size);\n        sendMessage(htMessage);\n    }\n\n    //===================================================================================\n\n\n    /**\n     * send image\n     *\n     * @param selectedImage\n     */\n    private void sendPicByUri(Uri selectedImage) {\n        String[] filePathColumn = {MediaStore.Images.Media.DATA};\n        Cursor cursor = getActivity().getContentResolver().query(selectedImage, filePathColumn, null, null, null);\n        if (cursor != null) {\n            cursor.moveToFirst();\n            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);\n            String picturePath = cursor.getString(columnIndex);\n            cursor.close();\n            cursor = null;\n\n            if (picturePath == null || picturePath.equals(\"null\")) {\n                Toast toast = Toast.makeText(getActivity(), R.string.cant_find_pictures, Toast.LENGTH_SHORT);\n                toast.setGravity(Gravity.CENTER, 0, 0);\n                toast.show();\n                return;\n            }\n            sendImageMessage(picturePath);\n        } else {\n            File file = new File(selectedImage.getPath());\n            if (!file.exists()) {\n                Toast toast = Toast.makeText(getActivity(), R.string.cant_find_pictures, Toast.LENGTH_SHORT);\n                toast.setGravity(Gravity.CENTER, 0, 0);\n                toast.show();\n                return;\n\n            }\n            sendImageMessage(file.getAbsolutePath());\n        }\n\n    }\n\n    /**\n     * capture new image\n     */\n    private void selectPicFromCamera() {\n        if (!CommonUtils.isSdcardExist()) {\n            Toast.makeText(getActivity(), R.string.sd_card_does_not_exist, Toast.LENGTH_SHORT).show();\n            return;\n        }\n\n        cameraFile = new File(new PathUtils(toChatUsername, getContext()).getImagePath() + \"/\" + HTApp.getInstance().getUsername()\n                + System.currentTimeMillis() + \".jpg\");\n        //   cameraFile.getParentFile().mkdirs();\n        startActivityForResult(\n                new Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile)),\n                REQUEST_CODE_CAMERA);\n    }\n\n    /**\n     * select local image\n     */\n    private void selectPicFromLocal() {\n        Intent intent;\n        if (Build.VERSION.SDK_INT < 19) {\n            intent = new Intent(Intent.ACTION_GET_CONTENT);\n            intent.setType(\"image/*\");\n        } else {\n            intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);\n        }\n        startActivityForResult(intent, REQUEST_CODE_LOCAL);\n    }\n\n\n    @Override\n    public void onDestroy() {\n\n        if (myBroadcastReciver != null) {\n            LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(myBroadcastReciver);\n        }\n        super.onDestroy();\n    }\n\n\n    /**\n     * 复制\n     *\n     * @param copyType\n     * @param localPath\n     * @param message1\n     * @param imagePath\n     */\n    private void showCopyContent(final String copyType, final String localPath, final HTMessage message1, String imagePath) {\n        AlertDialog.Builder buidler = new AlertDialog.Builder(getActivity());\n        View view = View.inflate(getActivity(), R.layout.item_dialog_gridview, null);\n        TextView tv_forward = (TextView) view.findViewById(R.id.tv_forward);\n        TextView textView = (TextView) view.findViewById(R.id.textView);\n        TextView tv_ok = (TextView) view.findViewById(R.id.tv_ok);\n        TextView tv_cancel = (TextView) view.findViewById(R.id.tv_cancel);\n        final ImageView imageView = (ImageView) view.findViewById(R.id.imageView);\n        imageView.setVisibility(View.GONE);\n        tv_forward.setText(R.string.copy);\n        textView.setText(R.string.really_copy_and_send);\n        buidler.setView(view);\n        if (\"image\".equals(copyType) && imagePath != null) {\n            imageView.setVisibility(View.VISIBLE);\n            Glide.with(getActivity()).load(imagePath).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);\n        }\n        final AlertDialog dialog = buidler.show();\n        tv_ok.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n                switch (copyType) {\n                    case \"text\":\n                        sendTextMessage(localPath);\n                        break;\n                    case \"voice\":\n                        HTMessageVoiceBody voiceBody = (HTMessageVoiceBody) message1.getBody();\n                        HTMessage voiceMSg = HTMessage.createVoiceSendMessage(toChatUsername, localPath, voiceBody.getAudioDuration());\n                        sendMessage(voiceMSg);\n                        break;\n                    case \"image\":\n                        HTMessageImageBody imageBody = (HTMessageImageBody) message1.getBody();\n                        HTMessage message = HTMessage.createImageSendMessage(toChatUsername, localPath, imageBody.getSize());\n                        sendMessage(message);\n                        break;\n                }\n            }\n        });\n        tv_cancel.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n            }\n        });\n\n    }\n\n    /**\n     * 撤回消息\n     *\n     * @param msgId\n     */\n    private void onMessageWithdrow(String msgId) {\n        for (int i = 0; i < htMessages.size(); i++) {\n            HTMessage htMessage = htMessages.get(i);\n            if (htMessage.getMsgId().equals(msgId)) {\n                HTMessage message = HTMessageUtils.creatWithDrowMsg(htMessage);\n                htMessages.set(i, message);\n                adapter.notifyDataSetChanged();\n            }\n        }\n    }\n\n    private class MyBroadcastReciver extends BroadcastReceiver {\n\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            if (intent.getAction().equals(IMAction.ACTION_MESSAGE_WITHDROW)) {\n                String msgId = intent.getStringExtra(\"msgId\");\n                onMessageWithdrow(msgId);\n            } else if (intent.getAction().equals(IMAction.ACTION_MESSAGE_FORWORD)) {\n                HTMessage message = intent.getParcelableExtra(\"message\");\n                if (message.getTo().equals(toChatUsername)) {\n                    if (!htMessages.contains(message)) {\n                        htMessages.add(message);\n                    }\n                    adapter.notifyDataSetChanged();\n                    if (htMessages.size() > 0) {\n                        listView.setSelection(listView.getCount() - 1);\n                    }\n                }\n            } else if (intent.getAction().equals(IMAction.ACTION_NEW_MESSAGE)) {\n                HTMessage message = intent.getParcelableExtra(\"message\");\n                if ((message.getChatType() == ChatType.singleChat) && (message.getFrom().equals(toChatUsername)) || ((message.getChatType() == ChatType.groupChat) && (message.getTo().equals(toChatUsername)))) {\n                    if (!htMessages.contains(message)) {\n                        htMessages.add(message);\n                    }\n                    adapter.notifyDataSetChanged();\n                    if (htMessages.size() > 0) {\n                        listView.setSelection(listView.getCount() - 1);\n                    }\n                    HTClient.getInstance().conversationManager().markAllMessageRead(toChatUsername);\n                }\n            } else if (IMAction.ACTION_MESSAGE_EMPTY.equals(intent.getAction())) {\n                htMessages.clear();\n                adapter.notifyDataSetChanged();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/ChatPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.chat;\n\n/**\n * Created by dell on 2017/7/1.\n */\n\npublic class ChatPresenter    {\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/activity/ChatSettingActivity.java",
    "content": "package com.htmessage.yichatopen.activity.chat.activity;\n\nimport android.app.Dialog;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.text.TextUtils;\nimport android.view.View;\nimport android.view.View.OnClickListener;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.sdk.client.HTClient;\n\n\npublic class ChatSettingActivity extends BaseActivity implements\n        OnClickListener {\n    // 、置顶\n    private RelativeLayout rl_switch_chattotop;\n    private RelativeLayout rl_switch_block_groupmsg;\n    private RelativeLayout re_clear;\n\n    // 状态变化\n    private ImageView iv_switch_chattotop;\n    private ImageView iv_switch_unchattotop;\n    private ImageView iv_switch_block_groupmsg;\n    private ImageView iv_switch_unblock_groupmsg;\n\n    private String userId;\n    private Dialog progressDialog;\n    public static ChatSettingActivity instance;\n    private User user;\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_chat_setting_single);\n        instance = this;\n        // 获取传过来的userId\n        userId = getIntent().getStringExtra(\"userId\");\n        user= ContactsManager.getInstance().getContactList().get(userId);\n        // 资料错误则不显示\n        if (user == null) {\n            finish();\n            return;\n        }\n        initView();\n        initData();\n\n    }\n\n    private void initView() {\n\n        rl_switch_chattotop = (RelativeLayout) findViewById(R.id.rl_switch_chattotop);\n        rl_switch_block_groupmsg = (RelativeLayout) findViewById(R.id.rl_switch_block_groupmsg);\n        re_clear = (RelativeLayout) findViewById(R.id.re_clear);\n\n        iv_switch_chattotop = (ImageView) findViewById(R.id.iv_switch_chattotop);\n        iv_switch_unchattotop = (ImageView) findViewById(R.id.iv_switch_unchattotop);\n        iv_switch_block_groupmsg = (ImageView) findViewById(R.id.iv_switch_block_groupmsg);\n        iv_switch_unblock_groupmsg = (ImageView) findViewById(R.id.iv_switch_unblock_groupmsg);\n\n//        // 初始化置顶和免打扰的状态\n//        if (!blackList.contains(userId)) {\n//            iv_switch_block_groupmsg.setVisibility(View.INVISIBLE);\n//            iv_switch_unblock_groupmsg.setVisibility(View.VISIBLE);\n//\n//        } else {\n//            iv_switch_block_groupmsg.setVisibility(View.VISIBLE);\n//            iv_switch_unblock_groupmsg.setVisibility(View.INVISIBLE);\n//        }\n\n\n    }\n\n    private void initData() {\n\n        rl_switch_chattotop.setOnClickListener(this);\n        rl_switch_block_groupmsg.setOnClickListener(this);\n        re_clear.setOnClickListener(this);\n\n        ImageView ivAvatar= (ImageView) this.findViewById(R.id.iv_avatar);\n        TextView tvNick = (TextView) this.findViewById(R.id.tv_username);\n        tvNick.setText(user.getNick());\n        String avatarUrl =user.getAvatar();\n//        String avatarUrl = HTConstant.URL_AVATAR + userJson.getString(HTConstant.JSON_KEY_AVATAR);\n        if(!TextUtils.isEmpty(avatarUrl)){\n            if (!avatarUrl.contains(\"http:\")){\n                avatarUrl = HTConstant.URL_AVATAR+avatarUrl;\n            }\n        }\n        Glide.with(this).load( avatarUrl).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(ivAvatar);\n\n        ivAvatar.setOnClickListener(new OnClickListener() {\n\n            @Override\n            public void onClick(View v) {\n\n                startActivity(new Intent(ChatSettingActivity.this,\n                        UserDetailsActivity.class).putExtra(HTConstant.KEY_USER_INFO, user.getUserInfo()));\n            }\n        });\n        ImageView ivAdd = (ImageView) this.findViewById(R.id.iv_avatar2);\n        ivAdd.setOnClickListener(new OnClickListener() {\n\n            @Override\n            public void onClick(View v) {\n\n            }\n\n        });\n\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n        case R.id.rl_switch_block_groupmsg: // 设置免打扰\n            progressDialog = HTApp.getInstance().createLoadingDialog(this,\"正在设置免打扰...\");\n            progressDialog.show();\n            if (iv_switch_block_groupmsg.getVisibility() == View.VISIBLE) {\n                new Handler().postDelayed(new Runnable() {\n\n                    public void run() {\n                        removeOutBlacklist(userId);\n                        progressDialog.dismiss();\n\n                    }\n\n                }, 2000);\n\n            } else {\n                moveToBlacklist(userId);\n            }\n            break;\n\n        case R.id.re_clear: // 清空聊天记录\n            progressDialog = HTApp.getInstance().createLoadingDialog(this,\"正在清空聊天记录...\");\n            progressDialog.show();\n             new Handler().postDelayed(new Runnable() {\n\n                public void run() {\n                    HTClient.getInstance().conversationManager().deleteConversationAndMessage(userId);\n                    LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(IMAction.ACTION_MESSAGE_EMPTY).putExtra(\"id\", userId));\n                    progressDialog.dismiss();\n\n                }\n\n            }, 2000);\n\n            break;\n\n        case R.id.rl_switch_chattotop:\n//            // 当前状态是已经置顶,点击后取消置顶\n//            if (iv_switch_chattotop.getVisibility() == View.VISIBLE) {\n//\n//                iv_switch_chattotop.setVisibility(View.INVISIBLE);\n//                iv_switch_unchattotop.setVisibility(View.VISIBLE);\n//\n//                if (topMap.containsKey(userId)) {\n//\n//                    topMap.remove(userId);\n//                    TopUserDao topUserDao = new TopUserDao(\n//                            ChatSettingSingleActivity.this);\n//\n//                    topUserDao.deleteTopUser(userId);\n//\n//                }\n//\n//            } else {\n//\n//                // 当前状态是未置顶点击后置顶\n//\n//                iv_switch_chattotop.setVisibility(View.VISIBLE);\n//                iv_switch_unchattotop.setVisibility(View.INVISIBLE);\n//\n//                if (!topMap.containsKey(userId)) {\n//                    TopUser topUser = new TopUser();\n//                    topUser.setTime(System.currentTimeMillis());\n//                    // 1---表示是群组0----个人\n//                    topUser.setType(0);\n//                    topUser.setUserName(userId);\n//                    Map<String, TopUser> map = new HashMap<String, TopUser>();\n//                    map.put(userId, topUser);\n//                    topMap.putAll(map);\n//                    TopUserDao topUserDao = new TopUserDao(\n//                            ChatSettingSingleActivity.this);\n//                    topUserDao.saveTopUser(topUser);\n//\n//                }\n//\n//            }\n\n            break;\n\n        default:\n            break;\n        }\n\n    }\n\n\n    /**\n     * 把user移入到免打扰\n     */\n    private void moveToBlacklist(final String username) {\n//\n//        new Thread(new Runnable() {\n//            public void run() {\n//                try {\n//                    // 加入到黑名单\n//                    EMClient.getInstance().contactManager().addUserToBlackList(username,\n//                            false);\n//                    runOnUiThread(new Runnable() {\n//                        public void run() {\n//                            progressDialog.dismiss();\n//                            iv_switch_block_groupmsg\n//                                    .setVisibility(View.VISIBLE);\n//                            iv_switch_unblock_groupmsg\n//                                    .setVisibility(View.INVISIBLE);\n//\n//                        }\n//                    });\n//                }  catch (final HyphenateException e) {\n//                    runOnUiThread(new Runnable() {\n//                        public void run() {\n//                            progressDialog.dismiss();\n//                            Toast.makeText(getApplicationContext(),\n//                                    \"设置失败，原因：\" + e.toString(),\n//                                    Toast.LENGTH_SHORT).show();\n//                        }\n//                    });\n//                    e.printStackTrace();\n//                }\n//            }\n//        }).start();\n\n    }\n\n    /**\n     * 移出免打扰\n     * \n     * @param tobeRemoveUser\n     */\n    private void removeOutBlacklist(final String tobeRemoveUser) {\n\n//        try {\n//\n//            // 移出黑民单\n//            EMClient.getInstance().contactManager().removeUserFromBlackList(tobeRemoveUser);\n//            iv_switch_block_groupmsg.setVisibility(View.INVISIBLE);\n//            iv_switch_unblock_groupmsg.setVisibility(View.VISIBLE);\n//        }   catch (HyphenateException e) {\n//            runOnUiThread(new Runnable() {\n//                public void run() {\n//\n//                    Toast.makeText(getApplicationContext(), \"设置失败\",\n//                            Toast.LENGTH_SHORT).show();\n//                }\n//            });\n//            e.printStackTrace();\n//        }\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/activity/ChooseContactActivity.java",
    "content": "package com.htmessage.yichatopen.activity.chat.activity;\n\nimport android.annotation.SuppressLint;\nimport android.app.AlertDialog;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.Button;\nimport android.widget.CheckBox;\nimport android.widget.ImageView;\nimport android.widget.ListView;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.manager.HTChatManager;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.sdk.model.HTMessageImageBody;\nimport com.htmessage.sdk.model.HTMessageVoiceBody;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 项目名称：yichat\n * 类描述：CheckPeopleActivity 描述: 选择转发人员\n * 创建人：songlijie\n * 创建时间：2017/3/18 17:04\n * 邮箱:814326663@qq.com\n */\npublic class ChooseContactActivity extends BaseActivity implements AdapterView.OnItemClickListener, View.OnClickListener {\n    private ArrayList<User> users = new ArrayList<>();\n    private ArrayList<User> friends = new ArrayList<>();\n    private TextView tv_group_check, tv_title;\n    private ListView list;\n    private ChooseContactAdapter adAdapter;\n    private String forwordType;\n    private String localUrl,obj,exobj;\n    private HTMessage message1;\n    private JSONObject object,extJSON;\n    private String imagePath,msgId,toChatUsername;\n    private Button btn_rtc;\n    private List<HTMessage> msgList;\n\n    @Override\n    protected void onCreate(Bundle arg0) {\n        super.onCreate(arg0);\n        setContentView(R.layout.activity_check_people);\n        getData();\n        initView();\n        initData();\n        setListener();\n    }\n\n    private void initData() {\n        btn_rtc.setVisibility(View.VISIBLE);\n        btn_rtc.setText(R.string.str_send);\n        msgList = HTClient.getInstance().messageManager().getMessageList(toChatUsername);\n        extJSON = JSONObject.parseObject(exobj);\n        message1 = getCopyMessage(msgId);\n        getContacts();\n        adAdapter = new ChooseContactAdapter(ChooseContactActivity.this, friends);\n        list.setAdapter(adAdapter);\n    }\n\n    private void getData() {\n        obj = getIntent().getStringExtra(\"obj\");\n        object = JSONObject.parseObject(obj);\n        imagePath = object.getString(\"imagePath\");\n        forwordType = object.getString(\"forwordType\");\n        localUrl = object.getString(\"localPath\");\n        msgId = object.getString(\"msgId\");\n        toChatUsername =object.getString(\"toChatUsername\");\n        exobj =object.getString(\"exobj\");\n        getContacts();\n    }\n\n    private void getContacts() {\n        friends.clear();\n        // 获取本地好友列表\n        Map<String, User> users = ContactsManager.getInstance().getContactList();\n        Iterator<Map.Entry<String, User>> iterator = users.entrySet().iterator();\n        while (iterator.hasNext()) {\n            Map.Entry<String, User> entry = iterator.next();\n\n                friends.add(entry.getValue());\n        }\n        // 对list进行排序\n        Collections.sort(friends, new PinyinComparator() {});\n    }\n\n    private void initView() {\n        tv_group_check = (TextView) findViewById(R.id.tv_group_check);\n        tv_title = (TextView) findViewById(R.id.tv_title);\n        list = (ListView) findViewById(R.id.list);\n        btn_rtc = (Button) findViewById(R.id.btn_rtc);\n    }\n\n    private void setListener() {\n        tv_group_check.setOnClickListener(this);\n        list.setOnItemClickListener(this);\n        btn_rtc.setOnClickListener(this);\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkbox);\n        checkBox.toggle();\n        ChooseContactAdapter.getIsSelected().put(position, checkBox.isChecked());//将CheckBox的选中状况记录下来\n        // 调整选定条目\n        if (checkBox.isChecked() == true) {\n            users.add(adAdapter.getItem(position));\n        } else {\n            users.remove(adAdapter.getItem(position));\n        }\n    }\n\n\n    public void getContactsInServer() {\n        if (!HTClient.getInstance().isLogined()) {\n            return;\n        }\n        List<Param> params = new ArrayList<Param>();\n       new OkHttpUtils(this).post(params, HTConstant.URL_FriendList, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                int code = jsonObject.getIntValue(\"code\");\n                switch (code) {\n                    case 1:\n                        JSONArray friends = jsonObject.getJSONArray(\"user\");\n                        if (friends != null || friends.size() != 0) {\n                            List<User> users = new ArrayList<User>();\n                            for (int i = 0; i < friends.size(); i++) {\n                                JSONObject friend = friends.getJSONObject(i);\n                                User user = CommonUtils.Json2User(friend);\n                                users.add(user);\n                            }\n                            ContactsManager.getInstance().saveContactList(users);\n                        }\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n\n            }\n        });\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.btn_rtc:\n                if (users.size() == 0 || users == null) {\n                    Toast.makeText(ChooseContactActivity.this, R.string.please_check_contant, Toast.LENGTH_SHORT).show();\n                    return;\n                }\n                showMessageFarWordDialog(users, forwordType, localUrl);\n                break;\n        }\n    }\n\n    private void showMessageFarWordDialog(final ArrayList<User> users, final String forwordType, final String localUrl) {\n        AlertDialog.Builder buidler = new AlertDialog.Builder(this);\n        View view = View.inflate(this, R.layout.item_dialog_gridview, null);\n        TextView tv_forward = (TextView) view.findViewById(R.id.tv_forward);\n        TextView textView = (TextView) view.findViewById(R.id.textView);\n        ImageView imageView = (ImageView) view.findViewById(R.id.imageView);\n        TextView tv_ok = (TextView) view.findViewById(R.id.tv_ok);\n        TextView tv_cancel = (TextView) view.findViewById(R.id.tv_cancel);\n        textView.setText(R.string.forword_always);\n        if (\"image\".equals(forwordType) && localUrl != null) {\n            imageView.setVisibility(View.VISIBLE);\n            Glide.with(this).load(imagePath).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);\n        }\n\n        tv_forward.setText(getString(R.string.forword_people).replace(\"1\", String.valueOf(users.size())));\n        buidler.setView(view);\n        final AlertDialog dialog = buidler.show();\n        tv_ok.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n                for (int i = 0; i < users.size(); i++) {\n                    User easeUser = users.get(i);\n                    switch (forwordType) {\n                        case \"text\":\n                            HTMessage textMessage= HTMessage.createTextSendMessage(easeUser.getUsername(),localUrl);\n                            sendMessage(textMessage);\n                            break;\n                        case \"voice\":\n                            HTMessageVoiceBody voiceBody = (HTMessageVoiceBody) message1.getBody();\n                            HTMessage voiceMSg = HTMessage.createVoiceSendMessage(easeUser.getUsername(), localUrl, voiceBody.getAudioDuration());\n                            sendMessage(voiceMSg);\n                            break;\n                        case \"image\":\n                            HTMessageImageBody imageBody = (HTMessageImageBody) message1.getBody();\n                            HTMessage message = HTMessage.createImageSendMessage(easeUser.getUsername(), localUrl, imageBody.getSize());\n                            sendMessage(message);\n                            break;\n                    }\n                }\n            }\n        });\n        tv_cancel.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n            }\n        });\n    }\n\n    private void sendMessage(final HTMessage htMessage){\n        htMessage.setAttributes(extJSON.toJSONString());\n        htMessage.setChatType(ChatType.singleChat);\n        HTClient.getInstance().chatManager().sendMessage(htMessage, new HTChatManager.HTMessageCallBack() {\n            @Override\n            public void onProgress() {\n            }\n\n            @Override\n            public void onSuccess() {\n                runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        htMessage.setStatus(HTMessage.Status.SUCCESS);\n                        HTClient.getInstance().messageManager().saveMessage(htMessage,false);\n                        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(IMAction.ACTION_MESSAGE_FORWORD).putExtra(\"message\",htMessage));\n                    }\n                });\n            }\n\n            @Override\n            public void onFailure() {\n                runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        htMessage.setStatus(HTMessage.Status.FAIL);\n                        HTClient.getInstance().messageManager().saveMessage(htMessage,false);\n                        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(new Intent(IMAction.ACTION_MESSAGE_FORWORD).putExtra(\"message\",htMessage));\n                    }\n                });\n            }\n        });\n        finish();\n    }\n    @Override\n    protected void onResume() {\n        super.onResume();\n        friends.clear();\n        getContacts();\n        if (adAdapter!=null){\n            adAdapter.notifyDataSetChanged();\n        }\n    }\n\n\n    private HTMessage getCopyMessage(String msgId) {\n        for (HTMessage htMessage : msgList) {\n            if (htMessage.getMsgId().equals(msgId)) {\n                return htMessage;\n            }\n        }\n        return null;\n    }\n    public class PinyinComparator implements Comparator<User> {\n\n        @SuppressLint(\"DefaultLocale\")\n        @Override\n        public int compare(User o1, User o2) {\n            String py1 = o1.getInitialLetter();\n            String py2 = o2.getInitialLetter();\n            if (py1.equals(py2)) {\n                return o1.getNick().compareTo(o2.getNick());\n            } else {\n                if (\"#\".equals(py1)) {\n                    return 1;\n                } else if (\"#\".equals(py2)) {\n                    return -1;\n                }\n                return py1.compareTo(py2);\n            }\n        }\n\n        private boolean isEmpty(String str) {\n            return \"\".equals(str.trim());\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/activity/ChooseContactAdapter.java",
    "content": "package com.htmessage.yichatopen.activity.chat.activity;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.CheckBox;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.domain.User;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\n\n/**\n * 项目名称：yichat\n * 类描述：PeopleCheckAdapter 描述: 选择转发人员的适配器\n * 创建人：songlijie\n * 创建时间：2017/3/18 17:27\n * 邮箱:814326663@qq.com\n */\npublic class ChooseContactAdapter extends BaseAdapter {\n\n    private Context mContext;\n    private ArrayList<User> beans = new ArrayList<>();\n\n    // 用来控制CheckBox的选中状况\n    private static HashMap<Integer, Boolean> isSelected;\n\n    public ChooseContactAdapter(Context mContext, ArrayList<User> beans) {\n        this.mContext = mContext;\n        this.beans = beans;\n        isSelected = new HashMap<Integer, Boolean>();\n        initDate();\n    }\n    @Override\n    public int getCount() {\n        return beans.size();\n    }\n    // 初始化isSelected的数据\n    private void initDate() {\n        for (int i = 0; i < beans.size(); i++) {\n            getIsSelected().put(i, false);\n        }\n    }\n\n    @Override\n    public User getItem(int position) {\n        return beans.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @Override\n    public View getView(final int position, View convertView, ViewGroup parent) {\n        ViewHolder holder;\n        if (convertView == null){\n            convertView = View.inflate(mContext, R.layout.latout_pre_videocall_item,null);\n            holder = new ViewHolder();\n            holder.iv_game_avatar = (ImageView) convertView.findViewById(R.id.iv_game_avatar);\n            holder.tv_username = (TextView) convertView.findViewById(R.id.tv_username);\n            holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);\n            convertView.setTag(holder);\n        }else{\n            holder = (ViewHolder) convertView.getTag();\n        }\n        User gameBean = beans.get(position);\n        holder.tv_username.setText(gameBean.getNick());\n        Glide.with(mContext).load(gameBean.getAvatar()).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).error(R.drawable.default_avatar).into(holder.iv_game_avatar);\n        // 根据isSelected来设置checkbox的选中状况\n        holder.checkbox.setChecked(getIsSelected().get(position));\n        return convertView;\n    }\n\n    public static class ViewHolder{\n        public TextView tv_username;\n        public ImageView iv_game_avatar;\n        public CheckBox checkbox;\n    }\n    public static HashMap<Integer, Boolean> getIsSelected() {\n        return isSelected;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/ChatExtendMenu.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ArrayAdapter;\nimport android.widget.GridView;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.widget.zxing.activity.DensityUtil;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Extend menu when user want send image, voice clip, etc\n *\n */\npublic class ChatExtendMenu extends GridView{\n\n    protected Context context;\n    private List<ChatMenuItemModel> itemModels = new ArrayList<ChatMenuItemModel>();\n\n    public ChatExtendMenu(Context context, AttributeSet attrs, int defStyle) {\n        this(context, attrs);\n    }\n\n    public ChatExtendMenu(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        init(context, attrs);\n    }\n\n    public ChatExtendMenu(Context context) {\n        super(context);\n        init(context, null);\n    }\n    \n    private void init(Context context, AttributeSet attrs){\n        this.context = context;\n        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ChatExtendMenu);\n        int numColumns = ta.getInt(R.styleable.ChatExtendMenu_numColumns, 4);\n        ta.recycle();\n        \n        setNumColumns(numColumns);\n        setStretchMode(GridView.STRETCH_COLUMN_WIDTH);\n        setGravity(Gravity.CENTER_VERTICAL);\n        setVerticalSpacing(DensityUtil.dip2px(context, 8));\n    }\n    \n    /**\n     * init\n     */\n    public void init(){\n        setAdapter(new ItemAdapter(context, itemModels));\n    }\n    \n    /**\n     * register menu item\n     * \n     * @param name\n     *            item name\n     * @param drawableRes\n     *            background of item\n     * @param itemId\n     *             id\n     * @param listener\n     *            on click event of item\n     */\n    public void registerMenuItem(String name, int drawableRes, int itemId, EaseChatExtendMenuItemClickListener listener) {\n        ChatMenuItemModel item = new ChatMenuItemModel();\n        item.name = name;\n        item.image = drawableRes;\n        item.id = itemId;\n        item.clickListener = listener;\n        itemModels.add(item);\n    }\n    \n    /**\n     * register menu item\n     * \n     * @param nameRes\n     *            resource id of itme name\n     * @param drawableRes\n     *            background of item\n     * @param itemId\n     *             id\n     * @param listener\n     *             on click event of item\n     */\n    public void registerMenuItem(int nameRes, int drawableRes, int itemId, EaseChatExtendMenuItemClickListener listener) {\n        registerMenuItem(context.getString(nameRes), drawableRes, itemId, listener);\n    }\n    \n    \n    private class ItemAdapter extends ArrayAdapter<ChatMenuItemModel>{\n\n        private Context context;\n\n        public ItemAdapter(Context context, List<ChatMenuItemModel> objects) {\n            super(context, 1, objects);\n            this.context = context;\n        }\n        \n        @Override\n        public View getView(final int position, View convertView, ViewGroup parent) {\n            ChatMenuItem menuItem = null;\n            if(convertView == null){\n                convertView = new ChatMenuItem(context);\n            }\n            menuItem = (ChatMenuItem) convertView;\n            menuItem.setImage(getItem(position).image);\n            menuItem.setText(getItem(position).name);\n            menuItem.setOnClickListener(new OnClickListener() {\n                \n                @Override\n                public void onClick(View v) {\n                    if(getItem(position).clickListener != null){\n                        getItem(position).clickListener.onClick(getItem(position).id, v);\n                    }\n                }\n            });\n            return convertView;\n        }\n        \n        \n    }\n    \n    \n    public interface EaseChatExtendMenuItemClickListener{\n        void onClick(int itemId, View view);\n    }\n    \n    \n    class ChatMenuItemModel{\n        String name;\n        int image;\n        int id;\n        EaseChatExtendMenuItemClickListener clickListener;\n    }\n    \n    class ChatMenuItem extends LinearLayout {\n        private ImageView imageView;\n        private TextView textView;\n\n        public ChatMenuItem(Context context, AttributeSet attrs, int defStyle) {\n            this(context, attrs);\n        }\n\n        public ChatMenuItem(Context context, AttributeSet attrs) {\n            super(context, attrs);\n            init(context, attrs);\n        }\n\n        public ChatMenuItem(Context context) {\n            super(context);\n            init(context, null);\n        }\n\n        private void init(Context context, AttributeSet attrs) {\n            LayoutInflater.from(context).inflate(R.layout.chat_menu_item, this);\n            imageView = (ImageView) findViewById(R.id.image);\n            textView = (TextView) findViewById(R.id.text);\n        }\n\n        public void setImage(int resid) {\n            imageView.setBackgroundResource(resid);\n        }\n\n        public void setText(int resid) {\n            textView.setText(resid);\n        }\n\n        public void setText(String text) {\n            textView.setText(text);\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/ChatInputView.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport android.graphics.Rect;\nimport android.os.Build;\nimport android.support.annotation.Nullable;\nimport android.support.design.widget.TabLayout;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentPagerAdapter;\nimport android.support.v4.content.ContextCompat;\nimport android.support.v4.view.PagerAdapter;\nimport android.support.v4.view.ViewPager;\nimport android.support.v7.app.AppCompatActivity;\nimport android.text.Editable;\nimport android.text.TextUtils;\nimport android.text.TextWatcher;\nimport android.util.AttributeSet;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.view.KeyEvent;\nimport android.view.LayoutInflater;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.WindowManager;\nimport android.view.inputmethod.InputMethodManager;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.chat.weight.emoji.DefaultEmojiconDatas;\nimport com.htmessage.yichatopen.activity.chat.weight.emoji.EmojiFragment;\nimport com.htmessage.yichatopen.activity.chat.weight.emoji.Emojicon;\nimport com.htmessage.yichatopen.activity.chat.weight.emoji.SmileUtils;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/7/4.\n * qq 84543217\n */\n\npublic class ChatInputView extends LinearLayout implements View.OnClickListener {\n    private static final String SHARE_PREFERENCE_NAME = \"com.yichatsystem.app\";\n    private static final String SHARE_PREFERENCE_TAG = \"soft_input_height\";\n    //切换到语音输入按钮\n    private Button btn_set_mode_voice;\n    //文本输入框\n    private EditText et_sendmessage;\n    //文本输入框的linearlayou\n    private LinearLayout ll_press_to_input;\n    //语音输入的linearlayout\n    private LinearLayout ll_press_to_speak;\n    //切换到文字输入的按钮\n    private Button btn_set_mode_keyboard;\n    //按住录音的按钮\n    private Button tv_recording;\n    //表情按钮正常状态\n    private Button btn_emoticons_normal;\n    //右边切换到输入状态的按钮\n    private Button btn_emoticons_checked;\n    //选择更多的消息类型\n    private Button btn_more;\n    //消息发送和按钮\n    private Button btn_send;\n    //表情及更多消息类型的父View\n    private LinearLayout ll_more;\n    //表情区域\n    private TabLayout tl_face_container;\n    private ViewPager emoji_viewpager;\n    //更多消息类型\n    private TabLayout tablelayout_extend;\n    private ViewPager extend_viewpager;\n    //   private EmotionInputDetector emotionInputDetector;\n    //输入框上面的view\n    private View mContentView;\n    private InputMethodManager mInputManager;\n    private SharedPreferences sp;\n    private LinearLayout ll_emoji;\n    private LinearLayout ll_extend;\n    private InputViewLisenter inputViewLisenter;\n\n    public ChatInputView(Context context) {\n        super(context);\n        init(context);\n    }\n\n    public ChatInputView(Context context, @Nullable AttributeSet attrs) {\n        super(context, attrs);\n        init(context);\n    }\n\n    public ChatInputView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context);\n    }\n\n    private void showEmotionLayout() {\n        int softInputHeight = getSupportSoftInputHeight();\n        if (softInputHeight == 0) {\n            softInputHeight = sp.getInt(SHARE_PREFERENCE_TAG, 400);\n        }\n\n        hideSoftInput();\n        ll_more.getLayoutParams().height = softInputHeight;\n        ll_more.setVisibility(View.VISIBLE);\n        //  inputViewLisenter.onEditTextUp();\n    }\n\n    public void init(Context context) {\n        LayoutInflater.from(context).inflate(R.layout.widget_input_view, this);\n\n    }\n\n    private ChatExtendMenu chatExtendMenus;\n\n    public void initView(Activity activity, View aboveView, InputViewLisenter inputViewLisenter, ChatExtendMenu chatExtendMenus) {\n        this.chatExtendMenus = chatExtendMenus;\n        this.inputViewLisenter = inputViewLisenter;\n        mContentView = aboveView;\n        //切换到语音输入按钮\n        btn_set_mode_voice = (Button) this.findViewById(R.id.btn_set_mode_voice);\n\n        //文本输入框\n        et_sendmessage = (EditText) this.findViewById(R.id.et_sendmessage);\n        //文本输入框的linearlayou\n\n        ll_press_to_input = (LinearLayout) this.findViewById(R.id.ll_press_to_input);\n\n        //语音输入的linearlayout\n        ll_press_to_speak = (LinearLayout) this.findViewById(R.id.ll_press_to_speak);\n\n        //切换到文字输入的按钮(左边)\n        btn_set_mode_keyboard = (Button) this.findViewById(R.id.btn_set_mode_keyboard);\n\n        //按住录音的按钮\n        tv_recording = (Button) this.findViewById(R.id.tv_recording);\n\n        //表情按钮正常状态\n        btn_emoticons_normal = (Button) this.findViewById(R.id.btn_emoticons_normal);\n\n        //右边切换到输入状态的按钮\n\n        btn_emoticons_checked = (Button) this.findViewById(R.id.btn_emoticons_checked);\n\n        //选择更多的消息类型\n\n        btn_more = (Button) this.findViewById(R.id.btn_more);\n\n        //消息发送和按钮\n\n        btn_send = (Button) this.findViewById(R.id.btn_send);\n\n        //表情及更多消息类型的父View\n        ll_more = (LinearLayout) this.findViewById(R.id.ll_more);\n\n        //表情区域\n        ll_emoji = (LinearLayout) this.findViewById(R.id.ll_emoji);\n        tl_face_container = (TabLayout) this.findViewById(R.id.tl_face_container);\n\n        emoji_viewpager = (ViewPager) this.findViewById(R.id.emoji_viewpager);\n\n        //更多消息类型\n        ll_extend = (LinearLayout) this.findViewById(R.id.ll_extend);\n        tablelayout_extend = (TabLayout) this.findViewById(R.id.tablelayout_extend);\n\n        extend_viewpager = (ViewPager) this.findViewById(R.id.extend_viewpager);\n\n        //初始化表情区域\n        initEmojiView(activity);\n        //初始化更多消息\n        ininExtendView();\n        //设置按钮监听\n        setListener();\n        mInputManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);\n        sp = getContext().getSharedPreferences(SHARE_PREFERENCE_NAME, Context.MODE_PRIVATE);\n        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN |\n                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);\n        hideSoftInput();\n    }\n\n\n//    public void setAboveView(Activity activity,View upView){\n//        emotionInputDetector=  EmotionInputDetector.with((AppCompatActivity)activity)\n//                .setEmotionView(ll_more)\n//                .bindToContent(upView)\n//                .bindToEditText(et_sendmessage)\n//                .bindToEmotionButton(btn_emoticons_normal)\n//                .build();\n//    }\n\n\n    public boolean interceptBackPress() {\n        // TODO: 15/11/2 change this method's name\n        if (ll_more.isShown()) {\n            hideEmotionLayout(false);\n            if (!btn_emoticons_normal.isShown()) {\n                btn_emoticons_checked.setVisibility(GONE);\n                btn_emoticons_normal.setVisibility(VISIBLE);\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    private void setListener() {\n        btn_set_mode_voice.setOnClickListener(this);\n        et_sendmessage.setOnClickListener(this);\n        btn_set_mode_keyboard.setOnClickListener(this);\n        btn_emoticons_normal.setOnClickListener(this);\n        btn_emoticons_checked.setOnClickListener(this);\n        btn_more.setOnClickListener(this);\n        btn_send.setOnClickListener(this);\n\n        et_sendmessage.requestFocus();\n        et_sendmessage.setOnTouchListener(new OnTouchListener() {\n            @Override\n            public boolean onTouch(View v, MotionEvent event) {\n                if (event.getAction() == MotionEvent.ACTION_UP) {\n                    if (!btn_emoticons_normal.isShown()) {\n                        btn_emoticons_checked.setVisibility(GONE);\n                        btn_emoticons_normal.setVisibility(VISIBLE);\n                    }\n                    if (ll_more.isShown()) {\n\n                        lockContentHeight();\n                        hideEmotionLayout(true);\n                        et_sendmessage.postDelayed(new Runnable() {\n                            @Override\n                            public void run() {\n                                unlockContentHeightDelayed();\n                            }\n                        }, 200L);\n                        inputViewLisenter.onEditTextUp();\n                        return false;\n                    }\n\n                    if (!isSoftInputShown()) {\n                        inputViewLisenter.onEditTextUp();\n                    }\n                }\n                return false;\n            }\n        });\n//        et_sendmessage.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {\n//            @Override\n//            public void onGlobalLayout() {\n//               // et_sendmessage.getViewTreeObserver().removeOnGlobalLayoutListener(this);\n//               float imagePositionX  = et_sendmessage.getX();\n//                float imagePositionY  = et_sendmessage.getY();\n//                float imageWidth      = et_sendmessage.getWidth();\n//                float imageHeight     = et_sendmessage.getHeight();\n//                //设置文本大小\n//               // tvInImage.setMaxWidth((int) imageWidth);\n//                Log.d(\"et_sendmessage--->\",imagePositionX+\"-\"+imagePositionY+\"-\"+imageWidth+\"-\"+imageHeight);\n//            }\n//        });\n//\n//\n\n\n        et_sendmessage.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n                if (!TextUtils.isEmpty(s.toString())) {\n                    btn_more.setVisibility(GONE);\n                    btn_send.setVisibility(VISIBLE);\n\n                } else {\n                    btn_send.setVisibility(GONE);\n                    btn_more.setVisibility(VISIBLE);\n                }\n                Log.d(\"onEditTextClicked1\", s.toString());\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                if (!TextUtils.isEmpty(s.toString())) {\n                    btn_more.setVisibility(GONE);\n                    btn_send.setVisibility(VISIBLE);\n\n                } else {\n                    btn_send.setVisibility(GONE);\n                    btn_more.setVisibility(VISIBLE);\n                }\n                Log.d(\"onEditTextClicked\", s.toString());\n            }\n        });\n//     //   tv_recording.setClickable(true);\n//        View ll_te=this.findViewById(R.id.ll_speak);\n//        ll_te.setClickable(true);\n//        ll_te.setLongClickable(true);\n        tv_recording.setOnTouchListener(new OnTouchListener() {\n            @Override\n            public boolean onTouch(View v, MotionEvent event) {\n                Log.d(\"voiceFilePath--->\", \"onTouch\");\n                if (inputViewLisenter != null) {\n                    Log.d(\"voiceFilePath--->\", \"inputViewLisenter\");\n                    inputViewLisenter.onPressToSpeakBtnTouch(v, event);\n                }\n\n                return false;\n            }\n        });\n        et_sendmessage.setOnLongClickListener(new OnLongClickListener() {\n            @Override\n            public boolean onLongClick(View v) {\n                if (inputViewLisenter != null) {\n                    return inputViewLisenter.onEditTextLongClick();\n                }\n                return false;\n            }\n        });\n\n    }\n\n    public void hideSoftInput() {\n        mInputManager.hideSoftInputFromWindow(et_sendmessage.getWindowToken(), 0);\n    }\n\n\n    private void hideEmotionLayout(boolean showSoftInput) {\n        if (ll_more.isShown()) {\n            ll_more.setVisibility(View.GONE);\n            if (showSoftInput) {\n                showSoftInput();\n            }\n        }\n    }\n\n    private void unlockContentHeightDelayed() {\n        et_sendmessage.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                ((LayoutParams) mContentView.getLayoutParams()).weight = 1.0F;\n            }\n        }, 200L);\n    }\n\n    private void showSoftInput() {\n        et_sendmessage.requestFocus();\n        et_sendmessage.post(new Runnable() {\n            @Override\n            public void run() {\n                mInputManager.showSoftInput(et_sendmessage, 0);\n                //  inputViewLisenter.onEditTextUp();\n            }\n        });\n    }\n\n    private void lockContentHeight() {\n        LayoutParams params = (LayoutParams) mContentView.getLayoutParams();\n        params.height = mContentView.getHeight();\n        params.weight = 0.0F;\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.btn_set_mode_voice:\n                showVoiceRecordingView();\n                inputViewLisenter.onEditTextUp();\n                btn_emoticons_checked.setVisibility(GONE);\n                btn_send.setVisibility(GONE);\n                btn_more.setVisibility(VISIBLE);\n                btn_emoticons_normal.setVisibility(VISIBLE);\n                break;\n//            case R.id.et_sendmessage:\n//\n//                break;\n            case R.id.btn_set_mode_keyboard:\n                showInputView();\n                inputViewLisenter.onEditTextUp();\n                if (!TextUtils.isEmpty(et_sendmessage.getText().toString())) {\n                    btn_more.setVisibility(GONE);\n                    btn_send.setVisibility(VISIBLE);\n                }\n                break;\n            case R.id.btn_emoticons_normal:\n                showInputView();\n                inputViewLisenter.onEditTextUp();\n                btn_emoticons_normal.setVisibility(GONE);\n                btn_emoticons_checked.setVisibility(VISIBLE);\n                if (isSoftInputShown()) {\n                    lockContentHeight();\n                    showEmotionLayout();\n\n                    unlockContentHeightDelayed();\n\n                } else {\n                    setEmojiMode();\n                    showEmotionLayout();\n                }\n\n                break;\n            case R.id.btn_emoticons_checked:\n                showInputView();\n                inputViewLisenter.onEditTextUp();\n                et_sendmessage.requestFocus();\n                btn_emoticons_checked.setVisibility(GONE);\n                btn_emoticons_normal.setVisibility(VISIBLE);\n\n                if (ll_extend.isShown()) {\n\n                    setEmojiMode();\n\n                } else {\n                    lockContentHeight();\n                    hideEmotionLayout(true);\n                    unlockContentHeightDelayed();\n                }\n\n\n                break;\n            case R.id.btn_more:\n                btn_emoticons_normal.setVisibility(VISIBLE);\n                btn_emoticons_checked.setVisibility(GONE);\n                showInputView();\n                inputViewLisenter.onEditTextUp();\n                if (ll_more.isShown()) {\n                    if (ll_emoji.isShown()) {\n                        setExtendMode();\n\n                    } else {\n                        lockContentHeight();\n                        hideEmotionLayout(true);\n                        unlockContentHeightDelayed();\n                    }\n\n                } else {\n\n                    if (isSoftInputShown()) {\n                        lockContentHeight();\n                        showEmotionLayout();\n                        unlockContentHeightDelayed();\n                    } else {\n                        setExtendMode();\n                        showEmotionLayout();\n                    }\n                }\n                break;\n            case R.id.btn_send:\n                String content = et_sendmessage.getText().toString();\n                et_sendmessage.setText(\"\");\n                inputViewLisenter.onSendButtonClicked(content);\n                break;\n\n        }\n\n    }\n\n\n    private boolean isSoftInputShown() {\n        return getSupportSoftInputHeight() != 0;\n    }\n\n    private void showVoiceRecordingView() {\n        ll_press_to_input.setVisibility(GONE);\n        ll_press_to_speak.setVisibility(VISIBLE);\n        interceptBackPress();\n    }\n\n    private void setEmojiMode() {\n        ll_extend.setVisibility(GONE);\n        ll_emoji.setVisibility(VISIBLE);\n    }\n\n    private void setExtendMode() {\n        ll_emoji.setVisibility(GONE);\n        ll_extend.setVisibility(VISIBLE);\n    }\n\n\n    private void showInputView() {\n        ll_press_to_speak.setVisibility(GONE);\n        ll_press_to_input.setVisibility(VISIBLE);\n    }\n\n    private void initEmojiView(Context context) {\n        ll_emoji.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_BEGINNING);\n        ll_emoji.setDividerDrawable(ContextCompat.getDrawable(getContext(), R.drawable.divider_horizontal));\n        final List<Fragment> fragmentList = new ArrayList<>();\n        fragmentList.add(new EmojiFragment(Arrays.asList(DefaultEmojiconDatas.getData()), 7, 3, new EmojiFragment.OnEmojiListener() {\n            @Override\n            public void onDeleteImageClicked() {\n                editTextDelete(et_sendmessage);\n            }\n\n            @Override\n            public void onExpressionClicked(Emojicon emojicon) {\n                editTextAddEmoji(emojicon);\n            }\n        }));\n        fragmentList.add(new EmojiFragment(Arrays.asList(DefaultEmojiconDatas.getData()), 7, 3, new EmojiFragment.OnEmojiListener() {\n            @Override\n            public void onDeleteImageClicked() {\n\n                editTextDelete(et_sendmessage);\n            }\n\n            @Override\n            public void onExpressionClicked(Emojicon emojicon) {\n                editTextAddEmoji(emojicon);\n            }\n        }));\n        emoji_viewpager.setAdapter(new FragmentPagerAdapter(((AppCompatActivity) context).getSupportFragmentManager()) {\n            @Override\n            public int getCount() {\n                return fragmentList.size();\n            }\n\n            @Override\n            public Fragment getItem(int position) {\n                return fragmentList.get(position);\n            }\n\n        });\n        tl_face_container.setupWithViewPager(emoji_viewpager);\n        TabLayout.Tab[] tabs = new TabLayout.Tab[fragmentList.size()];\n        for (int i = 0; i < fragmentList.size(); i++) {\n            tabs[i] = tl_face_container.getTabAt(i);\n            //   View view=View.inflate(getContext(),R.layout.wigth_emoji_bottom_item,null);\n            //(ImageView) view.findViewById(R.id.iv_emoji);\n            ImageView imageView = new ImageView(getContext());\n            imageView.setImageResource(R.drawable.ee_0);\n            tabs[i].setCustomView(imageView);\n\n        }\n        LinearLayout mLinearLayout = (LinearLayout) tl_face_container.getChildAt(0);\n// 在所有子控件的中间显示分割线（还可能只显示顶部、尾部和不显示分割线）\n        mLinearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END);\n        //   mLinearLayout.setShowDividers();\n// 设置分割线的距离本身（LinearLayout）的内间距\n        //   mLinearLayout.setDividerPadding(20);\n// 设置分割线的样式\n\n        mLinearLayout.setDividerDrawable(ContextCompat.getDrawable(getContext(), R.drawable.divider_vertical));\n\n\n    }\n\n    private void editTextDelete(EditText editText) {\n        if (!TextUtils.isEmpty(editText.getText())) {\n            KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL);\n            editText.dispatchKeyEvent(event);\n        }\n\n    }\n\n    private void editTextAddEmoji(Emojicon emojicon) {\n        if (emojicon.getType() != Emojicon.Type.BIG_EXPRESSION) {\n            if (emojicon.getEmojiText() != null) {\n                et_sendmessage.append(SmileUtils.getSmiledText(getContext(), emojicon.getEmojiText()));\n            }\n        } else {\n            if (inputViewLisenter != null) {\n                inputViewLisenter.onBigExpressionClicked(emojicon);\n            }\n        }\n    }\n\n    private int getSupportSoftInputHeight() {\n        Rect r = new Rect();\n        ((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(r);\n        int screenHeight = ((Activity) getContext()).getWindow().getDecorView().getRootView().getHeight();\n        int softInputHeight = screenHeight - r.bottom;\n        if (Build.VERSION.SDK_INT >= 20) {\n            // When SDK Level >= 20 (Android L), the softInputHeight will contain the height of softButtonsBar (if has)\n            softInputHeight = softInputHeight - getSoftButtonsBarHeight();\n        }\n        if (softInputHeight < 0) {\n            Log.w(\"EmotionInputDetector\", \"Warning: value of softInputHeight is below zero!\");\n        }\n        if (softInputHeight > 0) {\n            sp.edit().putInt(SHARE_PREFERENCE_TAG, softInputHeight).apply();\n        }\n        return softInputHeight;\n    }\n\n    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)\n    private int getSoftButtonsBarHeight() {\n        DisplayMetrics metrics = new DisplayMetrics();\n        ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);\n        int usableHeight = metrics.heightPixels;\n        ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRealMetrics(metrics);\n        int realHeight = metrics.heightPixels;\n        if (realHeight > usableHeight) {\n            return realHeight - usableHeight;\n        } else {\n            return 0;\n        }\n    }\n\n\n    public interface InputViewLisenter {\n\n        boolean onPressToSpeakBtnTouch(View v, MotionEvent event);\n\n        void onBigExpressionClicked(Emojicon emojicon);\n\n        void onSendButtonClicked(String content);\n\n        boolean onEditTextLongClick();\n\n        void onEditTextUp();\n\n    }\n\n    private void ininExtendView() {\n        final List<View> views = new ArrayList<>();\n\n        views.add(chatExtendMenus);\n        extend_viewpager.setAdapter(new PagerAdapter() {\n            @Override\n            public int getCount() {\n                return views.size();\n            }\n\n            @Override\n            public boolean isViewFromObject(View arg0, Object arg1) {\n                return arg0 == arg1;\n            }\n\n            @Override\n            public Object instantiateItem(ViewGroup arg0, int arg1) {\n                ((ViewPager) arg0).addView(views.get(arg1));\n                return views.get(arg1);\n            }\n\n            @Override\n            public void destroyItem(ViewGroup arg0, int arg1, Object arg2) {\n                ((ViewPager) arg0).removeView(views.get(arg1));\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/VoicePlayClickListener.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.graphics.drawable.AnimationDrawable;\nimport android.media.AudioManager;\nimport android.media.MediaPlayer;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.BaseAdapter;\nimport android.widget.ImageView;\n\nimport com.htmessage.yichatopen.HTClientHelper;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.model.HTMessageVoiceBody;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.yichatopen.manager.SettingsManager;\nimport com.htmessage.yichatopen.utils.HTMessageUtils;\n\nimport java.io.File;\n\n/**\n * Created by huangfangyi on 2016/12/5.\n * qq 84543217\n */\n\npublic class VoicePlayClickListener implements View.OnClickListener {\n    private static final String TAG = \"VoicePlayClickListener\";\n    HTMessage message;\n    ImageView voiceIconView;\n\n    private AnimationDrawable voiceAnimation = null;\n    MediaPlayer mediaPlayer = null;\n    ImageView iv_read_status;\n    Activity activity;\n    private ChatType chatType;\n    private BaseAdapter adapter;\n\n    public static boolean isPlaying = false;\n    public static VoicePlayClickListener currentPlayListener = null;\n    public static String playMsgId;\n    String chatTo;\n\n    public VoicePlayClickListener(HTMessage message, String chatTo, ImageView v, ImageView iv_read_status, BaseAdapter adapter, Activity context) {\n        this.message = message;\n        //     voiceBody = (EMVoiceMessageBody) message.getBody();\n        this.iv_read_status = iv_read_status;\n        this.adapter = adapter;\n        voiceIconView = v;\n        this.activity = context;\n        this.chatType = message.getChatType();\n        this.chatTo = chatTo;\n    }\n\n    public void stopPlayVoice() {\n        voiceAnimation.stop();\n        if (message.getDirect() == HTMessage.Direct.RECEIVE) {\n            voiceIconView.setImageResource(R.drawable.chatfrom_voice_playing);\n        } else {\n            voiceIconView.setImageResource(R.drawable.chatto_voice_playing);\n        }\n        // stop play voice\n        if (mediaPlayer != null) {\n            mediaPlayer.stop();\n            mediaPlayer.release();\n        }\n        isPlaying = false;\n        playMsgId = null;\n        adapter.notifyDataSetChanged();\n    }\n\n    public void playVoice(String filePath) {\n        if (!(new File(filePath).exists())) {\n            return;\n        }\n        playMsgId = message.getMsgId();\n        AudioManager audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);\n\n        mediaPlayer = new MediaPlayer();\n        if (SettingsManager.getInstance().getSettingMsgSpeaker()) {\n            audioManager.setMode(AudioManager.MODE_NORMAL);\n            audioManager.setSpeakerphoneOn(true);\n            mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);\n        } else {\n            audioManager.setSpeakerphoneOn(false);// 关闭扬声器\n            // 把声音设定成Earpiece（听筒）出来，设定为正在通话中\n            audioManager.setMode(AudioManager.MODE_IN_CALL);\n            mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);\n        }\n        try {\n            mediaPlayer.setDataSource(filePath);\n            mediaPlayer.prepare();\n            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {\n\n                @Override\n                public void onCompletion(MediaPlayer mp) {\n                    mediaPlayer.release();\n                    mediaPlayer = null;\n                    stopPlayVoice(); // stop animation\n                }\n\n            });\n            isPlaying = true;\n            currentPlayListener = this;\n            mediaPlayer.start();\n            showAnimation();\n\n            // 如果是接收的消息\n            if (message.getDirect() == HTMessage.Direct.RECEIVE) {\n//                if (!message.isAcked() && chatType == ChatType.Chat) {\n//                    // 告知对方已读这条消息\n//                    EMClient.getInstance().chatManager().ackMessageRead(message.getFrom(), message.getMsgId());\n//                }\n                if (message.getStatus() != HTMessage.Status.SUCCESS && iv_read_status != null && iv_read_status.getVisibility() == View.VISIBLE) {\n                    // 隐藏自己未播放这条语音消息的标志\n                    iv_read_status.setVisibility(View.INVISIBLE);\n                    HTClient.getInstance().messageManager().updateSuccess(message);\n//                    message.setListened(true);\n//                    EMClient.getInstance().chatManager().setMessageListened(message);\n                }\n\n            }\n\n        } catch (Exception e) {\n            System.out.println();\n        }\n    }\n\n    // show the voice playing animation\n    private void showAnimation() {\n        // play voice, and start animation\n        if (message.getDirect() == HTMessage.Direct.RECEIVE) {\n            voiceIconView.setImageResource(R.anim.voice_from_icon);\n        } else {\n            voiceIconView.setImageResource(R.anim.voice_to_icon);\n        }\n        voiceAnimation = (AnimationDrawable) voiceIconView.getDrawable();\n        voiceAnimation.start();\n    }\n\n    @Override\n    public void onClick(View v) {\n        String st = activity.getResources().getString(R.string.Is_download_voice_click_later);\n        if (isPlaying) {\n            if (playMsgId != null && playMsgId.equals(message.getMsgId())) {\n                currentPlayListener.stopPlayVoice();\n                return;\n            }\n            currentPlayListener.stopPlayVoice();\n        }\n        HTMessageVoiceBody htMessageVoiceBody = (HTMessageVoiceBody) message.getBody();\n        String loaclPath = htMessageVoiceBody.getLocalPath();\n        if (message.getDirect() == HTMessage.Direct.SEND) {\n\n            //   Log.d(\"getBodyJSON--->\",message.getBodyJSON().getString(MessageUtils.LOCAL_PATH));\n            // for sent msg, we will try to play the voice file directly\n            playVoice(loaclPath);\n        } else {\n\n            if (!TextUtils.isEmpty(loaclPath)) {\n                if (message.getStatus() == HTMessage.Status.SUCCESS) {\n                    File file = new File(loaclPath);\n                    if (file.exists() && file.isFile())\n                        playVoice(loaclPath);\n                    else\n                        Log.e(TAG, \"file not exist\");\n\n                }\n            } else {\n//                if(message.getBodyJSON().containsKey(MessageUtils.REMOTE_PATH)){\n\n//                    String remotePath=message.getBodyJSON().getString(MessageUtils.REMOTE_PATH);\n                downLoadVoiceFileFromServer(message);\n                //}\n\n\n            }\n\n//\n//                else if (message.status() == HTMessage.Status.INPROGRESS) {\n//                    Toast.makeText(activity, st, Toast.LENGTH_SHORT).show();\n//                } else if (message.status() == HTMessage.Status.FAIL) {\n//                    Toast.makeText(activity, st, Toast.LENGTH_SHORT).show();\n//                    new AsyncTask<Void, Void, Void>() {\n//\n//                        @Override\n//                        protected Void doInBackground(Void... params) {\n//                            EMClient.getInstance().chatManager().downloadAttachment(message);\n//                            ImageUtils.getScaledImage()\n//                            return null;\n//                        }\n//\n//                        @Override\n//                        protected void onPostExecute(Void result) {\n//                            super.onPostExecute(result);\n//                            adapter.notifyDataSetChanged();\n//                        }\n//\n//                    }.execute();\n//\n//                }\n\n\n        }\n\n\n    }\n\n\n    private void downLoadVoiceFileFromServer(final HTMessage htMessage) {\n\n        HTMessageUtils.loadMessageFile(htMessage, chatTo, activity,\n         new HTMessageUtils.CallBack() {\n            @Override\n            public void error() {\n\n            }\n\n            @Override\n            public void completed(String localPath) {\n                playVoice(localPath);\n                HTMessageVoiceBody htMessageVoiceBody = (HTMessageVoiceBody) htMessage.getBody();\n                //JSONObject jsonObject=htMessage.getBodyJSON();\n                // jsonObject.put(MessageUtils.LOCAL_PATH,localPath);\n                htMessageVoiceBody.setLocalPath(localPath);\n                htMessage.setBody(htMessageVoiceBody);\n                HTClient.getInstance().messageManager().updateSuccess(htMessage);\n            }\n\n\n        });\n\n//\n//        final JSONObject jsonObject = htMessage.getBodyJSON();\n//        if (!jsonObject.containsKey(MessageUtils.REMOTE_PATH) || !jsonObject.containsKey(MessageUtils.FILE_NAME)) {\n//\n//            return;\n//        }\n//        final ProgressDialog progressDialog = new ProgressDialog(activity);\n//        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);\n//        progressDialog.setCanceledOnTouchOutside(false);\n//        progressDialog.setMessage(\"正在加载\");\n//        progressDialog.show();\n//        HTPathUtils pathUtils = new HTPathUtils(chatTo, activity);\n//        String remotePath = jsonObject.getString(MessageUtils.REMOTE_PATH);\n//        String fileName = jsonObject.getString(MessageUtils.FILE_NAME);\n//        final String filePath = pathUtils.getImagePath().getAbsolutePath() + fileName;\n//        Log.d(\"filePath22--->\", filePath);\n//        FileDownloader.getImpl().create(remotePath)\n//                .setPath(filePath)\n//                .setListener(new FileDownloadListener() {\n//                    @Override\n//                    protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {\n//                    }\n//\n//                    @Override\n//                    protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {\n//                    }\n//\n//                    @Override\n//                    protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {\n//                    }\n//\n//                    @Override\n//                    protected void blockComplete(BaseDownloadTask task) {\n//                    }\n//\n//                    @Override\n//                    protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) {\n//                    }\n//\n//                    @Override\n//                    protected void completed(BaseDownloadTask task) {\n//                        //下载完成后,更新本地的图片cache,已经消息体的localPath\n//                        // jsonObject.put(MessageUtils.IMAGE_LOCAL_PATH,filePath);\n//                        ((Activity) context).runOnUiThread(new Runnable() {\n//                            @Override\n//                            public void run() {\n//                                progressDialog.dismiss();\n//\n//                            }\n//                        });\n//                        if (new File(filePath).exists()) {\n//                            final Bitmap bitmap = com.fanxin.tigase.utils.ImageUtils.decodeScaleImage(filePath, 240, 240);\n//                            ACache.get(context).put(htMessage.getMsgId(), bitmap);\n//                            jsonObject.put(MessageUtils.LOCAL_PATH, filePath);\n//                            htMessage.setBody(jsonObject.toJSONString());\n//                            ((Activity) context).runOnUiThread(new Runnable() {\n//                                @Override\n//                                public void run() {\n//                                    notifyDataSetChanged();\n//                                }\n//                            });\n//                            MessageManager.getInstance().saveMessage(chatTo, htMessage, false);\n//                            context.startActivity(new Intent(context, ShowBigImageActivity.class).putExtra(\"localPath\",filePath));\n//                        }\n//\n//\n//\n//                    }\n//\n//                    @Override\n//                    protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {\n//                    }\n//\n//                    @Override\n//                    protected void error(BaseDownloadTask task, Throwable e) {\n//                        ((Activity) context).runOnUiThread(new Runnable() {\n//                            @Override\n//                            public void run() {\n//                                progressDialog.dismiss();\n//                            }\n//                        });\n//                    }\n//\n//                    @Override\n//                    protected void warn(BaseDownloadTask task) {\n//                    }\n//                }).start();\n\n\n//        LinearLayout linearLayout;\n//        linearLayout.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {\n//            @Override\n//            public void onViewAttachedToWindow(View v) {\n//\n//            }\n//\n//            @Override\n//            public void onViewDetachedFromWindow(View v) {\n//\n//            }\n//        });\n\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/VoiceRecorder.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight;\n\nimport android.content.Context;\nimport android.media.MediaRecorder;\nimport android.os.Handler;\nimport android.os.SystemClock;\nimport android.text.format.Time;\nimport android.util.Log;\n\n\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.utils.PathUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.Date;\n\npublic class VoiceRecorder {\n    MediaRecorder recorder;\n\n    static final String PREFIX = \"voice\";\n    static final String EXTENSION = \".amr\";\n\n    private boolean isRecording = false;\n    private long startTime;\n    private String voiceFilePath = null;\n    private String voiceFileName = null;\n    private File file;\n    private Handler handler;\n\n    public VoiceRecorder(Handler handler) {\n        this.handler = handler;\n    }\n\n    /**\n     * start recording to the file\n     */\n    public String startRecording(Context appContext) {\n        file = null;\n        try {\n            // need to create recorder every time, otherwise, will got exception\n            // from setOutputFile when try to reuse\n            if (recorder != null) {\n                recorder.release();\n                recorder = null;\n            }\n            recorder = new MediaRecorder();\n            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);\n            recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);\n            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);\n            recorder.setAudioChannels(1); // MONO\n            recorder.setAudioSamplingRate(8000); // 8000Hz\n            recorder.setAudioEncodingBitRate(64); // seems if change this to\n                                                    // 128, still got same file\n                                                    // size.\n            // one easy way is to use temp file\n            // file = File.createTempFile(PREFIX + userId, EXTENSION,\n            // User.getVoicePath());\n            voiceFileName = getVoiceFileName(\"temp\");\n            ;\n            voiceFilePath = new PathUtils(null, HTApp.getInstance().getApplicationContext()).getVoicePath() + voiceFileName;\n            Log.d(\"voiceFilePath--->\",voiceFilePath);\n            file = new File(voiceFilePath);\n            recorder.setOutputFile(file.getAbsolutePath());\n            recorder.prepare();\n            isRecording = true;\n            recorder.start();\n        } catch (IOException e) {\n        //    EMLog.e(\"voice\", \"prepare() failed\");\n        }\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    while (isRecording) {\n                        android.os.Message msg = new android.os.Message();\n                        msg.what = recorder.getMaxAmplitude() * 13 / 0x7FFF;\n                        handler.sendMessage(msg);\n                        SystemClock.sleep(100);\n                    }\n                } catch (Exception e) {\n                    // from the crash report website, found one NPE crash from\n                    // one android 4.0.4 htc phone\n                    // maybe handler is null for some reason\n                 }\n            }\n        }).start();\n        startTime = new Date().getTime();\n         return file == null ? null : file.getAbsolutePath();\n    }\n\n    /**\n     * stop the recoding\n     * \n     * @return seconds of the voice recorded\n     */\n\n    public void discardRecording() {\n        if (recorder != null) {\n            try {\n                recorder.stop();\n                recorder.release();\n                recorder = null;\n                if (file != null && file.exists() && !file.isDirectory()) {\n                    file.delete();\n                }\n            } catch (IllegalStateException e) {\n            } catch (RuntimeException e){}\n            isRecording = false;\n        }\n    }\n\n    public int stopRecoding() {\n        if(recorder != null){\n            isRecording = false;\n            recorder.stop();\n            recorder.release();\n            recorder = null;\n            \n            if(file == null || !file.exists() || !file.isFile()){\n                return 401;\n            }\n            if (file.length() == 0) {\n                file.delete();\n                return 401;\n            }\n            int seconds = (int) (new Date().getTime() - startTime) / 1000;\n           // EMLog.d(\"voice\", \"voice recording finished. seconds:\" + seconds + \" file length:\" + file.length());\n            return seconds;\n        }\n        return 0;\n    }\n\n    protected void finalize() throws Throwable {\n        super.finalize();\n        if (recorder != null) {\n            recorder.release();\n        }\n    }\n\n    private String getVoiceFileName(String uid) {\n        Time now = new Time();\n        now.setToNow();\n        return uid + now.toString().substring(0, 15) + EXTENSION;\n    }\n\n    public boolean isRecording() {\n        return isRecording;\n    }\n\n    \n    public String getVoiceFilePath() {\n        return voiceFilePath;\n    }\n    \n    public String getVoiceFileName() {\n        return voiceFileName;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/VoiceRecorderView.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.graphics.drawable.Drawable;\nimport android.os.CountDownTimer;\nimport android.os.Handler;\nimport android.os.PowerManager;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.utils.CommonUtils;\n\n\n/**\n * Voice recorder view\n */\npublic class VoiceRecorderView extends RelativeLayout {\n    protected Context context;\n    protected LayoutInflater inflater;\n    protected Drawable[] micImages;\n    protected VoiceRecorder voiceRecorder;\n\n    protected PowerManager.WakeLock wakeLock;\n    protected ImageView micImage;\n    protected TextView recordingHint;\n    private int duration = 60;\n    protected Handler micImageHandler = new Handler() {\n        @Override\n        public void handleMessage(android.os.Message msg) {\n            // change image\n            micImage.setImageDrawable(micImages[msg.what]);\n        }\n    };\n\n    public VoiceRecorderView(Context context) {\n        super(context);\n        init(context);\n    }\n\n    public VoiceRecorderView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        init(context);\n    }\n\n    public VoiceRecorderView(Context context, AttributeSet attrs, int defStyle) {\n        super(context, attrs, defStyle);\n        init(context);\n    }\n\n    private void init(Context context) {\n        this.context = context;\n        LayoutInflater.from(context).inflate(R.layout.widget_voice_recorder, this);\n\n        micImage = (ImageView) findViewById(R.id.mic_image);\n        recordingHint = (TextView) findViewById(R.id.recording_hint);\n\n        voiceRecorder = new VoiceRecorder(micImageHandler);\n\n        // animation resources, used for recording\n        micImages = new Drawable[]{getResources().getDrawable(R.drawable.record_animate_01),\n                getResources().getDrawable(R.drawable.record_animate_02),\n                getResources().getDrawable(R.drawable.record_animate_03),\n                getResources().getDrawable(R.drawable.record_animate_04),\n                getResources().getDrawable(R.drawable.record_animate_05),\n                getResources().getDrawable(R.drawable.record_animate_06),\n                getResources().getDrawable(R.drawable.record_animate_07),\n                getResources().getDrawable(R.drawable.record_animate_08),\n                getResources().getDrawable(R.drawable.record_animate_09),\n                getResources().getDrawable(R.drawable.record_animate_10),\n                getResources().getDrawable(R.drawable.record_animate_11),\n                getResources().getDrawable(R.drawable.record_animate_12),\n                getResources().getDrawable(R.drawable.record_animate_13),\n                getResources().getDrawable(R.drawable.record_animate_14),};\n\n        wakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(\n                PowerManager.SCREEN_DIM_WAKE_LOCK, \"demo\");\n    }\n\n\n    /**\n     * on speak button touched\n     *\n     * @param v\n     * @param event\n     */\n\n    MyCountDownTimer myCountDownTimer;\n\n    public boolean onPressToSpeakBtnTouch(View v, MotionEvent event, EaseVoiceRecorderCallback recorderCallback) {\n        switch (event.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                duration = 60;\n                try {\n                    if (VoicePlayClickListener.isPlaying)\n                        VoicePlayClickListener.currentPlayListener.stopPlayVoice();\n                    v.setPressed(true);\n                    startRecording();\n\n                } catch (Exception e) {\n                    v.setPressed(false);\n                }\n                myCountDownTimer = new MyCountDownTimer(60000, 1000, v, recorderCallback, event);\n                myCountDownTimer.start();\n                return true;\n            case MotionEvent.ACTION_MOVE:\n                if (duration > 10) {\n                    if (event.getY() < 0) {\n                        showReleaseToCancelHint();\n                    } else {\n                        showMoveUpToCancelHint();\n                    }\n                }\n                return true;\n            case MotionEvent.ACTION_UP:\n\n                if (myCountDownTimer != null) {\n                    myCountDownTimer.onFinish();\n                    myCountDownTimer.cancel();\n                    myCountDownTimer = null;\n                    return true;\n                }\n\n                v.setPressed(false);\n                if (event.getY() < 0) {\n                     discardRecording();\n                } else {\n                     try {\n                        int length = stopRecoding();\n                        if (length > 0) {\n                            if (recorderCallback != null) {\n                                recorderCallback.onVoiceRecordComplete(getVoiceFilePath(), length);\n                            }\n                        } else if (length == 401) {\n                            Toast.makeText(context, R.string.Recording_without_permission, Toast.LENGTH_SHORT).show();\n                        } else {\n                            Toast.makeText(context, R.string.The_recording_time_is_too_short, Toast.LENGTH_SHORT).show();\n                        }\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                        Toast.makeText(context, R.string.send_failure_please, Toast.LENGTH_SHORT).show();\n                    }\n                }\n                return true;\n            default:\n                discardRecording();\n                return false;\n        }\n    }\n\n\n    /**\n     * 继承 CountDownTimer 防范\n     * <p>\n     * 重写 父类的方法 onTick() 、 onFinish()\n     */\n\n    public class MyCountDownTimer extends CountDownTimer {\n\n\n        private EaseVoiceRecorderCallback recorderCallback;\n        private View view;\n        private MotionEvent event;\n\n        public MyCountDownTimer(long millisInFuture, long countDownInterval, View view, EaseVoiceRecorderCallback recorderCallback, MotionEvent event) {\n            super(millisInFuture, countDownInterval);\n\n            this.recorderCallback = recorderCallback;\n            this.view = view;\n            this.event = event;\n        }\n\n        @Override\n        public void onFinish() {\n            duration = 60;\n            Log.d(\"onFinish--->\", \"onFinish\");\n            view.setPressed(false);\n            if (event.getY() < 0) {\n                // discard the recorded audio.\n                discardRecording();\n            } else {\n                // stop recording and send voice file\n                try {\n                    int length = stopRecoding();\n                    if (length > 0) {\n                        if (recorderCallback != null) {\n                            recorderCallback.onVoiceRecordComplete(getVoiceFilePath(), length);\n                        }\n                    } else if (length == 401) {\n                        Toast.makeText(context, R.string.Recording_without_permission, Toast.LENGTH_SHORT).show();\n                    } else {\n                        Toast.makeText(context, R.string.The_recording_time_is_too_short, Toast.LENGTH_SHORT).show();\n                    }\n                } catch (Exception e) {\n                    e.printStackTrace();\n                    Toast.makeText(context, R.string.send_failure_please, Toast.LENGTH_SHORT).show();\n                }\n            }\n        }\n\n        @Override\n        public void onTick(long millisUntilFinished) {\n            //  Log.d(\"millisUntilFinished--->\",millisUntilFinished+\"\");\n            if (millisUntilFinished / 1000 < 11) {\n                duration = (int) (millisUntilFinished / 1000);\n                recordingHint.setText(\"还可以录音\" + millisUntilFinished / 1000 + \"秒\");\n            }\n\n        }\n    }\n\n    public interface EaseVoiceRecorderCallback {\n        /**\n         * on voice record complete\n         *\n         * @param voiceFilePath   录音完毕后的文件路径\n         * @param voiceTimeLength 录音时长\n         */\n        void onVoiceRecordComplete(String voiceFilePath, int voiceTimeLength);\n    }\n\n    public void startRecording() {\n        if (!CommonUtils.isSdcardExist()) {\n            Toast.makeText(context, R.string.Send_voice_need_sdcard_support, Toast.LENGTH_SHORT).show();\n            return;\n        }\n        try {\n            wakeLock.acquire();\n            this.setVisibility(View.VISIBLE);\n            recordingHint.setText(context.getString(R.string.move_up_to_cancel));\n            recordingHint.setBackgroundColor(Color.TRANSPARENT);\n            voiceRecorder.startRecording(context);\n        } catch (Exception e) {\n            e.printStackTrace();\n            if (wakeLock.isHeld())\n                wakeLock.release();\n            if (voiceRecorder != null)\n                voiceRecorder.discardRecording();\n            this.setVisibility(View.INVISIBLE);\n            Toast.makeText(context, R.string.recoding_fail, Toast.LENGTH_SHORT).show();\n            return;\n        }\n    }\n\n    public void showReleaseToCancelHint() {\n        recordingHint.setText(context.getString(R.string.release_to_cancel));\n        recordingHint.setBackgroundResource(R.drawable.recording_text_hint_bg);\n    }\n\n    public void showMoveUpToCancelHint() {\n        recordingHint.setText(context.getString(R.string.move_up_to_cancel));\n        recordingHint.setBackgroundColor(Color.TRANSPARENT);\n    }\n\n    public void discardRecording() {\n        if (wakeLock.isHeld())\n            wakeLock.release();\n        try {\n            // stop recording\n            if (voiceRecorder.isRecording()) {\n                voiceRecorder.discardRecording();\n                this.setVisibility(View.INVISIBLE);\n            }\n        } catch (Exception e) {\n        }\n    }\n\n    public int stopRecoding() {\n        this.setVisibility(View.INVISIBLE);\n        if (wakeLock.isHeld())\n            wakeLock.release();\n        return voiceRecorder.stopRecoding();\n    }\n\n    public String getVoiceFilePath() {\n        return voiceRecorder.getVoiceFilePath();\n    }\n\n    public String getVoiceFileName() {\n        return voiceRecorder.getVoiceFileName();\n    }\n\n    public boolean isRecording() {\n        return voiceRecorder.isRecording();\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/DefaultEmojiconDatas.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.emoji;\n\n\nimport com.htmessage.yichatopen.R;\n\npublic class DefaultEmojiconDatas {\n    \n    private static String[] emojis = new String[]{\n        SmileUtils.ee_1,\n        SmileUtils.ee_2,\n        SmileUtils.ee_3,\n        SmileUtils.ee_4,\n        SmileUtils.ee_5,\n        SmileUtils.ee_6,\n        SmileUtils.ee_7,\n        SmileUtils.ee_8,\n        SmileUtils.ee_9,\n        SmileUtils.ee_10,\n        SmileUtils.ee_11,\n        SmileUtils.ee_12,\n        SmileUtils.ee_13,\n        SmileUtils.ee_14,\n        SmileUtils.ee_15,\n        SmileUtils.ee_16,\n        SmileUtils.ee_17,\n        SmileUtils.ee_18,\n        SmileUtils.ee_19,\n        SmileUtils.ee_20,\n        SmileUtils.ee_21,\n        SmileUtils.ee_22,\n        SmileUtils.ee_23,\n        SmileUtils.ee_24,\n        SmileUtils.ee_25,\n        SmileUtils.ee_26,\n        SmileUtils.ee_27,\n        SmileUtils.ee_28,\n        SmileUtils.ee_29,\n        SmileUtils.ee_30,\n        SmileUtils.ee_31,\n        SmileUtils.ee_32,\n        SmileUtils.ee_33,\n        SmileUtils.ee_34,\n        SmileUtils.ee_35,\n       \n    };\n    \n    private static int[] icons = new int[]{\n            R.drawable.ee_0,\n        R.drawable.ee_1,  \n        R.drawable.ee_2,\n        R.drawable.ee_3,  \n        R.drawable.ee_4,  \n        R.drawable.ee_5,  \n        R.drawable.ee_6,  \n        R.drawable.ee_7,  \n        R.drawable.ee_8,  \n        R.drawable.ee_9,  \n        R.drawable.ee_10,  \n        R.drawable.ee_11,  \n        R.drawable.ee_12,  \n        R.drawable.ee_13,  \n        R.drawable.ee_14,  \n        R.drawable.ee_15,  \n        R.drawable.ee_16,  \n        R.drawable.ee_17,  \n        R.drawable.ee_18,  \n        R.drawable.ee_19,  \n        R.drawable.ee_20,  \n        R.drawable.ee_21,  \n        R.drawable.ee_22,  \n        R.drawable.ee_23,  \n        R.drawable.ee_24,  \n        R.drawable.ee_25,  \n        R.drawable.ee_26,  \n        R.drawable.ee_27,  \n        R.drawable.ee_28,  \n        R.drawable.ee_29,  \n        R.drawable.ee_30,  \n        R.drawable.ee_31,  \n        R.drawable.ee_32,  \n        R.drawable.ee_33,  \n        R.drawable.ee_34,  \n\n    };\n    \n    \n    private static final Emojicon[] DATA = createData();\n    \n    private static Emojicon[] createData(){\n        Emojicon[] datas = new Emojicon[icons.length];\n        for(int i = 0; i < icons.length; i++){\n            datas[i] = new Emojicon(icons[i], emojis[i], Emojicon.Type.NORMAL);\n        }\n        return datas;\n    }\n    \n    public static Emojicon[] getData(){\n        return DATA;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/EmojiFragment.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.emoji;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.design.widget.TabLayout;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.view.PagerAdapter;\nimport android.support.v4.view.ViewPager;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.GridView;\nimport android.widget.ImageButton;\n\nimport com.htmessage.yichatopen.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/7/5.\n * qq 84543217\n */\n\npublic class EmojiFragment extends Fragment {\n    private ViewPager viewPager;\n    private TabLayout tableLayout;\n    private List<View> views;\n    private List<Emojicon> emojicons;\n    private int emojiconColumns = 7;\n    private int emojiconRows = 3;\n    private OnEmojiListener onEmojiListener;\n\n    public EmojiFragment(List<Emojicon> emojicons, int emojiconColumns, int emojiconRows, OnEmojiListener onEmojiListener) {\n        this.emojicons = emojicons;\n        this.emojiconColumns = emojiconColumns;\n        this.emojiconRows = emojiconRows;\n        this.onEmojiListener=onEmojiListener;\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View root = inflater.inflate(R.layout.fragment_emoji, container,false);\n        viewPager = (ViewPager) root.findViewById(R.id.viewpager_emoji);\n        tableLayout = (TabLayout) root.findViewById(R.id.tabLayout_dot);\n        return root;\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n       final List<View> views= getViews();\n        viewPager.setAdapter(new PagerAdapter() {\n            @Override\n            public int getCount() {\n                return views.size();\n            }\n\n            @Override\n            public boolean isViewFromObject(View arg0, Object arg1) {\n                return arg0 == arg1;\n            }\n\n            @Override\n            public Object instantiateItem(ViewGroup arg0, int arg1) {\n                ((ViewPager) arg0).addView(views.get(arg1));\n                return views.get(arg1);\n            }\n\n\n\n            @Override\n            public void destroyItem(ViewGroup arg0, int arg1, Object arg2) {\n                ((ViewPager) arg0).removeView(views.get(arg1));\n\n            }\n        });\n        tableLayout.setupWithViewPager(viewPager);\n        TabLayout.Tab[] tabs = new TabLayout.Tab[views.size()];\n\n        for (int i = 0; i < views.size(); i++) {\n             tabs[i] = tableLayout.getTabAt(i);\n            ImageButton imageView=new ImageButton(getContext());\n            imageView.setBackground(null);\n            imageView.setImageResource(R.drawable.dot_emoji);\n            tabs[i].setCustomView(imageView);\n\n        }\n\n    }\n\n    private List<View> getViews() {\n\n        int itemSize = emojiconColumns * emojiconRows -1;\n        int totalSize = emojicons.size();\n        Emojicon.Type emojiType = Emojicon.Type.NORMAL ;\n        if(totalSize!=0){\n            emojiType=emojicons.get(0).getType();\n        }\n\n        if(emojiType == Emojicon.Type.BIG_EXPRESSION){\n            itemSize = emojiconColumns * emojiconRows;\n        }\n        int pageSize = totalSize % itemSize == 0 ? totalSize/itemSize : totalSize/itemSize + 1;\n        List<View> views = new ArrayList<View>();\n        for(int i = 0; i < pageSize; i++){\n            View view = View.inflate(getContext(), R.layout.emoji_gridview, null);\n            GridView gv = (GridView) view.findViewById(R.id.gridview);\n            gv.setNumColumns(emojiconColumns);\n            List<Emojicon> list = new ArrayList<Emojicon>();\n            if(i != pageSize -1){\n                list.addAll(emojicons.subList(i * itemSize, (i+1) * itemSize));\n            }else{\n                list.addAll(emojicons.subList(i * itemSize, totalSize));\n            }\n            if(emojiType != Emojicon.Type.BIG_EXPRESSION){\n                Emojicon deleteIcon = new Emojicon();\n                deleteIcon.setEmojiText(SmileUtils.DELETE_KEY);\n                list.add(deleteIcon);\n            }\n            final EmojiconGridAdapter gridAdapter = new EmojiconGridAdapter(getContext(), 1, list, emojiType);\n            gv.setAdapter(gridAdapter);\n            gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n\n                @Override\n                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                    Emojicon emojicon = gridAdapter.getItem(position);\n                    if(onEmojiListener != null){\n                        String emojiText = emojicon.getEmojiText();\n                        if(emojiText != null && emojiText.equals(SmileUtils.DELETE_KEY)){\n                            onEmojiListener.onDeleteImageClicked();\n                        }else{\n                            onEmojiListener.onExpressionClicked(emojicon);\n                        }\n\n                    }\n\n                }\n            });\n\n            views.add(view);\n        }\n        return views;\n    }\n\n    public interface OnEmojiListener{\n        void onDeleteImageClicked();\n        void onExpressionClicked(Emojicon emojicon);\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/Emojicon.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.emoji;\n\npublic class Emojicon {\n    public Emojicon(){\n    }\n    \n    /**\n     * constructor\n     * @param icon- resource id of the icon\n     * @param emojiText- text of emoji icon\n     */\n    public Emojicon(int icon, String emojiText){\n        this.icon = icon;\n        this.emojiText = emojiText;\n        this.type = Type.NORMAL;\n    }\n    \n    /**\n     * constructor\n     * @param icon - resource id of the icon\n     * @param emojiText - text of emoji icon\n     * @param type - normal or big\n     */\n    public Emojicon(int icon, String emojiText, Type type){\n        this.icon = icon;\n        this.emojiText = emojiText;\n        this.type = type;\n    }\n    \n    \n    /**\n     * identity code\n     */\n    private String identityCode;\n    \n    /**\n     * static icon resource id\n     */\n    private int icon;\n    \n    /**\n     * dynamic icon resource id\n     */\n    private int bigIcon;\n    \n    /**\n     * text of emoji, could be null for big icon\n     */\n    private String emojiText;\n    \n    /**\n     * name of emoji icon\n     */\n    private String name;\n    \n    /**\n     * normal or big\n     */\n    private Type type;\n    \n    /**\n     * path of icon\n     */\n    private String iconPath;\n    \n    /**\n     * path of big icon\n     */\n    private String bigIconPath;\n    \n    \n    /**\n     * get the resource id of the icon\n     * @return\n     */\n    public int getIcon() {\n        return icon;\n    }\n\n\n    /**\n     * set the resource id of the icon\n     * @param icon\n     */\n    public void setIcon(int icon) {\n        this.icon = icon;\n    }\n\n\n    /**\n     * get the resource id of the big icon\n     * @return\n     */\n    public int getBigIcon() {\n        return bigIcon;\n    }\n\n\n    /**\n     * set the resource id of the big icon\n     * @return\n     */\n    public void setBigIcon(int dynamicIcon) {\n        this.bigIcon = dynamicIcon;\n    }\n\n\n    /**\n     * get text of emoji icon\n     * @return\n     */\n    public String getEmojiText() {\n        return emojiText;\n    }\n\n\n    /**\n     * set text of emoji icon\n     * @param emojiText\n     */\n    public void setEmojiText(String emojiText) {\n        this.emojiText = emojiText;\n    }\n\n    /**\n     * get name of emoji icon\n     * @return\n     */\n    public String getName() {\n        return name;\n    }\n    \n    /**\n     * set name of emoji icon\n     * @param name\n     */\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    /**\n     * get type\n     * @return\n     */\n    public Type getType() {\n        return type;\n    }\n\n\n    /**\n     * set type\n     * @param type\n     */\n    public void setType(Type type) {\n        this.type = type;\n    }\n\n\n    /**\n     * get icon path\n     * @return\n     */\n    public String getIconPath() {\n        return iconPath;\n    }\n\n\n    /**\n     * set icon path\n     * @param iconPath\n     */\n    public void setIconPath(String iconPath) {\n        this.iconPath = iconPath;\n    }\n\n\n    /**\n     * get path of big icon\n     * @return\n     */\n    public String getBigIconPath() {\n        return bigIconPath;\n    }\n\n\n    /**\n     * set path of big icon\n     * @param bigIconPath\n     */\n    public void setBigIconPath(String bigIconPath) {\n        this.bigIconPath = bigIconPath;\n    }\n\n    /**\n     * get identity code\n     * @return\n     */\n    public String getIdentityCode() {\n        return identityCode;\n    }\n    \n    /**\n     * set identity code\n     * @param\n     */\n    public void setIdentityCode(String identityCode) {\n        this.identityCode = identityCode;\n    }\n\n    public static final String newEmojiText(int codePoint) {\n        if (Character.charCount(codePoint) == 1) {\n            return String.valueOf(codePoint);\n        } else {\n            return new String(Character.toChars(codePoint));\n        }\n    }\n\n\n\n    public enum Type{\n        /**\n         * normal icon, can be input one or more in edit view\n         */\n        NORMAL,\n        /**\n         * big icon, send out directly when your press it\n         */\n        BIG_EXPRESSION\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/EmojiconGridAdapter.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.emoji;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ArrayAdapter;\nimport android.widget.ImageView;\n\nimport com.bumptech.glide.Glide;\nimport com.htmessage.yichatopen.R;\n\n\nimport java.util.List;\n\n\n\npublic class EmojiconGridAdapter extends ArrayAdapter<Emojicon>{\n\n    private Emojicon.Type emojiconType;\n\n\n    public EmojiconGridAdapter(Context context, int textViewResourceId, List<Emojicon> objects, Emojicon.Type emojiconType) {\n        super(context, textViewResourceId, objects);\n        this.emojiconType = emojiconType;\n    }\n    \n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        if(convertView == null){\n            if(emojiconType == Emojicon.Type.BIG_EXPRESSION){\n                convertView = View.inflate(getContext(), R.layout.row_big_expression, null);\n            }else{\n                convertView = View.inflate(getContext(), R.layout.row_expression, null);\n            }\n        }\n        \n        ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_expression);\n        Emojicon emojicon = getItem(position);\n\n        //if you want show a name for the icons, you can set text to R.id.tv_name\n\n        if(SmileUtils.DELETE_KEY.equals(emojicon.getEmojiText())){\n            imageView.setImageResource(R.drawable.delete_expression);\n        }else{\n            if(emojicon.getIcon() != 0){\n                imageView.setImageResource(emojicon.getIcon());\n            }else if(emojicon.getIconPath() != null){\n                Glide.with(getContext()).load(emojicon.getIconPath()).placeholder(R.drawable.default_expression).into(imageView);\n            }\n        }\n        \n        \n        return convertView;\n    }\n    \n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/emoji/SmileUtils.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.activity.chat.weight.emoji;\n\nimport java.io.File;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport android.net.Uri;\nimport android.text.Spannable;\nimport android.text.Spannable.Factory;\nimport android.text.style.ImageSpan;\n\nimport com.htmessage.yichatopen.R;\n\n\npublic class SmileUtils {\n    public static final String DELETE_KEY = \"em_delete_delete_expression\";\n    \n\tpublic static final String ee_1 = \"[):]\";\n\tpublic static final String ee_2 = \"[:D]\";\n\tpublic static final String ee_3 = \"[;)]\";\n\tpublic static final String ee_4 = \"[:-o]\";\n\tpublic static final String ee_5 = \"[:p]\";\n\tpublic static final String ee_6 = \"[(H)]\";\n\tpublic static final String ee_7 = \"[:@]\";\n\tpublic static final String ee_8 = \"[:s]\";\n\tpublic static final String ee_9 = \"[:$]\";\n\tpublic static final String ee_10 = \"[:(]\";\n\tpublic static final String ee_11 = \"[:-(]\";\n\tpublic static final String ee_12 = \"[:|]\"; \n\tpublic static final String ee_13 = \"[(a)]\";\n\tpublic static final String ee_14 = \"[8o|]\";\n\tpublic static final String ee_15 = \"[8-|]\";\n\tpublic static final String ee_16 = \"[+o(]\";\n\tpublic static final String ee_17 = \"[<o)]\";\n\tpublic static final String ee_18 = \"[|-)]\";\n\tpublic static final String ee_19 = \"[*-)]\";\n\tpublic static final String ee_20 = \"[:-#]\";\n\tpublic static final String ee_21 = \"[:-*]\";\n\tpublic static final String ee_22 = \"[^o)]\";\n\tpublic static final String ee_23 = \"[8-)]\";\n\tpublic static final String ee_24 = \"[(|)]\";\n\tpublic static final String ee_25 = \"[(u)]\";\n\tpublic static final String ee_26 = \"[(S)]\";\n\tpublic static final String ee_27 = \"[(*)]\";\n\tpublic static final String ee_28 = \"[(#)]\";\n\tpublic static final String ee_29 = \"[(R)]\";\n\tpublic static final String ee_30 = \"[({)]\";\n\tpublic static final String ee_31 = \"[(})]\";\n\tpublic static final String ee_32 = \"[(k)]\";\n\tpublic static final String ee_33 = \"[(F)]\";\n\tpublic static final String ee_34 = \"[(W)]\";\n\tpublic static final String ee_35 = \"[(D)]\";\n\n\n\t\n\tprivate static final Factory spannableFactory = Spannable.Factory\n\t        .getInstance();\n\t\n\tprivate static final Map<Pattern, Object> emoticons = new HashMap<Pattern, Object>();\n\t\n\n\tstatic {\n\t    Emojicon[] emojicons = DefaultEmojiconDatas.getData();\n\t    for(int i = 0; i < emojicons.length; i++){\n\t        addPattern(emojicons[i].getEmojiText(), emojicons[i].getIcon());\n\t    }\n\n\t    \n\t}\n\n\t/**\n\t * add text and icon to the map\n\t * @param emojiText-- text of emoji\n\t * @param icon -- resource id or local path\n\t */\n\tpublic static void addPattern(String emojiText, Object icon){\n\t    emoticons.put(Pattern.compile(Pattern.quote(emojiText)), icon);\n\t}\n\t\n\n\t/**\n\t * replace existing spannable with smiles\n\t * @param context\n\t * @param spannable\n\t * @return\n\t */\n\tpublic static boolean addSmiles(Context context, Spannable spannable) {\n\t    boolean hasChanges = false;\n\t    for (Entry<Pattern, Object> entry : emoticons.entrySet()) {\n\t        Matcher matcher = entry.getKey().matcher(spannable);\n\t        while (matcher.find()) {\n\t            boolean set = true;\n\t            for (ImageSpan span : spannable.getSpans(matcher.start(),\n\t                    matcher.end(), ImageSpan.class))\n\t                if (spannable.getSpanStart(span) >= matcher.start()\n\t                        && spannable.getSpanEnd(span) <= matcher.end())\n\t                    spannable.removeSpan(span);\n\t                else {\n\t                    set = false;\n\t                    break;\n\t                }\n\t            if (set) {\n\t                hasChanges = true;\n\t                Object value = entry.getValue();\n\t                if(value instanceof String && !((String) value).startsWith(\"http\")){\n\t                    File file = new File((String) value);\n\t                    if(!file.exists() || file.isDirectory()){\n\t                        return false;\n\t                    }\n\t                    ImageSpan imageSpan=new ImageSpan(context, Uri.fromFile(file));\n\t\t\t\t\t\tDrawable drawable=imageSpan.getDrawable();\n\t\t\t\t\t\tdrawable.setBounds(0,0,25,25);\n\t\t\t\t\t\timageSpan=new ImageSpan(drawable);\n\t                    spannable.setSpan(imageSpan,\n\t                            matcher.start(), matcher.end(),\n\t                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);\n\t                }else{\n\t\t\t\t\t\tImageSpan imageSpan=new ImageSpan(context, (Integer)value);\n\t\t\t\t\t\tDrawable drawable=imageSpan.getDrawable();\n\t\t\t\t\t\tint size=context.getResources().getDimensionPixelSize(R.dimen.emoji_size);\n\t\t\t\t\t\tdrawable.setBounds(0,0,size ,size);\n\t\t\t\t\t\timageSpan=new ImageSpan(drawable);\n\t\t\t\t\t\tspannable.setSpan(imageSpan,\n\t\t\t\t\t\t\t\tmatcher.start(), matcher.end(),\n\t\t\t\t\t\t\t\tSpannable.SPAN_EXCLUSIVE_EXCLUSIVE);\n\n\t                    spannable.setSpan(imageSpan,\n\t                            matcher.start(), matcher.end(),\n\t                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);\n\t                }\n\t            }\n\t        }\n\t    }\n\t    \n\t    return hasChanges;\n\t}\n\n\tpublic static Spannable getSmiledText(Context context, CharSequence text) {\n\t    Spannable spannable = spannableFactory.newSpannable(text);\n\t    addSmiles(context, spannable);\n\t    return spannable;\n\t}\n\t\n\tpublic static boolean containsKey(String key){\n\t\tboolean b = false;\n\t\tfor (Entry<Pattern, Object> entry : emoticons.entrySet()) {\n\t        Matcher matcher = entry.getKey().matcher(key);\n\t        if (matcher.find()) {\n\t        \tb = true;\n\t        \tbreak;\n\t        }\n\t\t}\n\t\t\n\t\treturn b;\n\t}\n\t\n\tpublic static int getSmilesSize(){\n        return emoticons.size();\n    }\n    \n\t\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/DensityUtil.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.loadmore;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.graphics.Rect;\nimport android.os.Handler;\nimport android.text.TextPaint;\nimport android.text.TextUtils;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.ViewTreeObserver;\nimport android.view.WindowManager;\nimport android.widget.ScrollView;\nimport android.widget.TextView;\n\nimport java.lang.reflect.Field;\n\npublic class DensityUtil {\n\n\tpublic static int dip2px(Context context, float dpValue) {\n\t\tfinal float scale = context.getResources().getDisplayMetrics().density;\n\t\treturn (int) (dpValue * scale + 0.5f);\n\t}\n\n\n\tpublic static int px2dip(Context context, float pxValue) {\n\t\tfinal float scale = context.getResources().getDisplayMetrics().density;\n\t\treturn (int) (pxValue / scale + 0.5f);\n\t}\n\t\n\tpublic static float getScreenDensity(Context context) {\n\t\treturn context.getResources().getDisplayMetrics().density;\n\t}\n\n\tpublic static int getStatusBarHeight(Context ctx) {\n\t\tClass<?> c = null;\n\n\t\tObject obj = null;\n\n\t\tField field = null;\n\n\t\tint x = 0, sbar = 0;\n\n\t\ttry {\n\n\t\t\tc = Class.forName(\"com.android.internal.R$dimen\");\n\n\t\t\tobj = c.newInstance();\n\n\t\t\tfield = c.getField(\"status_bar_height\");\n\n\t\t\tx = Integer.parseInt(field.get(obj).toString());\n\n\t\t\tsbar = ctx.getResources().getDimensionPixelSize(x);\n\n\t\t} catch (Exception e1) {\n\n\t\t\te1.printStackTrace();\n\n\t\t}\n\n\t\treturn sbar;\n\t}\n\t\n\tpublic static int getScreenHeightWithoutTitlebar(Context ctx) {\n\t\tint[] screenWidthAndHeight = getScreenWidthAndHeight(ctx);\n\t\treturn screenWidthAndHeight[1] -getStatusBarHeight(ctx)- dip2px(ctx, 48);\n\t}\n\n\tpublic static int[] getScreenWidthAndHeight(Context ctx) {\n\t\tWindowManager mWm = (WindowManager) ctx\n\t\t\t\t.getSystemService(Context.WINDOW_SERVICE);\n\n\t\tDisplayMetrics dm = new DisplayMetrics();\n\t\t// 获取屏幕信息\n\t\tmWm.getDefaultDisplay().getMetrics(dm);\n\n\t\tint screenWidth = dm.widthPixels;\n\n\t\tint screenHeigh = dm.heightPixels;\n\n\t\treturn new int[] { screenWidth, screenHeigh };\n\t}\n\t\n\tpublic static void addOnSoftKeyBoardVisibleListener(final Activity activity, final ScrollView scrollView) {\n\t\tfinal View decorView = activity.getWindow().getDecorView();\n\t\tdecorView.getViewTreeObserver().addOnGlobalLayoutListener(\n\t\t\t\tnew ViewTreeObserver.OnGlobalLayoutListener() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void onGlobalLayout() {\n\t\t\t\t\t\tRect rect = new Rect();\n\t\t\t\t\t\tdecorView.getWindowVisibleDisplayFrame(rect);\n\t\t\t\t\t\tint displayHight = rect.bottom - rect.top;\n\t\t\t\t\t\tint hight = decorView.getHeight();\n\t\t\t\t\t\tboolean visible = (double) displayHight / hight < 0.8;// 决断键盘是弹�?\n\t\t\t\t\t\tSystem.out.println(\"===监听\" + visible);\n\t\t\t\t\t\tif (visible) {\n\n\t\t\t\t\t\t\tHandler mHandler = new Handler();\n\t\t\t\t\t\t\tmHandler.postDelayed(new Runnable() {\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic void run() {\n//\t\t\t\t\t\t\t\t\tscrollView\n//\t\t\t\t\t\t\t\t\t\t\t.fullScroll(ScrollView.FOCUS_DOWN);// ScrollView滚动到底\n\t\t\t\t\t\t\t\t\tscrollView.scrollTo(0, DensityUtil.dip2px(activity, 167));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, 50);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n \tpublic static String getEllipsisedText(TextView textView) {\n\t    try {\n\t\t\tString text = textView.getText().toString();\n\t\t\tint lines = textView.getLineCount();\n\t\t\tint width = textView.getWidth();\n\t\t\tint len = text.length();\n\t\t\t\n\t\t\tLog.d(\"Test\", \"text-->\" + text + \"; lines-->\" + lines + \"; width-->\" + width + \";len-->\" + len);\n\t\t\tTextUtils.TruncateAt where = TextUtils.TruncateAt.END;\n\t\t\tTextPaint paint = textView.getPaint();\n\n\t\t\tStringBuffer result = new StringBuffer();\n\n\t\t\tint spos = 0, cnt, tmp, hasLines = 0;\n\n\t\t\twhile(hasLines < lines - 1) {\n\t\t\t    cnt = paint.breakText(text, spos, len, true, width, null);\n\t\t\t    if(cnt >= len - spos) {\n\t\t\t        result.append(text.substring(spos));\n\t\t\t        break;\n\t\t\t    }\n\n\t\t\t    tmp = text.lastIndexOf('\\n', spos + cnt - 1);\n\n\t\t\t    if(tmp >= 0 && tmp < spos + cnt) {\n\t\t\t        result.append(text.substring(spos, tmp + 1));\n\t\t\t        spos += tmp + 1;\n\t\t\t    }\n\t\t\t    else {\n\t\t\t        tmp = text.lastIndexOf(' ', spos + cnt - 1);\n\t\t\t        if(tmp >= spos) {\n\t\t\t            result.append(text.substring(spos, tmp + 1));\n\t\t\t            spos += tmp + 1;\n\t\t\t        }\n\t\t\t        else {\n\t\t\t            result.append(text.substring(spos, cnt));\n\t\t\t            spos += cnt;\n\t\t\t        }\n\t\t\t    }\n\n\t\t\t    hasLines++;\n\t\t\t}\n\n\t\t\tif(spos < len) {\n\t\t\t    result.append(TextUtils.ellipsize(text.subSequence(spos, len), paint, (float) width, where));\n\t\t\t}\n\n\t\t\treturn result.toString();\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t    \n\t    return null;\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/Pacman.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.loadmore;\n\nimport android.animation.Animator;\nimport android.animation.ValueAnimator;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.graphics.RectF;\nimport android.view.animation.LinearInterpolator;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by caizhiming on 2016/2/5.\n */\npublic class Pacman extends ProgressViewController {\n\n    private float translateX;\n\n    private int alpha;\n\n    private float degrees1,degrees2;\n\n    @Override\n    public void draw(Canvas canvas, Paint paint) {\n        drawPacman(canvas,paint);\n        drawCircle(canvas,paint);\n    }\n\n    private void drawPacman(Canvas canvas, Paint paint){\n        float x=getWidth()/2;\n        float y=getHeight()/2;\n\n        canvas.save();\n\n        canvas.translate(x, y);\n        canvas.rotate(degrees1);\n        paint.setAlpha(255);\n        RectF rectF1=new RectF(-x/1.7f,-y/1.7f,x/1.7f,y/1.7f);\n        canvas.drawArc(rectF1, 0, 270, true, paint);\n\n        canvas.restore();\n\n        canvas.save();\n        canvas.translate(x, y);\n        canvas.rotate(degrees2);\n        paint.setAlpha(255);\n        RectF rectF2=new RectF(-x/1.7f,-y/1.7f,x/1.7f,y/1.7f);\n        canvas.drawArc(rectF2,90,270,true,paint);\n        canvas.restore();\n    }\n\n\n    private void drawCircle(Canvas canvas, Paint paint) {\n        float radius=getWidth()/11;\n        paint.setAlpha(alpha);\n        canvas.drawCircle(translateX, getHeight() / 2, radius, paint);\n    }\n\n    @Override\n    public List<Animator> createAnimation() {\n        List<Animator> animators=new ArrayList<>();\n        float startT=getWidth()/11;\n        ValueAnimator translationAnim= ValueAnimator.ofFloat(getWidth()-startT,getWidth()/2);\n        translationAnim.setDuration(650);\n        translationAnim.setInterpolator(new LinearInterpolator());\n        translationAnim.setRepeatCount(-1);\n        translationAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                translateX = (float) animation.getAnimatedValue();\n                postInvalidate();\n            }\n        });\n        translationAnim.start();\n\n        ValueAnimator alphaAnim= ValueAnimator.ofInt(255,122);\n        alphaAnim.setDuration(650);\n        alphaAnim.setRepeatCount(-1);\n        alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                alpha = (int) animation.getAnimatedValue();\n                postInvalidate();\n            }\n        });\n        alphaAnim.start();\n\n        ValueAnimator rotateAnim1= ValueAnimator.ofFloat(0, 45, 0);\n        rotateAnim1.setDuration(650);\n        rotateAnim1.setRepeatCount(-1);\n        rotateAnim1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                degrees1 = (float) animation.getAnimatedValue();\n                postInvalidate();\n            }\n        });\n        rotateAnim1.start();\n\n        ValueAnimator rotateAnim2= ValueAnimator.ofFloat(0,-45,0);\n        rotateAnim2.setDuration(650);\n        rotateAnim2.setRepeatCount(-1);\n        rotateAnim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                degrees2 = (float) animation.getAnimatedValue();\n                postInvalidate();\n            }\n        });\n        rotateAnim2.start();\n\n        animators.add(translationAnim);\n        animators.add(alphaAnim);\n        animators.add(rotateAnim1);\n        animators.add(rotateAnim2);\n        return animators;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/ProgressView.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.loadmore;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.os.Build;\nimport android.util.AttributeSet;\nimport android.view.View;\n\n\n/**\n * Created by caizhiming on 2016/2/5.\n */\npublic class ProgressView extends View {\n\n\n    public static final int DEFAULT_SIZE=25;//dp\n\n    int mStyleColor;\n\n    Paint mPaint;\n\n    ProgressViewController mIndicatorController;\n\n    private boolean mHasAnimation;\n\n\n    public ProgressView(Context context) {\n        super(context);\n        init(null, 0);\n    }\n\n    public ProgressView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        init(attrs, 0);\n    }\n\n    public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(attrs, defStyleAttr);\n    }\n\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public ProgressView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n        init(attrs, defStyleAttr);\n    }\n\n    private void init(AttributeSet attrs, int defStyle) {\n        mStyleColor = Color.WHITE;\n        mPaint=new Paint();\n        mPaint.setColor(mStyleColor);\n        mPaint.setStyle(Paint.Style.FILL);\n        mPaint.setAntiAlias(true);\n        applyIndicator();\n    }\n    public void setStyleColor(int color){\n        mStyleColor = color;\n        mPaint.setColor(mStyleColor);\n        this.invalidate();\n    }\n\n    private void applyIndicator(){\n        mIndicatorController=new Pacman();\n        mIndicatorController.setTarget(this);\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        int width  = measureDimension(dp2px(DEFAULT_SIZE), widthMeasureSpec);\n        int height = measureDimension(dp2px(DEFAULT_SIZE), heightMeasureSpec);\n        setMeasuredDimension(width, height);\n    }\n\n    private int measureDimension(int defaultSize,int measureSpec){\n        int result = defaultSize;\n        int specMode = MeasureSpec.getMode(measureSpec);\n        int specSize = MeasureSpec.getSize(measureSpec);\n        if (specMode == MeasureSpec.EXACTLY) {\n            result = specSize;\n        } else if (specMode == MeasureSpec.AT_MOST) {\n            result = Math.min(defaultSize, specSize);\n        } else {\n            result = defaultSize;\n        }\n        return result;\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        drawIndicator(canvas);\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        super.onLayout(changed, left, top, right, bottom);\n        if (!mHasAnimation){\n            mHasAnimation=true;\n            applyAnimation();\n        }\n    }\n\n    @Override\n    public void setVisibility(int v) {\n        if (getVisibility() != v) {\n            super.setVisibility(v);\n            if (v == GONE || v == INVISIBLE) {\n                mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.END);\n            } else {\n                mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.START);\n            }\n        }\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        super.onDetachedFromWindow();\n        mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.CANCEL);\n    }\n\n    @Override\n    protected void onAttachedToWindow() {\n        super.onAttachedToWindow();\n        mIndicatorController.setAnimationStatus(ProgressViewController.AnimStatus.START);\n    }\n\n    void drawIndicator(Canvas canvas){\n        mIndicatorController.draw(canvas, mPaint);\n    }\n\n    void applyAnimation(){\n        mIndicatorController.initAnimation();\n    }\n\n    private int dp2px(int dpValue) {\n        return (int) getContext().getResources().getDisplayMetrics().density * dpValue;\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/ProgressViewController.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.loadmore;\n\nimport android.animation.Animator;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.view.View;\n\nimport java.util.List;\n\n/**\n * Created by caizhiming on 2016/2/5.\n */\npublic abstract class ProgressViewController {\n\n\n    private View mTarget;\n\n    private List<Animator> mAnimators;\n\n\n    public void setTarget(View target){\n        this.mTarget=target;\n    }\n\n    public View getTarget(){\n        return mTarget;\n    }\n\n\n    public int getWidth(){\n        return mTarget.getWidth();\n    }\n\n    public int getHeight(){\n        return mTarget.getHeight();\n    }\n\n    public void postInvalidate(){\n        mTarget.postInvalidate();\n    }\n\n    /**\n     * draw indicator\n     * @param canvas\n     * @param paint\n     */\n    public abstract void draw(Canvas canvas, Paint paint);\n\n    /**\n     * create animation or animations\n     */\n    public abstract List<Animator> createAnimation();\n\n    public void initAnimation(){\n        mAnimators=createAnimation();\n    }\n\n    /**\n     * make animation to start or end when target\n     * view was be Visible or Gone or Invisible.\n     * make animation to cancel when target view\n     * be onDetachedFromWindow.\n     * @param animStatus\n     */\n    public void setAnimationStatus(AnimStatus animStatus){\n        if (mAnimators==null){\n            return;\n        }\n        int count=mAnimators.size();\n        for (int i = 0; i < count; i++) {\n            Animator animator=mAnimators.get(i);\n            boolean isRunning=animator.isRunning();\n            switch (animStatus){\n                case START:\n                    if (!isRunning){\n                        animator.start();\n                    }\n                    break;\n                case END:\n                    if (isRunning){\n                        animator.end();\n                    }\n                    break;\n                case CANCEL:\n                    if (isRunning){\n                        animator.cancel();\n                    }\n                    break;\n            }\n        }\n    }\n\n\n    public enum AnimStatus{\n        START,END,CANCEL\n    }\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/PullToLoadMoreListView.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.loadmore;\n\nimport android.animation.Animator;\nimport android.animation.ValueAnimator;\nimport android.content.Context;\nimport android.support.v4.view.ViewCompat;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.MotionEvent;\nimport android.view.ViewGroup;\nimport android.view.animation.DecelerateInterpolator;\nimport android.widget.FrameLayout;\nimport android.widget.ListView;\n\n\n/**\n * Created by caizhiming on 2016/2/4.\n * 下拉加载更多控件（仿QQ和微信的对话聊天记录页面）\n */\npublic class PullToLoadMoreListView extends FrameLayout {\n    public static final String TAG = PullToLoadMoreListView.class.getSimpleName();\n\n    private RefreshHeader mRefreshHeader;\n    private ListView mListView;\n    private int mHeight;\n\n    private DecelerateInterpolator mInterpolator = new DecelerateInterpolator(5);\n\n\n    private int mHeaderHeight;\n    private float mStartY;\n    private float mCurY;\n    private boolean mIsRefreshing;\n\n    private int mLastCount = 0;\n    private float mLastTranslationY = 0f;\n\n\n    public static final int REFRESH_STATUS_PULL_REFRESH = 0;//查看更早记录...;\n    public static final int REFRESH_STATUS_RELEASE_REFRESH = 1;//松开开始加载...\n    public static final int REFRESH_STATUS_REFRESHING = 2;// \"正在加载...\";\n    public static final int REFRESH_STATUS_REFRESH_FINISH = 3;//\"加载完成\";\n    private int mRefreshStatus = REFRESH_STATUS_PULL_REFRESH;\n\n\n    public PullToLoadMoreListView(Context context) {\n        this(context, null, 0);\n    }\n\n    public PullToLoadMoreListView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public PullToLoadMoreListView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context, attrs, defStyleAttr);\n    }\n    public ListView getListView(){\n        return  mListView;\n    }\n    private void init(Context context, AttributeSet attrs, int defStyleAttr) {\n        mHeaderHeight =  DensityUtil.dip2px(getContext(), 50);\n\n        addHeaderView(context);\n        addListView(context, attrs);\n    }\n\n    private void addHeaderView(Context context){\n        mRefreshHeader = new RefreshHeader(context);\n        mHeaderHeight = (int) mRefreshHeader.getHeaderHeight();\n        addView(mRefreshHeader, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mHeaderHeight));\n    }\n    private void addListView(Context context, AttributeSet attrs){\n        mListView = new ListView(context,attrs);\n        addView(mListView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));\n    }\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        if(mHeight <= 0){\n            mHeight = getMeasuredHeight();\n            Log.d(\"czm\", \"Height =\" + mHeight);\n        }\n    }\n\n    private boolean canChildScrollUp() {\n        if (mListView == null) {\n            return false;\n        }\n        return ViewCompat.canScrollVertically(mListView, -1);\n    }\n    @Override\n    public boolean onInterceptTouchEvent(MotionEvent ev) {\n        if (mIsRefreshing) {\n            return true;\n        }\n        switch (ev.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                mStartY = ev.getY();\n                mCurY = mStartY;\n                break;\n            case MotionEvent.ACTION_MOVE:\n                float curY = ev.getY();\n                float dy = curY - mStartY;\n                Log.d(\"czm\", \"dy=\" + dy);\n                if (dy > 0 && !canChildScrollUp()) {\n                    return true;\n                }\n                break;\n        }\n        return super.onInterceptTouchEvent(ev);\n    }\n    @Override\n    public boolean onTouchEvent(MotionEvent event) {\n        if (mIsRefreshing) {\n            return super.onTouchEvent(event);\n        }\n        switch (event.getAction()) {\n            case MotionEvent.ACTION_MOVE:\n                mCurY = event.getY();\n                float dy = mCurY - mStartY;\n                Log.v(\"czm\",\"dy=====\"+dy);\n                if(dy <0)\n                    return true;\n                dy = Math.max(0, dy);\n                if (mListView != null) {\n                    Log.d(\"czm\", \"dy/mHeight=\" + (dy / mHeight));\n                    float offsetY = mInterpolator.getInterpolation(dy / mHeight) * dy/3;\n                    mListView.setTranslationY(offsetY);\n                    mRefreshHeader.getLayoutParams().height = (int) (offsetY+0.5f);\n                    mRefreshHeader.requestLayout();\n                    if(mListView.getTranslationY() >= mHeaderHeight){\n                        mRefreshStatus = REFRESH_STATUS_RELEASE_REFRESH;\n                        mRefreshHeader.updateRefreshStatus(mRefreshStatus);\n                    }else{\n                        mRefreshStatus = REFRESH_STATUS_PULL_REFRESH;\n                        mRefreshHeader.updateRefreshStatus(mRefreshStatus);\n                    }\n                }\n                return true;\n\n            case MotionEvent.ACTION_UP:\n            case MotionEvent.ACTION_CANCEL:\n                if(mListView != null){\n                    if(mListView.getTranslationY() >= mHeaderHeight){\n                        mRefreshStatus = REFRESH_STATUS_REFRESHING;\n                        mRefreshHeader.updateRefreshStatus(mRefreshStatus);\n                        mIsRefreshing = true;\n                        upToMiddleAnim();\n                    }else{\n                        upToTopAnim();\n                    }\n                }\n                return true;\n            default:\n                return super.onTouchEvent(event);\n        }\n    }\n    private void upToMiddleAnim(){\n        float offsetY = mListView.getTranslationY();\n        final ValueAnimator backToMiddleAnim = ValueAnimator.ofFloat(offsetY, 0);\n        final float pullHeight = offsetY;\n        backToMiddleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                float val = (float) animation.getAnimatedValue();\n                val = mInterpolator.getInterpolation(val / pullHeight) * val;\n                if (mListView != null) {\n                    mListView.setTranslationY(val);\n                }\n                mRefreshHeader.getLayoutParams().height = (int) (val + 0.5f);\n                mRefreshHeader.requestLayout();\n                Log.d(\"czm\", \"offsetY=\" + mListView.getTranslationY());\n                if (mListView.getTranslationY() <= mHeaderHeight) {\n                    backToMiddleAnim.cancel();\n                }\n            }\n        });\n        backToMiddleAnim.setDuration((long) (offsetY * 600 / pullHeight));\n        backToMiddleAnim.start();\n        backToMiddleAnim.addListener(new Animator.AnimatorListener() {\n            @Override\n            public void onAnimationStart(Animator animation) {\n\n            }\n\n            @Override\n            public void onAnimationEnd(Animator animation) {\n                if (mOnRefreshListener != null) {\n                    mLastCount = mListView.getAdapter().getCount();\n                    mOnRefreshListener.onPullDownLoadMore();\n                }\n            }\n\n            @Override\n            public void onAnimationCancel(Animator animation) {\n\n            }\n\n            @Override\n            public void onAnimationRepeat(Animator animation) {\n\n            }\n        });\n    }\n    private void upToTopAnim(){\n        float offsetY = mListView.getTranslationY();\n        final ValueAnimator backToTopAnim = ValueAnimator.ofFloat(offsetY, 0);\n        final float pullHeight = offsetY;\n        backToTopAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                float val = (float) animation.getAnimatedValue();\n                val = mInterpolator.getInterpolation(val / pullHeight) * val;\n                if (mListView != null) {\n                    mListView.setTranslationY(val);\n                }\n                mRefreshHeader.getLayoutParams().height = (int) (val+0.5f);\n                mRefreshHeader.requestLayout();\n                Log.d(\"czm\", \"offsetY=\" + mListView.getTranslationY());\n            }\n        });\n        backToTopAnim.addListener(new Animator.AnimatorListener() {\n            @Override\n            public void onAnimationStart(Animator animation) {\n\n            }\n\n            @Override\n            public void onAnimationEnd(Animator animation) {\n                mRefreshStatus = REFRESH_STATUS_PULL_REFRESH;\n                mRefreshHeader.updateRefreshStatus(mRefreshStatus);\n\n            }\n\n            @Override\n            public void onAnimationCancel(Animator animation) {\n\n            }\n\n            @Override\n            public void onAnimationRepeat(Animator animation) {\n\n            }\n        });\n\n        backToTopAnim.setDuration((long) (offsetY * 600 / pullHeight));\n        backToTopAnim.start();\n    }\n\n\n    private void completeBackToTop(){\n        mListView.setTranslationY(0);\n        int num = mListView.getAdapter().getCount() - mLastCount;\n        Log.v(\"czm\",\"num=\"+num);\n        if(num > 0){\n            mListView.setSelectionFromTop(num, (int) mLastTranslationY);\n        }\n    }\n    public void onRefreshComplete(){\n        mLastTranslationY = mListView.getTranslationY();\n        mIsRefreshing = false;\n        mRefreshStatus = REFRESH_STATUS_REFRESH_FINISH;\n        mRefreshHeader.updateRefreshStatus(mRefreshStatus);\n        completeBackToTop();\n    }\n    private OnRefreshListener mOnRefreshListener;\n    public void setOnRefreshListener(OnRefreshListener listener){\n        mOnRefreshListener = listener;\n    }\n    public interface OnRefreshListener{\n        void onPullDownLoadMore();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/chat/weight/loadmore/RefreshHeader.java",
    "content": "package com.htmessage.yichatopen.activity.chat.weight.loadmore;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.animation.Animation;\nimport android.view.animation.RotateAnimation;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.R;\n\n\n/**\n * Created by caizhiming on 2016/2/4.\n */\npublic class RefreshHeader extends LinearLayout {\n\n    private TextView mStatusTextView;\n    private ProgressView mProgressView;\n    private ImageView mStatusImageView;\n    private Animation mRotateUpAnim;\n    private Animation mRotateDownAnim;\n    private float mHeaderHeight = 0;\n    private String[] mTxtStatus = new String[]\n            {\n                    \"查看更早记录...\", \"松开开始加载...\",\n                    \"正在加载...\", \"加载完成\"\n            };\n    private int mStatus = PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH;\n    private static final int ROTATE_ANIM_DURATION = 200;\n    public RefreshHeader(Context context) {\n        this(context, null);\n    }\n\n    public RefreshHeader(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public RefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context, attrs, defStyleAttr);\n    }\n\n    public float getHeaderHeight() {\n        return this.mHeaderHeight;\n    }\n\n    private void init(Context context, AttributeSet attrs, int defStyleAttr) {\n        mHeaderHeight = DensityUtil.dip2px(context, 50);\n        //初始化自己\n        LayoutParams lpRoot = new LayoutParams(LayoutParams.MATCH_PARENT,\n                LayoutParams.MATCH_PARENT);\n        this.setOrientation(LinearLayout.HORIZONTAL);\n        this.setGravity(Gravity.CENTER_HORIZONTAL);\n        this.setLayoutParams(lpRoot);\n        this.setBackgroundColor(Color.parseColor(\"#458B00\"));\n\n        //add progress view\n        mProgressView = new ProgressView(context);\n        LayoutParams lp2 = new LayoutParams(\n                        DensityUtil.dip2px(context, 25), DensityUtil.dip2px(context, 25));\n        lp2.gravity = Gravity.BOTTOM;\n        lp2.bottomMargin = (int) (mHeaderHeight / 7.5);\n        this.addView(mProgressView, lp2);\n        mProgressView.setVisibility(View.GONE);\n\n        //add arrow ImageView\n        mStatusImageView = new ImageView(context);\n        mStatusImageView.setImageResource(R.drawable.arrow_down);\n        LayoutParams lp = new LayoutParams(\n                DensityUtil.dip2px(context, 20), DensityUtil.dip2px(context, 20));\n        lp.gravity = Gravity.BOTTOM;\n        lp.bottomMargin = (int) (mHeaderHeight / 5);\n        this.addView(mStatusImageView, lp);\n\n        //add refresh text status TextView\n        mStatusTextView = new TextView(context);\n        mStatusTextView.setText(mTxtStatus[0]);\n        mStatusTextView.setTextColor(Color.WHITE);\n        lp = new LayoutParams(\n                DensityUtil.dip2px(context, 100), LayoutParams.WRAP_CONTENT);\n        lp.gravity = Gravity.BOTTOM;\n        lp.leftMargin = DensityUtil.dip2px(context, 5);\n        lp.bottomMargin = (int) (mHeaderHeight / 10);\n        mStatusTextView.setGravity(Gravity.CENTER);\n        this.addView(mStatusTextView, lp);\n\n        mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,\n                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,\n                0.5f);\n        mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);\n        mRotateUpAnim.setFillAfter(true);\n        mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,\n                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,\n                0.5f);\n        mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);\n        mRotateDownAnim.setFillAfter(true);\n\n    }\n\n    public void updateRefreshStatus(int status) {\n        mStatusTextView.setText(mTxtStatus[status]);\n        if(status == PullToLoadMoreListView.REFRESH_STATUS_RELEASE_REFRESH\n                && mStatus == PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH){\n            mStatusImageView.clearAnimation();\n            mStatusImageView.startAnimation(mRotateUpAnim);\n        }\n        if(status == PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH\n                && mStatus == PullToLoadMoreListView.REFRESH_STATUS_RELEASE_REFRESH){\n            mStatusImageView.clearAnimation();\n            mStatusImageView.startAnimation(mRotateDownAnim);\n        }\n        if(status == PullToLoadMoreListView.REFRESH_STATUS_REFRESHING){\n            mStatusImageView.clearAnimation();\n            mStatusImageView.setVisibility(View.GONE);\n            mProgressView.setVisibility(View.VISIBLE);\n        }\n        if(status == PullToLoadMoreListView.REFRESH_STATUS_REFRESH_FINISH){\n            mProgressView.setVisibility(View.GONE);\n\n        }\n        if(status == PullToLoadMoreListView.REFRESH_STATUS_PULL_REFRESH\n                && mStatus == PullToLoadMoreListView.REFRESH_STATUS_REFRESH_FINISH){\n            mStatusImageView.setVisibility(View.VISIBLE);\n            mStatusImageView.startAnimation(mRotateDownAnim);\n        }\n        mStatus = status;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/CharacterParserUtil.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015��3��18��\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\npublic class CharacterParserUtil {\n    private static int[] pyvalue = new int[]{-20319, -20317, -20304, -20295, -20292, -20283,\n            -20265, -20257, -20242, -20230, -20051, -20036, -20032, -20026, -20002, -19990, -19986,\n            -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741,\n            -19739, -19728, -19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479,\n            -19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261, -19249, -19243, -19242,\n            -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003,\n            -18996, -18977, -18961, -18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735,\n            -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490, -18478, -18463,\n            -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183,\n            -18181, -18012, -17997, -17988, -17970, -17964, -17961, -17950, -17947, -17931, -17928,\n            -17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692, -17683,\n            -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185,\n            -16983, -16970, -16942, -16915, -16733, -16708, -16706, -16689, -16664, -16657, -16647,\n            -16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419,\n            -16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187,\n            -16180, -16171, -16169, -16158, -16155, -15959, -15958, -15944, -15933, -15920, -15915,\n            -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640,\n            -15631, -15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385,\n            -15377, -15375, -15369, -15363, -15362, -15183, -15180, -15165, -15158, -15153, -15150,\n            -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110,\n            -15109, -14941, -14937, -14933, -14930, -14929, -14928, -14926, -14922, -14921, -14914,\n            -14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857, -14678, -14674, -14670,\n            -14668, -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379,\n            -14368, -14355, -14353, -14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137,\n            -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094, -14092, -14090,\n            -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878,\n            -13870, -13859, -13847, -13831, -13658, -13611, -13601, -13406, -13404, -13400, -13398,\n            -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343, -13340, -13329, -13326,\n            -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063,\n            -13060, -12888, -12875, -12871, -12860, -12858, -12852, -12849, -12838, -12831, -12829,\n            -12812, -12802, -12607, -12597, -12594, -12585, -12556, -12359, -12346, -12320, -12300,\n            -12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831,\n            -11798, -11781, -11604, -11589, -11536, -11358, -11340, -11339, -11324, -11303, -11097,\n            -11077, -11067, -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018,\n            -11014, -10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533,\n            -10519, -10331, -10329, -10328, -10322, -10315, -10309, -10307, -10296, -10281, -10274,\n            -10270, -10262, -10260, -10256, -10254};\n\n    public static String[] pystr = new String[]{\"a\", \"ai\", \"an\", \"ang\", \"ao\", \"ba\", \"bai\", \"ban\",\n            \"bang\", \"bao\", \"bei\", \"ben\", \"beng\", \"bi\", \"bian\", \"biao\", \"bie\", \"bin\", \"bing\", \"bo\",\n            \"bu\", \"ca\", \"cai\", \"can\", \"cang\", \"cao\", \"ce\", \"ceng\", \"cha\", \"chai\", \"chan\", \"chang\",\n            \"chao\", \"che\", \"chen\", \"cheng\", \"chi\", \"chong\", \"chou\", \"chu\", \"chuai\", \"chuan\",\n            \"chuang\", \"chui\", \"chun\", \"chuo\", \"ci\", \"cong\", \"cou\", \"cu\", \"cuan\", \"cui\", \"cun\",\n            \"cuo\", \"da\", \"dai\", \"dan\", \"dang\", \"dao\", \"de\", \"deng\", \"di\", \"dian\", \"diao\", \"die\",\n            \"ding\", \"diu\", \"dong\", \"dou\", \"du\", \"duan\", \"dui\", \"dun\", \"duo\", \"e\", \"en\", \"er\", \"fa\",\n            \"fan\", \"fang\", \"fei\", \"fen\", \"feng\", \"fo\", \"fou\", \"fu\", \"ga\", \"gai\", \"gan\", \"gang\",\n            \"gao\", \"ge\", \"gei\", \"gen\", \"geng\", \"gong\", \"gou\", \"gu\", \"gua\", \"guai\", \"guan\", \"guang\",\n            \"gui\", \"gun\", \"guo\", \"ha\", \"hai\", \"han\", \"hang\", \"hao\", \"he\", \"hei\", \"hen\", \"heng\",\n            \"hong\", \"hou\", \"hu\", \"hua\", \"huai\", \"huan\", \"huang\", \"hui\", \"hun\", \"huo\", \"ji\", \"jia\",\n            \"jian\", \"jiang\", \"jiao\", \"jie\", \"jin\", \"jing\", \"jiong\", \"jiu\", \"ju\", \"juan\", \"jue\",\n            \"jun\", \"ka\", \"kai\", \"kan\", \"kang\", \"kao\", \"ke\", \"ken\", \"keng\", \"kong\", \"kou\", \"ku\",\n            \"kua\", \"kuai\", \"kuan\", \"kuang\", \"kui\", \"kun\", \"kuo\", \"la\", \"lai\", \"lan\", \"lang\", \"lao\",\n            \"le\", \"lei\", \"leng\", \"li\", \"lia\", \"lian\", \"liang\", \"liao\", \"lie\", \"lin\", \"ling\", \"liu\",\n            \"long\", \"lou\", \"lu\", \"lv\", \"luan\", \"lue\", \"lun\", \"luo\", \"ma\", \"mai\", \"man\", \"mang\",\n            \"mao\", \"me\", \"mei\", \"men\", \"meng\", \"mi\", \"mian\", \"miao\", \"mie\", \"min\", \"ming\", \"miu\",\n            \"mo\", \"mou\", \"mu\", \"na\", \"nai\", \"nan\", \"nang\", \"nao\", \"ne\", \"nei\", \"nen\", \"neng\", \"ni\",\n            \"nian\", \"niang\", \"niao\", \"nie\", \"nin\", \"ning\", \"niu\", \"nong\", \"nu\", \"nv\", \"nuan\",\n            \"nue\", \"nuo\", \"o\", \"ou\", \"pa\", \"pai\", \"pan\", \"pang\", \"pao\", \"pei\", \"pen\", \"peng\", \"pi\",\n            \"pian\", \"piao\", \"pie\", \"pin\", \"ping\", \"po\", \"pu\", \"qi\", \"qia\", \"qian\", \"qiang\", \"qiao\",\n            \"qie\", \"qin\", \"qing\", \"qiong\", \"qiu\", \"qu\", \"quan\", \"que\", \"qun\", \"ran\", \"rang\", \"rao\",\n            \"re\", \"ren\", \"reng\", \"ri\", \"rong\", \"rou\", \"ru\", \"ruan\", \"rui\", \"run\", \"ruo\", \"sa\",\n            \"sai\", \"san\", \"sang\", \"sao\", \"se\", \"sen\", \"seng\", \"sha\", \"shai\", \"shan\", \"shang\",\n            \"shao\", \"she\", \"shen\", \"sheng\", \"shi\", \"shou\", \"shu\", \"shua\", \"shuai\", \"shuan\",\n            \"shuang\", \"shui\", \"shun\", \"shuo\", \"si\", \"song\", \"sou\", \"su\", \"suan\", \"sui\", \"sun\",\n            \"suo\", \"ta\", \"tai\", \"tan\", \"tang\", \"tao\", \"te\", \"teng\", \"ti\", \"tian\", \"tiao\", \"tie\",\n            \"ting\", \"tong\", \"tou\", \"tu\", \"tuan\", \"tui\", \"tun\", \"tuo\", \"wa\", \"wai\", \"wan\", \"wang\",\n            \"wei\", \"wen\", \"weng\", \"wo\", \"wu\", \"xi\", \"xia\", \"xian\", \"xiang\", \"xiao\", \"xie\", \"xin\",\n            \"xing\", \"xiong\", \"xiu\", \"xu\", \"xuan\", \"xue\", \"xun\", \"ya\", \"yan\", \"yang\", \"yao\", \"ye\",\n            \"yi\", \"yin\", \"ying\", \"yo\", \"yong\", \"you\", \"yu\", \"yuan\", \"yue\", \"yun\", \"za\", \"zai\",\n            \"zan\", \"zang\", \"zao\", \"ze\", \"zei\", \"zen\", \"zeng\", \"zha\", \"zhai\", \"zhan\", \"zhang\",\n            \"zhao\", \"zhe\", \"zhen\", \"zheng\", \"zhi\", \"zhong\", \"zhou\", \"zhu\", \"zhua\", \"zhuai\",\n            \"zhuan\", \"zhuang\", \"zhui\", \"zhun\", \"zhuo\", \"zi\", \"zong\", \"zou\", \"zu\", \"zuan\", \"zui\",\n            \"zun\", \"zuo\"};\n\n    private StringBuilder buffer;\n\n    private String resource;\n\n    private static CharacterParserUtil characterParser = new CharacterParserUtil();\n\n    public static CharacterParserUtil getInstance() {\n        return characterParser;\n    }\n\n    public String getResource() {\n        return resource;\n    }\n\n    public void setResource(String resource) {\n        this.resource = resource;\n    }\n\n    /**\n     * 汉字转成ASCII码\n     *\n     * @param chs\n     * @return\n     */\n    private int getChsAscii(String chs) {\n        int asc = 0;\n        try {\n            byte[] bytes = chs.getBytes(\"gb2312\");\n            if (bytes == null || bytes.length > 2 || bytes.length <= 0) {\n                throw new RuntimeException(\"illegal resource string\");\n            }\n            if (bytes.length == 1) {\n                asc = bytes[0];\n            }\n            if (bytes.length == 2) {\n                int hightByte = 256 + bytes[0];\n                int lowByte = 256 + bytes[1];\n                asc = (256 * hightByte + lowByte) - 256 * 256;\n            }\n        } catch (Exception e) {\n            System.out.println(\"ERROR:ChineseSpelling.class-getChsAscii(String chs)\" + e);\n        }\n        return asc;\n    }\n\n    /**\n     * 单个字进行解析\n     *\n     * @param str\n     * @return\n     */\n    public String convert(String str) {\n        String result = null;\n        int ascii = getChsAscii(str);\n        if (ascii > 0 && ascii < 160) {\n            result = String.valueOf((char) ascii);\n        } else {\n            for (int i = (pyvalue.length - 1); i >= 0; i--) {\n                if (pyvalue[i] <= ascii) {\n                    result = pystr[i];\n                    break;\n                }\n            }\n        }\n        return result;\n    }\n\n    /***\n     * 词组解析\n     *\n     * @param chs\n     * @return\n     */\n    public String getSelling(String chs) {\n        String key, value;\n        buffer = new StringBuilder();\n        for (int i = 0; i < chs.length(); i++) {\n            key = chs.substring(i, i + 1);\n            if (key.getBytes().length >= 2) {\n                value = (String) convert(key);\n                if (value == null) {\n                    value = \"unknown\";\n                }\n            } else {\n                value = key;\n            }\n            buffer.append(value);\n        }\n        return buffer.toString();\n    }\n\n    public String getSpelling() {\n        return this.getSelling(this.getResource());\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/CountryCodeUtil.java",
    "content": "package com.htmessage.yichatopen.activity.country;\n\nimport android.content.Context;\n\nimport com.htmessage.yichatopen.R;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * 项目名称：htmessage_sdk\n * 类描述：CountryCodeUtil 描述:\n * 创建人：songlijie\n * 创建时间：2017/3/3 19:25\n * 邮箱:814326663@qq.com\n */\npublic class CountryCodeUtil {\n    /**\n     * 获取国家列表\n     */\n    public static List<CountrySortModel> getCountryList(Context context, boolean isCn) {\n\n        List<CountrySortModel> mAllCountryList = new ArrayList<>();\n        String[] countryList = context.getResources().getStringArray(R.array.country_code_list_ch);\n        if (!isCn){\n            countryList = context.getResources().getStringArray(R.array.country_code_list_en);\n        }\n\n        for (int i = 0, length = countryList.length; i < length; i++) {\n            String[] country = countryList[i].split(\"\\\\*\");\n            String countryName = country[0];\n            String countryNumber = country[1];\n            String countrySortKey = new CharacterParserUtil().getSelling(countryName);\n            CountrySortModel countrySortModel = new CountrySortModel(countryName, countryNumber,\n                    countrySortKey);\n            String sortLetter = new GetCountryNameSort().getSortLetterBySortKey(countrySortKey);\n            if (sortLetter == null) {\n                sortLetter = new GetCountryNameSort().getSortLetterBySortKey(countryName);\n            }\n            countrySortModel.sortLetters = sortLetter;\n            mAllCountryList.add(countrySortModel);\n        }\n        Collections.sort(mAllCountryList, new CountryComparator());\n        return mAllCountryList;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/CountryComparator.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015��3��18��\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\nimport java.util.Comparator;\n\n\npublic class CountryComparator implements Comparator<CountrySortModel> {\n\n    @Override\n    public int compare(CountrySortModel o1, CountrySortModel o2) {\n\n        if (o1.sortLetters.equals(\"@\") || o2.sortLetters.equals(\"#\")) {\n            return -1;\n        } else if (o1.sortLetters.equals(\"#\") || o2.sortLetters.equals(\"@\")) {\n            return 1;\n        } else {\n            return o1.sortLetters.compareTo(o2.sortLetters);\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/CountryModel.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015��3��30��\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\nimport android.graphics.drawable.Drawable;\n\npublic class CountryModel {\n    // 国家名称\n    public String countryName;\n\n    // 国家代码\n    public String countryNumber;\n\n    public String simpleCountryNumber;\n\n    // 国家名称缩写\n    public String countrySortKey;\n\n    // 国家图标\n    public Drawable contactPhoto;\n\n    public CountryModel(String countryName, String countryNumber, String countrySortKey) {\n        super();\n        this.countryName = countryName;\n        this.countryNumber = countryNumber;\n        this.countrySortKey = countrySortKey;\n        if (countryNumber != null) {\n            this.simpleCountryNumber = countryNumber.replaceAll(\"\\\\-|\\\\s\", \"\");\n        }\n    }\n\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/CountrySortAdapter.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015��3��21��\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\nimport android.content.Context;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.SectionIndexer;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Locale;\n\n\n/**\n * 国家码选择\n */\n\npublic class CountrySortAdapter extends BaseAdapter implements SectionIndexer {\n\n    private List<CountrySortModel> mList;\n\n    private Context mContext;\n\n    LayoutInflater mInflater;\n\n    /***\n     * 初始化\n     *\n     * @param mContext\n     * @param list\n     */\n    public CountrySortAdapter(Context mContext, List<CountrySortModel> list) {\n        this.mContext = mContext;\n        if (list == null) {\n            this.mList = new ArrayList<CountrySortModel>();\n        } else {\n            this.mList = list;\n        }\n    }\n\n    @Override\n    public int getCount() {\n        return this.mList.size();\n    }\n\n    @Override\n    public Object getItem(int position) {\n        return mList.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @Override\n    public View getView(int position, View view, ViewGroup parent) {\n        ViewHolder viewHolder = null;\n        final CountrySortModel mContent = mList.get(position);\n\n        if (view == null) {\n            viewHolder = new ViewHolder();\n            view = LayoutInflater.from(mContext).inflate(R.layout.coogame_country_item, null);\n            viewHolder.country_sortName = (TextView) view.findViewById(R.id.country_catalog);\n            viewHolder.country_name = (TextView) view.findViewById(R.id.country_name);\n            viewHolder.country_number = (TextView) view.findViewById(R.id.country_number);\n            view.setTag(viewHolder);\n        } else {\n            viewHolder = (ViewHolder) view.getTag();\n        }\n\n        // 根据position获取分类的首字母的Char ascii值\n        int section = getSectionForPosition(position);\n\n        // 如果当前位置等于该分类首字母的Char的位置 ，则认为是第一次出现\n        if (position == getPositionForSection(section)) {\n            viewHolder.country_sortName.setVisibility(View.VISIBLE);\n            viewHolder.country_sortName.setText(mContent.sortLetters);\n        } else {\n            viewHolder.country_sortName.setVisibility(View.GONE);\n        }\n\n        viewHolder.country_name.setText(this.mList.get(position).countryName);\n        viewHolder.country_number.setText(this.mList.get(position).countryNumber);\n\n        return view;\n    }\n\n    @Override\n    public int getPositionForSection(int section) {\n        if (section != 42) {\n            for (int i = 0; i < getCount(); i++) {\n                String sortStr = mList.get(i).sortLetters;\n                char firstChar = sortStr.toUpperCase(Locale.CHINESE).charAt(0);\n                if (firstChar == section) {\n                    return i;\n                }\n            }\n        } else {\n            return 0;\n        }\n\n        return -1;\n    }\n\n    @Override\n    public int getSectionForPosition(int position) {\n        return mList.get(position).sortLetters.charAt(0);\n    }\n\n    @Override\n    public Object[] getSections() {\n        return null;\n    }\n\n    /**\n     * 当ListView数据发生变化时,调用此方法来更新ListView\n     *\n     * @param list\n     */\n    public void updateListView(List<CountrySortModel> list) {\n        if (list == null) {\n            this.mList = new ArrayList<CountrySortModel>();\n        } else {\n            this.mList = list;\n        }\n        notifyDataSetChanged();\n    }\n\n    public static class ViewHolder {\n        // 国家码简拼所属的字母范围\n        public TextView country_sortName;\n\n        // 国家名\n        public TextView country_name;\n\n        // 代码\n        public TextView country_number;\n\n    }\n\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/CountrySortModel.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015��3��21��\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\npublic class CountrySortModel extends CountryModel {\n    // 显示数据拼音的首字母\n    public String sortLetters;\n\n    public CountrySortToken sortToken = new CountrySortToken();\n\n    public CountrySortModel(String name, String number, String countrySortKey) {\n        super(name, number, countrySortKey);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/CountrySortToken.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015��3��21��\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\npublic class CountrySortToken\n{\n\t// 简拼\n\tpublic String simpleSpell = \"\";\n\n\t// 全拼\n\tpublic String wholeSpell = \"\";\n\n\t// 中文全名\n\tpublic String chName = \"\";\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/GetCountryNameSort.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015��3��20��\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Locale;\n\n/**\n * 取姓名首字母及模糊匹配查询\n * <p>\n * <p>\n * 类详细描述\n * </p>\n *\n * @author duanbokan\n */\n\npublic class GetCountryNameSort {\n\n    CharacterParserUtil characterParser = CharacterParserUtil.getInstance();\n\n    String chReg = \"[\\\\u4E00-\\\\u9FA5]+\";// 中文字符串匹配\n\n    /***\n     * 将名字转化为拼音并获得首字母\n     *\n     * @param name\n     * @return\n     */\n    public String getSortLetter(String name) {\n        String letter = \"#\";\n        if (name == null) {\n            return letter;\n        }\n        // 汉字转换成拼音\n        String pinyin = characterParser.getSelling(name);\n        String sortString = pinyin.substring(0, 1).toUpperCase(Locale.CHINESE);\n\n        // 正则表达式，判断首字母是否是英文字母\n        if (sortString.matches(\"[A-Z]\")) {\n            letter = sortString.toUpperCase(Locale.CHINESE);\n        }\n        return letter;\n    }\n\n    /***\n     * 取首字母\n     *\n     * @param sortKey\n     * @return\n     */\n    public String getSortLetterBySortKey(String sortKey) {\n        if (sortKey == null || \"\".equals(sortKey.trim())) {\n            return null;\n        }\n        String letter = \"#\";\n        // 汉字转换成拼音\n        String sortString = sortKey.trim().substring(0, 1).toUpperCase(Locale.CHINESE);\n        // 正则表达式，判断首字母是否是英文字母\n        if (sortString.matches(\"[A-Z]\")) {\n            letter = sortString.toUpperCase(Locale.CHINESE);\n        }\n        return letter;\n    }\n\n    /***\n     * 根据输入内容进行查询\n     *\n     * @param str  输入内容\n     * @param list 需要查询的List\n     * @return 查询结果\n     */\n    public List<CountrySortModel> search(String str, List<CountrySortModel> list) {\n        List<CountrySortModel> filterList = new ArrayList<CountrySortModel>();// 过滤后的list\n        // if (str.matches(\"^([0-9]|[/+])*$\")) {// 正则表达式 匹配号码\n        if (str.matches(\"^([0-9]|[/+]).*\")) {// 正则表达式 匹配以数字或者加号开头的字符串(包括了带空格及-分割的号码)\n            String simpleStr = str.replaceAll(\"\\\\-|\\\\s\", \"\");\n            for (CountrySortModel contact : list) {\n                if (contact.countryName != null && contact.countryName != null) {\n                    if (contact.simpleCountryNumber.contains(simpleStr)\n                            || contact.countryName.contains(str)) {\n                        if (!filterList.contains(contact)) {\n                            filterList.add(contact);\n                        }\n                    }\n                }\n            }\n        } else {\n            for (CountrySortModel contact : list) {\n                if (contact.countryNumber != null && contact.countryName != null) {\n                    // 姓名全匹配,姓名首字母简拼匹配,姓名全字母匹配\n                    if (contact.countryName.toLowerCase(Locale.CHINESE).contains(\n                            str.toLowerCase(Locale.CHINESE))\n                            || contact.countrySortKey.toLowerCase(Locale.CHINESE).replace(\" \", \"\")\n                            .contains(str.toLowerCase(Locale.CHINESE))\n                            || contact.sortToken.simpleSpell.toLowerCase(Locale.CHINESE).contains(\n                            str.toLowerCase(Locale.CHINESE))\n                            || contact.sortToken.wholeSpell.toLowerCase(Locale.CHINESE).contains(\n                            str.toLowerCase(Locale.CHINESE))) {\n                        if (!filterList.contains(contact)) {\n                            filterList.add(contact);\n                        }\n                    }\n                }\n            }\n        }\n        return filterList;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/country/SideBar.java",
    "content": "/*      \t\t\t\t\t\t\n * Copyright 2010 Beijing Xinwei, Inc. All rights reserved.\n * \n * History:\n * ------------------------------------------------------------------------------\n * Date    \t|  Who  \t\t|  What  \n * 2015年3月18日\t| duanbokan \t| \tcreate the file                       \n */\n\npackage com.htmessage.yichatopen.activity.country;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.graphics.Typeface;\nimport android.util.AttributeSet;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.R;\n\n\n/**\n * 类简要描述\n */\npublic class SideBar extends View {\n    // 字母变化监听事件\n    private OnTouchingLetterChangedListener onTouchingLetterChangedListener;\n\n    // 字母数组\n    public static String[] b = {\"*\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\",\n            \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\", \"#\"};\n\n    // 选中\n    private int choose = -1;\n\n    private Paint paint = new Paint();\n\n    // 点击后提示当前选中字母\n    private TextView mTextDialog;\n\n    public void setTextView(TextView mTextDialog) {\n        this.mTextDialog = mTextDialog;\n    }\n\n    public SideBar(Context context, AttributeSet attrs, int defStyle) {\n        super(context, attrs, defStyle);\n    }\n\n    public SideBar(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    public SideBar(Context context) {\n        super(context);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        // 获取屏幕高度和宽度\n        int height = getHeight();\n        int width = getWidth();\n\n        // 设置字母高度\n        float letterHeight = (height * 1f) / b.length;\n        for (int i = 0; i < b.length; i++) {\n            paint.setColor(Color.rgb(23, 122, 126));\n            paint.setTypeface(Typeface.DEFAULT_BOLD);\n            // 抗锯齿\n            paint.setAntiAlias(true);\n            paint.setTextSize(20);\n\n            if (i == choose) {\n                paint.setColor(Color.BLUE);\n                // 设置为加粗字体\n                paint.setFakeBoldText(true);\n            }\n            // x坐标等于中间-字符串宽度的一半.\n            float xPos = width / 2 - paint.measureText(b[i]) / 2;\n            float yPos = letterHeight * i + letterHeight;\n            canvas.drawText(b[i], xPos, yPos, paint);\n            // 重置画笔\n            paint.reset();\n        }\n    }\n\n    @Override\n    public boolean dispatchTouchEvent(MotionEvent event) {\n        final int action = event.getAction();\n        final float touch_y = event.getY();\n        final int oldChoose = choose;\n\n        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;\n        // 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.\n        final int c = (int) (touch_y / getHeight() * b.length);\n\n        switch (action) {\n            case MotionEvent.ACTION_UP:\n                setBackgroundColor(Color.TRANSPARENT);\n                choose = -1;\n                invalidate();\n                if (mTextDialog != null) {\n                    mTextDialog.setVisibility(View.INVISIBLE);\n                }\n                break;\n\n            default:\n                setBackgroundResource(R.color.holo_green_light);\n                if (oldChoose != c) {\n                    if (c >= 0 && c < b.length) {\n                        if (listener != null) {\n                            listener.onTouchingLetterChanged(b[c]);\n                        }\n                        if (mTextDialog != null) {\n                            mTextDialog.setText(b[c]);\n                            mTextDialog.setVisibility(View.VISIBLE);\n                        }\n                        choose = c;\n                        invalidate();\n                    }\n                }\n                break;\n        }\n\n        return true;\n    }\n\n    /**\n     * 向外公开的方法\n     *\n     * @param onTouchingLetterChangedListener\n     */\n    public void setOnTouchingLetterChangedListener(\n            OnTouchingLetterChangedListener onTouchingLetterChangedListener) {\n        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;\n    }\n\n    /**\n     * 接口\n     *\n     * @author coder\n     */\n    public interface OnTouchingLetterChangedListener {\n        public void onTouchingLetterChanged(String s);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/login/LoginActivity.java",
    "content": "package com.htmessage.yichatopen.activity.login;\n\nimport android.annotation.TargetApi;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.FragmentTransaction;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.runtimepermissions.PermissionsManager;\nimport com.htmessage.yichatopen.runtimepermissions.PermissionsResultAction;\n\n/**\n * Login screen\n */\npublic class LoginActivity extends BaseActivity {\n\n\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_base);\n        hideBackView();\n        setTitle(R.string.login_by_mobile);\n        requestPermissions();\n        LoginFragment loginFragment =\n                (LoginFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (loginFragment == null) {\n            // Create the fragment\n            loginFragment =new  LoginFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame, loginFragment);\n            transaction.commit();\n        }\n\n        LoginPresenter presenter=new LoginPresenter(loginFragment);\n\n    }\n\n\n\n\n\n\n\n    @TargetApi(23)\n    private void requestPermissions() {\n        PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(this, new PermissionsResultAction() {\n            @Override\n            public void onGranted() {\n            }\n\n            @Override\n            public void onDenied(String permission) {\n            }\n        });\n    }\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,\n                                           @NonNull int[] grantResults) {\n        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/login/LoginContract.java",
    "content": "package com.htmessage.yichatopen.activity.login;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * Created by huangfangyi on 2017/6/21.\n * qq 84543217\n */\n\npublic interface LoginContract {\n\n    interface View extends BaseView<Presenter> {\n\n        void showDialog();\n\n        void cancelDialog();\n\n        String getUsername();\n\n        String getPassword();\n\n        void setButtonEnable();\n\n        void setButtonDisabel();\n\n        void showToast(int toastMsg);\n\n        String getCountryName();\n\n        String getCountryCode();\n\n        Activity getBaseActivity();\n\n        Context getBaseContext();\n\n\n    }\n\n    interface Presenter extends BasePresenter {\n\n        void requestServer(String username, String password);\n\n        void chooseCuntry(Context context, TextView tvCountryName, TextView tvCountryCode);\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/login/LoginFragment.java",
    "content": "package com.htmessage.yichatopen.activity.login;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.text.Editable;\nimport android.text.TextUtils;\nimport android.text.TextWatcher;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.main.password.PasswordResetActivity;\nimport com.htmessage.yichatopen.activity.register.RegisterActivity;\nimport com.htmessage.yichatopen.utils.Validator;\n\n/**\n * Created by dell on 2017/6/21.\n */\n\npublic class LoginFragment extends Fragment implements LoginContract.View, View.OnClickListener {\n    private LoginContract.Presenter mPresenter;\n    private EditText et_usertel, et_password;\n    private TextView tv_find_password, tv_country, tv_country_code;\n    private Button btn_login, btn_qtlogin;\n    private RelativeLayout rl_country;\n    private Dialog dialog;\n\n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        dialog = HTApp.getInstance().createLoadingDialog(getActivity(), getString(R.string.logining));\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View root = inflater.inflate(R.layout.fragment_login, container, false);\n        et_usertel = (EditText) root.findViewById(R.id.et_usertel);\n        et_password = (EditText) root.findViewById(R.id.et_password);\n        btn_login = (Button) root.findViewById(R.id.btn_login);\n        tv_country = (TextView) root.findViewById(R.id.tv_country);\n        tv_country_code = (TextView) root.findViewById(R.id.tv_country_code);\n        tv_find_password = (TextView) root.findViewById(R.id.tv_find_password);\n        rl_country = (RelativeLayout) root.findViewById(R.id.rl_country);\n        btn_qtlogin = (Button) root.findViewById(R.id.btn_qtlogin);\n\n        setLisenter();\n        return root;\n    }\n\n    private void setLisenter() {\n        //输入监听\n        TextChange textChange = new TextChange();\n        et_usertel.addTextChangedListener(textChange);\n        et_password.addTextChangedListener(textChange);\n        //登陆按钮监听\n        btn_login.setOnClickListener(this);\n        //选取国家监听\n        rl_country.setOnClickListener(this);\n        //跳转注册监听\n        btn_qtlogin.setOnClickListener(this);\n        tv_find_password.setOnClickListener(this);\n    }\n\n\n    @Override\n    public void setPresenter(LoginContract.Presenter presenter) {\n        mPresenter = presenter;\n    }\n\n\n\n    @Override\n    public void showDialog() {\n        if (dialog != null)\n            dialog.show();\n    }\n\n    @Override\n    public void cancelDialog() {\n        if (dialog != null && dialog.isShowing()) {\n            dialog.dismiss();\n        }\n    }\n\n    @Override\n    public String getUsername() {\n        return et_usertel.getText().toString().trim();\n    }\n\n    @Override\n    public String getPassword() {\n        return et_password.getText().toString().trim();\n    }\n\n    @Override\n    public void setButtonEnable() {\n        btn_login.setEnabled(true);\n\n    }\n\n    @Override\n    public void setButtonDisabel() {\n        btn_login.setEnabled(true);\n\n    }\n\n    @Override\n    public void showToast(int toastMsg) {\n        Toast.makeText(getActivity(), toastMsg, Toast.LENGTH_SHORT).show();\n    }\n\n\n\n\n\n    @Override\n    public String getCountryName() {\n        return tv_country.getText().toString().trim();\n    }\n\n    @Override\n    public String getCountryCode() {\n        return tv_country_code.getText().toString().trim();\n\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.btn_login:\n                if (TextUtils.isEmpty(getUsername())) {\n                    showToast( R.string.tel_is_not_allow_null );\n                    return;\n                }\n                //如果是中国地区,进行一个手机号验证\n                if (getCountryName().equals(getString(R.string.china)) && getCountryCode().equals(getString(R.string.country_code))) {\n                    if (!Validator.isMobile(getUsername())) {\n                        showToast( R.string.please_input_true_mobile );\n                        return;\n                    }\n                }\n                if (TextUtils.isEmpty(getPassword())) {\n                    showToast( R.string.pwd_is_not_allow_null);\n                    return;\n                }\n                mPresenter.requestServer(getUsername(), getPassword());\n                break;\n            case R.id.rl_country:\n                mPresenter.chooseCuntry(getContext(), tv_country, tv_country_code);\n                break;\n\n            case R.id.btn_qtlogin:\n                startActivity(new Intent(getActivity(), RegisterActivity.class));\n                break;\n            case R.id.tv_find_password:\n                startActivity(new Intent(getActivity(), PasswordResetActivity.class).putExtra(\"isReset\", false));\n                break;\n\n        }\n    }\n\n\n    // EditText监听器\n    private class TextChange implements TextWatcher {\n\n        @Override\n        public void afterTextChanged(Editable arg0) {\n\n        }\n\n        @Override\n        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,\n                                      int arg3) {\n\n        }\n\n        @Override\n        public void onTextChanged(CharSequence cs, int start, int before,\n                                  int count) {\n            boolean sign1 = et_usertel.getText().length() > 0;\n            boolean sign2 = et_password.getText().length() > 0;\n            if (sign1 & sign2) {\n                setButtonEnable();\n            } else {\n                setButtonDisabel();\n            }\n\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/login/LoginPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.login;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.widget.TextView;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.main.MainActivity;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.htmessage.yichatopen.utils.UpdateLastLoginTimeUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by huangfangyi on 2017/6/21.\n * qq 84543217\n */\n\npublic class LoginPresenter implements LoginContract.Presenter {\n   private LoginContract.View loginView;\n    public LoginPresenter(LoginContract.View loginView){\n        this.loginView=loginView;\n        this.loginView.setPresenter(this);\n\n    }\n\n    @Override\n    public void requestServer(String username, String password) {\n        loginView.showDialog();\n        List<Param> params = new ArrayList<>();\n        params.add(new Param(\"usertel\", username));\n        params.add(new Param(\"password\", password));\n        new OkHttpUtils(loginView.getBaseActivity() ).post(params, HTConstant.URL_LOGIN, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                int code = jsonObject.getInteger(\"code\");\n                switch(code){\n                    case 1:\n                        JSONObject userJson = jsonObject.getJSONObject(\"user\");\n                        loginIm(userJson);\n                        break;\n                    case -1:\n                        loginView.cancelDialog();\n                        loginView.showToast(R.string.Account_does_not_exist);\n\n                        break;\n                    case -2:\n                        loginView.cancelDialog();\n                        loginView.showToast(R.string.Incorrect_password);\n\n                        break;\n                    case -3:\n                        loginView.cancelDialog();\n                        loginView.showToast(R.string.Account_has_been_disabled);\n\n                        break;\n                    default:\n                        loginView.cancelDialog();\n                        loginView.showToast(R.string.Server_busy);\n\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                loginView.cancelDialog();\n            }\n        });\n    }\n\n    @Override\n    public void chooseCuntry(Context context, TextView tvCountryName, TextView tvCountryCode) {\n            CommonUtils.showPup(context,tvCountryName,tvCountryCode);\n\n    }\n\n\n\n\n\n    private void loginIm(final JSONObject userJson) {\n        HTClient.getInstance().login(userJson.getString(HTConstant.JSON_KEY_HXID), userJson.getString(HTConstant.JSON_KEY_PASSWORD), new HTClient.HTCallBack() {\n            @Override\n            public void onSuccess() {\n                 if (userJson == null) {\n                    return;\n                }\n                JSONArray friends = userJson.getJSONArray(\"friend\");\n                if (userJson.containsKey(\"friend\")) {\n                    userJson.remove(\"friend\");\n\n                }\n                HTApp.getInstance().setUserJson(userJson);\n                Map<String, User> userlist = new HashMap<String, User>();\n                if (friends != null) {\n                    for (int i = 0; i < friends.size(); i++) {\n                        JSONObject friend = friends.getJSONObject(i);\n                        User user = CommonUtils.Json2User(friend);\n                        userlist.put(user.getUsername(), user);\n                    }\n                    List<User> users = new ArrayList<User>(userlist.values());\n                    ContactsManager.getInstance().saveContactList(users);\n                }\n                //上传最近登录时间\n                UpdateLastLoginTimeUtils.sendLocalTimeToService(loginView.getBaseContext());\n               loginView.getBaseActivity(). runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        loginView.cancelDialog();\n                        loginView.showToast(R.string.login_success);\n\n                        Intent intent = new Intent(loginView.getBaseContext(),\n                                MainActivity.class);\n                        loginView.getBaseActivity().startActivity(intent);\n                        loginView.getBaseActivity().finish();\n                    }\n                });\n            }\n\n            @Override\n            public void onError() {\n                loginView.getBaseActivity().runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        loginView.cancelDialog();\n                        loginView.showToast(R.string.Login_failed);\n\n                    }\n                });\n            }\n        });\n\n    }\n\n\n    @Override\n    public void start() {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/MainActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport android.app.AlertDialog;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.design.widget.TabLayout;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentPagerAdapter;\nimport android.support.v4.view.ViewPager;\nimport android.support.v7.view.menu.MenuBuilder;\nimport android.support.v7.widget.Toolbar;\nimport android.util.Log;\nimport android.view.KeyEvent;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.TextView;\nimport android.widget.Toast;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.addfriends.add.pre.AddFriendsPreActivity;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.activity.ScanCaptureActivity;\nimport com.htmessage.yichatopen.activity.login.LoginActivity;\nimport com.htmessage.yichatopen.activity.main.contacts.FragmentContacts;\nimport com.htmessage.yichatopen.activity.main.conversation.ConversationFragment;\nimport com.htmessage.yichatopen.activity.main.find.FragmentFind;\nimport com.htmessage.yichatopen.activity.main.profile.FragmentProfile;\nimport com.htmessage.yichatopen.runtimepermissions.PermissionsManager;\nimport com.htmessage.yichatopen.runtimepermissions.PermissionsResultAction;\n\nimport java.lang.reflect.Method;\n\n/**\n * Created by huangfangyi on 2017/6/24.\n * qq 84543217\n */\n\npublic class MainActivity extends BaseActivity implements MainView {\n    private TabLayout mTablayout;\n    private ViewPager mViewPager;\n    private String[] mTitles;\n    private int[] drawabls = new int[]{R.drawable.tab_chat_bg, R.drawable.tab_contact_list_bg, R.drawable.tab_find_bg, R.drawable.tab_profile_bg};\n    private TabLayout.Tab[] tabs;\n    private Fragment[] fragments;\n    //新消息角标\n    private TextView unreadLabel;\n    // 新好友申请消息角标\n    public TextView unreadInvitionLable;\n\n    // user logged into another device\n    public boolean isConflict = false;\n    private android.app.AlertDialog.Builder exceptionBuilder;\n    private boolean isConflictDialogShow;\n    private MainPrestener mainPrestener;\n\n    @Override\n    protected void onCreate(Bundle arg0) {\n        if (arg0 != null && arg0.getBoolean(\"isConflict\", false)) {\n            finish();\n            startActivity(new Intent(this, LoginActivity.class));\n            return;\n        }\n        super.onCreate(arg0);\n        setContentView(R.layout.activity_base_main);\n        mainPrestener = new MainPrestener(this);\n        mTitles = new String[]{getString(R.string.app_chat), getString(R.string.address_book), getString(R.string.bottom_find), getString(R.string.me)};\n        Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar);\n        setSupportActionBar(toolbar);\n        toolbar.setTitle(getString(R.string.app_name));\n        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {\n            @Override\n            public boolean onMenuItemClick(MenuItem item) {\n                switch (item.getItemId()) {\n                    case R.id.item_search:\n                        Toast.makeText(getApplicationContext(), R.string.wait_do, Toast.LENGTH_SHORT).show();\n                        break;\n                    case R.id.item_add_friend:\n                        startActivity(new Intent(MainActivity.this, AddFriendsPreActivity.class));\n\n                        break;\n                    case R.id.item_add_group:\n                        Toast.makeText(getApplicationContext(), R.string.open_notice, Toast.LENGTH_SHORT).show();\n                        break;\n                    case R.id.item_scan:\n                        startActivity(new Intent(MainActivity.this, ScanCaptureActivity.class));\n                        break;\n\n                }\n\n\n                return true;\n            }\n        });\n\n\n        if (getIntent().getBooleanExtra(IMAction.ACTION_CONFLICT, false) && !isConflictDialogShow) {\n            showConflicDialog();\n        }\n\n        initViews();\n\n        requestPermissions();\n        mainPrestener.checkVersion();\n\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.menu_main, menu);\n\n        return true;\n    }\n\n\n    @Override\n    protected boolean onPrepareOptionsPanel(View view, Menu menu) {\n        //解决menu item设置的图标不显示\n        if (menu != null) {\n            if (menu.getClass() == MenuBuilder.class) {\n                try {\n                    Method m = menu.getClass().getDeclaredMethod(\"setOptionalIconsVisible\", Boolean.TYPE);\n                    m.setAccessible(true);\n                    m.invoke(menu, true);\n                } catch (Exception e) {\n                    //   Out.print(getClass().getSimpleName() + \"onMenuOpened...unable to set icons for overflow menu\" + e);\n                }\n            }\n        }\n        return super.onPrepareOptionsPanel(view, menu);\n    }\n\n\n    private void initViews() {\n\n        mTablayout = (TabLayout) findViewById(R.id.tabLayout);\n        mViewPager = (ViewPager) findViewById(R.id.viewPager);\n        fragments = new Fragment[]{new ConversationFragment(), new FragmentContacts(), new FragmentFind(), new FragmentProfile()};\n        mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {\n            @Override\n            public Fragment getItem(int position) {\n                return fragments[position];\n            }\n\n            @Override\n            public int getCount() {\n                return fragments.length;\n            }\n        });\n\n        mTablayout.setupWithViewPager(mViewPager);\n        tabs = new TabLayout.Tab[mTitles.length];\n        for (int i = 0; i < mTitles.length; i++) {\n            tabs[i] = mTablayout.getTabAt(i);\n            tabs[i].setCustomView(getBottomView(i, drawabls[i]));\n        }\n    }\n\n\n    @Override\n    protected void onStart() {\n        super.onStart();\n        mainPrestener.start();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n\n        if (exceptionBuilder != null) {\n            exceptionBuilder.create().dismiss();\n            exceptionBuilder = null;\n            isConflictDialogShow = false;\n        }\n\n    }\n\n\n\n\n\n    private View getBottomView(final int index, int drawableRes) {\n        View view = getLayoutInflater().inflate(R.layout.widget_main_button, null);\n        Button button = (Button) view.findViewById(R.id.button);\n        button.setCompoundDrawablesWithIntrinsicBounds(0, drawableRes, 0, 0);\n        //  button.setCompoundDrawables(null, dr, null, null);\n        button.setText(mTitles[index]);\n        button.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (tabs[index] != null) {\n                    tabs[index].select();\n                }\n            }\n        });\n        if (isCompatible(Build.VERSION_CODES.LOLLIPOP)) {\n            button.setStateListAnimator(null);\n        }\n        TextView textView = (TextView) view.findViewById(R.id.unread_msg_number);\n        if (index == 0) {\n            unreadLabel = textView;\n        } else if (index == 1) {\n            unreadInvitionLable = textView;\n        }\n        return view;\n    }\n\n\n    @Override\n    public void setPresenter(MainPrestener presenter) {\n        mainPrestener = presenter;\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return this;\n    }\n\n    @Override\n    public void showConflicDialog() {\n        isConflictDialogShow = true;\n        //HTClientHelper.getInstance().logout(null);\n        String st = getResources().getString(R.string.Logoff_notification);\n        if (!MainActivity.this.isFinishing()) {\n            // clear up global variables\n            try {\n                if (exceptionBuilder == null)\n                    exceptionBuilder = new android.app.AlertDialog.Builder(MainActivity.this);\n                exceptionBuilder.setTitle(st);\n                exceptionBuilder.setMessage(R.string.connect_conflict);\n                exceptionBuilder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {\n\n                    @Override\n                    public void onClick(DialogInterface dialog, int which) {\n                        dialog.dismiss();\n                        exceptionBuilder = null;\n                        isConflictDialogShow = false;\n                        HTApp.getInstance().setUserJson(null);\n                        finish();\n                        Intent intent = new Intent(MainActivity.this, LoginActivity.class);\n                        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);\n                        startActivity(intent);\n\n                    }\n                });\n                exceptionBuilder.setCancelable(false);\n                exceptionBuilder.show();\n                isConflict = true;\n            } catch (Exception e) {\n                Log.e(TAG, \"---------color conflictBuilder error\" + e.getMessage());\n            }\n        }\n    }\n\n\n    @Override\n    public void showUpdateDialog(String message, final String url, final String isForce) {\n        String title = getString(R.string.has_update);\n        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);\n        View dialogView = View.inflate(MainActivity.this, R.layout.layout_alert_dialog_delete, null);\n        TextView tv_delete_people = (TextView) dialogView.findViewById(R.id.tv_delete_people);\n        View view_line_dialog = dialogView.findViewById(R.id.view_line_dialog);\n        TextView tv_delete_title = (TextView) dialogView.findViewById(R.id.tv_delete_title);\n        TextView tv_cancle = (TextView) dialogView.findViewById(R.id.tv_cancle);\n        TextView tv_ok = (TextView) dialogView.findViewById(R.id.tv_ok);\n        tv_delete_title.setText(title);\n        tv_delete_people.setText(message);\n        tv_cancle.setText(R.string.update_later);\n        tv_ok.setText(R.string.update_now);\n        builder.setView(dialogView);\n        final AlertDialog dialog = builder.show();\n        if (isForce.equals(\"1\")) {\n            view_line_dialog.setVisibility(View.GONE);\n            tv_cancle.setVisibility(View.GONE);\n            tv_ok.setText(R.string.update_has);\n            dialog.setCancelable(false);//点击屏幕外不取消  返回键也没用\n            dialog.setCanceledOnTouchOutside(false); //点击屏幕外取消,返回键有用\n        } else {\n            dialog.setCancelable(true);//点击屏幕外取消  返回键也没用\n            dialog.setCanceledOnTouchOutside(true); //点击屏幕外取消,返回键有用\n        }\n        tv_cancle.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n                if (isForce.equals(\"1\")) {\n                    logout();\n                }\n            }\n        });\n        tv_ok.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (!isForce.equals(\"1\")) {\n                    dialog.dismiss();\n                }\n                Intent intent = new Intent();\n                intent.setAction(Intent.ACTION_VIEW);\n                Uri uri = Uri.parse(url);\n                intent.setData(uri);\n                MainActivity.this.startActivity(intent);\n\n            }\n        });\n\n    }\n\n    @Override\n    public void onUnReadMsgs(int count) {\n        if (unreadLabel == null) {\n            return;\n        }\n        if (count > 0) {\n\n            unreadLabel.setText(String.valueOf(count));\n            unreadLabel.setVisibility(View.VISIBLE);\n        } else {\n            unreadLabel.setVisibility(View.INVISIBLE);\n        }\n\n    }\n\n\n    @Override\n    protected void onNewIntent(Intent intent) {\n        super.onNewIntent(intent);\n        if (intent.getBooleanExtra(IMAction.ACTION_CONFLICT, false) && !isConflictDialogShow) {\n            showConflicDialog();\n        }\n    }\n\n\n    @Override\n    public boolean onKeyDown(int keyCode, KeyEvent event) {\n        if (keyCode == KeyEvent.KEYCODE_BACK) {\n            moveTaskToBack(false);\n            return true;\n        }\n        return super.onKeyDown(keyCode, event);\n    }\n\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,\n                                           @NonNull int[] grantResults) {\n        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);\n    }\n\n\n    private void logout() {\n        HTClient.getInstance().logout(new HTClient.HTCallBack() {\n            @Override\n            public void onSuccess() {\n\n                HTApp.getInstance().setUserJson(null);\n                HTApp.getInstance().finishActivities();\n                finish();\n            }\n\n            @Override\n            public void onError() {\n\n                HTApp.getInstance().setUserJson(null);\n                HTApp.getInstance().finishActivities();\n                finish();\n            }\n        });\n    }\n\n\n    @TargetApi(23)\n    private void requestPermissions() {\n        PermissionsManager.getInstance().requestAllManifestPermissionsIfNecessary(this, new PermissionsResultAction() {\n            @Override\n            public void onGranted() {\n//\t\t\t\tToast.makeText(MainActivity.this, \"All permissions have been granted\", Toast.LENGTH_SHORT).show();\n            }\n\n            @Override\n            public void onDenied(String permission) {\n                //Toast.makeText(MainActivity.this, \"Permission \" + permission + \" has been denied\", Toast.LENGTH_SHORT).show();\n            }\n        });\n    }\n\n\n    @Override\n    public void showInvitionCount(int count) {\n        if (unreadInvitionLable == null){\n            return;\n        }\n        if (count > 0) {\n            //   unreadInvitionLable.setText(String.valueOf(count));\n            unreadInvitionLable.setVisibility(View.VISIBLE);\n        } else {\n            unreadInvitionLable.setVisibility(View.INVISIBLE);\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/MainBasePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * Created by huangfangyi on 2017/6/27.\n * qq 84543217\n */\n\npublic interface MainBasePrester extends BasePresenter {\n\n    //检查更新\n    void checkVersion();\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/MainPrestener.java",
    "content": "package com.htmessage.yichatopen.activity.main;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.PowerManager;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;\n\n/**\n * Created by huangfangyi on 2017/6/25.\n * qq 84543217\n */\n\npublic class MainPrestener implements MainBasePrester {\n\n    private MainView mainView;\n    private Context context;\n\n    public MainPrestener(MainView _mainView){\n        this.mainView=_mainView;\n        mainView.setPresenter(this);\n        context=mainView.getBaseContext();\n     }\n\n    @Override\n    public void start() {\n        try {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n                String packageName = context.getPackageName();\n                PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);\n                if (!pm.isIgnoringBatteryOptimizations(packageName)) {\n                    Intent intent = new Intent();\n                    intent.setAction(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);\n                    intent.setFlags(FLAG_ACTIVITY_NEW_TASK);\n                    intent.setData(Uri.parse(\"package:\" + packageName));\n                    context.startActivity(intent);\n                }\n            }\n        } catch (RuntimeException e) {\n            e.printStackTrace();\n        }\n    }\n\n\n\n    /**\n     * 获取VersionCode\n     *\n     * @return 当前应用的VersionCode\n     */\n    public String getVersionCode() {\n        try {\n            PackageManager manager = context.getPackageManager();\n            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);\n            String version = String.valueOf(info.versionCode);\n            return version;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return null;\n        }\n    }\n\n\n\n\n    @Override\n    public void checkVersion() {\n            final String version = getVersionCode();\n            List<Param> params = new ArrayList<>();\n            params.add(new Param(\"system\", \"0\"));\n            new OkHttpUtils(context).post(params, HTConstant.URL_CHECK_UPDATE, new OkHttpUtils.HttpCallBack() {\n                @Override\n                public void onResponse(JSONObject jsonObject) {\n                    if (jsonObject != null) {\n                        String serviceVersion = jsonObject.getString(\"newVersion\");\n                        String url = jsonObject.getString(\"url\");\n                        String info = jsonObject.getString(\"info\");\n                        String statue = jsonObject.getString(\"statue\");\n                        if (!version.equals(serviceVersion) && (Integer.valueOf(version) < Integer.valueOf(serviceVersion))) {\n                            mainView.showUpdateDialog(info, url, statue);\n\n                        }\n                    }\n                }\n\n                @Override\n                public void onFailure(String errorMsg) {\n                }\n            });\n\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/MainView.java",
    "content": "package com.htmessage.yichatopen.activity.main;\n\nimport com.htmessage.yichatopen.activity.BaseView;\nimport com.htmessage.yichatopen.activity.main.contacts.FragmentContacts;\nimport com.htmessage.yichatopen.activity.main.conversation.ConversationFragment;\n\n/**\n * Created by huangfangyi on 2017/6/25.\n * qq 84543217\n */\n\npublic interface MainView extends BaseView<MainPrestener>,ConversationFragment.NewMeesageListener,FragmentContacts.ContactsListener {\n\n    void showConflicDialog();\n\n     void showUpdateDialog( String message,String url,String isForce);\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/BaseContactsPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.main.contacts;\n\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/6/28.\n * qq 84543217\n */\n\npublic interface BaseContactsPresenter extends BasePresenter{\n    List<User> getContactsListInDb();\n    void deleteContacts(String userId);\n    void moveUserToBlack(String userId);\n    List<User> sortList(  List<User> users);\n    void refreshContactsInServer();\n    int getInvitionCount();\n    int getContactsCount();\n    void clearInvitionCount();\n    void refreshContactsInLocal();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/ContactsAdapter.java",
    "content": "package com.htmessage.yichatopen.activity.main.contacts;\n\nimport android.content.Context;\nimport android.util.SparseIntArray;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ImageView;\nimport android.widget.SectionIndexer;\nimport android.widget.TextView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.domain.User;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/6/28.\n * qq 84543217\n */\n\npublic class ContactsAdapter extends BaseAdapter implements SectionIndexer {\n    private Context context;\n    private List<User> data;\n\n    public ContactsAdapter(Context context, List<User> data) {\n        this.context = context;\n        this.data = data;\n    }\n\n    @Override\n    public int getCount() {\n        return data.size();\n    }\n\n    @Override\n    public User getItem(int position) {\n        return data.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n\n        if (convertView == null) {\n            convertView = View.inflate(context, R.layout.item_contact_list, null);\n        }\n        ViewHolder holder = (ViewHolder) convertView.getTag();\n        if (holder == null) {\n            holder = new ViewHolder();\n            holder.tvHeader = (TextView) convertView.findViewById(R.id.header);\n            holder.nameTextview = (TextView) convertView.findViewById(R.id.tv_name);\n            holder.iv_avatar = (ImageView) convertView.findViewById(R.id.iv_avatar);\n\n            convertView.setTag(holder);\n        }\n\n        User user = data.get(position);\n\n        holder.tvHeader.setVisibility(View.VISIBLE);\n        String nick = user.getNick();\n        String avatar = user.getAvatar();\n        String headerLetter = user.getInitialLetter();\n        String preHeaderLetter = getPreHeaderLeeter(position);\n\n        if (headerLetter.equals(preHeaderLetter)) {\n            holder.tvHeader.setVisibility(View.GONE);\n\n        } else {\n            holder.tvHeader.setVisibility(View.VISIBLE);\n            holder.tvHeader.setText(headerLetter);\n        }\n        holder.nameTextview.setText(nick);\n        Glide.with(context).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).error(R.drawable.default_avatar).into(holder.iv_avatar);\n\n        return convertView;\n    }\n    List<String> list;\n    private SparseIntArray positionOfSection;\n    private SparseIntArray sectionOfPosition;\n    @Override\n    public Object[] getSections() {\n        positionOfSection = new SparseIntArray();\n        sectionOfPosition = new SparseIntArray();\n        int count = getCount();\n        list = new ArrayList<String>();\n        list.add(context.getString(R.string.search_header));\n        positionOfSection.put(0, 0);\n        sectionOfPosition.put(0, 0);\n        for (int i = 1; i < count; i++) {\n\n            String letter = getItem(i).getInitialLetter();\n            System.err.println(\"contactadapter getsection getHeader:\" + letter\n                    + \" name:\" + getItem(i).getUsername());\n            int section = list.size() - 1;\n            if (list.get(section) != null && !list.get(section).equals(letter)) {\n                list.add(letter);\n                section++;\n                positionOfSection.put(section, i);\n            }\n            sectionOfPosition.put(i, section);\n        }\n        return list.toArray(new String[list.size()]);\n\n    }\n\n\n    public int getPositionForSection(int section) {\n        return positionOfSection.get(section)+1;\n    }\n\n    public int getSectionForPosition(int position) {\n        return sectionOfPosition.get(position);\n    }\n\n    private class ViewHolder {\n        ImageView iv_avatar;\n        TextView nameTextview, tvHeader;\n    }\n\n    private String getPreHeaderLeeter(int position) {\n        if (position > 0) {\n            User user = getItem(position - 1);\n            return user.getInitialLetter();\n        }\n        return null;\n\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/ContactsPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.main.contacts;\n\nimport android.app.AlertDialog;\nimport android.app.ProgressDialog;\nimport android.view.View;\nimport android.widget.TextView;\nimport android.widget.Toast;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.manager.HTChatManager;\nimport com.htmessage.sdk.model.CmdMessage;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.domain.InviteMessgeDao;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.domain.UserDao;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.UUID;\n\n/**\n * Created by huangfangyi on 2017/6/28.\n * qq 84543217\n */\n\npublic class ContactsPresenter implements BaseContactsPresenter {\n\n\n\n    private ContactsView contactsView;\n    private List<User> contacts;\n    private InviteMessgeDao inviteMessgeDao;\n    public ContactsPresenter (ContactsView view){\n        contactsView=view;\n        contactsView.setPresenter(this);\n        contacts=new ArrayList<>(ContactsManager.getInstance().getContactList().values());\n        inviteMessgeDao=new InviteMessgeDao(contactsView.getBaseContext());\n    }\n\n\n    @Override\n    public List<User> getContactsListInDb() {\n        contacts= sortList(new ArrayList<User>(ContactsManager.getInstance().getContactList().values()));\n        return contacts;\n    }\n    //删除好友\n    @Override\n    public void deleteContacts(String userId) {\n        Map<String, User> users = ContactsManager.getInstance().getContactList();\n        User user = users.get(userId);\n        users.remove(user.getUsername());\n        contacts.remove(user);\n        deleteContact(user);\n    }\n    //移入黑名单\n    @Override\n    public void moveUserToBlack(final String userId) {\n        View diaglogView = View.inflate(contactsView.getBaseContext(), R.layout.layout_alert_dialog_delete, null);\n        TextView tv_delete_title = (TextView) diaglogView.findViewById(R.id.tv_delete_title);\n        TextView tv_delete_people = (TextView) diaglogView.findViewById(R.id.tv_delete_people);\n        TextView tv_cancle = (TextView) diaglogView.findViewById(R.id.tv_cancle);\n        TextView tv_ok = (TextView) diaglogView.findViewById(R.id.tv_ok);\n        tv_delete_title.setText(R.string.prompt);\n        tv_delete_people.setText(R.string.Into_the_blacklist);\n        AlertDialog.Builder builder = new AlertDialog.Builder(contactsView.getBaseActivity());\n        builder.setView(diaglogView);\n        final AlertDialog dialog = builder.show();\n        tv_ok.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n                showMoveToBlackDialog(userId);\n            }\n        });\n        tv_cancle.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                dialog.dismiss();\n            }\n        });\n    }\n\n    //移除用户\n    public void deleteContactOnBroast(String id) {\n        Map<String, User> users = ContactsManager.getInstance().getContactList();\n        User user = users.get(id);\n        users.remove(id);\n        InviteMessgeDao dao = new InviteMessgeDao(contactsView.getBaseActivity());\n        dao.deleteMessage(id);\n        UserDao userDao = new UserDao(contactsView.getBaseActivity());\n        userDao.deleteContact(id);\n        contacts.remove(user);\n        HTClient.getInstance().conversationManager().deleteConversationAndMessage(id);\n    }\n\n    /**\n     * 删除用户\n     *\n     * @param user\n     */\n    private void deleteContact(final User user) {\n        final ProgressDialog pd = new ProgressDialog(contactsView.getBaseActivity());\n        pd.setMessage(contactsView.getBaseContext().getResources().getString(R.string.deleting));\n        pd.setCanceledOnTouchOutside(false);\n        pd.show();\n        List<Param> params = new ArrayList<>();\n        params.add(new Param(HTConstant.JSON_KEY_HXID, user.getUsername()));\n        new OkHttpUtils(contactsView.getBaseActivity()).post(params, HTConstant.URL_DELETE_FRIEND, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                pd.dismiss();\n                int code = jsonObject.getIntValue(\"code\");\n                switch (code) {\n                    case 1:\n                        InviteMessgeDao dao = new InviteMessgeDao(contactsView.getBaseActivity());\n                        dao.deleteMessage(user.getUsername());\n                        UserDao userDao = new UserDao(contactsView.getBaseActivity());\n                        userDao.deleteContact(user.getUsername());\n                        HTClient.getInstance().conversationManager().deleteConversationAndMessage(user.getUsername());\n                        sendDeleteCmd(user);\n                        Toast.makeText(contactsView.getBaseActivity(), R.string.delete_sucess, Toast.LENGTH_SHORT).show();\n                        break;\n                    default:\n                        Toast.makeText(contactsView.getBaseActivity(), R.string.Delete_failed, Toast.LENGTH_SHORT).show();\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                pd.dismiss();\n                Toast.makeText(contactsView.getBaseActivity(), R.string.Delete_failed, Toast.LENGTH_SHORT).show();\n            }\n        });\n    }\n\n    private void sendDeleteCmd(User user) {\n        JSONObject userJson = HTApp.getInstance().getUserJson();\n        CmdMessage customMessage = new CmdMessage();\n        JSONObject jsonObject = new JSONObject();\n        jsonObject.put(\"action\", 1003);\n        JSONObject data = new JSONObject();\n        data.put(\"userId\", userJson.getString(\"userId\"));\n        data.put(\"nick\", userJson.getString(\"nick\"));\n        data.put(\"avatar\", userJson.getString(\"avatar\"));\n        data.put(\"role\", userJson.getString(HTConstant.JSON_KEY_ROLE));\n        data.put(\"teamId\", userJson.getString(\"teamId\"));\n        jsonObject.put(\"data\", data);\n        customMessage.setMsgId(UUID.randomUUID().toString());\n        customMessage.setFrom(HTApp.getInstance().getUsername());\n        customMessage.setTime(System.currentTimeMillis());\n        customMessage.setTo(user.getUsername());\n        customMessage.setBody(jsonObject.toJSONString());\n        customMessage.setChatType(ChatType.singleChat);\n        HTClient.getInstance().chatManager().sendCmdMessage(customMessage, new HTChatManager.HTMessageCallBack() {\n            @Override\n            public void onProgress() {\n\n            }\n\n            @Override\n            public void onSuccess() {\n\n            }\n\n            @Override\n            public void onFailure() {\n\n            }\n        });\n    }\n\n    \n    \n    \n    \n    @Override\n    public List<User> sortList(List<User> users) {\n        PinyinComparator comparator = new PinyinComparator();\n        Collections.sort(users, comparator);\n        return users;\n    }\n    public class PinyinComparator implements Comparator<User> {\n\n        @Override\n        public int compare(User o1, User o2) {\n            String py1 = o1.getInitialLetter();\n            String py2 = o2.getInitialLetter();\n            if (py1.equals(py2)) {\n                return o1.getNick().compareTo(o2.getNick());\n            } else {\n                if (\"#\".equals(py1)) {\n                    return 1;\n                } else if (\"#\".equals(py2)) {\n                    return -1;\n                }\n                return py1.compareTo(py2);\n            }\n\n        }\n    }\n\n\n        @Override\n    public void refreshContactsInServer() {\n        List<Param> params = new ArrayList();\n        new OkHttpUtils(contactsView.getBaseContext()).post(params, HTConstant.URL_FriendList, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                int code = jsonObject.getIntValue(\"code\");\n                switch (code) {\n                    case 1:\n                        JSONArray friends = jsonObject.getJSONArray(\"user\");\n                        if (friends != null || friends.size() != 0) {\n\n                            List<User> users = new ArrayList<User>();\n                            for (int i = 0; i < friends.size(); i++) {\n                                JSONObject friend = friends.getJSONObject(i);\n                                User user = CommonUtils.Json2User(friend);\n                                users.add(user);\n                            }\n                            ContactsManager.getInstance().saveContactList(users);\n                            contacts.clear();\n                            contacts.addAll(sortList(users));\n                            contactsView.refresh();\n                        }\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n\n            }\n        });\n\n    }\n\n    @Override\n    public int getInvitionCount() {\n        int unreadAddressCountTotal = 0;\n        unreadAddressCountTotal = inviteMessgeDao.getUnreadMessagesCount();\n        return unreadAddressCountTotal;\n    }\n\n    @Override\n    public int getContactsCount() {\n        return contacts.size();\n    }\n\n    @Override\n    public void clearInvitionCount() {\n        inviteMessgeDao.saveUnreadMessageCount(0);\n        contactsView.showInvitionCount(0);\n    }\n\n    @Override\n    public void refreshContactsInLocal() {\n\n        contacts.clear();\n        contacts.addAll(sortList(new ArrayList<User>(ContactsManager.getInstance().getContactList().values())));\n        contactsView.refresh();\n    }\n\n    @Override\n    public void start() {\n\n    }\n\n    /**\n     * 移入黑名单\n     * @param userId\n     */\n    private void showMoveToBlackDialog(final String userId) {\n        Map<String, User> users = ContactsManager.getInstance().getContactList();\n       final User user = users.get(userId);\n        users.remove(userId);\n        getContactsListInDb().remove(user);\n       final ProgressDialog dialog = new ProgressDialog(contactsView.getBaseContext());\n        dialog.setMessage(contactsView.getBaseContext().getString(R.string.Is_moved_into_blacklist));\n        dialog.show();\n        List<Param> params = new ArrayList<>();\n        params.add(new Param(HTConstant.JSON_KEY_HXID,userId));\n        new OkHttpUtils(contactsView.getBaseContext()).post(params, HTConstant.URL_ADD_BLACKLIST, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                dialog.dismiss();\n                int code = jsonObject.getIntValue(\"code\");\n                switch (code){\n                    case 1:\n                        InviteMessgeDao dao = new InviteMessgeDao(contactsView.getBaseActivity());\n                        dao.deleteMessage(userId);\n                        UserDao userDao = new UserDao(contactsView.getBaseActivity());\n                        userDao.deleteContact(userId);\n                        HTClient.getInstance().conversationManager().deleteConversationAndMessage(userId);\n                        Toast.makeText(contactsView.getBaseContext(), R.string.Move_into_blacklist_success, Toast.LENGTH_SHORT).show();\n                        break;\n                    default:\n                        Toast.makeText(contactsView.getBaseContext(), R.string.Move_into_blacklist_failure, Toast.LENGTH_SHORT).show();\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                dialog.dismiss();\n                Toast.makeText(contactsView.getBaseContext(), R.string.Move_into_blacklist_failure, Toast.LENGTH_SHORT).show();\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/ContactsView.java",
    "content": "package com.htmessage.yichatopen.activity.main.contacts;\n\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * Created by huangfangyi on 2017/6/28.\n * qq 84543217\n */\n\npublic interface ContactsView extends BaseView<ContactsPresenter> {\n    void showItemDialog(User user);\n    void showSiderBar();\n    void showInvitionCount(int count);\n    void showContactsCount(int count);\n    void refresh();\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/FragmentContacts.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n * <p>\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.activity.main.contacts;\n\nimport android.app.Activity;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.AdapterView.OnItemClickListener;\nimport android.widget.ListView;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.addfriends.newfriend.NewFriendsActivity;\nimport com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.widget.HTAlertDialog;\n\n/**\n * contact list\n */\npublic class FragmentContacts extends Fragment implements View.OnClickListener, ContactsView {\n    private ContactsAdapter adapter;\n    private ListView listView;\n    private Sidebar sidebar;\n    private TextView tv_unread;\n    private TextView tv_total;\n    private ContactsPresenter contactsPresenter;\n\n    public interface ContactsListener {\n        void showInvitionCount(int count);\n    }\n\n    private ContactsListener contactsListener;\n\n    @Override\n    public void onAttach(Context context) {\n        super.onAttach(context);\n        contactsPresenter = new ContactsPresenter(this);\n        if (context instanceof ContactsListener) {\n            contactsListener = (ContactsListener) context;\n        }\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        View root = inflater.inflate(R.layout.fragment_contactlist, container, false);\n        listView = (ListView) root.findViewById(R.id.list);\n\n        View footerView = LayoutInflater.from(getActivity()).inflate(R.layout.item_contact_list_footer,\n                null);\n        View headView = LayoutInflater.from(getActivity()).inflate(R.layout.item_contact_list_header,\n                null);\n        listView.addHeaderView(headView);\n        listView.addFooterView(footerView);\n        sidebar = (Sidebar) root.findViewById(R.id.sidebar);\n        tv_unread = (TextView) headView.findViewById(R.id.tv_unread);\n        tv_total = (TextView) footerView.findViewById(R.id.tv_total);\n\n        showSiderBar();\n\n        headView.findViewById(R.id.re_newfriends).setOnClickListener(this);\n        headView.findViewById(R.id.re_chatroom).setOnClickListener(this);\n        headView.findViewById(R.id.re_tag).setOnClickListener(this);\n        headView.findViewById(R.id.re_public).setOnClickListener(this);\n        return root;\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        adapter = new ContactsAdapter(getActivity(), contactsPresenter.getContactsListInDb());\n        listView.setAdapter(adapter);\n        listView.setOnItemClickListener(new OnItemClickListener() {\n            @Override\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                if (position != 0 && position != adapter.getCount() + 1) {\n                    User user = adapter.getItem(position - 1);\n                    startActivity(new Intent(getActivity(), UserDetailsActivity.class)\n                            .putExtra(HTConstant.KEY_USER_INFO, user.getUserInfo()));\n                }\n            }\n        });\n        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {\n            @Override\n            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {\n\n                if (position != 0 && position != adapter.getCount() + 1) {\n                    User user = adapter.getItem(position - 1);\n                    showItemDialog(user);\n                }\n\n                return true;\n            }\n        });\n        contactsPresenter.refreshContactsInServer();\n        registerBroadReciever();\n    }\n\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.re_newfriends:\n                startActivityForResult(new Intent(getActivity(), NewFriendsActivity.class),10086);\n                contactsPresenter.clearInvitionCount();\n                break;\n            case R.id.re_chatroom:\n                Toast.makeText(getActivity(), R.string.open_notice, Toast.LENGTH_SHORT).show();\n                break;\n            case R.id.re_tag:\n                break;\n            case R.id.re_public:\n                break;\n        }\n\n    }\n\n    @Override\n    public void setPresenter(ContactsPresenter presenter) {\n\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void showItemDialog(final User user) {\n        HTAlertDialog fxAlertDialog = new HTAlertDialog(getContext(), null, new String[]{getResources().getString(R.string.delete)});\n        fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                switch (position) {\n                    case 0:\n                        contactsPresenter.deleteContacts(user.getUsername());\n                        break;\n                    case 1:\n                        contactsPresenter.moveUserToBlack(user.getUsername());\n                        break;\n                }\n                refresh();\n            }\n        });\n\n    }\n\n    @Override\n    public void showSiderBar() {\n        sidebar.setVisibility(View.VISIBLE);\n        sidebar.setListView(listView);\n    }\n\n    @Override\n    public void showInvitionCount(int count) {\n        if (count != 0) {\n            tv_unread.setVisibility(View.VISIBLE);\n            // tv_unread.setText(  count+\"\");\n\n        } else {\n            tv_unread.setVisibility(View.GONE);\n        }\n        contactsListener.showInvitionCount(count);\n    }\n\n    @Override\n    public void showContactsCount(int count) {\n        tv_total.setText(count + getString(R.string.more_people));\n\n    }\n\n    @Override\n    public void refresh() {\n        adapter.notifyDataSetChanged();\n        showContactsCount(contactsPresenter.getContactsCount());\n    }\n\n    private class MyBroadcastReceiver extends BroadcastReceiver {\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            String action = intent.getAction();\n            if (IMAction.ACTION_CONTACT_CHANAGED.equals(action)) {\n                contactsPresenter.refreshContactsInLocal();\n            } else if (IMAction.ACTION_INVITE_MESSAGE.equals(action)) {\n                showInvitionCount(1);\n            } else if (IMAction.CMD_DELETE_FRIEND.equals(action)) {\n                String userId = intent.getStringExtra(HTConstant.JSON_KEY_HXID);\n                contactsPresenter.deleteContactOnBroast(userId);\n                refresh();\n            }\n        }\n    }\n\n    private MyBroadcastReceiver myBroadcastReceiver;\n\n    private void registerBroadReciever() {\n        myBroadcastReceiver = new MyBroadcastReceiver();\n        IntentFilter intentFilter = new IntentFilter();\n        intentFilter.addAction(IMAction.ACTION_CONTACT_CHANAGED);\n        intentFilter.addAction(IMAction.ACTION_INVITE_MESSAGE);\n        intentFilter.addAction(IMAction.CMD_DELETE_FRIEND);\n        LocalBroadcastManager.getInstance(getContext()).registerReceiver(myBroadcastReceiver, intentFilter);\n    }\n\n    @Override\n    public void onDestroy() {\n        try {\n            LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(myBroadcastReceiver);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        super.onDestroy();\n\n    }\n\n    @Override\n    public void onActivityResult(int requestCode, int resultCode, Intent data) {\n        if (resultCode == Activity.RESULT_OK){\n            showInvitionCount(0);\n        }\n        super.onActivityResult(requestCode, resultCode, data);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/contacts/Sidebar.java",
    "content": "/**\n * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.activity.main.contacts;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.graphics.Paint.Align;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.widget.HeaderViewListAdapter;\nimport android.widget.ListView;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.R;\n\n\npublic class Sidebar extends View{\n\tprivate Paint paint;\n\tprivate TextView header;\n\tprivate float height;\n\tprivate ListView mListView;\n\tprivate Context context;\n\n\tpublic void setListView(ListView listView){\n\t\tmListView = listView;\n\t}\n\n\n\tpublic Sidebar(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t\tthis.context = context;\n\t\tinit();\n\t}\n\n\tprivate String[] sections = new String[]{\"↑\",\"☆\",\"A\",\"B\",\"C\",\"D\",\"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\",\"#\"};\n\n\tprivate void init(){\n\t\tpaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n\t\tpaint.setColor(Color.DKGRAY);\n\t\tpaint.setTextAlign(Align.CENTER);\n\n\t\t paint.setTextSize(getResources().getDimensionPixelSize(R.dimen.sider_bar_textsize));\n\t}\n\n\n\t@Override\n\tprotected void onDraw(Canvas canvas) {\n\t\tsuper.onDraw(canvas);\n\t\tfloat center = getWidth() / 2;\n\t\theight = getHeight() / sections.length;\n\t\tfor (int i = sections.length - 1; i > -1; i--) {\n\t\t\tcanvas.drawText(sections[i], center, height * (i+1), paint);\n\t\t}\n\t}\n\n\tprivate int sectionForPoint(float y) {\n\t\tint index = (int) (y / height);\n\t\tif(index < 0) {\n\t\t\tindex = 0;\n\t\t}\n\t\tif(index > sections.length - 1){\n\t\t\tindex = sections.length - 1;\n\t\t}\n\t\treturn index;\n\t}\n\n\tprivate void setHeaderTextAndscroll(MotionEvent event){\n\t\t if (mListView == null) {\n\t\t        //check the mListView to avoid NPE. but the mListView shouldn't be null\n\t\t        //need to check the call stack later\n\t\t        return;\n\t\t    }\n\t\tString headerString = sections[sectionForPoint(event.getY())];\n\t\theader.setText(headerString);\n\t\t  HeaderViewListAdapter ha = (HeaderViewListAdapter) mListView.getAdapter();\n\t\t  ContactsAdapter adapter = (ContactsAdapter) ha.getWrappedAdapter();\n//\t\tContactAdapter adapter = (ContactAdapter) mListView.getAdapter();\n\t\tString[] adapterSections = (String[]) adapter.getSections();\n\t\ttry {\n\t\t\tfor (int i = adapterSections.length - 1; i > -1; i--) {\n\t\t\t\tif(adapterSections[i].equals(headerString)){\n\t\t\t\t\tmListView.setSelection(adapter.getPositionForSection(i));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tLog.e(\"setHeaderTextAndscroll\", e.getMessage());\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic boolean onTouchEvent(MotionEvent event) {\n\t\tswitch (event.getAction()) {\n\t\tcase MotionEvent.ACTION_DOWN:{\n\t\t\tif(header == null){\n\t\t\t\theader = (TextView) ((View)getParent()).findViewById(R.id.floating_header);\n\t\t\t}\n\t\t\tsetHeaderTextAndscroll(event);\n\t\t\theader.setVisibility(View.VISIBLE);\n\t\t\tsetBackgroundResource(R.drawable.sidebar_background_pressed);\n\t\t\treturn true;\n\t\t}\n\t\tcase MotionEvent.ACTION_MOVE:{\n\t\t\tsetHeaderTextAndscroll(event);\n\t\t\treturn true;\n\t\t}\n\t\tcase MotionEvent.ACTION_UP:\n\t\t\theader.setVisibility(View.INVISIBLE);\n\t\t\tsetBackgroundColor(Color.TRANSPARENT);\n\t\t\treturn true;\n\t\tcase MotionEvent.ACTION_CANCEL:\n\t\t\theader.setVisibility(View.INVISIBLE);\n\t\t\tsetBackgroundColor(Color.TRANSPARENT);\n\t\t\treturn true;\n\t\t}\n\t\treturn super.onTouchEvent(event);\n\t}\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/BaseConversationPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.main.conversation;\n\nimport com.htmessage.sdk.model.HTConversation;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/6/27.\n * qq 84543217\n */\n\npublic interface BaseConversationPresenter extends BasePresenter\n{\n    List<HTConversation> getAllConversations();\n    void deleteConversation(HTConversation conversation);\n    void setTopConversation(HTConversation conversation);\n    void cancelTopConversation(HTConversation conversation);\n    void refreshConversations();\n    void onNewMsgReceived(HTMessage htmessage);\n    int getUnreadMsgCount();\n    void markAllMessageRead(HTConversation conversation);\n\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationAdapter.java",
    "content": "package com.htmessage.yichatopen.activity.main.conversation;\n\nimport android.content.Context;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.activity.chat.weight.emoji.SmileUtils;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.utils.DateUtils;\nimport com.htmessage.sdk.model.HTConversation;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.sdk.model.HTMessageTextBody;\n\nimport java.util.Date;\nimport java.util.List;\n\n\npublic class ConversationAdapter extends BaseAdapter {\n    private List<HTConversation> htConversations;\n    private Context context;\n\n    public ConversationAdapter(Context context, List<HTConversation> htConversations) {\n        this.context = context;\n        this.htConversations = htConversations;\n      }\n\n    @Override\n    public int getCount() {\n        return htConversations.size();\n    }\n\n    @Override\n    public HTConversation getItem(int position) {\n\n        return htConversations.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        if (convertView == null) {\n            convertView = LayoutInflater.from(context).inflate(R.layout.item_conversation_single, parent, false);\n        }\n        ViewHolder holder = (ViewHolder) convertView.getTag();\n        if (holder == null) {\n            holder = new ViewHolder();\n            holder.tv_name = (TextView) convertView.findViewById(R.id.name);\n            holder.tv_content = (TextView) convertView.findViewById(R.id.message);\n            holder.tv_time = (TextView) convertView.findViewById(R.id.time);\n            holder.tv_unread = (TextView) convertView.findViewById(R.id.unread_msg_number);\n            holder.ivAvatar = (ImageView) convertView.findViewById(R.id.avatar);\n            holder.tv_group_tag=(TextView) convertView.findViewById(R.id.tv_group_tag);\n            holder.re_main=(RelativeLayout) convertView.findViewById(R.id.re_main);\n            convertView.setTag(holder);\n        }\n        HTConversation htConversation = getItem(position);\n        HTMessage htMessage = null;\n        List<HTMessage> messages = htConversation.getAllMessages();\n        if (messages.size() > 0) {\n            htMessage = htConversation.getLastMessage();\n        }\n        String userId = htConversation.getUserId();\n            User user = ContactsManager.getInstance().getContactList().get(userId);\n            holder.tv_group_tag.setVisibility(View.INVISIBLE);\n            if (user != null) {\n                holder.tv_name.setText(user.getNick());\n                Glide.with(context).load(user.getAvatar()).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(holder.ivAvatar);\n            } else {\n                holder.tv_name.setText(userId);\n                Glide.with(context).load(R.drawable.default_avatar).into(holder.ivAvatar);\n            }\n        if (htConversation.getUnReadCount() > 0) {\n            // show unread message count\n            holder.tv_unread.setText(String.valueOf(htConversation.getUnReadCount()));\n            holder.tv_unread.setVisibility(View.VISIBLE);\n        } else {\n            holder.tv_unread.setVisibility(View.INVISIBLE);\n        }\n\n        if (htMessage != null) {\n            holder.tv_content.setText(SmileUtils.getSmiledText(context, getContent(htMessage)),\n                    TextView.BufferType.SPANNABLE);\n            holder.tv_time.setText(DateUtils.getTimestampString(new Date(htMessage.getTime())));\n        }else{\n            holder.tv_content.setText(\"\");\n            holder.tv_time.setText(DateUtils.getTimestampString(new Date(htConversation.getTime())));\n        }\n        if(htConversation.getTopTimestamp()!=0){\n\n            holder.re_main.setBackgroundResource(R.drawable.list_item_bg_gray);\n        }else{\n            holder.re_main.setBackgroundResource(R.drawable.list_item_bg_white);\n        }\n\n        return convertView;\n    }\n\n    private static class ViewHolder {\n        /**\n         * 和谁的聊天记录\n         */\n        TextView tv_name;\n        /**\n         * 消息未读数\n         */\n        TextView tv_unread;\n        /**\n         * 最后一条消息的内容\n         */\n        TextView tv_content;\n        /**\n         * 最后一条消息的时间\n         */\n        TextView tv_time;\n\n        ImageView ivAvatar;\n\n        //群组的标识\n        TextView tv_group_tag;\n        RelativeLayout re_main;\n\n    }\n\n    protected final static String[] msgs = { \"[图片消息]\", \"[语音消息]\"};\n\n    private String getContent(HTMessage message) {\n        String notifyText = \"\";\n\n        if (message.getType() == null) {\n            return \"\";\n        }\n        switch (message.getType()) {\n            case TEXT:\n\n                HTMessageTextBody textBody = (HTMessageTextBody) message.getBody();\n\n                String content = textBody.getContent();\n                if (content != null) {\n                    notifyText += content;\n\n                } else {\n                    notifyText += msgs[0];\n                }\n\n                break;\n            case IMAGE:\n                notifyText += msgs[0];\n                break;\n            case VOICE:\n\n                notifyText += msgs[1];\n                break;\n        }\n        return  notifyText;\n    }\n\n//    /**\n//     * 根据消息内容和消息类型获取消息内容提示\n//     *\n//     * @param message\n//     * @param context\n//     * @return\n//     */\n//    private String getMessageDigest(HTMessage message, Context context) {\n//        String digest = \"\";\n//        switch (message.getType()) {\n//        case LOCATION: // 位置消息\n//            if (message.getDirect() == HTMessage.Direct.RECEIVE) {\n//\n//                digest = getStrng(context, R.string.location_recv);\n//                digest = String.format(digest, message.getFrom());\n//                return digest;\n//            } else {\n//                // digest = EasyUtils.getAppResourceString(context,\n//                // \"location_prefix\");\n//                digest = getStrng(context, R.string.location_prefix);\n//            }\n//            break;\n//        case IMAGE: // 图片消息\n//\n//            digest = getStrng(context, R.string.picture);\n//\n//            break;\n//        case VOICE:// 语音消息\n//            digest = getStrng(context, R.string.voice);\n//            break;\n//        case VIDEO: // 视频消息\n//            digest = getStrng(context, R.string.video);\n//            break;\n//        case TXT: // 文本消息\n//            if (!message.getBooleanAttribute(\n//                    Constant.MESSAGE_ATTR_IS_VOICE_CALL, false)) {\n//                TextMessageBody txtBody = (TextMessageBody) message.getBody();\n//                digest = txtBody.getMessage();\n//            } else {\n//                TextMessageBody txtBody = (TextMessageBody) message.getBody();\n//                digest = getStrng(context, R.string.voice_call)\n//                        + txtBody.getMessage();\n//            }\n//            break;\n//        case FILE: // 普通文件消息\n//            digest = getStrng(context, R.string.file);\n//            break;\n//        default:\n//            System.err.println(\"error, unknow type\");\n//            return \"\";\n//        }\n//\n//        return digest;\n//    }\n\n    String getStrng(Context context, int resId) {\n        return context.getResources().getString(resId);\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.conversation;\n\nimport android.app.Activity;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.ListView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\n\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.model.HTConversation;\nimport com.htmessage.sdk.utils.MessageUtils;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.activity.chat.ChatActivity;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.widget.HTAlertDialog;\n\npublic class ConversationFragment extends Fragment implements ConversationView {\n\n\n    private ListView listView;\n    private ConversationAdapter adapter;\n\n    public RelativeLayout errorItem;\n    public TextView errorText;\n    public NewMeesageListener mListener;\n    private ConversationPresenter conPresenter;\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        View root = inflater.inflate(R.layout.fragment_home, container, false);\n        errorItem = (RelativeLayout) root.findViewById(R.id.rl_error_item);\n        errorText = (TextView) errorItem.findViewById(R.id.tv_connect_errormsg);\n        listView = (ListView) root.findViewById(R.id.list);\n        return root;\n    }\n\n    @Override\n    public void setPresenter(ConversationPresenter presenter) {\n        //  conPresenter = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void showItemDialog(final HTConversation htConversation) {\n        String topTitle = getString(R.string.stick_conversation);\n        if (htConversation.getTopTimestamp() != 0) {\n            //已经置顶的会话,显示取消置顶\n            topTitle = getString(R.string.cancle_stick_conversation);\n        }\n        HTAlertDialog fxAlertDialog = new HTAlertDialog(getActivity(), null, new String[]{getString(R.string.delete), topTitle});\n        fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                if (position == 0) {\n                    conPresenter.deleteConversation(htConversation);\n                } else if (position == 1) {\n                    if (htConversation.getTopTimestamp() != 0) {//如果是置顶过的 就取消置顶\n                        conPresenter.cancelTopConversation(htConversation);\n                    } else {  //如果是没有置顶的就置顶\n                        conPresenter.setTopConversation(htConversation);\n                    }\n                }\n            }\n        });\n    }\n\n    @Override\n    public void refresh() {\n        conPresenter.refreshConversations();\n        adapter.notifyDataSetChanged();\n        onUnreadMsgChange();\n    }\n\n    public interface NewMeesageListener {\n        //返回多少条未读消息\n        void onUnReadMsgs(int count);\n    }\n\n    @Override\n    public void onAttach(Context context) {\n        super.onAttach(context);\n        conPresenter = new ConversationPresenter(this);\n        if (context instanceof NewMeesageListener) {\n            mListener = ((NewMeesageListener) context);\n            onUnreadMsgChange();\n        }\n    }\n\n    private void onUnreadMsgChange() {\n        mListener.onUnReadMsgs(conPresenter.getUnreadMsgCount());\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        adapter = new ConversationAdapter(getActivity(), conPresenter.getAllConversations());\n        // 设置adapter\n        listView.setAdapter(adapter);\n        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n            @Override\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                HTConversation htConversation = adapter.getItem(position);\n                conPresenter.markAllMessageRead(htConversation);\n                Intent intent = new Intent(getActivity(), ChatActivity.class).putExtra(\"userId\", htConversation.getUserId());\n                if (htConversation.getChatType() == ChatType.groupChat) {\n                    intent.putExtra(\"chatType\", MessageUtils.CHAT_GROUP);\n                }\n                startActivity(intent);\n            }\n        });\n        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {\n            @Override\n            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {\n                HTConversation htConversation = adapter.getItem(i);\n                showItemDialog(htConversation);\n                return true;\n            }\n        });\n        registerConnectionBroadCast();\n    }\n\n    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {\n        @Override\n        public void onReceive(Context context, Intent intent) {\n\n            if (IMAction.ACTION_CONNECTION_CHANAGED.equals(intent.getAction())) {\n                boolean isConnected = intent.getBooleanExtra(\"state\", true);\n                if (isConnected) {\n                    errorItem.setVisibility(View.GONE);\n                } else {\n                    errorItem.setVisibility(View.VISIBLE);\n                    if (CommonUtils.isNetWorkConnected(getContext())) {\n                        errorText.setText(R.string.can_not_connect_chat_server_connection);\n                    } else {\n                        errorText.setText(R.string.the_current_network);\n                    }\n                }\n\n            } else if (IMAction.ACTION_NEW_MESSAGE.equals(intent.getAction()) || IMAction.ACTION_MESSAGE_WITHDROW.equals(intent.getAction())\n                    || IMAction.ACTION_REMOVED_FROM_GROUP.equals(intent.getAction()) || IMAction.CMD_DELETE_FRIEND.equals(intent.getAction())) {\n                //   收到新消息,收到撤回消息,收到群相关消息-被提出群聊\n                refresh();\n            }\n        }\n    };\n\n\n    private void registerConnectionBroadCast() {\n\n        IntentFilter intentFilter = new IntentFilter();\n        intentFilter.addAction(IMAction.ACTION_CONNECTION_CHANAGED);\n        intentFilter.addAction(IMAction.ACTION_NEW_MESSAGE);\n        intentFilter.addAction(IMAction.ACTION_MESSAGE_WITHDROW);\n        intentFilter.addAction(IMAction.CMD_DELETE_FRIEND);\n        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(broadcastReceiver, intentFilter);\n\n    }\n\n    @Override\n    public void onDestroy() {\n        LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(broadcastReceiver);\n        super.onDestroy();\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n        refresh();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.main.conversation;\n\nimport android.content.Context;\n\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.model.HTConversation;\nimport com.htmessage.sdk.model.HTMessage;\n\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/6/27.\n * qq 84543217\n */\n\npublic class ConversationPresenter implements BaseConversationPresenter {\n    private ConversationView conversationView;\n    private Context context;\n    private List<HTConversation> allConversations;\n\n    public ConversationPresenter(ConversationView view) {\n        conversationView = view;\n        conversationView.setPresenter(this);\n        context = conversationView.getBaseContext();\n        allConversations = HTClient.getInstance().conversationManager().getAllConversations();\n    }\n\n\n    @Override\n    public void start() {\n\n    }\n\n    @Override\n    public List<HTConversation> getAllConversations() {\n\n        return allConversations;\n    }\n\n    @Override\n    public void deleteConversation(HTConversation htConversation) {\n        allConversations.remove(htConversation);\n        HTClient.getInstance().messageManager().deleteUserMessage(htConversation.getUserId(), true);\n        conversationView.refresh();\n    }\n\n    @Override\n    public void setTopConversation(HTConversation htConversation) {\n        HTClient.getInstance().conversationManager().setConversationTop(htConversation,System.currentTimeMillis());\n        conversationView.refresh();\n\n    }\n\n    @Override\n    public void cancelTopConversation(HTConversation htConversation) {\n        HTClient.getInstance().conversationManager().setConversationTop(htConversation,0);\n        conversationView.refresh();\n    }\n\n    @Override\n    public void refreshConversations() {\n        allConversations.clear();\n        allConversations.addAll(HTClient.getInstance().conversationManager().getAllConversations());\n     }\n\n    @Override\n    public void onNewMsgReceived(HTMessage htMessage) {\n\n    }\n\n    @Override\n    public int getUnreadMsgCount() {\n        int unreadMsgCountTotal = 0;\n        if (allConversations.size() != 0 && allConversations != null) {\n            for (int i = 0; i < allConversations.size(); i++) {\n                 unreadMsgCountTotal += allConversations.get(i).getUnReadCount();\n            }\n        }\n        return unreadMsgCountTotal;\n    }\n\n    @Override\n    public void markAllMessageRead(HTConversation conversation) {\n\n        HTClient.getInstance().conversationManager().markAllMessageRead(conversation.getUserId());\n        conversationView.refresh();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/conversation/ConversationView.java",
    "content": "package com.htmessage.yichatopen.activity.main.conversation;\n\nimport com.htmessage.sdk.model.HTConversation;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * Created by huangfangyi on 2017/6/27.\n * qq 84543217\n */\n\npublic interface ConversationView extends BaseView<ConversationPresenter>{\n\n    void showItemDialog(HTConversation htConversation);\n    void refresh();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailesFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.details;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.text.TextUtils;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Button;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.addfriends.add.end.AddFriendsFinalActivity;\nimport com.htmessage.yichatopen.activity.chat.ChatActivity;\n\n/**\n * 项目名称：yichat0504\n * 类描述：UserDetailesFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 11:52\n * 邮箱:814326663@qq.com\n */\npublic class UserDetailesFragment extends Fragment implements UserDetailsView ,View.OnClickListener{\n    private UserDetailsPrester prester;\n    private Button btnMsg,btnAdd;\n    private ImageView iv_avatar,iv_sex;\n    private TextView tv_name,tv_yichat_number,tv_mobile,tv_region,tv_mixin;\n    private RelativeLayout rl_region,rl_yichat_id,re_mobile;\n    private Dialog dialog;\n    private JSONObject userJson;\n\n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        dialog = HTApp.getInstance().createLoadingDialog(getBaseActivity(),getString(R.string.now_refresh_msg));\n        dialog.setCancelable(true);\n        dialog.setCanceledOnTouchOutside(true);\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View infoView = inflater.inflate(R.layout.activity_userinfo, container, false);\n        initView(infoView);\n        getData();\n        setLstenter();\n        return infoView;\n    }\n\n    private void getData() {\n        if (!TextUtils.isEmpty(getFxid())){\n            prester.refreshInfo(getFxid(),true);\n            return;\n        }\n        if (getUserJson() == null){\n            getBaseActivity().finish();\n            return;\n        }\n        showUi(getUserJson());\n        if (prester.isFriend(getUserJson().getString(HTConstant.JSON_KEY_HXID))){\n            prester.refreshInfo(getUserJson().getString(HTConstant.JSON_KEY_HXID),false);\n        }else{\n            prester.refreshInfo(getUserJson().getString(HTConstant.JSON_KEY_HXID),true);\n        }\n    }\n\n    private void setLstenter() {\n        btnAdd.setOnClickListener(this);\n        btnMsg.setOnClickListener(this);\n    }\n\n    private void initView(View infoView) {\n        btnMsg = (Button) infoView.findViewById(R.id.btn_msg);\n        btnAdd= (Button) infoView.findViewById(R.id.btn_add);\n        iv_avatar = (ImageView) infoView.findViewById(R.id.iv_avatar);\n        iv_sex = (ImageView) infoView.findViewById(R.id.iv_sex);\n        tv_name = (TextView) infoView.findViewById(R.id.tv_name);\n        tv_yichat_number = (TextView) infoView.findViewById(R.id.tv_yichat_number);\n        tv_mobile = (TextView) infoView.findViewById(R.id.tv_mobile);\n        tv_region = (TextView) infoView.findViewById(R.id.tv_region);\n        tv_mixin = (TextView) infoView.findViewById(R.id.tv_mixin);\n        rl_region = (RelativeLayout) infoView.findViewById(R.id.rl_region);\n        rl_yichat_id = (RelativeLayout) infoView.findViewById(R.id.rl_yichat_id);\n        re_mobile = (RelativeLayout) infoView.findViewById(R.id.re_mobile);\n    }\n\n    @Override\n    public void onRefreshSuccess(String msg) {\n        Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void onRefreshFailed(String error) {\n        Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public String getFxid() {\n        return getBaseActivity().getIntent().getStringExtra(HTConstant.JSON_KEY_HXID);\n    }\n\n    @Override\n    public JSONObject getUserJson() {\n        String extra = getBaseActivity().getIntent().getStringExtra(HTConstant.KEY_USER_INFO);\n        JSONObject object = JSONObject.parseObject(extra);\n        return object;\n    }\n\n    @Override\n    public void showDialog() {\n        if (dialog!=null){\n            dialog.show();\n        }\n    }\n\n    @Override\n    public void hintDialog() {\n        if (dialog!=null){\n            dialog.dismiss();\n        }\n    }\n\n    @Override\n    public void showUi(JSONObject object) {\n        this.userJson = object;\n        String hxid = object.getString(HTConstant.JSON_KEY_HXID);\n        String yichatId = object.getString(HTConstant.JSON_KEY_FXID);\n        String Tel = object.getString(HTConstant.JSON_KEY_TEL);\n        String province = object.getString(HTConstant.JSON_KEY_PROVINCE);\n        String city = object.getString(HTConstant.JSON_KEY_CITY);\n        String sign = object.getString(HTConstant.JSON_KEY_SIGN);\n        if (!TextUtils.isEmpty(yichatId)){\n            tv_mixin.setText(getString(R.string.app_id)+yichatId);\n        }else{\n            tv_mixin.setText(getString(R.string.app_id)+getString(R.string.not_set));\n        }\n        if (!TextUtils.isEmpty(sign)) {\n            tv_yichat_number.setText(sign);\n        } else {\n            tv_yichat_number.setText(R.string.not_set);\n        }\n\n        if (!TextUtils.isEmpty(Tel)){\n            tv_mobile.setText(Tel);\n        }else{\n            tv_mobile.setText(R.string.not_set);\n        }\n        if (!TextUtils.isEmpty(province) && !TextUtils.isEmpty(city)){\n            tv_region.setText(province+\" \"+city);\n            if (province.equals(city)) {\n                tv_region.setText(city);\n            }\n        }else{\n            tv_region.setText(R.string.not_set);\n        }\n        String nick = object.getString(HTConstant.JSON_KEY_NICK);\n        String avatarUrl =object.getString(HTConstant.JSON_KEY_AVATAR);\n        if(!TextUtils.isEmpty(avatarUrl)){\n            if (!avatarUrl.contains(\"http:\")){\n                avatarUrl = HTConstant.URL_AVATAR+avatarUrl;\n            }\n        }\n        Glide.with(this).load(avatarUrl).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(iv_avatar);\n        tv_name.setText(nick);\n        String sex = object.getString(HTConstant.JSON_KEY_SEX);\n        if (!TextUtils.isEmpty(sex)){\n            if (\"1\".equals(sex) || sex.equals(getString(R.string.male))) {\n                iv_sex.setImageResource(R.drawable.icon_male);\n            } else if (\"0\".equals(sex) || sex.equals(getString(R.string.female))){\n                iv_sex.setImageResource(R.drawable.icon_female);\n            }\n        }else{\n            iv_sex.setImageResource(R.drawable.icon_male);\n        }\n\n        //资料是自己\n        if (prester.isMe(hxid)) {\n            btnMsg.setVisibility(View.GONE);\n            btnAdd.setVisibility(View.GONE);\n            return;\n        }\n        //不是好友的\n        if (!prester.isFriend(hxid)) {\n            btnMsg.setVisibility(View.GONE);\n            btnAdd.setVisibility(View.VISIBLE);\n            return;\n        }\n    }\n\n    @Override\n    public void setPresenter(UserDetailsPrester presenter) {\n        this.prester = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()){\n            case R.id.btn_add:\n                startActivity(new Intent(getBaseActivity(), AddFriendsFinalActivity.class).putExtra(HTConstant.KEY_USER_INFO, userJson.toJSONString()));\n                break;\n            case R.id.btn_msg:\n                startActivity(new Intent(getBaseActivity(), ChatActivity.class).putExtra(\"userId\",userJson.getString(HTConstant.JSON_KEY_HXID)));\n                break;\n        }\n    }\n\n    @Override\n    public void onDestroy() {\n        prester.onDestory();\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main.details;\n\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.R;\n\n/**\n * Created by huangfangyi on 2016/7/6.\\\n * QQ:84543217\n */\npublic class UserDetailsActivity extends BaseActivity {\n    /**\n     *\n     * 用户详情页接收两种传值\n     * 1：用户完整资料的JSON字符串-userInfo-这种情况如果是好友进行刷新\n     * 2：只传用户的hxid，这种情况直接从网络取数据显示-如果是好友，刷新资料\n     *\n     */\n\n    @Override\n    protected void onCreate(Bundle arg0) {\n        super.onCreate(arg0);\n        setContentView(R.layout.activity_base);\n        setTitle(R.string.Detailed_information);\n        UserDetailesFragment fragment = (UserDetailesFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (fragment == null){\n            fragment = new UserDetailesFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame,fragment);\n            transaction.commit();\n        }\n        new UserDetailsPrester(fragment);\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsBasePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.details;\n\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * 项目名称：yichat0504\n * 类描述：UserDetailsBasePrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 11:35\n * 邮箱:814326663@qq.com\n */\npublic interface UserDetailsBasePrester extends BasePresenter {\n        void onDestory();\n        void refreshInfo(String userId, boolean backTask);\n        boolean isMe(String userId);\n        boolean isFriend(String userId);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsPrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.details;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.domain.UserDao;\nimport com.htmessage.yichatopen.manager.ContactsManager;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：UserDetailsPrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 11:40\n * 邮箱:814326663@qq.com\n */\npublic class UserDetailsPrester implements UserDetailsBasePrester {\n\n    private UserDetailsView detailsView;\n\n    public UserDetailsPrester(UserDetailsView detailsView) {\n        this.detailsView = detailsView;\n        this.detailsView.setPresenter(this);\n    }\n\n    @Override\n    public void onDestory() {\n        detailsView = null;\n    }\n\n    @Override\n    public void refreshInfo(final String userId, final boolean backTask) {\n        if (!backTask){\n            detailsView.showDialog();\n        }\n        List<Param> parms = new ArrayList<>();\n        parms.add(new Param(\"userId\", userId));\n        new OkHttpUtils(detailsView.getBaseContext()).post(parms, HTConstant.URL_Get_UserInfo, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                int code = jsonObject.getInteger(\"code\");\n                if (!backTask){\n                    detailsView.hintDialog();\n                }\n                switch (code){\n                    case 1:\n                        JSONObject json = jsonObject.getJSONObject(\"user\");\n                        //刷新ui\n                        if (isFriend(userId)) {\n                            User user = CommonUtils.Json2User(json);\n                            UserDao dao = new UserDao(detailsView.getBaseContext());\n                            dao.saveContact(user);\n                            ContactsManager.getInstance().getContactList().put(user.getUsername(), user);\n                        }\n                        detailsView.showUi(json);\n                        break;\n                    default:\n                        detailsView.hintDialog();\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                detailsView.onRefreshFailed(errorMsg);\n                if (!backTask){\n                    detailsView.hintDialog();\n                }\n            }\n        });\n    }\n\n    @Override\n    public boolean isMe(String userId) {\n        return HTApp.getInstance().getUsername().equals(userId);\n    }\n\n    @Override\n    public boolean isFriend(String userId) {\n        return ContactsManager.getInstance().getContactList().containsKey(userId);\n    }\n\n    @Override\n    public void start() {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/details/UserDetailsView.java",
    "content": "package com.htmessage.yichatopen.activity.main.details;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * 项目名称：yichat0504\n * 类描述：UserDetailsView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 11:45\n * 邮箱:814326663@qq.com\n */\npublic interface UserDetailsView extends BaseView<UserDetailsPrester> {\n    void onRefreshSuccess(String msg);\n    void onRefreshFailed(String error);\n    String getFxid();\n    JSONObject getUserJson();\n    void showDialog();\n    void hintDialog();\n    void showUi(JSONObject object);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/find/FragmentFind.java",
    "content": "package com.htmessage.yichatopen.activity.main.find;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.RelativeLayout;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.ScanCaptureActivity;\nimport com.htmessage.yichatopen.activity.main.find.recentlypeople.PeopleRecentlyActivity;\n\n\npublic class FragmentFind extends Fragment implements View.OnClickListener {\n    private RelativeLayout rl_friends, re_qrcode, rl_near;\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_find, container, false);\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        if (savedInstanceState != null\n                && savedInstanceState.getBoolean(\"isConflict\", false))\n            return;\n        super.onActivityCreated(savedInstanceState);\n        initView();\n        initData();\n        setListener();\n    }\n\n    private void setListener() {\n        rl_friends.setOnClickListener(this);\n        re_qrcode.setOnClickListener(this);\n         rl_near.setOnClickListener(this);\n\n    }\n\n    private void initData() {\n\n    }\n\n    private void initView() {\n        rl_friends = (RelativeLayout) getView().findViewById(R.id.rl_friends);\n        re_qrcode = (RelativeLayout) getView().findViewById(R.id.re_qrcode);\n\n        rl_near = (RelativeLayout) getView().findViewById(R.id.rl_near);\n\n    }\n\n\n    @Override\n    public void onClick(View view) {\n        switch (view.getId()) {\n            case R.id.rl_friends://志工圈\n                break;\n            case R.id.re_qrcode: //扫一扫\n                startActivity(new Intent(getActivity(), ScanCaptureActivity.class));\n                break;\n\n            case R.id.rl_near://最近在线\n                startActivity(new Intent(getActivity(), PeopleRecentlyActivity.class));\n                 break;\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main.find.recentlypeople;\n\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\n\n/**\n * 项目名称：yichat0504\n * 类描述：PeopleRecentlyActivity 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/5 16:53\n * 邮箱:814326663@qq.com\n */\npublic class PeopleRecentlyActivity extends BaseActivity {\n\n    @Override\n    protected void onCreate(Bundle arg0) {\n        super.onCreate(arg0);\n        setContentView(R.layout.activity_base);\n        setTitle(R.string.people_time);\n        PeopleRecentlyFragment peopleRecentlyFragment =\n                (PeopleRecentlyFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (peopleRecentlyFragment == null) {\n            // Create the fragment\n            peopleRecentlyFragment = new PeopleRecentlyFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame, peopleRecentlyFragment);\n            transaction.commit();\n        }\n        PeopleRecentlyPrestener prestener = new PeopleRecentlyPrestener(peopleRecentlyFragment);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyAdapter.java",
    "content": "package com.htmessage.yichatopen.activity.main.find.recentlypeople;\n\nimport android.content.Context;\nimport android.text.TextUtils;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.utils.DateUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：PeopleRecentlyAdapter 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/5 17:17\n * 邮箱:814326663@qq.com\n */\npublic class PeopleRecentlyAdapter extends BaseAdapter {\n    private Context context;\n    private List<JSONObject> peoples = new ArrayList<>();\n\n    public PeopleRecentlyAdapter(Context context, List<JSONObject> peoples) {\n        this.context = context;\n        this.peoples = peoples;\n    }\n\n    @Override\n    public int getCount() {\n        return peoples.size();\n    }\n\n    @Override\n    public JSONObject getItem(int position) {\n        return peoples.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        ViewHolder holder;\n        if (convertView == null) {\n            convertView = View.inflate(parent.getContext(), R.layout.item_people_recently, null);\n            holder = new ViewHolder(convertView);\n            convertView.setTag(holder);\n        } else {\n            holder = (ViewHolder) convertView.getTag();\n        }\n        JSONObject jsonObject = peoples.get(position);\n        String nick = jsonObject.getString(HTConstant.JSON_KEY_NICK);\n        if (TextUtils.isEmpty(nick)) {\n            nick = jsonObject.getString(HTConstant.JSON_KEY_HXID);\n        }\n        String recentlytime = jsonObject.getString(\"recentlyTime\");\n        String serviceTime = jsonObject.getString(\"serviceTime\");\n        long l = Long.valueOf(recentlytime) * 1000;\n        long l2 = Long.valueOf(serviceTime) * 1000;\n        String difference = DateUtils.getTimeDifference(parent.getContext(),l, l2);\n        String avatar = null;\n        if (jsonObject.containsKey(HTConstant.JSON_KEY_AVATAR)) {\n            avatar = jsonObject.getString(HTConstant.JSON_KEY_AVATAR);\n            if (!TextUtils.isEmpty(avatar)) {\n                if (!avatar.contains(\"http\")) {\n                    avatar = HTConstant.baseOssUrl + avatar;\n                }\n            }\n        }\n        String sex = jsonObject.getString(HTConstant.JSON_KEY_SEX);\n        if (!TextUtils.isEmpty(sex)) {\n            if (\"1\".equals(sex) || sex.equals(parent.getContext().getString(R.string.male))) {\n                holder.iv_sex.setImageResource(R.drawable.icon_male);\n            } else if (\"0\".equals(sex) || sex.equals(parent.getContext().getString(R.string.female))) {\n                holder.iv_sex.setImageResource(R.drawable.icon_female);\n            }\n        } else {\n            holder.iv_sex.setImageResource(R.drawable.icon_male);\n        }\n        String sign = jsonObject.getString(HTConstant.JSON_KEY_SIGN);\n        if (!TextUtils.isEmpty(sign)) {\n            holder.ll_sign.setVisibility(View.VISIBLE);\n            holder.tv_sign.setText(sign);\n        } else {\n            holder.ll_sign.setVisibility(View.GONE);\n        }\n        holder.tv_name.setText(nick);\n        holder.tv_time.setText(difference);//DateUtils.getStringTime(Long.valueOf(recentlytime) * 1000)\n        Glide.with(parent.getContext()).load(avatar).placeholder(R.drawable.default_avatar).error(R.drawable.default_avatar).diskCacheStrategy(DiskCacheStrategy.ALL).into(holder.iv_avatar);\n        return convertView;\n    }\n\n    private class ViewHolder {\n        private TextView tv_name, tv_time, tv_sign;\n        private ImageView iv_avatar, iv_sex;\n        private LinearLayout ll_sign;\n\n        public ViewHolder(View view) {\n            tv_name = (TextView) view.findViewById(R.id.tv_name);\n            tv_time = (TextView) view.findViewById(R.id.tv_time);\n            tv_sign = (TextView) view.findViewById(R.id.tv_sign);\n            iv_avatar = (ImageView) view.findViewById(R.id.iv_avatar);\n            iv_sex = (ImageView) view.findViewById(R.id.iv_sex);\n            ll_sign = (LinearLayout) view.findViewById(R.id.ll_sign);\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyBasePrestener.java",
    "content": "package com.htmessage.yichatopen.activity.main.find.recentlypeople;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * 项目名称：yichat0504\n * 类描述：PeopleRecentlyBasePrestener 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/5 16:28\n * 邮箱:814326663@qq.com\n */\npublic interface PeopleRecentlyBasePrestener extends BasePresenter {\n    void requestData(int page,int pageSize,boolean loadMore);\n    void onListClickListener(JSONObject object);\n    void onDestory();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.find.recentlypeople;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.ListView;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.widget.swipyrefresh.SwipyRefreshLayout;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：PeopleRecentlyFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/5 16:54\n * 邮箱:814326663@qq.com\n */\npublic class PeopleRecentlyFragment extends Fragment implements PeopleRecentlyView,AdapterView.OnItemClickListener ,SwipyRefreshLayout.OnRefreshListener{\n    private PeopleRecentlyPrestener prestener;\n    private Dialog diallog;\n    private SwipyRefreshLayout swipyrefresh;\n    private ListView listview_people_recently;\n    private List<JSONObject> peoples = new ArrayList<>();\n    private PeopleRecentlyAdapter adapter;\n\n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        diallog = HTApp.getInstance().createLoadingDialog(getBaseContext(),getString(R.string.loading));\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View timeview = inflater.inflate(R.layout.activity_people_recently, container, false);\n        initView(timeview);\n        initData();\n        setListener();\n        return timeview;\n    }\n\n    private void setListener() {\n        listview_people_recently.setOnItemClickListener(this);\n        swipyrefresh.setOnRefreshListener(this);\n    }\n\n    private void initData() {\n        adapter = new PeopleRecentlyAdapter(getBaseContext(), peoples);\n        listview_people_recently.setAdapter(adapter);\n        onRefresh(1);\n    }\n\n    private void initView(View timeview) {\n        swipyrefresh = (SwipyRefreshLayout)timeview.findViewById(R.id.swipyrefresh);\n        listview_people_recently = (ListView) timeview.findViewById(R.id.listview_people_recently);\n    }\n\n    @Override\n    public void showLoadingDialog() {\n        if (diallog!=null){\n            diallog.show();\n        }\n    }\n\n    @Override\n    public void hideLoadingDialog() {\n        if (diallog!=null){\n            diallog.dismiss();\n        }\n        swipyrefresh.setRefreshing(false);\n    }\n\n    @Override\n    public void onRequestSuccess(List<JSONObject> peopleList) {\n        swipyrefresh.setRefreshing(false);\n        peoples.addAll(peopleList);\n        adapter.notifyDataSetChanged();\n\n    }\n\n    @Override\n    public void onRequestFailed(String errorMsg) {\n        swipyrefresh.setRefreshing(false);\n        Toast.makeText(getBaseContext(), errorMsg, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void setPresenter(PeopleRecentlyPrestener presenter) {\n        this.prestener = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        JSONObject item = adapter.getItem(position);\n        prestener.onListClickListener(item);\n    }\n\n    @Override\n    public void onRefresh(int index) {\n        peoples.clear();\n        index = 1;\n        prestener.requestData(index,20,false);\n    }\n\n    @Override\n    public void onLoad(int index) {\n        index++;\n        prestener.requestData(index,20,true);\n    }\n\n    @Override\n    public void onDestroy() {\n        prestener.onDestory();\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyPrestener.java",
    "content": "package com.htmessage.yichatopen.activity.main.find.recentlypeople;\n\nimport android.content.Intent;\nimport android.util.Log;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.main.details.UserDetailsActivity;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：PeopleRecentlyPrestener 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/5 16:34\n * 邮箱:814326663@qq.com\n */\npublic class PeopleRecentlyPrestener implements PeopleRecentlyBasePrestener {\n    private PeopleRecentlyView timeView;\n\n    public PeopleRecentlyPrestener(PeopleRecentlyView timeView) {\n        this.timeView = timeView;\n        this.timeView.setPresenter(this);\n    }\n\n    @Override\n    public void requestData(int page, int pageSize, final boolean loadMore) {\n        timeView.showLoadingDialog();\n        List<Param> params = new ArrayList<>();\n        params.add(new Param(\"currentPage\",String.valueOf(page)));\n        params.add(new Param(\"pageSize\",String.valueOf(pageSize)));\n        new OkHttpUtils(timeView.getBaseContext()).post(params, HTConstant.URL_GET_RECENTLY_PEOPLE, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                timeView.hideLoadingDialog();\n                int code = jsonObject.getIntValue(\"code\");\n                switch (code){\n                    case 1:\n                        List<JSONObject> peoples = new ArrayList<JSONObject>();\n                        JSONArray data = jsonObject.getJSONArray(\"data\");\n                        if (data!=null && data.size()!=0){\n                            for (int i = 0; i <data.size() ; i++) {\n                                JSONObject object = data.getJSONObject(i);\n                                if (!peoples.contains(object)){\n                                    peoples.add(object);\n                                }\n                            }\n                            timeView.onRequestSuccess(peoples);\n                        }else{\n                            timeView.onRequestFailed(timeView.getBaseContext().getString(R.string.load_failed));\n                        }\n                        break;\n                    default:\n                        if (loadMore){\n                            timeView.onRequestFailed(timeView.getBaseContext().getString(R.string.load_more_failed));\n                        }else{\n                            timeView.onRequestFailed(timeView.getBaseContext().getString(R.string.load_failed));\n                        }\n                        break;\n                }\n                Log.d(\"slj\",\"----最近上线的人:\"+jsonObject.toJSONString());\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                timeView.hideLoadingDialog();\n                timeView.onRequestFailed(errorMsg);\n            }\n        });\n    }\n\n    @Override\n    public void onListClickListener(JSONObject object) {\n        timeView.getBaseActivity().startActivity(new Intent(timeView.getBaseActivity(), UserDetailsActivity.class).putExtra(HTConstant.KEY_USER_INFO,object.toJSONString()));\n    }\n\n    @Override\n    public void onDestory() {\n        timeView = null;\n    }\n\n    @Override\n    public void start() {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/find/recentlypeople/PeopleRecentlyView.java",
    "content": "package com.htmessage.yichatopen.activity.main.find.recentlypeople;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.activity.BaseView;\n\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：PeopleRecentlyView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/5 16:30\n * 邮箱:814326663@qq.com\n */\npublic interface PeopleRecentlyView extends BaseView<PeopleRecentlyPrestener> {\n    void showLoadingDialog();\n    void hideLoadingDialog();\n    void onRequestSuccess(List<JSONObject> peoples);\n    void onRequestFailed(String errorMsg);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordBasePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.password;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * 项目名称：HTOpen\n * 类描述：PasswordBasePrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 14:59\n * 邮箱:814326663@qq.com\n */\npublic interface PasswordBasePrester  extends BasePresenter {\n    void sendSMSCode(String mobile,String countryName,String countryCode);\n    void resetPassword(String cacheCode,String smsCode,String password,String confimPwd,String mobile);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordPrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.password;\n\nimport android.app.ProgressDialog;\nimport android.content.Intent;\nimport android.text.TextUtils;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.activity.login.LoginActivity;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.htmessage.yichatopen.utils.Validator;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：HTOpen\n * 类描述：PasswordPrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 15:07\n * 邮箱:814326663@qq.com\n */\npublic class PasswordPrester implements PasswordBasePrester {\n    private String TAG = PasswordPrester.class.getSimpleName();\n    private PasswordView passwordView;\n\n    public PasswordPrester(PasswordView passwordView) {\n        this.passwordView = passwordView;\n        this.passwordView.setPresenter(this);\n    }\n\n    @Override\n    public void sendSMSCode(String mobile, String countryName, String countryCode) {\n        if (TextUtils.isEmpty(mobile)) {\n            Toast.makeText(passwordView.getBaseContext(), R.string.mobile_not_be_null, Toast.LENGTH_SHORT).show();\n            return;\n        }\n        if (countryName.equals(passwordView.getBaseContext().getString(R.string.china)) && countryCode.equals(passwordView.getBaseContext().getString(R.string.country_code))){\n            if (!Validator.isMobile(mobile)) {\n                Toast.makeText(passwordView.getBaseContext(), R.string.please_input_true_mobile, Toast.LENGTH_SHORT).show();\n                return;\n            }\n            passwordView.startTimeDown();\n\n        }else{\n            passwordView.onSendSMSCodeSuccess(\"1234\");\n        }\n    }\n\n    @Override\n    public void resetPassword(String cacheCode, String smsCode, String password, String confimPwd, String mobile) {\n        if (TextUtils.isEmpty(mobile)) {\n            Toast.makeText(passwordView.getBaseContext(), R.string.mobile_not_be_null, Toast.LENGTH_SHORT).show();\n            return;\n        }\n//        if (TextUtils.isEmpty(smsCode) || TextUtils.isEmpty(cacheCode)) {\n//            Toast.makeText(passwordView.getBaseContext(), R.string.please_input_code, Toast.LENGTH_SHORT).show();\n//            return;\n//        }\n        if (TextUtils.isEmpty(password) || TextUtils.isEmpty(confimPwd)) {\n            Toast.makeText(passwordView.getBaseContext(), R.string.new_password_cannot_be_empty, Toast.LENGTH_SHORT).show();\n            return;\n        }\n//        if (!cacheCode.equals(smsCode)){\n//            Toast.makeText(passwordView.getBaseContext(), R.string.code_is_wrong, Toast.LENGTH_SHORT).show();\n//            return;\n//        }\n        if (!password.equals(confimPwd)) {\n            Toast.makeText(passwordView.getBaseContext(), R.string.Two_input_password, Toast.LENGTH_SHORT).show();\n            return;\n        }\n        final ProgressDialog progressDialog = new ProgressDialog(passwordView.getBaseContext());\n        progressDialog.setMessage(passwordView.getBaseContext().getString(R.string.are_reset_password));\n        progressDialog.setCanceledOnTouchOutside(false);\n        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);\n        progressDialog.show();\n        List<Param> params = new ArrayList<Param>();\n        params.add(new Param(\"newPassword\", password));\n        params.add(new Param(\"tel\", mobile));\n        new OkHttpUtils(passwordView.getBaseContext()).post(params, HTConstant.URL_RESETPASSWORD, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                progressDialog.dismiss();\n                int code = jsonObject.getIntValue(\"code\");\n                switch(code){\n                    case 1:\n                        passwordView.clearCacheCode();\n                        passwordView.onResetSuccess(passwordView.getBaseContext().getString(R.string.password_reset_success));\n                        logOut(passwordView.getIsReset());\n                        break;\n                    default:\n                        passwordView.onResetFailed(passwordView.getBaseContext().getString(R.string.password_reset_failed));\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                progressDialog.dismiss();\n                passwordView.onResetFailed(passwordView.getBaseContext().getString(R.string.password_reset_failed));\n            }\n        });\n    }\n\n    private void logOut(boolean isReset) {\n        if (isReset){\n            HTClient.getInstance().logout(new HTClient.HTCallBack() {\n\n                @Override\n                public void onSuccess() {\n                    passwordView.getBaseActivity().runOnUiThread(new Runnable() {\n                        public void run() {\n                            // show login scree\n                            HTApp.getInstance().setUserJson(null);\n                            HTApp.getInstance().finishActivities();\n                            passwordView.getBaseActivity().startActivity(new Intent(passwordView.getBaseActivity(), LoginActivity.class));\n                            passwordView.getBaseActivity().finish();\n                        }\n                    });\n                }\n\n                @Override\n                public void onError() {\n                    passwordView.getBaseActivity().runOnUiThread(new Runnable() {\n\n                        @Override\n                        public void run() {\n                            passwordView.onLogOutFailed(passwordView.getBaseContext().getString(R.string.logout_failed));\n                        }\n                    });\n                }\n            });\n        }else{\n            passwordView.getBaseActivity().finish();\n        }\n    }\n\n    @Override\n    public void start() {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordResetActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main.password;\n\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\n\n/**\n * Created by huangfangyi on 2016/10/7.\n * qq 84543217\n */\n\npublic class PasswordResetActivity extends BaseActivity{\n    @Override\n    protected void onCreate(Bundle arg0) {\n        super.onCreate(arg0);\n        setContentView(R.layout.activity_base);\n        getData();\n        initView();\n    }\n\n    private void initView() {\n        PasswordResetFragment fragment = (PasswordResetFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (fragment == null){\n            fragment = new PasswordResetFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame, fragment);\n            transaction.commit();\n        }\n        PasswordPrester prester = new PasswordPrester(fragment);\n    }\n\n    private void getData() {\n        boolean isReset = getIntent().getBooleanExtra(\"isReset\", false);\n        if (isReset){\n            setTitle(R.string.resetPassword);\n        }else{\n            setTitle(R.string.find_pwd);\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordResetFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.password;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.View.OnClickListener;\nimport android.view.ViewGroup;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.utils.ACache;\nimport com.htmessage.yichatopen.utils.CommonUtils;\n\n/**\n * 项目名称：HTOpen\n * 类描述：PasswordResetFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 15:33\n * 邮箱:814326663@qq.com\n */\npublic class PasswordResetFragment extends Fragment implements PasswordView ,OnClickListener{\n    private Button btn_ok, btn_code;\n    private EditText et_code,et_usertel,et_password,et_password_confire;\n     private String mobile;\n    private TextView tv_title;\n    private ACache aCache;\n    private TextView tv_country,tv_country_code;\n    private RelativeLayout rl_country,rl_smscode;\n    private PasswordPrester prester;\n\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View pswView = inflater.inflate(R.layout.activity_psw_reset, container, false);\n        getData();\n        initView(pswView);\n        initData();\n        setListener();\n        return pswView;\n    }\n\n    private void setListener() {\n        tv_country.setOnClickListener(this);\n        tv_country_code.setOnClickListener(this);\n        rl_country.setOnClickListener(this);\n        btn_ok.setOnClickListener(this);\n        btn_code.setOnClickListener(this);\n    }\n\n    private void initData() {\n        rl_smscode.setVisibility(View.GONE);\n         if (getIsReset()) {\n            tv_title.setText(R.string.resetPassword);\n            btn_ok.setText(R.string.resetPassword);\n            mobile = HTApp.getInstance().getUserJson().getString(HTConstant.JSON_KEY_TEL);\n            et_usertel.setText(mobile);\n            et_usertel.setEnabled(false);\n            et_usertel.clearFocus();\n        } else {\n            tv_title.setText(R.string.find_pwd);\n            btn_ok.setText(R.string.find_pwd);\n            et_usertel.setHint(R.string.input_bind_mobile);\n            et_usertel.setEnabled(true);\n            et_usertel.requestFocus();\n        }\n    }\n\n    private void initView(View pswView) {\n        //获取国家code\n        tv_country = (TextView) pswView.findViewById(R.id.tv_country);\n        tv_country_code = (TextView) pswView.findViewById(R.id.tv_country_code);\n        rl_country = (RelativeLayout) pswView.findViewById(R.id.rl_country);\n        rl_smscode = (RelativeLayout) pswView.findViewById(R.id.rl_smscode);\n        et_usertel = (EditText) pswView.findViewById(R.id.et_usertel);\n        et_password = (EditText) pswView.findViewById(R.id.et_password);\n        et_password_confire = (EditText) pswView.findViewById(R.id.et_password_confire);\n        et_code = (EditText) pswView.findViewById(R.id.et_code);\n        btn_ok = (Button) pswView.findViewById(R.id.btn_ok);\n        btn_code = (Button) pswView.findViewById(R.id.btn_code);\n        tv_title= (TextView) pswView.findViewById(R.id.tv_title);\n    }\n\n    private void getData() {\n        aCache = ACache.get(getActivity());\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()){\n\n            case R.id.rl_country:\n                    CommonUtils.showPup(getBaseActivity(),tv_country,tv_country_code);\n                break;\n            case R.id.btn_code:\n                prester.sendSMSCode(getMobile(),getCountryName(),getCountryCode());\n                break;\n            case R.id.btn_ok:\n                prester.resetPassword(getCacheCode(),getSMSCode(),getPwd(),getConfimPwd(),getMobile());\n                break;\n        }\n    }\n\n    @Override\n    public String getCountryName() {\n        return tv_country.getText().toString().trim();\n    }\n\n    @Override\n    public String getCountryCode() {\n        return tv_country_code.getText().toString().trim();\n    }\n\n    @Override\n    public String getCacheCode() {\n        return  aCache.getAsString(\"code\");\n    }\n\n    @Override\n    public String getSMSCode() {\n        return et_code.getText().toString().trim();\n    }\n\n    @Override\n    public boolean getIsReset() {\n        return getActivity().getIntent().getBooleanExtra(\"isReset\", false);\n    }\n\n    @Override\n    public String getMobile() {\n        return et_usertel.getText().toString().trim();\n    }\n\n    @Override\n    public String getPwd() {\n        return et_password.getText().toString().trim();\n    }\n\n    @Override\n    public String getConfimPwd() {\n        return et_password_confire.getText().toString().trim();\n    }\n\n    @Override\n    public void clearCacheCode() {\n        aCache.put(\"code\",\"\");\n    }\n\n    @Override\n    public void onSendSMSCodeSuccess(String msg) {\n        if (\"1234\".equals(msg)){\n            et_code.setText(msg);\n        }\n        aCache.put(\"code\",msg);\n        Toast.makeText(getBaseContext(), R.string.code_is_send, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void onSendSMSCodeFailed(String error) {\n        Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void onResetSuccess(String msg) {\n        Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void onResetFailed(String error) {\n        Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void startTimeDown() {\n\n    }\n\n    @Override\n    public void finishTimeDown() {\n\n    }\n\n\n    @Override\n    public void onLogOutFailed(String msg) {\n        Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void setPresenter(PasswordPrester presenter) {\n        this.prester = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/password/PasswordView.java",
    "content": "package com.htmessage.yichatopen.activity.main.password;\n\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * 项目名称：HTOpen\n * 类描述：PasswordView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 15:08\n * 邮箱:814326663@qq.com\n */\npublic interface PasswordView extends BaseView<PasswordPrester>{\n    String getCountryName();\n    String getCountryCode();\n    String getCacheCode();\n    String getSMSCode();\n    boolean getIsReset();\n    String getMobile();\n    String getPwd();\n    String getConfimPwd();\n    void clearCacheCode();\n    void onSendSMSCodeSuccess(String msg);\n    void onSendSMSCodeFailed(String error);\n    void onResetSuccess(String msg);\n    void onResetFailed(String error);\n    void startTimeDown();\n    void finishTimeDown();\n    void onLogOutFailed(String msg);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/FragmentProfile.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.text.TextUtils;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.main.qrcode.QrCodeActivity;\nimport com.htmessage.yichatopen.activity.main.profile.info.profile.ProfileActivity;\nimport com.htmessage.yichatopen.activity.SettingsActivity;\n\npublic class FragmentProfile extends Fragment implements View.OnClickListener {\n    private InfoChangedListener listener;\n    private ImageView ivAvatar;\n    private TextView tvNick;\n    private TextView tvFxid;\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_profile, container, false);\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        getData();\n        setListener();\n        initView(HTApp.getInstance().getUserJson());\n    }\n\n    private void getData() {\n        IntentFilter intent = new IntentFilter(IMAction.ACTION_UPDATE_INFO);\n        listener = new InfoChangedListener();\n        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(listener, intent);\n\n    }\n\n    private void initView(JSONObject jsonObject) {\n\n        ivAvatar = (ImageView) getView().findViewById(R.id.iv_avatar);\n        tvNick = (TextView) getView().findViewById(R.id.tv_name);\n\n        tvFxid = (TextView) getView().findViewById(R.id.tv_fxid);\n        String avatarUrl = jsonObject.getString(HTConstant.JSON_KEY_AVATAR);\n        Glide.with(getActivity()).load(avatarUrl).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(ivAvatar);\n        tvNick.setText(jsonObject.getString(HTConstant.JSON_KEY_NICK));\n        String fxid = jsonObject.getString(HTConstant.JSON_KEY_FXID);\n        if (!TextUtils.isEmpty(fxid)) {\n            tvFxid.setText(getString(R.string.app_id) + fxid);\n        } else {\n            tvFxid.setText(getString(R.string.app_id) + getString(R.string.not_set));\n        }\n    }\n\n    private void setListener() {\n        getView().findViewById(R.id.re_myinfo).setOnClickListener(this);\n        getView().findViewById(R.id.re_setting).setOnClickListener(this);\n        getView().findViewById(R.id.re_xiangce).setOnClickListener(this);\n        getView().findViewById(R.id.rl_qrcode).setOnClickListener(this);\n\n        getView().findViewById(R.id.re_pro_test).setOnClickListener(this);\n        getView().findViewById(R.id.re_github).setOnClickListener(this);\n        getView().findViewById(R.id.re_oschina).setOnClickListener(this);\n\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.re_myinfo:\n                startActivity(new Intent(getActivity(), ProfileActivity.class));\n                break;\n\n            case R.id.re_setting:\n                startActivity(new Intent(getActivity(), SettingsActivity.class));\n                break;\n\n            case R.id.re_xiangce:\n                break;\n            case R.id.rl_qrcode: //我的二维码\n                startActivity(new Intent(getActivity(), QrCodeActivity.class));\n                break;\n            case R.id.re_pro_test://pro版本\n                toStartBrowser(HTConstant.YICHATPROURL);\n                break;\n            case R.id.re_github:\n                toStartBrowser(HTConstant.GITHUBURL);\n                break;\n            case R.id.re_oschina:\n                toStartBrowser(HTConstant.OSCHINAURL);\n                break;\n\n        }\n    }\n\n    private void toStartBrowser(String url) {\n        Intent intent = new Intent();\n        intent.setAction(Intent.ACTION_VIEW);\n        Uri uri = Uri.parse(url);\n        intent.setData(uri);\n        intent.setClassName(\"com.android.browser\", \"com.android.browser.BrowserActivity\");\n        startActivity(intent);\n    }\n\n\n    private class InfoChangedListener extends BroadcastReceiver {\n\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            if (IMAction.ACTION_UPDATE_INFO.equals(intent.getAction())) {\n                String type = intent.getStringExtra(HTConstant.KEY_CHANGE_TYPE);\n                if (HTConstant.JSON_KEY_AVATAR.equals(type)) {\n                    String avatar = intent.getStringExtra(HTConstant.JSON_KEY_AVATAR);\n                    Glide.with(getActivity()).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(ivAvatar);\n                } else if (HTConstant.JSON_KEY_FXID.equals(type)) {\n                    String fxid = intent.getStringExtra(HTConstant.JSON_KEY_FXID);\n                    tvFxid.setText(getString(R.string.app_id) + fxid);\n                } else if (HTConstant.JSON_KEY_NICK.equals(type)) {\n                    String nick = intent.getStringExtra(HTConstant.JSON_KEY_NICK);\n                    tvNick.setText(nick);\n                }\n            }\n        }\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        if (listener != null) {\n            LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(listener);\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.profile;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\n\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.R;\n\npublic class ProfileActivity extends BaseActivity {\n    private ProfilePrester prester;\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_base);\n        setTitle(R.string.title_user_profile);\n        ProfileFragment fragment =  (ProfileFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (fragment == null){\n            fragment = new ProfileFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame, fragment);\n            transaction.commit();\n        }\n        prester = new ProfilePrester(fragment);\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        prester.result(requestCode,resultCode,data);\n        super.onActivityResult(requestCode, resultCode, data);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileBasePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.profile;\n\nimport android.content.Intent;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * 项目名称：HTOpen\n * 类描述：ProfileBasePrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 10:50\n * 邮箱:814326663@qq.com\n */\npublic interface ProfileBasePrester  extends BasePresenter {\n    void resgisteRecivier();\n    void showPhotoDialog();\n    void showSexDialog();\n    void result(int requestCode, int resultCode, Intent intent);\n    void onDestory();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.profile;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.text.TextUtils;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\nimport com.alibaba.fastjson.JSONObject;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.main.qrcode.QrCodeActivity;\nimport com.htmessage.yichatopen.activity.main.region.RegionActivity;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.activity.main.profile.info.update.ProfileUpdateActivity;\n\n/**\n * 项目名称：HTOpen\n * 类描述：ProfileFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 11:47\n * 邮箱:814326663@qq.com\n */\npublic class ProfileFragment extends Fragment implements ProfileView, View.OnClickListener{\n    private RelativeLayout re_avatar,re_name,re_fxid,re_sex,re_region,re_sign,re_qrcode;\n    private ImageView iv_avatar;\n    private TextView tv_name;\n    private TextView tv_fxid;\n    private TextView tv_sex;\n    private TextView tv_sign, tv_region;\n    private String sex;\n    private ProfilePrester prester;\n    private JSONObject userJson;\n    private static final int UPDATE_REGION = 7;\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View view = inflater.inflate(R.layout.fragment_profile_info, container, false);\n        initView(view);\n        initData();\n        setListener();\n        return view;\n    }\n\n    private void setListener() {\n        //设置监听\n        re_avatar.setOnClickListener(this);\n        re_name.setOnClickListener(this);\n        re_fxid.setOnClickListener(this);\n        re_sex.setOnClickListener(this);\n        re_region.setOnClickListener(this);\n        re_sign.setOnClickListener(this);\n        re_qrcode.setOnClickListener(this);\n    }\n\n    private void initData() {\n        prester.resgisteRecivier();\n        userJson = getUserJson();\n        String nick = userJson.getString(HTConstant.JSON_KEY_NICK);\n        String fxid = userJson.getString(HTConstant.JSON_KEY_FXID);\n        sex = userJson.getString(HTConstant.JSON_KEY_SEX);\n        String sign = userJson.getString(HTConstant.JSON_KEY_SIGN);\n        String province = userJson.getString(HTConstant.JSON_KEY_PROVINCE);\n        String city = userJson.getString(HTConstant.JSON_KEY_CITY);\n\n        String avatarUrl = userJson.getString(HTConstant.JSON_KEY_AVATAR);\n        if (!TextUtils.isEmpty(avatarUrl)) {\n            if (!avatarUrl.contains(\"http:\")) {\n                avatarUrl = HTConstant.URL_AVATAR + avatarUrl;\n            }\n        }\n        Glide.with(getBaseContext()).load(avatarUrl).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).into(iv_avatar);\n        tv_name.setText(nick);\n        if (TextUtils.isEmpty(fxid)) {\n            tv_fxid.setText(R.string.not_set);\n        } else {\n            tv_fxid.setText(fxid);\n        }\n        if (!TextUtils.isEmpty(sex)) {\n            switch (sex) {\n                case \"1\":\n                case \"男\":\n                    tv_sex.setText(R.string.male);\n                    break;\n                case \"0\":\n                case \"女\":\n                    tv_sex.setText(R.string.female);\n                    break;\n                default:\n                    tv_sex.setText(R.string.not_set);\n                    break;\n            }\n        } else {\n            tv_sex.setText(R.string.not_set);\n        }\n        if (TextUtils.isEmpty(sign)) {\n            tv_sign.setText(R.string.not_input);\n        } else {\n            tv_sign.setText(sign);\n        }\n\n        if (!TextUtils.isEmpty(province) && !TextUtils.isEmpty(city)) {\n            tv_region.setText(province + \" \" + city);\n        } else {\n            tv_region.setText(R.string.not_set);\n        }\n    }\n\n    private void initView(View view) {\n        iv_avatar = (ImageView) view.findViewById(R.id.iv_avatar);\n        tv_name = (TextView) view.findViewById(R.id.tv_name);\n        tv_fxid = (TextView) view.findViewById(R.id.tv_fxid);\n        tv_sex = (TextView) view.findViewById(R.id.tv_sex);\n        tv_sign = (TextView) view.findViewById(R.id.tv_sign);\n        tv_region = (TextView) view.findViewById(R.id.tv_region);\n\n        re_avatar = (RelativeLayout) view.findViewById(R.id.re_avatar);\n        re_name= (RelativeLayout) view.findViewById(R.id.re_name);\n        re_fxid = (RelativeLayout) view.findViewById(R.id.re_fxid);\n        re_sex = (RelativeLayout) view.findViewById(R.id.re_sex);\n        re_region= (RelativeLayout) view.findViewById(R.id.re_region);\n        re_sign = (RelativeLayout) view.findViewById(R.id.re_sign);\n        re_qrcode = (RelativeLayout) view.findViewById(R.id.re_qrcode);\n    }\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.re_avatar:\n                prester.showPhotoDialog();\n                break;\n            case R.id.re_name:\n                startActivity(new Intent(getActivity(), ProfileUpdateActivity.class)\n                        .putExtra(\"type\", ProfileUpdateActivity.TYPE_NICK)\n                        .putExtra(\"default\", userJson.getString(HTConstant.JSON_KEY_NICK)));\n                break;\n            case R.id.re_fxid:\n                if (TextUtils.isEmpty(userJson.getString(HTConstant.JSON_KEY_FXID))) {\n                    startActivity(new Intent(getActivity(), ProfileUpdateActivity.class)\n                            .putExtra(\"type\", ProfileUpdateActivity.TYPE_FXID));\n                }\n                break;\n            case R.id.re_sex:\n                prester.showSexDialog();\n                break;\n            case R.id.re_region:\n                getBaseActivity().startActivityForResult(new Intent(getBaseActivity(), RegionActivity.class), UPDATE_REGION);\n                break;\n            case R.id.re_sign:\n                startActivity(new Intent(getActivity(), ProfileUpdateActivity.class)\n                        .putExtra(\"type\", ProfileUpdateActivity.TYPE_SIGN)\n                        .putExtra(\"default\", userJson.getString(HTConstant.JSON_KEY_SIGN)));\n                break;\n            case R.id.re_qrcode:\n                startActivity(new Intent(getActivity(), QrCodeActivity.class));\n                break;\n\n        }\n    }\n\n    @Override\n    public void onNickUpdate(String nick, boolean isHang) {\n        tv_name.setText(nick);\n    }\n\n    @Override\n    public void onSexUpdate(int sex, boolean isHang) {\n        tv_sex.setText(sex);\n    }\n\n    @Override\n    public void onSignUpdate(String sign, boolean isHang) {\n        tv_sign.setText(sign);\n    }\n\n    @Override\n    public void onAvatarUpdate(String avatar, boolean isHang) {\n        Glide.with(getBaseContext()).load(avatar).diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.default_avatar).error(R.drawable.default_avatar).into(iv_avatar);\n    }\n\n    @Override\n    public void onRegionUpdate(String region, boolean isHang) {\n        tv_region.setText(region);\n    }\n\n    @Override\n    public void onFxidUpdate(String fxid, boolean isHang) {\n        tv_fxid.setText(fxid);\n    }\n\n    @Override\n    public void onUpdateSuccess(String msg) {\n        Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void onUpdateFailed(String error) {\n        Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public JSONObject getUserJson() {\n        return HTApp.getInstance().getUserJson();\n    }\n\n    @Override\n    public void setPresenter(ProfilePrester presenter) {\n        this.prester = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void onDestroy() {\n        prester.onDestory();\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfilePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.profile;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.net.Uri;\nimport android.provider.MediaStore;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.sdk.android.oss.ClientException;\nimport com.alibaba.sdk.android.oss.ServiceException;\nimport com.alibaba.sdk.android.oss.model.PutObjectRequest;\nimport com.alibaba.sdk.android.oss.model.PutObjectResult;\nimport com.htmessage.sdk.utils.UploadFileUtils;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.htmessage.yichatopen.widget.HTAlertDialog;\nimport com.soundcloud.android.crop.Crop;\n\nimport java.io.File;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * 项目名称：HTOpen\n * 类描述：ProfilePrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 10:49\n * 邮箱:814326663@qq.com\n */\npublic class ProfilePrester implements ProfileBasePrester {\n    private static final int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照\n    private static final int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择\n    private static final int PHOTO_REQUEST_CUT = 3;// 结果\n    private static final int UPDATE_REGION = 7;\n    private String imageName;\n    private String dirPath;\n    private JSONObject userJson;\n    private ProfileView profileView;\n    private InfoChangedListener listener;\n\n    public ProfilePrester(ProfileView profileView) {\n        this.profileView = profileView;\n        this.profileView.setPresenter(this);\n        dirPath = HTApp.getInstance().getDirFilePath();\n        userJson =  profileView.getUserJson();\n    }\n\n    @Override\n    public void resgisteRecivier() {\n        IntentFilter intent = new IntentFilter(IMAction.ACTION_UPDATE_INFO);\n        listener = new InfoChangedListener();\n        LocalBroadcastManager.getInstance(profileView.getBaseContext()).registerReceiver(listener, intent);\n    }\n\n    private void updateInfo(final String key, final String value) {\n        if (TextUtils.isEmpty(key) && TextUtils.isEmpty(value)){\n            return;\n        }\n        final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(profileView.getBaseContext(), profileView.getBaseContext().getString(R.string.are_uploading));\n        progressDialog.show();\n        List<Param> params = new ArrayList<Param>();\n        params.add(new Param(key, value));\n        params.add(new Param(\"userId\", HTApp.getInstance().getUsername()));\n        new OkHttpUtils(profileView.getBaseContext()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                progressDialog.dismiss();\n                int code = jsonObject.getIntValue(\"code\");\n                if (code == 1) {\n                    //update ui\n                    if (key.equals(HTConstant.JSON_KEY_SEX)) {\n                        switch (value) {\n                            case \"1\":\n                                profileView.onSexUpdate(R.string.male,true);\n                                break;\n                            case \"0\":\n                                profileView.onSexUpdate(R.string.female,true);\n                                break;\n                        }\n                    }\n                    userJson.put(key, value);\n                    HTApp.getInstance().setUserJson(userJson);\n                    profileView.onUpdateSuccess(profileView.getBaseContext().getString(R.string.update_success));\n                } else {\n                    profileView.onUpdateFailed(profileView.getBaseContext().getString(R.string.upload_failed)+code);\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                profileView.onUpdateFailed(errorMsg);\n                progressDialog.dismiss();\n            }\n        });\n\n    }\n\n    private void updateRegion(final String province,final String city) {\n        if (TextUtils.isEmpty(province) && TextUtils.isEmpty(city)){\n            return;\n        }\n        final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(profileView.getBaseContext(), profileView.getBaseContext().getString(R.string.are_uploading));\n        progressDialog.show();\n        final List<Param> params = new ArrayList<Param>();\n        params.add(new Param(HTConstant.JSON_KEY_PROVINCE, province));\n        params.add(new Param(HTConstant.JSON_KEY_CITY, city));\n        params.add(new Param(\"userId\", HTApp.getInstance().getUsername()));\n        new OkHttpUtils(profileView.getBaseContext()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                progressDialog.dismiss();\n                int code = jsonObject.getIntValue(\"code\");\n                if (code == 1) {\n                    //update ui\n                    userJson.put(HTConstant.JSON_KEY_PROVINCE, province);\n                    userJson.put(HTConstant.JSON_KEY_CITY, city);\n                    HTApp.getInstance().setUserJson(userJson);\n                    profileView.onRegionUpdate(province +\" \"+city,true);\n                    profileView.onUpdateSuccess(profileView.getBaseContext().getString(R.string.update_success));\n                } else {\n                    profileView.onUpdateFailed(profileView.getBaseContext().getString(R.string.upload_failed) + code);\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                profileView.onUpdateFailed(errorMsg);\n                progressDialog.dismiss();\n            }\n        });\n    }\n\n    private void updateAvatar(final String key,final String value){\n        if (TextUtils.isEmpty(key) && TextUtils.isEmpty(value)){\n            return;\n        }\n        final Dialog progressDialog = HTApp.getInstance().createLoadingDialog(profileView.getBaseContext(), profileView.getBaseContext().getString(R.string.are_uploading));\n        progressDialog.show();\n        final String fileName = value.substring(value.lastIndexOf(\"/\") + 1);\n        new UploadFileUtils(profileView.getBaseContext(), fileName, value).asyncUploadFile(new UploadFileUtils.a() {\n            @Override\n            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {\n\n            }\n\n            @Override\n            public void onSuccess(PutObjectRequest request, PutObjectResult result) {\n                final String url = HTConstant.baseOssUrl + fileName;\n                profileView.getBaseActivity().runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        UpLoadAvator(value, key, url, progressDialog);\n                    }\n                });\n            }\n\n            @Override\n            public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {\n                profileView.getBaseActivity().runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        progressDialog.dismiss();\n                    }\n                });\n            }\n        });\n    }\n    private void UpLoadAvator(final String filePath, final String key, final String value, final Dialog progressDialog) {\n        List<Param> params = new ArrayList<Param>();\n        params.add(new Param(key, value));\n        new OkHttpUtils(profileView.getBaseContext()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                progressDialog.dismiss();\n                int code = jsonObject.getIntValue(\"code\");\n                switch (code) {\n                    case 1:\n                        if (key.equals(HTConstant.JSON_KEY_AVATAR)) {\n                            userJson.put(HTConstant.JSON_KEY_AVATAR, value);\n                            HTApp.getInstance().setUserJson(userJson);\n                            profileView.onAvatarUpdate(filePath,true);\n                            LocalBroadcastManager.getInstance(profileView.getBaseContext()).sendBroadcast(new Intent(IMAction.ACTION_UPDATE_INFO).putExtra(HTConstant.JSON_KEY_AVATAR, value).putExtra(HTConstant.KEY_CHANGE_TYPE, HTConstant.JSON_KEY_AVATAR));\n                        }\n                        profileView.onUpdateSuccess(profileView.getBaseContext().getString(R.string.update_success));\n                        break;\n                    default:\n                        String info = jsonObject.getString(\"info\");\n                        profileView.onUpdateFailed(info);\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                profileView.onUpdateFailed(errorMsg);\n                progressDialog.dismiss();\n            }\n        });\n    }\n\n    @Override\n    public void showPhotoDialog() {\n        HTAlertDialog fxAlertDialog = new HTAlertDialog(profileView.getBaseContext(), null, new String[]{profileView.getBaseContext().getString(R.string.attach_take_pic), profileView.getBaseContext().getString(R.string.image_manager)});\n        fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                switch (position) {\n                    case 0:\n                        imageName = getNowTime() + \".png\";\n                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);\n                        // 指定调用相机拍照后照片的储存路径\n                        intent.putExtra(MediaStore.EXTRA_OUTPUT,\n                                Uri.fromFile(new File(dirPath, imageName)));\n                        profileView.getBaseActivity().startActivityForResult(intent, PHOTO_REQUEST_TAKEPHOTO);\n                        break;\n                    case 1:\n                        imageName = getNowTime() + \".png\";\n                        Crop.pickImage(profileView.getBaseActivity(), PHOTO_REQUEST_GALLERY);\n                        break;\n                }\n            }\n        });\n    }\n\n    @Override\n    public void showSexDialog() {\n        String title = profileView.getBaseContext().getString(R.string.sex);\n        HTAlertDialog fxAlertDialog = new HTAlertDialog(profileView.getBaseContext(), title, new String[]{profileView.getBaseContext().getString(R.string.male), profileView.getBaseContext().getString(R.string.female)});\n        fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                switch (position) {\n                    case 0:\n                        updateInfo(HTConstant.JSON_KEY_SEX, \"1\");\n                        break;\n                    case 1:\n                        updateInfo(HTConstant.JSON_KEY_SEX, \"0\");\n                        break;\n                }\n            }\n        });\n    }\n\n    @Override\n    public void result(int requestCode, int resultCode, Intent intent) {\n        if (resultCode == Activity.RESULT_OK) {\n            switch (requestCode) {\n                case PHOTO_REQUEST_TAKEPHOTO:\n                    beginCrop(Uri.fromFile(new File(dirPath, imageName)));\n                    break;\n\n                case PHOTO_REQUEST_GALLERY:\n                    if (intent != null)\n                        beginCrop(intent.getData());\n                    break;\n\n                case PHOTO_REQUEST_CUT:\n                    Uri output = Crop.getOutput(intent);\n                    updateAvatar(HTConstant.JSON_KEY_AVATAR, output.getPath());\n                    break;\n                case UPDATE_REGION:\n                    Log.d(\"slj\",\"-----更新地区:\"+UPDATE_REGION);\n                    if (intent != null) {\n                        String province = intent.getStringExtra(\"province\");\n                        String city = intent.getStringExtra(\"city\");\n                        updateRegion(province, city);\n                    }\n                    break;\n            }\n        }\n    }\n    private void unRegisterReciver(){\n        if (listener != null){\n            LocalBroadcastManager.getInstance(profileView.getBaseContext()).unregisterReceiver(listener);\n        }\n    }\n    @Override\n    public void onDestory() {\n        unRegisterReciver();\n        profileView = null;\n    }\n\n    @Override\n    public void start() {\n\n    }\n\n\n    private class InfoChangedListener extends BroadcastReceiver {\n\n        @Override\n        public void onReceive(Context context, Intent intent) {\n            if (IMAction.ACTION_UPDATE_INFO.equals(intent.getAction())) {\n                String type = intent.getStringExtra(HTConstant.KEY_CHANGE_TYPE);\n                if (HTConstant.JSON_KEY_SIGN.equals(type)) {\n                    String sign = intent.getStringExtra(HTConstant.JSON_KEY_SIGN);\n                    profileView.onSignUpdate(sign,true);\n                } else if (HTConstant.JSON_KEY_FXID.equals(type)) {\n                    String fxid = intent.getStringExtra(HTConstant.JSON_KEY_FXID);\n                    profileView.onFxidUpdate(fxid,true);\n                } else if (HTConstant.JSON_KEY_NICK.equals(type)) {\n                    String nick = intent.getStringExtra(HTConstant.JSON_KEY_NICK);\n                    profileView.onNickUpdate(nick,true);\n                }\n            }\n        }\n    }\n    private void beginCrop(Uri source) {\n        Uri destination = Uri.fromFile(new File(dirPath, imageName));\n        Crop.of(source, destination).asSquare().start(profileView.getBaseActivity(), PHOTO_REQUEST_CUT);\n    }\n\n    private String getNowTime() {\n        Date date = new Date(System.currentTimeMillis());\n        SimpleDateFormat dateFormat = new SimpleDateFormat(\"MMddHHmmssSS\");\n        return dateFormat.format(date);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/profile/ProfileView.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.profile;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * 项目名称：HTOpen\n * 类描述：ProfileView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 11:00\n * 邮箱:814326663@qq.com\n */\npublic interface ProfileView extends BaseView<ProfilePrester>{\n    void onNickUpdate(String nick,boolean isHang);\n    void onSexUpdate(int sex,boolean isHang);\n    void onSignUpdate(String sign,boolean isHang);\n    void onAvatarUpdate(String avatar,boolean isHang);\n    void onRegionUpdate(String region,boolean isHang);\n    void onFxidUpdate(String fxid,boolean isHang);\n    void onUpdateSuccess(String msg);\n    void onUpdateFailed(String error);\n    JSONObject getUserJson();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/ProfileUpdateActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.update;\n\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\nimport android.view.View;\n\nimport com.htmessage.yichatopen.activity.BaseActivity;\nimport com.htmessage.yichatopen.R;\n\n/**\n * Created by huangfangyi on 2016/7/3.\\\n * QQ:84543217\n */\npublic class ProfileUpdateActivity extends BaseActivity {\n    public static final int TYPE_NICK = 0;\n    public static final int TYPE_FXID = 1;\n    public static final int TYPE_SIGN = 2;\n    private UpdateProfilePrestener prestener;\n    private String title;\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_base);\n        int type = getIntent().getIntExtra(\"type\", 0);\n        switch (type){\n            case 0:\n                title = getString(R.string.change_nick);\n                break;\n            case 1:\n                title = getString(R.string.change_mixin);\n                break;\n            case 2:\n                title = getString(R.string.change_personalized_signature);\n                break;\n        }\n        setTitle(title);\n        ProfileUpdateFragment fragment = (ProfileUpdateFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (fragment == null){\n            fragment = new ProfileUpdateFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame,fragment);\n            transaction.commit();\n        }\n        prestener = new UpdateProfilePrestener(fragment);\n        showRightTextView(R.string.ok, new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                prestener.update();\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/ProfileUpdateFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.update;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.EditText;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.htmessage.yichatopen.R;\n\n/**\n * 项目名称：HTOpen\n * 类描述：ProfileUpdateFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 16:20\n * 邮箱:814326663@qq.com\n */\npublic class ProfileUpdateFragment extends Fragment implements UpdateProfileView,View.OnClickListener{\n\n    private String defaultStr;\n    private TextView saveTV;\n    private EditText infoET;\n    private TextView titleTV;\n    private int type;\n    private UpdateProfilePrestener prestener;\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View updateView = inflater.inflate(R.layout.activity_update_info, container, false);\n        getData();\n        initView(updateView);\n        initData();\n        setListener();\n        return updateView;\n    }\n\n    private void setListener() {\n        saveTV.setOnClickListener(this);\n    }\n\n    private void initData() {\n        String title = prestener.getTitle(type);\n        titleTV.setText(title);\n        if (defaultStr != null) {\n            infoET.setText(defaultStr);\n            infoET.setSelection(infoET.getText().length());\n        }\n    }\n\n    private void initView(View updateView) {\n        titleTV = (TextView) updateView.findViewById(R.id.tv_title);\n        saveTV = (TextView) updateView.findViewById(R.id.tv_save);\n        infoET = (EditText) updateView.findViewById(R.id.et_info);\n    }\n\n    private void getData() {\n        defaultStr = getDefultString();\n        type = getType();\n    }\n\n    @Override\n    public String getDefultString() {\n        return getBaseActivity().getIntent().getStringExtra(\"default\");\n    }\n\n    @Override\n    public int getType() {\n        return  getBaseActivity().getIntent().getIntExtra(\"type\", 0);\n    }\n\n    @Override\n    public String getInputString() {\n        return infoET.getText().toString().trim();\n    }\n\n    @Override\n    public void onUpdateSuccess(String msg) {\n        Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();\n        getBaseActivity().finish();\n    }\n\n    @Override\n    public void onUpdateFailed(String msg) {\n        Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void setPresenter(UpdateProfilePrestener presenter) {\n        this.prestener = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()){\n            case R.id.tv_save:\n                prestener.updateInfo(prestener.getKey(type),getInputString(),getDefultString());\n                break;\n        }\n    }\n\n    @Override\n    public void onDestroy() {\n        prestener.onDestory();\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/UpdateProfileBasePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.update;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * 项目名称：HTOpen\n * 类描述：UpdateProfileBasePrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 13:32\n * 邮箱:814326663@qq.com\n */\npublic interface UpdateProfileBasePrester  extends BasePresenter {\n    void update();\n    void updateInfo(String key,String value,String defaultStr);\n    String getTitle(int type);\n    String getKey(int type);\n    void onDestory();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/UpdateProfilePrestener.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.update;\n\nimport android.app.Dialog;\nimport android.content.Intent;\nimport android.support.v4.content.LocalBroadcastManager;\nimport android.text.TextUtils;\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.IMAction;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.htmessage.yichatopen.utils.Validator;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：HTOpen\n * 类描述：UpdateProfilePrestener 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 13:38\n * 邮箱:814326663@qq.com\n */\npublic class UpdateProfilePrestener implements UpdateProfileBasePrester {\n    private UpdateProfileView updateProfileView;\n    private static final int TYPE_NICK = 0;\n    private static final int TYPE_FXID = 1;\n    private static final int TYPE_SIGN = 2;\n\n    public UpdateProfilePrestener(UpdateProfileView updateProfileView) {\n        this.updateProfileView = updateProfileView;\n        this.updateProfileView.setPresenter(this);\n    }\n\n    @Override\n    public void update() {\n        updateInfo(getKey(updateProfileView.getType()),updateProfileView.getInputString(),updateProfileView.getDefultString());\n    }\n\n    @Override\n    public void updateInfo(final String key, final String value , String defaultStr) {\n        if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value) || ((defaultStr != null) && value.equals(defaultStr))) {\n            return;\n        }\n        if(HTConstant.JSON_KEY_FXID.equals(key)){\n            if(Validator.isChinese(value)){\n                updateProfileView.onUpdateFailed(updateProfileView.getBaseActivity().getString(R.string.mixin_can_not_has_chinese));\n                return;\n            }\n        }\n        if (value.length() > 30) {\n            updateProfileView.onUpdateFailed(updateProfileView.getBaseActivity().getString(R.string.string_not_30));\n            return;\n        }\n        final Dialog progressDialog =  HTApp.getInstance().createLoadingDialog(updateProfileView.getBaseActivity(),updateProfileView.getBaseActivity().getString(R.string.are_uploading));\n        progressDialog.show();\n        //本地用户资料\n        final JSONObject userJson = HTApp.getInstance().getUserJson();\n        List<Param> params = new ArrayList<Param>();\n        params.add(new Param(key, value));\n        new OkHttpUtils(updateProfileView.getBaseActivity()).post(params, HTConstant.URL_UPDATE, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                progressDialog.dismiss();\n                int code = jsonObject.getIntValue(\"code\");\n                if (code == 1) {\n                    userJson.put(key, value);\n                    HTApp.getInstance().setUserJson(userJson);\n                    LocalBroadcastManager.getInstance(updateProfileView.getBaseActivity()).sendBroadcast(new Intent(IMAction.ACTION_UPDATE_INFO).putExtra(HTConstant.KEY_CHANGE_TYPE,key).putExtra(key,value));\n                    updateProfileView.onUpdateSuccess(updateProfileView.getBaseActivity().getString(R.string.update_success));\n                } else {\n                    updateProfileView.onUpdateFailed(updateProfileView.getBaseActivity().getString(R.string.upload_failed)+code);\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                updateProfileView.onUpdateFailed(errorMsg);\n                progressDialog.dismiss();\n            }\n        });\n    }\n\n    @Override\n    public String getTitle(int type) {\n        String title = \"\";\n        switch (type) {\n            case TYPE_NICK:\n                title = updateProfileView.getBaseActivity().getString(R.string.change_nick);\n                break;\n            case TYPE_FXID:\n                title = updateProfileView.getBaseActivity().getString(R.string.change_mixin);\n                break;\n            case TYPE_SIGN:\n                title = updateProfileView.getBaseActivity().getString(R.string.change_personalized_signature);\n                break;\n        }\n        return title;\n    }\n\n    @Override\n    public String getKey(int type) {\n        String key = \"\";\n        switch (type) {\n            case TYPE_NICK:\n                key = HTConstant.JSON_KEY_NICK;\n                break;\n            case TYPE_FXID:\n                key = HTConstant.JSON_KEY_FXID;\n                break;\n            case TYPE_SIGN:\n                key = HTConstant.JSON_KEY_SIGN;\n                break;\n        }\n        return key;\n    }\n\n\n    @Override\n    public void onDestory() {\n        updateProfileView = null;\n    }\n\n    @Override\n    public void start() {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/profile/info/update/UpdateProfileView.java",
    "content": "package com.htmessage.yichatopen.activity.main.profile.info.update;\n\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * 项目名称：HTOpen\n * 类描述：UpdateProfileView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/7 13:41\n * 邮箱:814326663@qq.com\n */\npublic interface UpdateProfileView extends BaseView<UpdateProfilePrestener>{\n    String getDefultString();\n    int getType();\n    String getInputString();\n    void onUpdateSuccess(String msg);\n    void onUpdateFailed(String msg);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main.qrcode;\n\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\n\n\npublic class QrCodeActivity extends BaseActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_base);\n        setTitle(R.string.me_qrcode);\n        QrCodeFragment fragment = (QrCodeFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (fragment == null){\n            fragment = new QrCodeFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame,fragment);\n            transaction.commit();\n        }\n        new QrCodePrester(fragment);\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeBasePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.qrcode;\n\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\n/**\n * 项目名称：yichat0504\n * 类描述：QrCodeBasePrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 10:36\n * 邮箱:814326663@qq.com\n */\npublic interface QrCodeBasePrester  extends BasePresenter {\n    void onDestory();\n    void CreateQrCode();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.qrcode;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\nimport android.widget.Toast;\n\nimport com.htmessage.yichatopen.R;\n\n\n/**\n * 项目名称：yichat0504\n * 类描述：QrCodeFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 10:52\n * 邮箱:814326663@qq.com\n */\npublic class QrCodeFragment extends Fragment implements QrCodeView {\n    private ImageView imageView;\n    private QrCodePrester prester;\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View view = inflater.inflate(R.layout.activity_qrcode_generate, container, false);\n        initView(view);\n        getData();\n        return view;\n    }\n\n    private void getData() {\n        prester.CreateQrCode();\n    }\n\n    private void initView(View view) {\n        imageView = (ImageView) view.findViewById(R.id.code_image);\n    }\n\n    @Override\n    public void showQrCode(Bitmap bitmap) {\n        imageView.setImageBitmap(bitmap);\n    }\n\n    @Override\n    public void showError(String error) {\n        Toast.makeText(getBaseContext(), error, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void setPresenter(QrCodePrester presenter) {\n        this.prester = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n    @Override\n    public void onDestroy() {\n        prester.onDestory();\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodePrester.java",
    "content": "package com.htmessage.yichatopen.activity.main.qrcode;\n\nimport android.graphics.Bitmap;\nimport android.graphics.Color;\nimport android.util.Log;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.google.zxing.BarcodeFormat;\nimport com.google.zxing.WriterException;\nimport com.google.zxing.common.BitMatrix;\nimport com.google.zxing.qrcode.QRCodeWriter;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\n\n/**\n * 项目名称：yichat0504\n * 类描述：QrCodePrester 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 10:44\n * 邮箱:814326663@qq.com\n */\npublic class QrCodePrester implements QrCodeBasePrester {\n    private String TAG = QrCodePrester.class.getSimpleName();\n\n    private QrCodeView codeView;\n\n    public QrCodePrester(QrCodeView codeView) {\n        this.codeView = codeView;\n        this.codeView.setPresenter(this);\n    }\n\n    @Override\n    public void onDestory() {\n        codeView = null;\n    }\n\n    @Override\n    public void CreateQrCode() {\n        JSONObject userJson = HTApp.getInstance().getUserJson();\n        String key = \"userInfo:\";\n        JSONObject object =new JSONObject();\n        object.put(HTConstant.JSON_KEY_HXID,HTApp.getInstance().getUsername());\n        object.put(HTConstant.JSON_KEY_NICK,userJson.getString(HTConstant.JSON_KEY_NICK));\n        object.put(HTConstant.JSON_KEY_TEL,userJson.getString(HTConstant.JSON_KEY_TEL));\n        object.put(HTConstant.JSON_KEY_FXID,userJson.getString(HTConstant.JSON_KEY_FXID));\n        object.put(HTConstant.JSON_KEY_SEX,userJson.getString(HTConstant.JSON_KEY_SEX));\n        object.put(HTConstant.JSON_KEY_AVATAR,userJson.getString(HTConstant.JSON_KEY_AVATAR));\n        object.put(HTConstant.JSON_KEY_PROVINCE,userJson.getString(HTConstant.JSON_KEY_PROVINCE));\n        object.put(HTConstant.JSON_KEY_CITY,userJson.getString(HTConstant.JSON_KEY_CITY));\n        object.put(HTConstant.JSON_KEY_SIGN,userJson.getString(HTConstant.JSON_KEY_SIGN));\n        try {\n            Bitmap bitmap = generateQRCode(key + object.toJSONString());\n            codeView.showQrCode(bitmap);\n        } catch (WriterException e) {\n            codeView.showError(e.getMessage());\n            e.printStackTrace();\n        }\n    }\n\n    @Override\n    public void start() {\n\n    }\n\n\n\n    private Bitmap bitMatrix2Bitmap(BitMatrix matrix) {\n        int w = matrix.getWidth();\n        int h = matrix.getHeight();\n        int[] rawData = new int[w * h];\n        for (int i = 0; i < w; i++) {\n            for (int j = 0; j < h; j++) {\n                int color = Color.WHITE;\n                if (matrix.get(i, j)) {\n                    color = Color.BLACK;\n                }\n                rawData[i + (j * w)] = color;\n            }\n        }\n\n        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);\n        bitmap.setPixels(rawData, 0, w, 0, 0, w, h);\n        return bitmap;\n    }\n\n    private Bitmap generateQRCode(String content) throws WriterException {\n            Log.d(TAG,\"二维码:\"+content);\n            QRCodeWriter writer = new QRCodeWriter();\n            BitMatrix matrix = writer.encode(content, BarcodeFormat.QR_CODE,\n                    500, 500);\n            return bitMatrix2Bitmap(matrix);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/qrcode/QrCodeView.java",
    "content": "package com.htmessage.yichatopen.activity.main.qrcode;\n\nimport android.graphics.Bitmap;\n\nimport com.htmessage.yichatopen.activity.BaseView;\n\n\n/**\n * 项目名称：yichat0504\n * 类描述：QrCodeView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 10:44\n * 邮箱:814326663@qq.com\n */\npublic interface QrCodeView extends BaseView<QrCodePrester> {\n    void showQrCode(Bitmap bitmap);\n    void showError(String error);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionActivity.java",
    "content": "package com.htmessage.yichatopen.activity.main.region;\n\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\n\npublic class RegionActivity extends BaseActivity {\n\n\t@Override\n\tprotected void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_base);\n\t\tsetTitle(R.string.region);\n\t\tRegionFragment fragment = (RegionFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n\t\tif (fragment == null){\n\t\t\tfragment = new RegionFragment();\n\t\t\tFragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n\t\t\ttransaction.add(R.id.contentFrame,fragment);\n\t\t\ttransaction.commit();\n\t\t}\n\t\tnew RegionPresenter(fragment);\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionBasePrestener.java",
    "content": "package com.htmessage.yichatopen.activity.main.region;\n\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\n\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：RegionBasePrestener 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 13:53\n * 邮箱:814326663@qq.com\n */\npublic interface RegionBasePrestener extends BasePresenter {\n    List<String> getProvinceList();\n    List<String> getCityList(int position);\n    void onDestory();\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionFragment.java",
    "content": "package com.htmessage.yichatopen.activity.main.region;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.BaseAdapter;\nimport android.widget.ListView;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：RegionFragment 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 14:21\n * 邮箱:814326663@qq.com\n */\npublic class RegionFragment extends Fragment implements RegionView{\n    private ListView list_province;\n    private ListView list_city;\n    // 一个城市的数据列表\n    private List<String> citys = new ArrayList<String>();\n    private RegionAdapter cAdapter;\n    private RegionAdapter pAdapter;\n    private String province;\n    private RegionPresenter presenter;\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View regionView = inflater.inflate(R.layout.activity_region, container, false);\n        initView(regionView);\n        initData();\n        setListener();\n        return regionView;\n    }\n\n    private void setListener() {\n        list_province.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n            @Override\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                presenter.onItemClickListener(position,1);\n            }\n        });\n        list_city.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n            @Override\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                presenter.onItemClickListener(position,2);\n            }\n        });\n    }\n\n    private void initData() {\n        pAdapter = new RegionAdapter(getBaseContext(), presenter.getProvinceList());\n        cAdapter = new RegionAdapter(getBaseContext(), citys);\n        list_province.setAdapter(pAdapter);\n        list_city.setAdapter(cAdapter);\n    }\n\n    private void initView(View regionView) {\n        list_province = (ListView) regionView.findViewById(R.id.list_province);\n        list_city = (ListView) regionView.findViewById(R.id.list_city);\n    }\n\n    @Override\n    public void showCityList(List<String> cityList) {\n        cAdapter.setData(cityList);\n        cAdapter.notifyDataSetChanged();\n    }\n\n    @Override\n    public void showProvince(String province) {\n        this.province = province;\n    }\n\n    @Override\n    public void showCity(String city) {\n        Intent intent=new Intent();\n        intent.putExtra(\"city\", city);\n        intent.putExtra(\"province\", province);\n        getBaseActivity().setResult(Activity.RESULT_OK,intent);\n        getBaseActivity().finish();\n    }\n\n    @Override\n    public void setPresenter(RegionPresenter presenter) {\n        this.presenter = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n\n    private class RegionAdapter extends BaseAdapter {\n        private Context context;\n        private List<String> data;\n        private LayoutInflater inflater;\n        public RegionAdapter(Context _context, List<String> data) {\n            this.context = _context;\n            this.data = data;\n            inflater = LayoutInflater.from(context);\n        }\n\n        public void setData(List<String> _data) {\n            data = _data;\n        }\n\n        @Override\n        public int getCount() {\n            return data.size();\n        }\n\n        @Override\n        public String getItem(int position) {\n            return data.get(position);\n        }\n\n        @Override\n        public long getItemId(int position) {\n            return position;\n        }\n\n        @Override\n        public View getView(int position, View convertView, ViewGroup parent) {\n            if (convertView == null) {\n                convertView = inflater.inflate(R.layout.item_region, parent, false);\n            }\n            ViewHolder holder = (ViewHolder) convertView.getTag();\n            if (holder == null) {\n                holder = new ViewHolder();\n                holder.tv_name = (TextView) convertView\n                        .findViewById(R.id.tv_name);\n                convertView.setTag(holder);\n            }\n            String regionName = getItem(position);\n            holder.tv_name.setText(regionName);\n            return convertView;\n        }\n    }\n\n    static class ViewHolder {\n        TextView tv_name;\n    }\n\n    @Override\n    public void onDestroy() {\n        presenter.onDestory();\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.main.region;\n\nimport com.htmessage.yichatopen.R;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：RegionPresenter 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 14:04\n * 邮箱:814326663@qq.com\n */\npublic class RegionPresenter implements RegionBasePrestener {\n    // 一个省份的数据列表\n    private List<String> provinces = new ArrayList<String>();\n    // 一个城市的数据列表\n    private List<String> citys = new ArrayList<String>();\n    // 所有省份下的城市列表\n    private final int[] ARRAY_CITY = new int[] { R.array.beijin_province_item,\n            R.array.heibei_province_item, R.array.shandong_province_item,\n            R.array.shanghai_province_item, R.array.guangdong_province_item,\n            R.array.anhui_province_item, R.array.fujian_province_item,\n            R.array.gansu_province_item, R.array.guangxi_province_item,\n            R.array.guizhou_province_item, R.array.hainan_province_item,\n            R.array.henan_province_item, R.array.heilongjiang_province_item,\n            R.array.hubei_province_item, R.array.hunan_province_item,\n            R.array.jilin_province_item, R.array.jiangsu_province_item,\n            R.array.jiangxi_province_item, R.array.liaoning_province_item,\n            R.array.neimenggu_province_item, R.array.ningxia_province_item,\n            R.array.qinghai_province_item, R.array.shanxi1_province_item,\n            R.array.shanxi2_province_item, R.array.sichuan_province_item,\n            R.array.tianjin_province_item, R.array.xizang_province_item,\n            R.array.xinjiang_province_item, R.array.yunnan_province_item,\n            R.array.zhejiang_province_item, R.array.chongqing_province_item,\n            R.array.taiwan_province_item, R.array.hongkong_province_item,\n            R.array.aomen_province_item };\n\n    private RegionView regionView;\n\n    public RegionPresenter(RegionView regionView) {\n        this.regionView = regionView;\n        this.regionView.setPresenter(this);\n    }\n\n    @Override\n    public List<String> getProvinceList() {\n        provinces = Arrays.asList(regionView.getBaseActivity().getResources().getStringArray(R.array.province_item));\n        return provinces;\n    }\n\n    @Override\n    public List<String> getCityList(int position) {\n       citys =  Arrays.asList(regionView.getBaseActivity().getResources().getStringArray(ARRAY_CITY[position]));\n        return citys;\n    }\n\n    @Override\n    public void onDestory() {\n        regionView = null;\n    }\n\n    @Override\n    public void start() {\n\n    }\n   public void onItemClickListener(int position,int type){\n       if (type ==1){\n            String province = provinces.get(position);\n            regionView.showProvince(province);\n            regionView.showCityList(getCityList(position));\n       }else{\n           String city = citys.get(position);\n           regionView.showCity(city);\n       }\n   }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/main/region/RegionView.java",
    "content": "package com.htmessage.yichatopen.activity.main.region;\n\n\nimport com.htmessage.yichatopen.activity.BaseView;\n\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：RegionView 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/10 14:05\n * 邮箱:814326663@qq.com\n */\npublic interface RegionView extends BaseView<RegionPresenter> {\n    void showCityList(List<String> cityList);\n    void showProvince(String province);\n    void showCity(String city);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/register/RegisterActivity.java",
    "content": "package com.htmessage.yichatopen.activity.register;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentTransaction;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.BaseActivity;\n\n\n\n\n/**\n * 注册页\n */\npublic class RegisterActivity extends BaseActivity   {\n    private RegisterPresenter presenter;\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_base);\n        setTitle(R.string.register);\n        RegisterFragment registerFragment =\n                (RegisterFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);\n        if (registerFragment == null) {\n            // Create the fragment\n            registerFragment =new  RegisterFragment();\n            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\n            transaction.add(R.id.contentFrame, registerFragment);\n            transaction.commit();\n        }\n\n        presenter=new RegisterPresenter(registerFragment);\n    }\n\n    @Override\n    public void onActivityResult(int requestCode, int resultCode, Intent data) {\n        presenter.result(requestCode, resultCode, data);\n\n        super.onActivityResult(requestCode, resultCode, data);\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/register/RegisterContract.java",
    "content": "package com.htmessage.yichatopen.activity.register;\n\nimport android.app.Activity;\nimport android.content.Intent;\n\nimport com.htmessage.yichatopen.activity.BasePresenter;\nimport com.htmessage.yichatopen.activity.BaseView;\n\n/**\n * Created by huangfangyi on 2017/6/23.\n * qq 84543217\n */\n\npublic interface RegisterContract {\n    public     int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照\n    public     int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择\n    public     int PHOTO_REQUEST_CUT = 3;// 结果\n    public interface View extends BaseView<Presenter>{\n        void showAvatar(String imagePath);\n        void showDialog();\n        void cancelDialog();\n        void showPassword();\n        void hidePassword();\n        void enableButton();\n        void disableButton();\n        void showToast(int msgRes);\n        String getOriginImagePath();\n        Activity getBaseActivity();\n\n\n    }\n\n    public interface Presenter extends BasePresenter{\n\n        void registerInServer(String nickName,String mobile,String password);\n         void result(int requsetCode, int resultCode, Intent intent);\n\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/register/RegisterFragment.java",
    "content": "package com.htmessage.yichatopen.activity.register;\n\nimport android.Manifest;\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.pm.PackageManager;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.provider.MediaStore;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.text.Editable;\nimport android.text.Html;\nimport android.text.Selection;\nimport android.text.Spannable;\nimport android.text.TextUtils;\nimport android.text.TextWatcher;\nimport android.text.method.HideReturnsTransformationMethod;\nimport android.text.method.PasswordTransformationMethod;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.utils.CommonUtils;\nimport com.htmessage.yichatopen.utils.Validator;\nimport com.htmessage.yichatopen.widget.HTAlertDialog;\nimport com.soundcloud.android.crop.Crop;\n\nimport java.io.File;\n\n/**\n * Created by huangfangyi on 2017/6/23.\n * qq 84543217\n */\n\npublic class RegisterFragment extends Fragment implements View.OnClickListener, RegisterContract.View {\n\n    private EditText et_usernick, et_usertel, et_password;\n    private Button btn_register;\n    private ImageView iv_hide, iv_show, iv_photo;\n    private TextView tv_xieyi, tv_country, tv_country_code;\n    private RelativeLayout rl_country;\n\n    private RegisterContract.Presenter mPresenter;\n    //选取的原始图片\n    private String imagePathOrigin = null;\n    private Dialog dialog;\n\n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        dialog = HTApp.getInstance().createLoadingDialog(getActivity(), getString(R.string.Is_the_registered));\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View root = inflater.inflate(R.layout.fragment_register, container, false);\n        et_usernick = (EditText) root.findViewById(R.id.et_usernick);\n        et_usertel = (EditText) root.findViewById(R.id.et_usertel);\n        et_password = (EditText) root.findViewById(R.id.et_password);\n        //获取国家code\n        tv_country = (TextView) root.findViewById(R.id.tv_country);\n        tv_country_code = (TextView) root.findViewById(R.id.tv_country_code);\n        rl_country = (RelativeLayout) root.findViewById(R.id.rl_country);\n        btn_register = (Button) root.findViewById(R.id.btn_register);\n        tv_xieyi = (TextView) root.findViewById(R.id.tv_xieyi);\n        iv_hide = (ImageView) root.findViewById(R.id.iv_hide);\n        iv_show = (ImageView) root.findViewById(R.id.iv_show);\n        iv_photo = (ImageView) root.findViewById(R.id.iv_photo);\n        initView();\n        setLisenter();\n        return root;\n    }\n\n    private void initView() {\n        String xieyi = \"<font color=\" + \"\\\"\" + \"#AAAAAA\" + \"\\\">\" + getString(R.string.press_top)\n                + \"&nbsp;\" + \"\\\"\" + getString(R.string.register) + \"\\\"\" + \"&nbsp;\" + getString(R.string.btn_means_agree) + \"</font>\" + \"<u>\"\n                + \"<font color=\" + \"\\\"\" + \"#576B95\" + \"\\\">\" + getString(R.string.Secret_agreement)\n                + \"</font>\" + \"</u>\";\n        tv_xieyi.setText(Html.fromHtml(xieyi));\n    }\n\n    private void setLisenter() {\n        // 监听多个输入框\n        TextChange textChange = new TextChange();\n        et_usernick.addTextChangedListener(textChange);\n        et_usertel.addTextChangedListener(textChange);\n        et_password.addTextChangedListener(textChange);\n\n        tv_country.setOnClickListener(this);\n        tv_country_code.setOnClickListener(this);\n        rl_country.setOnClickListener(this);\n        iv_hide.setOnClickListener(this);\n        iv_show.setOnClickListener(this);\n        iv_photo.setOnClickListener(this);\n        btn_register.setOnClickListener(this);\n    }\n\n    @Override\n    public void setPresenter(RegisterContract.Presenter presenter) {\n        mPresenter = presenter;\n    }\n\n    @Override\n    public Context getBaseContext() {\n        return getContext();\n    }\n\n    @Override\n    public void showAvatar(String imagePath) {\n        Glide.with(getActivity()).load(imagePath).diskCacheStrategy(DiskCacheStrategy.ALL).error(R.drawable.default_image).into(iv_photo);\n\n    }\n\n    @Override\n    public void showDialog() {\n        if (dialog != null)\n            dialog.show();\n    }\n\n    @Override\n    public void cancelDialog() {\n        if (dialog != null && dialog.isShowing()) {\n            dialog.dismiss();\n        }\n    }\n\n    @Override\n    public void showPassword() {\n        iv_show.setVisibility(View.GONE);\n        iv_hide.setVisibility(View.VISIBLE);\n        et_password\n                .setTransformationMethod(PasswordTransformationMethod\n                        .getInstance());\n    }\n\n    // 切换后将密码EditText光标置于末尾\n    private void editTextEnd() {\n        CharSequence charSequence = et_password.getText();\n        if (charSequence instanceof Spannable) {\n            Spannable spanText = (Spannable) charSequence;\n            Selection.setSelection(spanText, charSequence.length());\n        }\n    }\n\n    @Override\n    public void hidePassword() {\n        iv_hide.setVisibility(View.GONE);\n        iv_show.setVisibility(View.VISIBLE);\n        et_password\n                .setTransformationMethod(HideReturnsTransformationMethod\n                        .getInstance());\n    }\n\n    @Override\n    public void enableButton() {\n        btn_register.setEnabled(true);\n    }\n\n    @Override\n    public void disableButton() {\n        btn_register.setEnabled(false);\n\n    }\n\n    @Override\n    public void showToast(int msgRes) {\n        Toast.makeText(getActivity(), msgRes, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public String getOriginImagePath() {\n        return imagePathOrigin;\n    }\n\n    @Override\n    public Activity getBaseActivity() {\n        return getActivity();\n    }\n\n\n    // EditText监听器\n    class TextChange implements TextWatcher {\n\n        @Override\n        public void afterTextChanged(Editable arg0) {\n\n        }\n\n        @Override\n        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,\n                                      int arg3) {\n\n        }\n\n        @Override\n        public void onTextChanged(CharSequence cs, int start, int before,\n                                  int count) {\n\n            boolean sign1 = et_usernick.getText().length() > 0;\n            boolean sign2 = et_usertel.getText().length() > 0;\n            boolean sign3 = et_password.getText().length() > 0;\n\n            if (sign1 & sign2 & sign3) {\n\n                enableButton();\n            } else {\n                disableButton();\n            }\n        }\n\n    }\n\n\n    @Override\n    public void onClick(View v) {\n        switch (v.getId()) {\n            case R.id.iv_hide:\n                hidePassword();\n                editTextEnd();\n                break;\n            case R.id.iv_show:\n                showPassword();\n                editTextEnd();\n                break;\n            case R.id.btn_register:\n                String usernick = et_usernick.getText().toString().trim();\n                String password = et_password.getText().toString().trim();\n                String usertel = et_usertel.getText().toString().trim();\n                String country = tv_country.getText().toString().trim();\n                String countryCode = tv_country_code.getText().toString().trim();\n\n                if (TextUtils.isEmpty(usertel)) {\n                    showToast(R.string.mobile_not_be_null);\n                    return;\n                }\n                if (country.equals(getString(R.string.china)) && countryCode.equals(getString(R.string.country_code))) {\n                    if (!Validator.isMobile(usertel)) {\n                        showToast(R.string.please_input_true_mobile);\n                        return;\n                    }\n                }\n\n                if (TextUtils.isEmpty(password)) {\n                    showToast(R.string.pwd_is_not_allow_null);\n                    return;\n                }\n                mPresenter.registerInServer(usernick,  usertel,password);\n\n                break;\n            case R.id.rl_country:\n                CommonUtils.showPup(getContext(), tv_country, tv_country_code);\n                break;\n\n            case R.id.iv_photo:\n                showCamera();\n                break;\n\n\n        }\n    }\n\n    private String getAvatarName() {\n\n        return HTApp.getInstance().getDirFilePath() + \"org_\" + System.currentTimeMillis() + \".png\";\n    }\n\n    // 拍照部分\n    private void showCamera() {\n        HTAlertDialog fxAlertDialog = new HTAlertDialog(getActivity(), null, new String[]{getString(R.string.attach_take_pic), getString(R.string.image_manager)});\n        fxAlertDialog.init(new HTAlertDialog.OnItemClickListner() {\n            @Override\n            public void onClick(int position) {\n                imagePathOrigin = getAvatarName();\n                switch (position) {\n                    case 0:\n                        if(!checkPermission(Manifest.permission.CAMERA)){\n                            return;\n                        }\n\n                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);\n                        // 指定调用相机拍照后照片的储存路径\n                        intent.putExtra(MediaStore.EXTRA_OUTPUT,\n                                Uri.fromFile(new File(imagePathOrigin)));\n                        getActivity().startActivityForResult(intent, RegisterContract.PHOTO_REQUEST_TAKEPHOTO);\n                        break;\n                    case 1:\n                        if( !checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ){\n                            return;\n                        }\n\n                        Crop.pickImage(getActivity(), RegisterContract.PHOTO_REQUEST_GALLERY);\n                        break;\n                }\n            }\n        });\n\n    }\n\n\n    private boolean checkPermission(String permissionName) {\n        PackageManager pm = getActivity().getPackageManager();\n        boolean permission = (PackageManager.PERMISSION_GRANTED ==\n                pm.checkPermission(permissionName,  getActivity().getPackageName()));\n        if (permission) {\n           return true;\n        }else {\n            showToast(R.string.no_permission_camera);\n            requestPermissions(new String[]{permissionName},\n                    REQUEST_CODE);\n             return false;\n\n        }\n    }\n\n    private static final int REQUEST_CODE=100;\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,\n                                           @NonNull int[] grantResults) {\n        if(requestCode==REQUEST_CODE){\n            for(int i=0;i<permissions.length;i++){\n                if(permissions[i].equals(Manifest.permission.CAMERA)||permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE) ){\n                    if(PackageManager.PERMISSION_GRANTED==grantResults[i]){\n                       showToast(R.string.permission_ok);\n                    }else {\n                        showToast(R.string.permission_error);\n                    }\n                }\n\n            }\n\n        }\n\n    }\n\n}\n\n\n\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/activity/register/RegisterPresenter.java",
    "content": "package com.htmessage.yichatopen.activity.register;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.sdk.android.oss.ClientException;\nimport com.alibaba.sdk.android.oss.ServiceException;\nimport com.alibaba.sdk.android.oss.model.PutObjectRequest;\nimport com.alibaba.sdk.android.oss.model.PutObjectResult;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.utils.UploadFileUtils;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.utils.OkHttpUtils;\nimport com.htmessage.yichatopen.utils.Param;\nimport com.soundcloud.android.crop.Crop;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by huangfangyi on 2017/6/23.\n * qq 84543217\n */\n\npublic class RegisterPresenter implements RegisterContract.Presenter {\n    private RegisterContract.View registerView;\n    private String cropImagePath = null;\n\n    public RegisterPresenter(RegisterContract.View view) {\n        registerView = view;\n        registerView.setPresenter(this);\n    }\n\n    @Override\n    public void start() {\n\n    }\n\n    @Override\n    public void registerInServer(String nickName, String mobile, String password) {\n        registerView.showDialog();\n        if(cropImagePath!=null&&new File(cropImagePath).exists()){\n            uploadAvatar(nickName, password, mobile, new File(cropImagePath).getAbsolutePath());\n        }else {\n            register(nickName, password, mobile, null);\n        }\n    }\n\n\n    private void register(String usernick, String password, String usertel, String imageName) {\n        registerView.showDialog();\n        List<Param> params = new ArrayList<Param>();\n        params.add(new Param(\"usertel\", usertel));\n        params.add(new Param(\"password\", password));\n        params.add(new Param(\"usernick\", usernick));\n        if (!TextUtils.isEmpty(imageName)) {\n            params.add(new Param(\"avatar\", imageName));\n        }\n        new OkHttpUtils(registerView.getBaseActivity()).post(params, HTConstant.URL_REGISTER, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                int status = jsonObject.getInteger(\"code\");\n                switch (status) {\n                    case 1:\n                        JSONObject user = jsonObject.getJSONObject(\"user\");\n\n                        if (user != null) {\n                            HTClient.getInstance().register(user.getString(HTConstant.JSON_KEY_HXID), user.getString(HTConstant.JSON_KEY_PASSWORD), new HTClient.HTCallBack() {\n                                @Override\n                                public void onSuccess() {\n                                    registerView.getBaseActivity().runOnUiThread(new Runnable() {\n                                        @Override\n                                        public void run() {\n                                            registerView.cancelDialog();\n                                            registerView.showToast(R.string.Registered_successfully);\n\n\n                                            registerView.getBaseActivity().finish();\n                                        }\n                                    });\n                                }\n\n                                @Override\n                                public void onError() {\n                                    registerView.getBaseActivity().runOnUiThread(new Runnable() {\n                                        @Override\n                                        public void run() {\n                                            registerView.cancelDialog();\n                                            registerView.showToast(R.string.Registration_failed);\n\n                                        }\n                                    });\n\n                                }\n                            });\n                        }\n                        break;\n                    case -1:\n                        registerView.cancelDialog();\n                        registerView.showToast(R.string.mobile_is_register);\n                         break;\n                    case -2:\n                        registerView.cancelDialog();\n                        registerView.showToast(R.string.Incorrect_phone_number_format);\n\n                         break;\n                    default:\n                        registerView.cancelDialog();\n                        registerView.showToast(R.string.Server_busy);\n                         break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                registerView.cancelDialog();\n                registerView.showToast(R.string.Server_busy);\n             }\n        });\n\n    }\n\n    private void uploadAvatar(final String usernick, final String password, final String usertel, String filePath) {\n        final String fileName = filePath.substring(filePath.lastIndexOf(\"/\") + 1);\n        new UploadFileUtils(registerView.getBaseActivity(), fileName, filePath).asyncUploadFile(new UploadFileUtils.a() {\n            @Override\n            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {\n\n            }\n\n            @Override\n            public void onSuccess(PutObjectRequest request, PutObjectResult result) {\n                final String url = HTConstant.baseOssUrl + fileName;\n                registerView.getBaseActivity(). runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        register(usernick, password, usertel, url);\n                    }\n                });\n            }\n\n            @Override\n            public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {\n                registerView.getBaseActivity().runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        registerView.cancelDialog();\n                    }\n                });\n            }\n        });\n    }\n\n\n\n\n\n    @Override\n    public void result(int requestCode, int resultCode, Intent intent) {\n        if (resultCode == Activity.RESULT_OK) {\n            switch (requestCode) {\n                case RegisterContract.PHOTO_REQUEST_GALLERY:\n                    if (intent != null)\n                        beginCrop(intent.getData());\n\n                    break;\n\n\n\n                case RegisterContract.PHOTO_REQUEST_TAKEPHOTO:\n                    beginCrop(Uri.fromFile(new File(registerView.getOriginImagePath())));\n                    break;\n\n                case RegisterContract.PHOTO_REQUEST_CUT:\n                    Uri output = Crop.getOutput(intent);\n                    Log.d(\"output---->\",output.getPath());\n                    registerView.showAvatar(output.getPath());\n                    break;\n\n            }\n        } else {\n            //裁剪失败\n            if(requestCode==RegisterContract.PHOTO_REQUEST_CUT){\n                cropImagePath=null;\n                registerView.showAvatar(null);\n            }\n\n        }\n    }\n\n    private void beginCrop(Uri inputUri) {\n        cropImagePath= HTApp.getInstance().getDirFilePath()  + \"crop_\" + System.currentTimeMillis() + \".png\";\n        Uri outputUri = Uri.fromFile(new File(cropImagePath));\n        Crop.of(inputUri, outputUri).asSquare().start(registerView.getBaseActivity(), RegisterContract.PHOTO_REQUEST_CUT);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/domain/InviteMessage.java",
    "content": "package com.htmessage.yichatopen.domain;\n\npublic class InviteMessage {\n\tprivate String from;\n\tprivate long time;\n\tprivate String reason;\n \tprivate Status status;\n\tprivate int id;\n\n\tpublic String getFrom() {\n\t\treturn from;\n\t}\n\n\tpublic void setFrom(String from) {\n\t\tthis.from = from;\n\t}\n\n\tpublic long getTime() {\n\t\treturn time;\n\t}\n\n\tpublic void setTime(long time) {\n\t\tthis.time = time;\n\t}\n\n\n\tpublic String getReason() {\n\t\treturn reason;\n\t}\n\n\tpublic void setReason(String reason) {\n\t\tthis.reason = reason;\n\t}\n\n\tpublic Status getStatus() {\n\t\treturn status;\n\t}\n\n\tpublic void setStatus(Status status) {\n\t\tthis.status = status;\n\t}\n\n\tpublic int getId() {\n\t\treturn id;\n\t}\n\n\tpublic void setId(int id) {\n\t\tthis.id = id;\n\t}\n\n\n\tpublic enum Status {\n\n \t\tBEINVITEED,\n \t\tBEREFUSED,\n \t\tBEAGREED,\n \t\tAGREED,\n \t\tREFUSED\n\t}\n\t\n}\n\n\n\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/domain/InviteMessgeDao.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.domain;\n\nimport android.content.ContentValues;\nimport android.content.Context;\n\nimport com.htmessage.yichatopen.manager.DBManager;\n\nimport java.util.List;\n\npublic class InviteMessgeDao {\n\tpublic static final String TABLE_NAME = \"new_friends_msgs\";\n\tpublic static final String COLUMN_NAME_ID = \"id\";\n\tpublic static final String COLUMN_NAME_FROM = \"username\";\n\tpublic static final String COLUMN_NAME_GROUP_ID = \"groupid\";\n\tpublic static final String COLUMN_NAME_GROUP_Name = \"groupname\";\n\n\tpublic static final String COLUMN_NAME_TIME = \"time\";\n\tpublic static final String COLUMN_NAME_REASON = \"reason\";\n\t public static final String COLUMN_NAME_STATUS = \"status\";\n\tpublic static final String COLUMN_NAME_ISINVITEFROMME = \"isInviteFromMe\";\n\tpublic static final String COLUMN_NAME_GROUPINVITER = \"groupinviter\";\n\n\tpublic static final String COLUMN_NAME_UNREAD_MSG_COUNT = \"unreadMsgCount\";\n\t\n\t\t\n\tpublic InviteMessgeDao(Context context){\n\t}\n\t\n\t/**\n\t * save message\n\t * @param message\n\t * @return  return cursor of the message\n\t */\n\tpublic Integer saveMessage(InviteMessage message){\n\t\treturn DBManager.getInstance().saveMessage(message);\n\t}\n\t\n\t/**\n\t * update message\n\t * @param msgId\n\t * @param values\n\t */\n\tpublic void updateMessage(int msgId,ContentValues values){\n\t    DBManager.getInstance().updateMessage(msgId, values);\n\t}\n\t\n\t/**\n\t * get messges\n\t * @return\n\t */\n\tpublic List<InviteMessage> getMessagesList(){\n\t\treturn DBManager.getInstance().getMessagesList();\n\t}\n\t\n\tpublic void deleteMessage(String from){\n\t    DBManager.getInstance().deleteMessage(from);\n\t}\n\t\n\tpublic int getUnreadMessagesCount(){\n\t    return DBManager.getInstance().getUnreadNotifyCount();\n\t}\n\t\n\tpublic void saveUnreadMessageCount(int count){\n\t    DBManager.getInstance().setUnreadNotifyCount(count);\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/domain/User.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.domain;\n\nimport android.annotation.SuppressLint;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport android.text.TextUtils;\n\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.utils.CommonUtils;\n\n\n@SuppressLint(\"ParcelCreator\")\npublic class User implements Parcelable {\n    \n    /**\n     * initial letter for nickname\n     */\n\tprotected String initialLetter;\n\n\tpublic String getUsername() {\n\t\treturn username;\n\t}\n\n\tpublic void setUsername(String username) {\n\t\tthis.username = username;\n\t}\n\n\t/**\n\t * avatar of the user\n\n\t */\n\tprotected String avatar;\n\tprivate String username;\n\tprotected String userInfo;\n\tprivate String nick;\n\n\tpublic String getNick() {\n\t\treturn nick;\n\t}\n\n\tpublic void setNick(String nick) {\n\t\tthis.nick = nick;\n\t}\n\n\tpublic User(String username){\n\t    this.username = username;\n\t}\n\n\tpublic String getInitialLetter() {\n\t    if(initialLetter == null){\n            CommonUtils.setUserInitialLetter(this);\n        }\n\t\treturn initialLetter;\n\t}\n\n\tpublic void setInitialLetter(String initialLetter) {\n\t\tthis.initialLetter = initialLetter;\n\t}\n\n\n\tpublic String getAvatar() {\n\t\tif(!TextUtils.isEmpty(avatar)){\n\t\t\tif (!avatar.contains(\"http\")){\n\t\t\t\tavatar = HTConstant.URL_AVATAR+avatar;\n\t\t\t}\n\t\t}\n        return avatar;\n    }\n\n    public void setAvatar(String avatar) {\n        this.avatar = avatar;\n    }\n\tpublic String getUserInfo(){\n\n\t\treturn userInfo;\n\n\t}\n\tpublic void setUserInfo(String userInfo){\n\t\tthis.userInfo=userInfo;\n\t}\n\n    @Override\n\tpublic int hashCode() {\n\t\treturn 17 * getUsername().hashCode();\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (o == null || !(o instanceof User)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn getUsername().equals(((User) o).getUsername());\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn nick == null ? username : nick;\n\t}\n\n\t@Override\n\tpublic int describeContents() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void writeToParcel(Parcel parcel, int i) {\n\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/domain/UserDao.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.domain;\n\nimport android.content.Context;\n\n\nimport com.htmessage.yichatopen.manager.DBManager;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic class UserDao {\n\tpublic static final String TABLE_NAME = \"uers\";\n\tpublic static final String COLUMN_NAME_ID = \"username\";\n\tpublic static final String COLUMN_NAME_NICK = \"nick\";\n\tpublic static final String COLUMN_NAME_AVATAR = \"avatar\";\n\tpublic static final String COLUMN_NAME_INFO = \"userInfo\";\n\tpublic static final String PREF_TABLE_NAME = \"pref\";\n\tpublic static final String COLUMN_NAME_DISABLED_GROUPS = \"disabled_groups\";\n\tpublic static final String COLUMN_NAME_DISABLED_IDS = \"disabled_ids\";\n\n\tpublic static final String ROBOT_TABLE_NAME = \"robots\";\n\tpublic static final String ROBOT_COLUMN_NAME_ID = \"username\";\n\tpublic static final String ROBOT_COLUMN_NAME_NICK = \"nick\";\n\tpublic static final String ROBOT_COLUMN_NAME_AVATAR = \"avatar\";\n\t\n\t\n\tpublic UserDao(Context context) {\n\t}\n\n\t/**\n\t * save contact list\n\t * \n\t * @param contactList\n\t */\n\tpublic void saveContactList(List<User> contactList) {\n \t    DBManager.getInstance().saveContactList(contactList);\n\t}\n\n\t/**\n\t * get contact list\n\t * \n\t * @return\n\t */\n\tpublic Map<String, User> getContactList() {\n  \t    return DBManager.getInstance().getContactList();\n\t}\n\t\n\t/**\n\t * delete a contact\n\t * @param username\n\t */\n\tpublic void deleteContact(String username){\n\t    DBManager.getInstance().deleteContact(username);\n\t}\n\t\n\t/**\n\t * save a contact\n\t * @param user\n\t */\n\tpublic void saveContact(User user){\n\t    DBManager.getInstance().saveContact(user);\n\t}\n\t\n\tpublic void setDisabledGroups(List<String> groups){\n\t    DBManager.getInstance().setDisabledGroups(groups);\n    }\n    \n    public List<String>  getDisabledGroups(){       \n        return DBManager.getInstance().getDisabledGroups();\n    }\n    \n    public void setDisabledIds(List<String> ids){\n        DBManager.getInstance().setDisabledIds(ids);\n    }\n    \n    public List<String> getDisabledIds(){\n        return DBManager.getInstance().getDisabledIds();\n    }\n    \n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/ContactsManager.java",
    "content": "package com.htmessage.yichatopen.manager;\n\nimport android.content.Context;\nimport android.util.Log;\n\n\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.domain.UserDao;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by huangfangyi on 2016/12/8.\n * qq 84543217\n */\n\npublic class ContactsManager {\n\n    private static ContactsManager contactsManager;\n    private Context context;\n    private UserDao userDao;\n    private Map<String,User> contacts=null;\n\n\n    synchronized public static void init(Context context) {\n        if (contactsManager == null) {\n            contactsManager = new ContactsManager(context);\n        }\n    }\n\n    public ContactsManager(Context context) {\n        this.context = context;\n        userDao= new UserDao(context);\n        initContacts();\n\n    }\n\n    public static ContactsManager getInstance(){\n\n        if(contactsManager==null){\n\n            throw  new RuntimeException(\"please init this first!\");\n        }\n\n        return  contactsManager;\n\n    }\n\n    public boolean saveContactList(List<User> contactList) {\n        Log.d(\"saveContactList----->\",contactList.size()+\"\");\n        contacts.clear();\n        for (User user:contactList){\n            contacts.put(user.getUsername(),user);\n        }\n        userDao.saveContactList(contactList);\n        return true;\n    }\n\n    public Map<String, User> getContactList() {\n        if(contacts==null){\n             contacts=userDao.getContactList();\n        }\n       \n        return contacts;\n    }\n\n    public void saveContact(User user){\n               contacts.put(user.getUsername(),user);\n        userDao.saveContact(user);\n     }\n\n\n   private void  initContacts(){\n       contacts=userDao.getContactList();\n   }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/DBManager.java",
    "content": "package com.htmessage.yichatopen.manager;\n\nimport android.content.ContentValues;\nimport android.database.Cursor;\nimport android.database.sqlite.SQLiteDatabase;\nimport android.util.Log;\n\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.domain.InviteMessage;\nimport com.htmessage.yichatopen.domain.InviteMessage.Status;\nimport com.htmessage.yichatopen.domain.InviteMessgeDao;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.domain.UserDao;\nimport com.htmessage.yichatopen.utils.CommonUtils;\n\nimport java.util.ArrayList;\nimport java.util.Hashtable;\nimport java.util.List;\nimport java.util.Map;\n\npublic class DBManager {\n    static private DBManager dbMgr = new DBManager();\n    private DbOpenHelper dbHelper;\n\n    private DBManager() {\n        dbHelper = DbOpenHelper.getInstance(HTApp.getInstance().getApplicationContext());\n    }\n\n    public static synchronized DBManager getInstance() {\n        if (dbMgr == null) {\n            dbMgr = new DBManager();\n        }\n        return dbMgr;\n    }\n\n\n    /**\n     * save contact list\n     *\n     * @param contactList\n     */\n    synchronized public void saveContactList(List<User> contactList) {\n        Log.d(\"saveContactList3----->\", contactList.size() + \"\");\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        if (db.isOpen()) {\n            db.delete(UserDao.TABLE_NAME, null, null);\n            for (User user : contactList) {\n                ContentValues values = new ContentValues();\n                values.put(UserDao.COLUMN_NAME_ID, user.getUsername());\n                if (user.getNick() != null)\n                    values.put(UserDao.COLUMN_NAME_NICK, user.getNick());\n                if (user.getAvatar() != null)\n                    values.put(UserDao.COLUMN_NAME_AVATAR, user.getAvatar());\n                if (user.getUserInfo() != null)\n                    values.put(UserDao.COLUMN_NAME_INFO, user.getUserInfo());\n                db.replace(UserDao.TABLE_NAME, null, values);\n            }\n        }\n    }\n\n\n    /**\n     * get contact list\n     *\n     * @return\n     */\n    synchronized public Map<String, User> getContactList() {\n        SQLiteDatabase db = dbHelper.getReadableDatabase();\n        Map<String, User> users = new Hashtable<String, User>();\n        if (db.isOpen()) {\n            Cursor cursor = db.rawQuery(\"select * from \" + UserDao.TABLE_NAME /* + \" desc\" */, null);\n            while (cursor.moveToNext()) {\n                String username = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_ID));\n                String nick = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_NICK));\n                String avatar = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_AVATAR));\n                String userInfo = cursor.getString(cursor.getColumnIndex(UserDao.COLUMN_NAME_INFO));\n                User user = new User(username);\n                user.setNick(nick);\n                user.setAvatar(avatar);\n                user.setUserInfo(userInfo);\n                CommonUtils.setUserInitialLetter(user);\n                if (\"123456789\".contains(user.getInitialLetter())) {\n                    user.setInitialLetter(\"#\");\n                }\n                users.put(username, user);\n            }\n            cursor.close();\n        }\n        return users;\n    }\n\n    /**\n     * delete a contact\n     *\n     * @param username\n     */\n    synchronized public void deleteContact(String username) {\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        if (db.isOpen()) {\n            db.delete(UserDao.TABLE_NAME, UserDao.COLUMN_NAME_ID + \" = ?\", new String[]{username});\n        }\n    }\n\n    /**\n     * save a contact\n     *\n     * @param user\n     */\n    synchronized public void saveContact(User user) {\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        ContentValues values = new ContentValues();\n        values.put(UserDao.COLUMN_NAME_ID, user.getUsername());\n        if (user.getNick() != null)\n            values.put(UserDao.COLUMN_NAME_NICK, user.getNick());\n        if (user.getAvatar() != null)\n            values.put(UserDao.COLUMN_NAME_AVATAR, user.getAvatar());\n        if (user.getUserInfo() != null)\n            values.put(UserDao.COLUMN_NAME_INFO, user.getUserInfo());\n        if (db.isOpen()) {\n            db.replace(UserDao.TABLE_NAME, null, values);\n        }\n    }\n\n    public void setDisabledGroups(List<String> groups) {\n        setList(UserDao.COLUMN_NAME_DISABLED_GROUPS, groups);\n    }\n\n    public List<String> getDisabledGroups() {\n        return getList(UserDao.COLUMN_NAME_DISABLED_GROUPS);\n    }\n\n    public void setDisabledIds(List<String> ids) {\n        setList(UserDao.COLUMN_NAME_DISABLED_IDS, ids);\n    }\n\n    public List<String> getDisabledIds() {\n        return getList(UserDao.COLUMN_NAME_DISABLED_IDS);\n    }\n\n    synchronized private void setList(String column, List<String> strList) {\n        StringBuilder strBuilder = new StringBuilder();\n\n        for (String hxid : strList) {\n            strBuilder.append(hxid).append(\"$\");\n        }\n\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        if (db.isOpen()) {\n            ContentValues values = new ContentValues();\n            values.put(column, strBuilder.toString());\n\n            db.update(UserDao.PREF_TABLE_NAME, values, null, null);\n        }\n    }\n\n    synchronized private List<String> getList(String column) {\n        SQLiteDatabase db = dbHelper.getReadableDatabase();\n        Cursor cursor = db.rawQuery(\"select \" + column + \" from \" + UserDao.PREF_TABLE_NAME, null);\n        if (!cursor.moveToFirst()) {\n            cursor.close();\n            return null;\n        }\n\n        String strVal = cursor.getString(0);\n        if (strVal == null || strVal.equals(\"\")) {\n            return null;\n        }\n\n        cursor.close();\n\n        String[] array = strVal.split(\"$\");\n\n        if (array != null && array.length > 0) {\n            List<String> list = new ArrayList<String>();\n            for (String str : array) {\n                list.add(str);\n            }\n\n            return list;\n        }\n\n        return null;\n    }\n\n    /**\n     * save a message\n     *\n     * @param message\n     * @return return cursor of the message\n     */\n    public synchronized Integer saveMessage(InviteMessage message) {\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        int id = -1;\n        if (db.isOpen()) {\n            ContentValues values = new ContentValues();\n            values.put(InviteMessgeDao.COLUMN_NAME_FROM, message.getFrom());\n\n            values.put(InviteMessgeDao.COLUMN_NAME_REASON, message.getReason());\n            values.put(InviteMessgeDao.COLUMN_NAME_TIME, message.getTime());\n            values.put(InviteMessgeDao.COLUMN_NAME_STATUS, message.getStatus().ordinal());\n             db.insert(InviteMessgeDao.TABLE_NAME, null, values);\n\n            Cursor cursor = db.rawQuery(\"select last_insert_rowid() from \" + InviteMessgeDao.TABLE_NAME, null);\n            if (cursor.moveToFirst()) {\n                id = cursor.getInt(0);\n            }\n\n            cursor.close();\n        }\n        return id;\n    }\n\n\n    /**\n     * update message\n     *\n     * @param msgId\n     * @param values\n     */\n    synchronized public void updateMessage(int msgId, ContentValues values) {\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        if (db.isOpen()) {\n            db.update(InviteMessgeDao.TABLE_NAME, values, InviteMessgeDao.COLUMN_NAME_ID + \" = ?\", new String[]{String.valueOf(msgId)});\n        }\n    }\n\n    /**\n     * get messges\n     *\n     * @return\n     */\n    synchronized public List<InviteMessage> getMessagesList() {\n        SQLiteDatabase db = dbHelper.getReadableDatabase();\n        List<InviteMessage> msgs = new ArrayList<InviteMessage>();\n        if (db.isOpen()) {\n            Cursor cursor = db.rawQuery(\"select * from \" + InviteMessgeDao.TABLE_NAME + \" desc\", null);\n            while (cursor.moveToNext()) {\n                InviteMessage msg = new InviteMessage();\n                int id = cursor.getInt(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_ID));\n                String from = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_FROM));\n                String groupid = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_GROUP_ID));\n                String groupname = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_GROUP_Name));\n                String reason = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_REASON));\n                long time = cursor.getLong(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_TIME));\n                int status = cursor.getInt(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_STATUS));\n                String groupInviter = cursor.getString(cursor.getColumnIndex(InviteMessgeDao.COLUMN_NAME_GROUPINVITER));\n\n                msg.setId(id);\n                msg.setFrom(from);\n                msg.setReason(reason);\n                msg.setTime(time);\n\n\n                if (status == Status.BEINVITEED.ordinal())\n                    msg.setStatus(Status.BEINVITEED);\n                else if (status == Status.BEAGREED.ordinal())\n                    msg.setStatus(Status.BEAGREED);\n                else if (status == Status.BEREFUSED.ordinal())\n                    msg.setStatus(Status.BEREFUSED);\n                else if (status == Status.AGREED.ordinal())\n                    msg.setStatus(Status.AGREED);\n                else if (status == Status.REFUSED.ordinal())\n                    msg.setStatus(Status.REFUSED);\n\n                msgs.add(msg);\n            }\n            cursor.close();\n        }\n        return msgs;\n    }\n\n    /**\n     * delete invitation message\n     *\n     * @param from\n     */\n    synchronized public void deleteMessage(String from) {\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        if (db.isOpen()) {\n            db.delete(InviteMessgeDao.TABLE_NAME, InviteMessgeDao.COLUMN_NAME_FROM + \" = ?\", new String[]{from});\n        }\n    }\n\n    public synchronized int getUnreadNotifyCount() {\n        int count = 0;\n        SQLiteDatabase db = dbHelper.getReadableDatabase();\n        if (db.isOpen()) {\n            Cursor cursor = db.rawQuery(\"select \" + InviteMessgeDao.COLUMN_NAME_UNREAD_MSG_COUNT + \" from \" + InviteMessgeDao.TABLE_NAME, null);\n            if (cursor.moveToFirst()) {\n                count = cursor.getInt(0);\n            }\n            cursor.close();\n        }\n        return count;\n    }\n\n    public synchronized void setUnreadNotifyCount(int count) {\n        SQLiteDatabase db = dbHelper.getWritableDatabase();\n        if (db.isOpen()) {\n            ContentValues values = new ContentValues();\n            values.put(InviteMessgeDao.COLUMN_NAME_UNREAD_MSG_COUNT, count);\n\n            db.update(InviteMessgeDao.TABLE_NAME, values, null, null);\n\n        }\n    }\n\n\n    synchronized public void closeDB() {\n        if (dbHelper != null) {\n            dbHelper.closeDB();\n        }\n        dbMgr = null;\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/DbOpenHelper.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n * <p/>\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.manager;\n\nimport android.content.Context;\nimport android.database.sqlite.SQLiteDatabase;\nimport android.database.sqlite.SQLiteOpenHelper;\nimport android.util.Log;\n\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.domain.InviteMessgeDao;\nimport com.htmessage.yichatopen.domain.UserDao;\n\npublic class DbOpenHelper extends SQLiteOpenHelper {\n\n    private static final int DATABASE_VERSION = 1;\n    private static DbOpenHelper instance;\n\n\n    private static final String USERNAME_TABLE_CREATE = \"CREATE TABLE \"\n            + UserDao.TABLE_NAME + \" (\"\n            + UserDao.COLUMN_NAME_NICK + \" TEXT, \"\n            + UserDao.COLUMN_NAME_AVATAR + \" TEXT, \"\n            + UserDao.COLUMN_NAME_INFO+ \" TEXT, \"\n            + UserDao.COLUMN_NAME_ID + \" TEXT PRIMARY KEY);\";\n\n    private static final String INIVTE_MESSAGE_TABLE_CREATE = \"CREATE TABLE \"\n            + InviteMessgeDao.TABLE_NAME + \" (\"\n            + InviteMessgeDao.COLUMN_NAME_ID + \" INTEGER PRIMARY KEY AUTOINCREMENT, \"\n            + InviteMessgeDao.COLUMN_NAME_FROM + \" TEXT, \"\n            + InviteMessgeDao.COLUMN_NAME_GROUP_ID + \" TEXT, \"\n            + InviteMessgeDao.COLUMN_NAME_GROUP_Name + \" TEXT, \"\n            + InviteMessgeDao.COLUMN_NAME_REASON + \" TEXT, \"\n            + InviteMessgeDao.COLUMN_NAME_STATUS + \" INTEGER, \"\n            + InviteMessgeDao.COLUMN_NAME_ISINVITEFROMME + \" INTEGER, \"\n            + InviteMessgeDao.COLUMN_NAME_UNREAD_MSG_COUNT + \" INTEGER, \"\n            + InviteMessgeDao.COLUMN_NAME_TIME + \" TEXT, \"\n            + InviteMessgeDao.COLUMN_NAME_GROUPINVITER + \" TEXT); \";\n\n\n    private DbOpenHelper(Context context) {\n\n        super(context, getUserDatabaseName(), null, DATABASE_VERSION);\n         Log.d(\"SDKDbOpenHelper----->\",getUserDatabaseName());\n    }\n\n    public static DbOpenHelper getInstance(Context context) {\n         if (instance == null) {\n             instance = new DbOpenHelper(context.getApplicationContext());\n        }\n        return instance;\n    }\n\n    private static String getUserDatabaseName() {\n        return HTApp.getInstance().getUsername()+ \"_app.db\";\n    }\n\n    @Override\n    public void onCreate(SQLiteDatabase db) {\n        db.execSQL(USERNAME_TABLE_CREATE);\n        db.execSQL(INIVTE_MESSAGE_TABLE_CREATE);\n\n    }\n\n    @Override\n    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {\n\n\n    }\n\n    public void closeDB() {\n        if (instance != null) {\n            try {\n                SQLiteDatabase db = instance.getWritableDatabase();\n                db.close();\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n            instance = null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/LocalUserManager.java",
    "content": "/**\n * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.\n * <p/>\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.manager;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport android.util.Log;\n\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\n\npublic class LocalUserManager {\n    /**\n     * 保存Preference的name\n     */\n    public static final String PREFERENCE_NAME = \"userInfo\";\n    private static SharedPreferences mSharedPreferences;\n    private static LocalUserManager mPreferencemManager;\n    private static SharedPreferences.Editor editor;\n    private String SHARED_KEY_USER_INFO = \"shared_key_user_info\";\n    private static Context context;\n\n    private LocalUserManager(Context cxt) {\n        this.context=cxt;\n         mSharedPreferences = cxt.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);\n        editor = mSharedPreferences.edit();\n    }\n\n    public static synchronized void init(Context cxt) {\n         if (mPreferencemManager == null) {\n            mPreferencemManager = new LocalUserManager(cxt);\n        }\n    }\n\n    /**\n     * 单例模式，获取instance实例\n     *\n     * @param\n     * @return\n     */\n    public synchronized static LocalUserManager getInstance() {\n        Log.d(\"CurrentUserManager---->\",context.getPackageName());\n        if (mPreferencemManager == null) {\n            throw new RuntimeException(\"please init first!\");\n        }\n\n        return mPreferencemManager;\n    }\n\n\n    public void setUserJson(JSONObject userJson) {\n        String userInfo = \"\";\n        if (userJson != null) {\n            try {\n                userInfo = userJson.toJSONString();\n            } catch (JSONException e) {\n            }\n        }\n        editor.putString(SHARED_KEY_USER_INFO, userInfo);\n        editor.commit();\n    }\n\n    public JSONObject getUserJson() {\n        JSONObject userJson =null;\n\n        String userStr = mSharedPreferences.getString(SHARED_KEY_USER_INFO, null);\n        if (userStr != null) {\n            userJson = JSONObject.parseObject(userStr);\n\n        }\n        return userJson;\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/Manager.java",
    "content": "package com.htmessage.yichatopen.manager;\n\nimport android.content.Context;\n\n/**\n * Created by huangfangyi on 2016/12/8.\n * qq 84543217\n */\n\npublic class Manager {\n\n    public static void initManagerList(Context context){\n        NotifierManager.init(context);\n        ContactsManager.init(context);\n        SettingsManager.init(context);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/MyNotification.java",
    "content": "package com.htmessage.yichatopen.manager;\n\nimport android.app.Notification;\nimport android.app.NotificationManager;\nimport android.app.PendingIntent;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.NotificationCompat;\n\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.domain.User;\nimport com.htmessage.yichatopen.activity.chat.ChatActivity;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.model.HTConversation;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.sdk.model.HTMessageTextBody;\n\n/**\n * Created by huangfangyi on 2016/12/19.\n * qq 84543217\n */\n\npublic class MyNotification {\n\n    private static MyNotification myNotification;\n\n\n    private static NotificationManager manager = null;\n    private Context mContext;\n    private Notification.Builder nBuilder;\n    private NotificationCompat.Builder builder;\n    private boolean isOpenOutGoing = false;//默认不打开常驻  打开滑动删除\n    private static Notification notification;\n\n    public MyNotification(Context context) {\n\n        this.mContext = context;\n        manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);\n        //为了版本兼容  选择V4包下的NotificationCompat进行构造\n        builder = new NotificationCompat.Builder(mContext);\n        nBuilder = new Notification.Builder(mContext);\n        setOutGoingAndAutoCancle(isOpenOutGoing);// 默认不打开常驻\n    }\n\n    public static void init(Context context) {\n        if (myNotification == null) {\n            myNotification = new MyNotification(context);\n        }\n\n    }\n\n    public static MyNotification getInstance() {\n        if (myNotification == null) {\n            throw new RuntimeException(\"please init first~!\");\n\n        }\n        return myNotification;\n    }\n\n    /**\n     * 设置常驻和滑动删除是否打开\n     *\n     * @param flag false 打开滑动删除,不设置常驻  true 设置常驻,不设置滑动删除\n     */\n    public void setOutGoingAndAutoCancle(@NonNull boolean flag) {\n        if (builder != null) {\n            builder.setAutoCancel(!flag);\n            builder.setOngoing(flag);\n        }\n        if (nBuilder != null) {\n            nBuilder.setAutoCancel(!flag);\n            nBuilder.setOngoing(flag);\n        }\n    }\n\n    public void onNewMessage(HTMessage htMessage) {\n        String userId = htMessage.getUsername();\n        String userNick = userId;\n        Intent intent = new Intent();\n        intent.setClass(mContext, ChatActivity.class);\n        intent.putExtra(\"userId\", userId);\n        if (htMessage.getChatType() == ChatType.singleChat) {\n            User user = ContactsManager.getInstance().getContactList().get(userId);\n            if (user != null) {\n                userNick = user.getNick();\n            }\n        }\n        // 如果当前Activity启动在前台，则不开启新的Activity。\n        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);\n        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, Integer.valueOf(userId), intent, PendingIntent.FLAG_UPDATE_CURRENT);\n        builder\n                .setContentIntent(pendingIntent)\n                .setContentTitle(userNick)\n                //  .setTicker(\"发来一个新消息\")\n                .setContentText(getContent(htMessage))\n                .setWhen(System.currentTimeMillis())\n                .setSmallIcon(mContext.getApplicationInfo().icon);\n        notification = builder.build();\n\n\n        notification.flags = Notification.FLAG_ONGOING_EVENT;\n        notification.flags = Notification.FLAG_AUTO_CANCEL;\n        manager.notify(Integer.valueOf(userId), notification);//发送通知\n    }\n\n    public void cancel(int id) {\n        manager.cancel(id);\n    }\n\n    protected final static String[] msgs = { \"发来一张图片\", \"发来一段语音\"};\n\n    private String getContent(HTMessage message) {\n        HTConversation htConversation = HTClient.getInstance().conversationManager().getConversation(message.getFrom());\n        String notifyText = \"\";\n        if (htConversation != null) {\n            if (htConversation.getUnReadCount() > 0) {\n                notifyText = mContext.getString(R.string.zhongkuohao) + htConversation.getUnReadCount() + mContext.getString(R.string.zhongkuohao_msg);\n\n            }\n\n        }\n\n        switch (message.getType()) {\n            case TEXT:\n                HTMessageTextBody htMessageTextBody = (HTMessageTextBody) message.getBody();\n\n                String content = htMessageTextBody.getContent();\n                if (content != null) {\n                    notifyText += content;\n                } else {\n                    notifyText += msgs[0];\n                }\n\n                break;\n            case IMAGE:\n                notifyText += msgs[0];\n                break;\n            case VOICE:\n                notifyText += msgs[1];\n                break;\n        }\n        return notifyText;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/Notifier.java",
    "content": "/************************************************************\n * * Hyphenate CONFIDENTIAL\n * __________________\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n * <p>\n * NOTICE: All information contained herein is, and remains\n * the property of Hyphenate Inc.\n * Dissemination of this information or reproduction of this material\n * is strictly forbidden unless prior written permission is obtained\n * from Hyphenate Inc.\n */\npackage com.htmessage.yichatopen.manager;\n\nimport android.app.ActivityManager;\nimport android.app.NotificationManager;\nimport android.content.Context;\nimport android.media.AudioManager;\nimport android.media.Ringtone;\nimport android.media.RingtoneManager;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Vibrator;\n\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Locale;\n\n/**\n * new message notifier class\n * <p>\n * this class is subject to be inherited and implement the relative APIs\n */\npublic class Notifier {\n    private final static String TAG = \"notify\";\n    Ringtone ringtone = null;\n\n    protected final static String[] msg_eng = {\"sent a message\", \"sent a picture\", \"sent a voice\",\n            \"sent location message\", \"sent a video\", \"sent a file\", \"%1 contacts sent %2 messages\"\n    };\n    protected final static String[] msg_ch = {\"发来一条消息\", \"发来一张图片\", \"发来一段语音\", \"发来位置信息\", \"发来一个视频\", \"发来一个文件\",\n            \"%1个联系人发来%2条消息\"\n    };\n\n    protected static int notifyID = 0525; // start notification id\n    protected static int foregroundNotifyID = 0555;\n\n    protected NotificationManager notificationManager = null;\n\n    protected HashSet<String> fromUsers = new HashSet<String>();\n    protected int notificationNum = 0;\n\n    protected Context appContext;\n    protected String packageName;\n    protected String[] msgs;\n    protected long lastNotifiyTime;\n    protected AudioManager audioManager;\n    protected Vibrator vibrator;\n\n    public Notifier() {\n    }\n\n    /**\n     * this function can be override\n     *\n     * @param context\n     * @return\n     */\n    public Notifier init(Context context) {\n        appContext = context;\n        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);\n\n        packageName = appContext.getApplicationInfo().packageName;\n        if (Locale.getDefault().getLanguage().equals(\"zh\")) {\n            msgs = msg_ch;\n        } else {\n            msgs = msg_eng;\n        }\n\n        audioManager = (AudioManager) appContext.getSystemService(Context.AUDIO_SERVICE);\n        vibrator = (Vibrator) appContext.getSystemService(Context.VIBRATOR_SERVICE);\n\n        return this;\n    }\n\n    /**\n     * this function can be override\n     */\n    public void reset() {\n        resetNotificationCount();\n        cancelNotificaton();\n    }\n\n    void resetNotificationCount() {\n        notificationNum = 0;\n        fromUsers.clear();\n    }\n\n    void cancelNotificaton() {\n        if (notificationManager != null)\n            notificationManager.cancel(notifyID);\n    }\n\n\n    public static boolean isAppRunningForeground(Context context) {\n        ActivityManager var1 = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n        List var2 = var1.getRunningTasks(1);\n        return context.getPackageName().equalsIgnoreCase(((ActivityManager.RunningTaskInfo) var2.get(0)).baseActivity.getPackageName());\n    }\n\n\n//\n//\n//    /**\n//     * vibrate and  play tone\n//     */\n//    public void vibrateAndPlayTone( String string) {\n//\n//\n//        if (System.currentTimeMillis() - lastNotifiyTime < 1000) {\n//            // received new messages within 2 seconds, skip play ringtone\n//            return;\n//        }\n//\n//        try {\n//            lastNotifiyTime = System.currentTimeMillis();\n//\n//            // check if in silent mode\n//            if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {\n//                 return;\n//            }\n//\n////                long[] pattern = new long[] { 0, 180, 80, 120 };\n////                vibrator.vibrate(pattern, -1);\n//            if (ringtone == null) {\n//                Uri notificationUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);\n//\n//                ringtone = RingtoneManager.getRingtone(appContext, notificationUri);\n//                if (ringtone == null) {\n//                     return;\n//                }\n//            }\n//\n//            if (!ringtone.isPlaying()) {\n//                String vendor = Build.MANUFACTURER;\n//\n//                ringtone.play();\n//                // for samsung S3, we meet a bug that the phone will\n//                // continue ringtone without stop\n//                // so add below special handler to stop it after 3s if\n//                // needed\n//                if (vendor != null && vendor.toLowerCase().contains(\"samsung\")) {\n//                    Thread ctlThread = new Thread() {\n//                        public void run() {\n//                            try {\n//                                Thread.sleep(3000);\n//                                if (ringtone.isPlaying()) {\n//                                    ringtone.stop();\n//                                }\n//                            } catch (Exception e) {\n//                            }\n//                        }\n//                    };\n//                    ctlThread.run();\n//                }\n//            }\n//\n//        } catch (Exception e) {\n//            e.printStackTrace();\n//        }\n//    }\n\n    /**\n     * vibrate and  play tone\n     */\n    public void vibrateAndPlayTone(String string) {\n\n        if (System.currentTimeMillis() - lastNotifiyTime < 1000) { //时间间隔小于1秒钟的返回\n            // received new messages within 2 seconds, skip play ringtone\n            return;\n        }\n        lastNotifiyTime=System.currentTimeMillis();\n\n         playSoundAndVibrator();\n\n    }\n\n    /**\n     * 播放声音\n     */\n    private void playSound() {\n        try {\n            lastNotifiyTime = System.currentTimeMillis();\n            // check if in silent mode\n            if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {\n                return;\n            }\n            if (ringtone == null) {\n                Uri notificationUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);\n\n                ringtone = RingtoneManager.getRingtone(appContext, notificationUri);\n                if (ringtone == null) {\n                    return;\n                }\n            }\n            if (!ringtone.isPlaying()) {\n                String vendor = Build.MANUFACTURER;\n                ringtone.play();\n                // for samsung S3, we meet a bug that the phone will\n                // continue ringtone without stop\n                // so add below special handler to stop it after 3s if\n                // needed\n                if (vendor != null && vendor.toLowerCase().contains(\"samsung\")) {\n                    Thread ctlThread = new Thread() {\n                        public void run() {\n                            try {\n                                Thread.sleep(3000);\n                                if (ringtone.isPlaying()) {\n                                    ringtone.stop();\n                                }\n                            } catch (Exception e) {\n                            }\n                        }\n                    };\n                    ctlThread.run();\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    /**\n     * 声音和震动\n     */\n    private void playSoundAndVibrator() {\n        try {\n            lastNotifiyTime = System.currentTimeMillis();\n            // check if in silent mode\n            if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {\n                return;\n            }\n            if (vibrator == null) {\n                vibrator = (Vibrator) appContext.getSystemService(Context.VIBRATOR_SERVICE);\n            }\n            if (ringtone == null) {\n                Uri notificationUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);\n\n                ringtone = RingtoneManager.getRingtone(appContext, notificationUri);\n                if (ringtone == null) {\n                    return;\n                }\n            }\n            /**\n             * 四个参数就是——停止 开启 停止 开启\n             * -1不重复，非-1为从pattern的指定下标开始重复\n             */\n            long[] pattern = new long[]{0, 180, 80, 120};\n            vibrator.vibrate(pattern, -1);\n            /**\n             * 播放声音\n             */\n            if (!ringtone.isPlaying()) {\n                String vendor = Build.MANUFACTURER;\n                ringtone.play();\n                // for samsung S3, we meet a bug that the phone will\n                // continue ringtone without stop\n                // so add below special handler to stop it after 3s if\n                // needed\n                if (vendor != null && vendor.toLowerCase().contains(\"samsung\")) {\n                    Thread ctlThread = new Thread() {\n                        public void run() {\n                            try {\n                                Thread.sleep(3000);\n                                if (ringtone.isPlaying()) {\n                                    ringtone.stop();\n                                }\n                            } catch (Exception e) {\n                            }\n                        }\n                    };\n                    ctlThread.run();\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    /**\n     * 震动\n     */\n    private void playVibrator() {\n        lastNotifiyTime = System.currentTimeMillis();\n        if (vibrator == null) {\n            vibrator = (Vibrator) appContext.getSystemService(Context.VIBRATOR_SERVICE);\n        }\n        /**\n         * 四个参数就是——停止 开启 停止 开启\n         * -1不重复，非-1为从pattern的指定下标开始重复\n         */\n        long[] pattern = new long[]{0, 180, 80, 120};\n        vibrator.vibrate(pattern, -1);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/NotifierManager.java",
    "content": "package com.htmessage.yichatopen.manager;\n\nimport android.content.Context;\n\n/**\n * Created by huangfangyi on 2016/10/12.\n * qq 84543217\n */\n\npublic class NotifierManager {\n\n    private static NotifierManager notifierManager = null;\n    /**\n     * application context\n     */\n    private Context appContext;\n\n    /**\n     * get notifierManager of EaseUI\n     *\n     * @return\n     */\n    public static NotifierManager getInstance() {\n        if (notifierManager == null) {\n            throw new RuntimeException(\"NotifierManager please init first!\");\n        }\n        return notifierManager;\n    }\n\n\n    public static synchronized void init(Context context) {\n        if (notifierManager == null) {\n\n            notifierManager = new NotifierManager(context);\n        }\n\n    }\n\n    public NotifierManager(Context context) {\n\n        appContext = context;\n        initNotifier();\n    }\n\n    /**\n     * the notifier\n     */\n    private Notifier notifier = null;\n\n    private void initNotifier() {\n        notifier = createNotifier();\n        notifier.init(appContext);\n    }\n\n    protected Notifier createNotifier() {\n        return new Notifier();\n    }\n\n    public Notifier getNotifier() {\n        return notifier;\n    }\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/PreferenceManager.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n * <p>\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.manager;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\n\npublic class PreferenceManager {\n    /**\n     * name of preference\n     */\n    public static final String PREFERENCE_NAME = \"saveInfo\";\n    private static SharedPreferences mSharedPreferences;\n    private static PreferenceManager mPreferencemManager;\n    private static SharedPreferences.Editor editor;\n\n    private String SHARED_KEY_SETTING_NOTIFICATION = \"shared_key_setting_notification\";\n    private String SHARED_KEY_SETTING_SOUND = \"shared_key_setting_sound\";\n    private String SHARED_KEY_SETTING_VIBRATE = \"shared_key_setting_vibrate\";\n    private String SHARED_KEY_SETTING_SPEAKER = \"shared_key_setting_speaker\";\n\n    private static String SHARED_KEY_SETTING_CHATROOM_OWNER_LEAVE = \"shared_key_setting_chatroom_owner_leave\";\n    private static String SHARED_KEY_SETTING_DELETE_MESSAGES_WHEN_EXIT_GROUP = \"shared_key_setting_delete_messages_when_exit_group\";\n    private static String SHARED_KEY_SETTING_AUTO_ACCEPT_GROUP_INVITATION = \"shared_key_setting_auto_accept_group_invitation\";\n    private static String SHARED_KEY_SETTING_ADAPTIVE_VIDEO_ENCODE = \"shared_key_setting_adaptive_video_encode\";\n\n    private static String SHARED_KEY_SETTING_GROUPS_SYNCED = \"SHARED_KEY_SETTING_GROUPS_SYNCED\";\n    private static String SHARED_KEY_SETTING_CONTACT_SYNCED = \"SHARED_KEY_SETTING_CONTACT_SYNCED\";\n    private static String SHARED_KEY_SETTING_BALCKLIST_SYNCED = \"SHARED_KEY_SETTING_BALCKLIST_SYNCED\";\n\n    private static String SHARED_KEY_CURRENTUSER_USERNAME = \"SHARED_KEY_CURRENTUSER_USERNAME\";\n    private static String SHARED_KEY_CURRENTUSER_NICK = \"SHARED_KEY_CURRENTUSER_NICK\";\n    private static String SHARED_KEY_CURRENTUSER_AVATAR = \"SHARED_KEY_CURRENTUSER_AVATAR\";\n\n    private PreferenceManager(Context cxt) {\n        mSharedPreferences = cxt.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);\n        editor = mSharedPreferences.edit();\n    }\n\n    public static synchronized void init(Context cxt) {\n        if (mPreferencemManager == null) {\n            mPreferencemManager = new PreferenceManager(cxt);\n        }\n    }\n\n    /**\n     * get instance of PreferenceManager\n     *\n     * @param\n     * @return\n     */\n    public synchronized static PreferenceManager getInstance() {\n        if (mPreferencemManager == null) {\n            throw new RuntimeException(\"please init first!\");\n        }\n\n        return mPreferencemManager;\n    }\n\n\n    public void setSettingMsgNotification(boolean paramBoolean) {\n         editor.putBoolean(SHARED_KEY_SETTING_NOTIFICATION, paramBoolean);\n        editor.commit();\n    }\n\n    private static final String KEY_GROUP = \"KEY_GROUP\";\n\n    public void setActivityCount(String groupId, int count) {\n        editor.putInt(KEY_GROUP + groupId, count);\n        editor.commit();\n    }\n\n    public int getActivityCount(String groupId) {\n\n        return mSharedPreferences.getInt(KEY_GROUP + groupId, 0);\n    }\n\n\n    public boolean getSettingMsgNotification() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_NOTIFICATION, true);\n    }\n\n    public void setSettingMsgSound(boolean paramBoolean) {\n         editor.putBoolean(SHARED_KEY_SETTING_SOUND, paramBoolean);\n        editor.commit();\n    }\n\n    public boolean getSettingMsgSound() {\n\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_SOUND, true);\n    }\n\n    public void setSettingMsgVibrate(boolean paramBoolean) {\n         editor.putBoolean(SHARED_KEY_SETTING_VIBRATE, paramBoolean);\n        editor.commit();\n    }\n\n    public boolean getSettingMsgVibrate() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_VIBRATE, true);\n    }\n\n    public void setSettingMsgSpeaker(boolean paramBoolean) {\n         editor.putBoolean(SHARED_KEY_SETTING_SPEAKER, paramBoolean);\n        editor.commit();\n    }\n\n    public boolean getSettingMsgSpeaker() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_SPEAKER, true);\n    }\n\n    public void setSettingAllowChatroomOwnerLeave(boolean value) {\n        editor.putBoolean(SHARED_KEY_SETTING_CHATROOM_OWNER_LEAVE, value);\n        editor.commit();\n    }\n\n    public boolean getSettingAllowChatroomOwnerLeave() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_CHATROOM_OWNER_LEAVE, true);\n    }\n\n    public void setDeleteMessagesAsExitGroup(boolean value) {\n         editor.putBoolean(SHARED_KEY_SETTING_DELETE_MESSAGES_WHEN_EXIT_GROUP, value);\n        editor.commit();\n    }\n\n    public boolean isDeleteMessagesAsExitGroup() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_DELETE_MESSAGES_WHEN_EXIT_GROUP, true);\n    }\n\n    public void setAutoAcceptGroupInvitation(boolean value) {\n        editor.putBoolean(SHARED_KEY_SETTING_AUTO_ACCEPT_GROUP_INVITATION, value);\n        editor.commit();\n    }\n\n    public boolean isAutoAcceptGroupInvitation() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_AUTO_ACCEPT_GROUP_INVITATION, true);\n    }\n\n    public void setAdaptiveVideoEncode(boolean value) {\n        editor.putBoolean(SHARED_KEY_SETTING_ADAPTIVE_VIDEO_ENCODE, value);\n        editor.commit();\n    }\n\n    public boolean isAdaptiveVideoEncode() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_ADAPTIVE_VIDEO_ENCODE, false);\n    }\n\n    public void setGroupsSynced(boolean synced) {\n        editor.putBoolean(SHARED_KEY_SETTING_GROUPS_SYNCED, synced);\n        editor.commit();\n    }\n\n    public boolean isGroupsSynced() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_GROUPS_SYNCED, false);\n    }\n\n    public void setContactSynced(boolean synced) {\n        editor.putBoolean(SHARED_KEY_SETTING_CONTACT_SYNCED, synced);\n        editor.commit();\n    }\n\n    public boolean isContactSynced() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_CONTACT_SYNCED, false);\n    }\n\n    public void setBlacklistSynced(boolean synced) {\n        editor.putBoolean(SHARED_KEY_SETTING_BALCKLIST_SYNCED, synced);\n        editor.commit();\n    }\n\n    public boolean isBacklistSynced() {\n        return mSharedPreferences.getBoolean(SHARED_KEY_SETTING_BALCKLIST_SYNCED, false);\n    }\n\n    public void setCurrentUserNick(String nick) {\n        editor.putString(SHARED_KEY_CURRENTUSER_NICK, nick);\n        editor.commit();\n    }\n\n    public void setCurrentUserAvatar(String avatar) {\n        editor.putString(SHARED_KEY_CURRENTUSER_AVATAR, avatar);\n        editor.commit();\n    }\n\n    public String getCurrentUserNick() {\n        return mSharedPreferences.getString(SHARED_KEY_CURRENTUSER_NICK, null);\n    }\n\n    public String getCurrentUserAvatar() {\n        return mSharedPreferences.getString(SHARED_KEY_CURRENTUSER_AVATAR, null);\n    }\n\n    public void setCurrentUserName(String username) {\n        editor.putString(SHARED_KEY_CURRENTUSER_USERNAME, username);\n        editor.commit();\n    }\n\n    public String getCurrentUsername() {\n        return mSharedPreferences.getString(SHARED_KEY_CURRENTUSER_USERNAME, null);\n    }\n\n\n    public void removeCurrentUserInfo() {\n        editor.remove(SHARED_KEY_CURRENTUSER_NICK);\n        editor.remove(SHARED_KEY_CURRENTUSER_AVATAR);\n        editor.commit();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/manager/SettingsManager.java",
    "content": "package com.htmessage.yichatopen.manager;\n\nimport android.content.Context;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class SettingsManager {\n\n    protected Context context = null;\n    protected Map<Key,Object> valueCache = new HashMap<Key,Object>();\n    private static SettingsManager settingManager;\n    public SettingsManager(Context ctx){\n        context = ctx;\n        PreferenceManager.init(context);\n    }\n\n    public synchronized static void init(Context context){\n        if(settingManager==null){\n            settingManager=new SettingsManager(context);\n        }\n\n    }\n\n    public static SettingsManager getInstance(){\n        if(settingManager==null){\n\n            throw new RuntimeException(\"settingManager please init first\");\n        }\n\n        return  settingManager;\n    }\n    public void setSettingMsgNotification(boolean paramBoolean) {\n        PreferenceManager.getInstance().setSettingMsgNotification(paramBoolean);\n        valueCache.put(Key.VibrateAndPlayToneOn, paramBoolean);\n    }\n\n    public boolean getSettingMsgNotification() {\n        Object val = valueCache.get(Key.VibrateAndPlayToneOn);\n\n        if(val == null){\n            val = PreferenceManager.getInstance().getSettingMsgNotification();\n            valueCache.put(Key.VibrateAndPlayToneOn, val);\n        }\n       \n        return (Boolean) (val != null?val:true);\n    }\n\n    public void setSettingMsgSound(boolean paramBoolean) {\n        PreferenceManager.getInstance().setSettingMsgSound(paramBoolean);\n        valueCache.put(Key.PlayToneOn, paramBoolean);\n    }\n\n    public boolean getSettingMsgSound() {\n        Object val = valueCache.get(Key.PlayToneOn);\n\n        if(val == null){\n            val = PreferenceManager.getInstance().getSettingMsgSound();\n            valueCache.put(Key.PlayToneOn, val);\n        }\n       \n        return (Boolean) (val != null?val:true);\n    }\n\n    public void setSettingMsgVibrate(boolean paramBoolean) {\n        PreferenceManager.getInstance().setSettingMsgVibrate(paramBoolean);\n        valueCache.put(Key.VibrateOn, paramBoolean);\n    }\n\n    public boolean getSettingMsgVibrate() {\n        Object val = valueCache.get(Key.VibrateOn);\n\n        if(val == null){\n            val = PreferenceManager.getInstance().getSettingMsgVibrate();\n            valueCache.put(Key.VibrateOn, val);\n        }\n       \n        return (Boolean) (val != null?val:true);\n    }\n\n    public void setSettingMsgSpeaker(boolean paramBoolean) {\n        PreferenceManager.getInstance().setSettingMsgSpeaker(paramBoolean);\n        valueCache.put(Key.SpakerOn, paramBoolean);\n    }\n\n    public boolean getSettingMsgSpeaker() {        \n        Object val = valueCache.get(Key.SpakerOn);\n\n        if(val == null){\n            val = PreferenceManager.getInstance().getSettingMsgSpeaker();\n            valueCache.put(Key.SpakerOn, val);\n        }\n       \n        return (Boolean) (val != null?val:true);\n    }\n\n\n\n    public void allowChatroomOwnerLeave(boolean value){\n        PreferenceManager.getInstance().setSettingAllowChatroomOwnerLeave(value);\n    }\n    \n    public boolean isChatroomOwnerLeaveAllowed(){\n        return PreferenceManager.getInstance().getSettingAllowChatroomOwnerLeave();\n    }\n   \n    public void setDeleteMessagesAsExitGroup(boolean value) {\n        PreferenceManager.getInstance().setDeleteMessagesAsExitGroup(value);\n    }\n    \n    public boolean isDeleteMessagesAsExitGroup() {\n        return PreferenceManager.getInstance().isDeleteMessagesAsExitGroup();\n    }\n    \n    public void setAutoAcceptGroupInvitation(boolean value) {\n        PreferenceManager.getInstance().setAutoAcceptGroupInvitation(value);\n    }\n    \n    public boolean isAutoAcceptGroupInvitation() {\n        return PreferenceManager.getInstance().isAutoAcceptGroupInvitation();\n    }\n    \n\n    public void setAdaptiveVideoEncode(boolean value) {\n        PreferenceManager.getInstance().setAdaptiveVideoEncode(value);\n    }\n    \n    public boolean isAdaptiveVideoEncode() {\n        return PreferenceManager.getInstance().isAdaptiveVideoEncode();\n    }\n    \n    enum Key{\n        VibrateAndPlayToneOn,\n        VibrateOn,\n        PlayToneOn,\n        SpakerOn,\n        DisabledGroups,\n        DisabledIds\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/runtimepermissions/Permissions.java",
    "content": "/**\n * Copyright 2015 Anthony Restaino\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n http://www.apache.org/licenses/LICENSE-2.0\n Unless required by applicable law or agreed to in writing,\n software distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n either express or implied. See the License for the specific language governing\n permissions and limitations under the License.\n */\npackage com.htmessage.yichatopen.runtimepermissions;\n\n/**\n * Enum class to handle the different states\n * of permissions since the PackageManager only\n * has a granted and denied state.\n */\nenum Permissions {\n  GRANTED,\n  DENIED,\n  NOT_FOUND\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/runtimepermissions/PermissionsManager.java",
    "content": "/**\n * Copyright 2015 Anthony Restaino\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n http://www.apache.org/licenses/LICENSE-2.0\n Unless required by applicable law or agreed to in writing,\n software distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n either express or implied. See the License for the specific language governing\n permissions and limitations under the License.\n */\npackage com.htmessage.yichatopen.runtimepermissions;\n\nimport android.Manifest;\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.os.Build;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.ActivityCompat;\nimport android.support.v4.app.Fragment;\nimport android.util.Log;\n\nimport java.lang.ref.WeakReference;\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * A class to help you manage your permissions simply.\n */\npublic class PermissionsManager {\n\n  private static final String TAG = PermissionsManager.class.getSimpleName();\n\n  private final Set<String> mPendingRequests = new HashSet<String>(1);\n  private final Set<String> mPermissions = new HashSet<String>(1);\n  private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<WeakReference<PermissionsResultAction>>(1);\n\n  private static PermissionsManager mInstance = null;\n\n  public static PermissionsManager getInstance() {\n    if (mInstance == null) {\n      mInstance = new PermissionsManager();\n    }\n    return mInstance;\n  }\n\n  private PermissionsManager() {\n    initializePermissionsMap();\n  }\n\n  /**\n   * This method uses reflection to read all the permissions in the Manifest class.\n   * This is necessary because some permissions do not exist on older versions of Android,\n   * since they do not exist, they will be denied when you check whether you have permission\n   * which is problematic since a new permission is often added where there was no previous\n   * permission required. We initialize a Set of available permissions and check the set\n   * when checking if we have permission since we want to know when we are denied a permission\n   * because it doesn't exist yet.\n   */\n  private synchronized void initializePermissionsMap() {\n    Field[] fields = Manifest.permission.class.getFields();\n    for (Field field : fields) {\n      String name = null;\n      try {\n        name = (String) field.get(\"\");\n      } catch (IllegalAccessException e) {\n        Log.e(TAG, \"Could not access field\", e);\n      }\n      mPermissions.add(name);\n    }\n  }\n\n  /**\n   * This method retrieves all the permissions declared in the application's manifest.\n   * It returns a non null array of permisions that can be declared.\n   *\n   * @param activity the Activity necessary to check what permissions we have.\n   * @return a non null array of permissions that are declared in the application manifest.\n   */\n  @NonNull\n  private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {\n    PackageInfo packageInfo = null;\n    List<String> list = new ArrayList<String>(1);\n    try {\n      Log.d(TAG, activity.getPackageName());\n      packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);\n    } catch (PackageManager.NameNotFoundException e) {\n      Log.e(TAG, \"A problem occurred when retrieving permissions\", e);\n    }\n    if (packageInfo != null) {\n      String[] permissions = packageInfo.requestedPermissions;\n      if (permissions != null) {\n        for (String perm : permissions) {\n          Log.d(TAG, \"Manifest contained permission: \" + perm);\n          list.add(perm);\n        }\n      }\n    }\n    return list.toArray(new String[list.size()]);\n  }\n\n  /**\n   * This method adds the {@link PermissionsResultAction} to the current list\n   * of pending actions that will be completed when the permissions are\n   * received. The list of permissions passed to this method are registered\n   * in the PermissionsResultAction object so that it will be notified of changes\n   * made to these permissions.\n   *\n   * @param permissions the required permissions for the action to be executed.\n   * @param action      the action to add to the current list of pending actions.\n   */\n  private synchronized void addPendingAction(@NonNull String[] permissions,\n      @Nullable PermissionsResultAction action) {\n    if (action == null) {\n      return;\n    }\n    action.registerPermissions(permissions);\n    mPendingActions.add(new WeakReference<PermissionsResultAction>(action));\n  }\n\n  /**\n   * This method removes a pending action from the list of pending actions.\n   * It is used for cases where the permission has already been granted, so\n   * you immediately wish to remove the pending action from the queue and\n   * execute the action.\n   *\n   * @param action the action to remove\n   */\n  private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {\n    for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();\n        iterator.hasNext(); ) {\n      WeakReference<PermissionsResultAction> weakRef = iterator.next();\n      if (weakRef.get() == action || weakRef.get() == null) {\n        iterator.remove();\n      }\n    }\n  }\n\n  /**\n   * This static method can be used to check whether or not you have a specific permission.\n   * It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)}\n   * and will simply return a boolean whether or not you have the permission. If you pass\n   * in a null Context object, it will return false as otherwise it cannot check the permission.\n   * However, the Activity parameter is nullable so that you can pass in a reference that you\n   * are not always sure will be valid or not (e.g. getActivity() from Fragment).\n   *\n   * @param context    the Context necessary to check the permission\n   * @param permission the permission to check\n   * @return true if you have been granted the permission, false otherwise\n   */\n  @SuppressWarnings(\"unused\")\n  public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {\n    return context != null && (ActivityCompat.checkSelfPermission(context, permission)\n        == PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));\n  }\n\n  /**\n   * This static method can be used to check whether or not you have several specific permissions.\n   * It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)}\n   * for each permission and will simply return a boolean whether or not you have all the permissions.\n   * If you pass in a null Context object, it will return false as otherwise it cannot check the\n   * permission. However, the Activity parameter is nullable so that you can pass in a reference\n   * that you are not always sure will be valid or not (e.g. getActivity() from Fragment).\n   *\n   * @param context     the Context necessary to check the permission\n   * @param permissions the permissions to check\n   * @return true if you have been granted all the permissions, false otherwise\n   */\n  @SuppressWarnings(\"unused\")\n  public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {\n    if (context == null) {\n      return false;\n    }\n    boolean hasAllPermissions = true;\n    for (String perm : permissions) {\n      hasAllPermissions &= hasPermission(context, perm);\n    }\n    return hasAllPermissions;\n  }\n\n  /**\n   * This method will request all the permissions declared in your application manifest\n   * for the specified {@link PermissionsResultAction}. The purpose of this method is to enable\n   * all permissions to be requested at one shot. The PermissionsResultAction is used to notify\n   * you of the user allowing or denying each permission. The Activity and PermissionsResultAction\n   * parameters are both annotated Nullable, but this method will not work if the Activity\n   * is null. It is only annotated Nullable as a courtesy to prevent crashes in the case\n   * that you call this from a Fragment where {@link Fragment#getActivity()} could yield\n   * null. Additionally, you will not receive any notification of permissions being granted\n   * if you provide a null PermissionsResultAction.\n   *\n   * @param activity the Activity necessary to request and check permissions.\n   * @param action   the PermissionsResultAction used to notify you of permissions being accepted.\n   */\n  @SuppressWarnings(\"unused\")\n  public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,\n      final @Nullable PermissionsResultAction action) {\n    if (activity == null) {\n      return;\n    }\n    String[] perms = getManifestPermissions(activity);\n    requestPermissionsIfNecessaryForResult(activity, perms, action);\n  }\n\n  /**\n   * This method should be used to execute a {@link PermissionsResultAction} for the array\n   * of permissions passed to this method. This method will request the permissions if\n   * they need to be requested (i.e. we don't have permission yet) and will add the\n   * PermissionsResultAction to the queue to be notified of permissions being granted or\n   * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.\n   * The Activity variable is nullable, but if it is null, the method will fail to execute.\n   * This is only nullable as a courtesy for Fragments where getActivity() may yeild null\n   * if the Fragment is not currently added to its parent Activity.\n   *\n   * @param activity    the activity necessary to request the permissions.\n   * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.\n   * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.\n   */\n  @SuppressWarnings(\"unused\")\n  public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,\n      @NonNull String[] permissions,\n      @Nullable PermissionsResultAction action) {\n    if (activity == null) {\n      return;\n    }\n    addPendingAction(permissions, action);\n    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {\n      doPermissionWorkBeforeAndroidM(activity, permissions, action);\n    } else {\n      List<String> permList = getPermissionsListToRequest(activity, permissions, action);\n      if (permList.isEmpty()) {\n        //if there is no permission to request, there is no reason to keep the action int the list\n        removePendingAction(action);\n      } else {\n        String[] permsToRequest = permList.toArray(new String[permList.size()]);\n        mPendingRequests.addAll(permList);\n        ActivityCompat.requestPermissions(activity, permsToRequest, 1);\n      }\n    }\n  }\n\n  /**\n   * This method should be used to execute a {@link PermissionsResultAction} for the array\n   * of permissions passed to this method. This method will request the permissions if\n   * they need to be requested (i.e. we don't have permission yet) and will add the\n   * PermissionsResultAction to the queue to be notified of permissions being granted or\n   * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.\n   * The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method\n   * will fail to work as the activity reference is necessary to check for permissions.\n   *\n   * @param fragment    the fragment necessary to request the permissions.\n   * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.\n   * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.\n   */\n  @SuppressWarnings(\"unused\")\n  public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,\n      @NonNull String[] permissions,\n      @Nullable PermissionsResultAction action) {\n    Activity activity = fragment.getActivity();\n    if (activity == null) {\n      return;\n    }\n    addPendingAction(permissions, action);\n    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {\n      doPermissionWorkBeforeAndroidM(activity, permissions, action);\n    } else {\n      List<String> permList = getPermissionsListToRequest(activity, permissions, action);\n      if (permList.isEmpty()) {\n        //if there is no permission to request, there is no reason to keep the action int the list\n        removePendingAction(action);\n      } else {\n        String[] permsToRequest = permList.toArray(new String[permList.size()]);\n        mPendingRequests.addAll(permList);\n        fragment.requestPermissions(permsToRequest, 1);\n      }\n    }\n  }\n\n  /**\n   * This method notifies the PermissionsManager that the permissions have change. If you are making\n   * the permissions requests using an Activity, then this method should be called from the\n   * Activity callback onRequestPermissionsResult() with the variables passed to that method. If\n   * you are passing a Fragment to make the permissions request, then you should call this in\n   * the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method.\n   * It will notify all the pending PermissionsResultAction objects currently\n   * in the queue, and will remove the permissions request from the list of pending requests.\n   *\n   * @param permissions the permissions that have changed.\n   * @param results     the values for each permission.\n   */\n  @SuppressWarnings(\"unused\")\n  public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {\n    int size = permissions.length;\n    if (results.length < size) {\n      size = results.length;\n    }\n    Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();\n    while (iterator.hasNext()) {\n      PermissionsResultAction action = iterator.next().get();\n      for (int n = 0; n < size; n++) {\n        if (action == null || action.onResult(permissions[n], results[n])) {\n          iterator.remove();\n          break;\n        }\n      }\n    }\n    for (int n = 0; n < size; n++) {\n      mPendingRequests.remove(permissions[n]);\n    }\n  }\n\n  /**\n   * When request permissions on devices before Android M (Android 6.0, API Level 23)\n   * Do the granted or denied work directly according to the permission status\n   *\n   * @param activity    the activity to check permissions\n   * @param permissions the permissions names\n   * @param action      the callback work object, containing what we what to do after\n   *                    permission check\n   */\n  private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,\n      @NonNull String[] permissions,\n      @Nullable PermissionsResultAction action) {\n    for (String perm : permissions) {\n      if (action != null) {\n        if (!mPermissions.contains(perm)) {\n          action.onResult(perm, Permissions.NOT_FOUND);\n        } else if (ActivityCompat.checkSelfPermission(activity, perm)\n            != PackageManager.PERMISSION_GRANTED) {\n          action.onResult(perm, Permissions.DENIED);\n        } else {\n          action.onResult(perm, Permissions.GRANTED);\n        }\n      }\n    }\n  }\n\n  /**\n   * Filter the permissions list:\n   * If a permission is not granted, add it to the result list\n   * if a permission is granted, do the granted work, do not add it to the result list\n   *\n   * @param activity    the activity to check permissions\n   * @param permissions all the permissions names\n   * @param action      the callback work object, containing what we what to do after\n   *                    permission check\n   * @return a list of permissions names that are not granted yet\n   */\n  @NonNull\n  private List<String> getPermissionsListToRequest(@NonNull Activity activity,\n      @NonNull String[] permissions,\n      @Nullable PermissionsResultAction action) {\n    List<String> permList = new ArrayList<String>(permissions.length);\n    for (String perm : permissions) {\n      if (!mPermissions.contains(perm)) {\n        if (action != null) {\n          action.onResult(perm, Permissions.NOT_FOUND);\n        }\n      } else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {\n        if (!mPendingRequests.contains(perm)) {\n          permList.add(perm);\n        }\n      } else {\n        if (action != null) {\n          action.onResult(perm, Permissions.GRANTED);\n        }\n      }\n    }\n    return permList;\n  }\n\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/runtimepermissions/PermissionsResultAction.java",
    "content": "/**\n * Copyright 2015 Anthony Restaino\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n http://www.apache.org/licenses/LICENSE-2.0\n Unless required by applicable law or agreed to in writing,\n software distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n either express or implied. See the License for the specific language governing\n permissions and limitations under the License.\n */\npackage com.htmessage.yichatopen.runtimepermissions;\n\nimport android.content.pm.PackageManager;\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.support.annotation.CallSuper;\nimport android.support.annotation.NonNull;\nimport android.util.Log;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * This abstract class should be used to create an if/else action that the PermissionsManager\n * can execute when the permissions you request are granted or denied. Simple use involves\n * creating an anonymous instance of it and passing that instance to the\n * requestPermissionsIfNecessaryForResult method. The result will be sent back to you as\n * either onGranted (all permissions have been granted), or onDenied (a required permission\n * has been denied). Ideally you put your functionality in the onGranted method and notify\n * the user what won't work in the onDenied method.\n */\npublic abstract class PermissionsResultAction {\n\n  private static final String TAG = PermissionsResultAction.class.getSimpleName();\n  private final Set<String> mPermissions = new HashSet<String>(1);\n  private Looper mLooper = Looper.getMainLooper();\n\n  /**\n   * Default Constructor\n   */\n  public PermissionsResultAction() {}\n\n  /**\n   * Alternate Constructor. Pass the looper you wish the PermissionsResultAction\n   * callbacks to be executed on if it is not the current Looper. For instance,\n   * if you are making a permissions request from a background thread but wish the\n   * callback to be on the UI thread, use this constructor to specify the UI Looper.\n   *\n   * @param looper the looper that the callbacks will be called using.\n   */\n  @SuppressWarnings(\"unused\")\n  public PermissionsResultAction(@NonNull Looper looper) {mLooper = looper;}\n\n  /**\n   * This method is called when ALL permissions that have been\n   * requested have been granted by the user. In this method\n   * you should put all your permissions sensitive code that can\n   * only be executed with the required permissions.\n   */\n  public abstract void onGranted();\n\n  /**\n   * This method is called when a permission has been denied by\n   * the user. It provides you with the permission that was denied\n   * and will be executed on the Looper you pass to the constructor\n   * of this class, or the Looper that this object was created on.\n   *\n   * @param permission the permission that was denied.\n   */\n  public abstract void onDenied(String permission);\n\n  /**\n   * This method is used to determine if a permission not\n   * being present on the current Android platform should\n   * affect whether the PermissionsResultAction should continue\n   * listening for events. By default, it returns true and will\n   * simply ignore the permission that did not exist. Usually this will\n   * work fine since most new permissions are introduced to\n   * restrict what was previously allowed without permission.\n   * If that is not the case for your particular permission you\n   * request, override this method and return false to result in the\n   * Action being denied.\n   *\n   * @param permission the permission that doesn't exist on this\n   *                   Android version\n   * @return return true if the PermissionsResultAction should\n   * ignore the lack of the permission and proceed with exection\n   * or false if the PermissionsResultAction should treat the\n   * absence of the permission on the API level as a denial.\n   */\n  @SuppressWarnings({\"WeakerAccess\", \"SameReturnValue\"})\n  public synchronized boolean shouldIgnorePermissionNotFound(String permission) {\n    Log.d(TAG, \"Permission not found: \" + permission);\n    return true;\n  }\n\n  @SuppressWarnings(\"WeakerAccess\")\n  @CallSuper\n  protected synchronized final boolean onResult(final @NonNull String permission, int result) {\n    if (result == PackageManager.PERMISSION_GRANTED) {\n      return onResult(permission, Permissions.GRANTED);\n    } else {\n      return onResult(permission, Permissions.DENIED);\n    }\n\n  }\n\n  /**\n   * This method is called when a particular permission has changed.\n   * This method will be called for all permissions, so this method determines\n   * if the permission affects the state or not and whether it can proceed with\n   * calling onGranted or if onDenied should be called.\n   *\n   * @param permission the permission that changed.\n   * @param result     the result for that permission.\n   * @return this method returns true if its primary action has been completed\n   * and it should be removed from the data structure holding a reference to it.\n   */\n  @SuppressWarnings(\"WeakerAccess\")\n  @CallSuper\n  protected synchronized final boolean onResult(final @NonNull String permission, Permissions result) {\n    mPermissions.remove(permission);\n    if (result == Permissions.GRANTED) {\n      if (mPermissions.isEmpty()) {\n        new Handler(mLooper).post(new Runnable() {\n          @Override\n          public void run() {\n            onGranted();\n          }\n        });\n        return true;\n      }\n    } else if (result == Permissions.DENIED) {\n      new Handler(mLooper).post(new Runnable() {\n        @Override\n        public void run() {\n          onDenied(permission);\n        }\n      });\n      return true;\n    } else if (result == Permissions.NOT_FOUND) {\n      if (shouldIgnorePermissionNotFound(permission)) {\n        if (mPermissions.isEmpty()) {\n          new Handler(mLooper).post(new Runnable() {\n            @Override\n            public void run() {\n              onGranted();\n            }\n          });\n          return true;\n        }\n      } else {\n        new Handler(mLooper).post(new Runnable() {\n          @Override\n          public void run() {\n            onDenied(permission);\n          }\n        });\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * This method registers the PermissionsResultAction object for the specified permissions\n   * so that it will know which permissions to look for changes to. The PermissionsResultAction\n   * will then know to look out for changes to these permissions.\n   *\n   * @param perms the permissions to listen for\n   */\n  @SuppressWarnings(\"WeakerAccess\")\n  @CallSuper\n  protected synchronized final void registerPermissions(@NonNull String[] perms) {\n    Collections.addAll(mPermissions, perms);\n  }\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/ACache.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.graphics.Canvas;\nimport android.graphics.PixelFormat;\nimport android.graphics.drawable.BitmapDrawable;\nimport android.graphics.drawable.Drawable;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.io.BufferedReader;\nimport java.io.BufferedWriter;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.FileOutputStream;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.io.OutputStream;\nimport java.io.RandomAccessFile;\nimport java.io.Serializable;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\n\npublic class ACache {\n    public static final int TIME_HOUR = 60 * 60;\n    public static final int TIME_DAY = TIME_HOUR * 24;\n    private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb\n    private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量\n    private static Map<String, ACache> mInstanceMap = new HashMap<String, ACache>();\n    private ACacheManager mCache;\n\n    public static ACache get(Context ctx) {\n        return get(ctx, \"ACache\");\n    }\n\n    public static ACache get(Context ctx, String cacheName) {\n        File f = new File(ctx.getCacheDir(), cacheName);\n        return get(f, MAX_SIZE, MAX_COUNT);\n    }\n\n    public static ACache get(File cacheDir) {\n        return get(cacheDir, MAX_SIZE, MAX_COUNT);\n    }\n\n    public static ACache get(Context ctx, long max_zise, int max_count) {\n        File f = new File(ctx.getCacheDir(), \"ACache\");\n        return get(f, max_zise, max_count);\n    }\n\n    public static ACache get(File cacheDir, long max_zise, int max_count) {\n        ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());\n        if (manager == null) {\n            manager = new ACache(cacheDir, max_zise, max_count);\n            mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager);\n        }\n        return manager;\n    }\n\n    private static String myPid() {\n        return \"_\" + android.os.Process.myPid();\n    }\n\n    private ACache(File cacheDir, long max_size, int max_count) {\n        if (!cacheDir.exists() && !cacheDir.mkdirs()) {\n            throw new RuntimeException(\"can't make dirs in \" + cacheDir.getAbsolutePath());\n        }\n        mCache = new ACacheManager(cacheDir, max_size, max_count);\n    }\n\n\n    class xFileOutputStream extends FileOutputStream {\n        File file;\n\n        public xFileOutputStream(File file) throws FileNotFoundException {\n            super(file);\n            this.file = file;\n        }\n\n        public void close() throws IOException {\n            super.close();\n            mCache.put(file);\n        }\n    }\n\n    // =======================================\n    // ============ String数据 读写 ==============\n    // =======================================\n\n    /**\n     * 保存 String数据 到 缓存中\n     *\n     * @param key   保存的key\n     * @param value 保存的String数据\n     */\n    public void put(String key, String value) {\n        File file = mCache.newFile(key);\n        BufferedWriter out = null;\n        try {\n            out = new BufferedWriter(new FileWriter(file), 1024);\n            out.write(value);\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            if (out != null) {\n                try {\n                    out.flush();\n                    out.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n            mCache.put(file);\n        }\n    }\n\n    /**\n     * 保存 String数据 到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的String数据\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, String value, int saveTime) {\n        put(key, Utils.newStringWithDateInfo(saveTime, value));\n    }\n\n    /**\n     * 读取 String数据\n     *\n     * @param key\n     * @return String 数据\n     */\n    public String getAsString(String key) {\n        File file = mCache.get(key);\n        if (!file.exists())\n            return null;\n        boolean removeFile = false;\n        BufferedReader in = null;\n        try {\n            in = new BufferedReader(new FileReader(file));\n            String readString = \"\";\n            String currentLine;\n            while ((currentLine = in.readLine()) != null) {\n                readString += currentLine;\n            }\n            if (!Utils.isDue(readString)) {\n                return Utils.clearDateInfo(readString);\n            } else {\n                removeFile = true;\n                return null;\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n            return null;\n        } finally {\n            if (in != null) {\n                try {\n                    in.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n            if (removeFile)\n                remove(key);\n        }\n    }\n\n    // =======================================\n    // ============= JSONObject 数据 读写 ==============\n    // =======================================\n\n    /**\n     * 保存 JSONObject数据 到 缓存中\n     *\n     * @param key   保存的key\n     * @param value 保存的JSON数据\n     */\n    public void put(String key, JSONObject value) {\n        put(key, value.toJSONString());\n    }\n\n    /**\n     * 保存 JSONObject数据 到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的JSONObject数据\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, JSONObject value, int saveTime) {\n        put(key, value.toString(), saveTime);\n    }\n\n    /**\n     * 读取JSONObject数据\n     *\n     * @param key\n     * @return JSONObject数据\n     */\n    public JSONObject getAsJSONObject(String key) {\n        String JSONString = getAsString(key);\n        try {\n            JSONObject obj = JSONObject.parseObject(JSONString);\n            return obj;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return null;\n        }\n    }\n\n    // =======================================\n    // ============ JSONArray 数据 读写 =============\n    // =======================================\n\n    /**\n     * 保存 JSONArray数据 到 缓存中\n     *\n     * @param key   保存的key\n     * @param value 保存的JSONArray数据\n     */\n    public void put(String key, JSONArray value) {\n        put(key, value.toJSONString());\n    }\n\n    /**\n     * 保存 JSONArray数据 到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的JSONArray数据\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, JSONArray value, int saveTime) {\n        put(key, value.toJSONString(), saveTime);\n    }\n\n    /**\n     * 读取JSONArray数据\n     *\n     * @param key\n     * @return JSONArray数据\n     */\n    public JSONArray getAsJSONArray(String key) {\n        String JSONString = getAsString(key);\n        try {\n            JSONArray obj = JSONArray.parseArray(JSONString);\n            return obj;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return null;\n        }\n    }\n\n    // =======================================\n    // ============== byte 数据 读写 =============\n    // =======================================\n\n    /**\n     * 保存 byte数据 到 缓存中\n     *\n     * @param key   保存的key\n     * @param value 保存的数据\n     */\n    public void put(String key, byte[] value) {\n        File file = mCache.newFile(key);\n        FileOutputStream out = null;\n        try {\n            out = new FileOutputStream(file);\n            out.write(value);\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            if (out != null) {\n                try {\n                    out.flush();\n                    out.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n            mCache.put(file);\n        }\n    }\n\n    /**\n     * Cache for a stream\n     *\n     * @param key the file name.\n     * @return OutputStream stream for writing data.\n     * @throws FileNotFoundException if the file can not be created.\n     */\n    public OutputStream put(String key) throws FileNotFoundException {\n        return new xFileOutputStream(mCache.newFile(key));\n    }\n\n    /**\n     * @param key the file name.\n     * @return (InputStream or null) stream previously saved in cache.\n     * @throws FileNotFoundException if the file can not be opened\n     */\n    public InputStream get(String key) throws FileNotFoundException {\n        File file = mCache.get(key);\n        if (!file.exists())\n            return null;\n        return new FileInputStream(file);\n    }\n\n    /**\n     * 保存 byte数据 到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的数据\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, byte[] value, int saveTime) {\n        put(key, Utils.newByteArrayWithDateInfo(saveTime, value));\n    }\n\n    /**\n     * 获取 byte 数据\n     *\n     * @param key\n     * @return byte 数据\n     */\n    public byte[] getAsBinary(String key) {\n        RandomAccessFile RAFile = null;\n        boolean removeFile = false;\n        try {\n            File file = mCache.get(key);\n            if (!file.exists())\n                return null;\n            RAFile = new RandomAccessFile(file, \"r\");\n            byte[] byteArray = new byte[(int) RAFile.length()];\n            RAFile.read(byteArray);\n            if (!Utils.isDue(byteArray)) {\n                return Utils.clearDateInfo(byteArray);\n            } else {\n                removeFile = true;\n                return null;\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n            return null;\n        } finally {\n            if (RAFile != null) {\n                try {\n                    RAFile.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n            if (removeFile)\n                remove(key);\n        }\n    }\n\n    // =======================================\n    // ============= 序列化 数据 读写 ===============\n    // =======================================\n\n    /**\n     * 保存 Serializable数据 到 缓存中\n     *\n     * @param key   保存的key\n     * @param value 保存的value\n     */\n    public void put(String key, Serializable value) {\n        put(key, value, -1);\n    }\n\n    /**\n     * 保存 Serializable数据到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的value\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, Serializable value, int saveTime) {\n        ByteArrayOutputStream baos = null;\n        ObjectOutputStream oos = null;\n        try {\n            baos = new ByteArrayOutputStream();\n            oos = new ObjectOutputStream(baos);\n            oos.writeObject(value);\n            byte[] data = baos.toByteArray();\n            if (saveTime != -1) {\n                put(key, data, saveTime);\n            } else {\n                put(key, data);\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                oos.close();\n            } catch (IOException e) {\n            }\n        }\n    }\n\n\n    /**\n     * 保存 Serializable数据到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的value\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, Object value) {\n        ByteArrayOutputStream baos = null;\n        ObjectOutputStream oos = null;\n        try {\n            baos = new ByteArrayOutputStream();\n            oos = new ObjectOutputStream(baos);\n            oos.writeObject(value);\n            byte[] data = baos.toByteArray();\n\n            put(key, data);\n\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                oos.close();\n            } catch (IOException e) {\n            }\n        }\n    }\n\n    /**\n     * 读取 Serializable数据\n     *\n     * @param key\n     * @return Serializable 数据\n     */\n    public Object getAsObject(String key) {\n        byte[] data = getAsBinary(key);\n        if (data != null) {\n            ByteArrayInputStream bais = null;\n            ObjectInputStream ois = null;\n            try {\n                bais = new ByteArrayInputStream(data);\n                ois = new ObjectInputStream(bais);\n                Object reObject = ois.readObject();\n                return reObject;\n            } catch (Exception e) {\n                e.printStackTrace();\n                return null;\n            } finally {\n                try {\n                    if (bais != null)\n                        bais.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n                try {\n                    if (ois != null)\n                        ois.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n        return null;\n\n    }\n\n    // =======================================\n    // ============== bitmap 数据 读写 =============\n    // =======================================\n\n    /**\n     * 保存 bitmap 到 缓存中\n     *\n     * @param key   保存的key\n     * @param value 保存的bitmap数据\n     */\n    public void put(String key, Bitmap value) {\n        put(key, Utils.Bitmap2Bytes(value));\n    }\n\n    /**\n     * 保存 bitmap 到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的 bitmap 数据\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, Bitmap value, int saveTime) {\n        put(key, Utils.Bitmap2Bytes(value), saveTime);\n    }\n\n    /**\n     * 读取 bitmap 数据\n     *\n     * @param key\n     * @return bitmap 数据\n     */\n    public Bitmap getAsBitmap(String key) {\n        if (getAsBinary(key) == null) {\n            return null;\n        }\n        return Utils.Bytes2Bimap(getAsBinary(key));\n    }\n\n    // =======================================\n    // ============= drawable 数据 读写 =============\n    // =======================================\n\n    /**\n     * 保存 drawable 到 缓存中\n     *\n     * @param key   保存的key\n     * @param value 保存的drawable数据\n     */\n    public void put(String key, Drawable value) {\n        put(key, Utils.drawable2Bitmap(value));\n    }\n\n    /**\n     * 保存 drawable 到 缓存中\n     *\n     * @param key      保存的key\n     * @param value    保存的 drawable 数据\n     * @param saveTime 保存的时间，单位：秒\n     */\n    public void put(String key, Drawable value, int saveTime) {\n        put(key, Utils.drawable2Bitmap(value), saveTime);\n    }\n\n    /**\n     * 读取 Drawable 数据\n     *\n     * @param key\n     * @return Drawable 数据\n     */\n    public Drawable getAsDrawable(String key) {\n        if (getAsBinary(key) == null) {\n            return null;\n        }\n        return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key)));\n    }\n\n    /**\n     * 获取缓存文件\n     *\n     * @param key\n     * @return value 缓存的文件\n     */\n    public File file(String key) {\n        File f = mCache.newFile(key);\n        if (f.exists())\n            return f;\n        return null;\n    }\n\n    /**\n     * 移除某个key\n     *\n     * @param key\n     * @return 是否移除成功\n     */\n    public boolean remove(String key) {\n        return mCache.remove(key);\n    }\n\n    /**\n     * 清除所有数据\n     */\n    public void clear() {\n        mCache.clear();\n    }\n\n    /**\n     * @author 杨福海（michael） www.yangfuhai.com\n     * @version 1.0\n     * @title 缓存管理器\n     */\n    public class ACacheManager {\n        private final AtomicLong cacheSize;\n        private final AtomicInteger cacheCount;\n        private final long sizeLimit;\n        private final int countLimit;\n        private final Map<File, Long> lastUsageDates = Collections.synchronizedMap(new HashMap<File, Long>());\n        protected File cacheDir;\n\n        private ACacheManager(File cacheDir, long sizeLimit, int countLimit) {\n            this.cacheDir = cacheDir;\n            this.sizeLimit = sizeLimit;\n            this.countLimit = countLimit;\n            cacheSize = new AtomicLong();\n            cacheCount = new AtomicInteger();\n            calculateCacheSizeAndCacheCount();\n        }\n\n        /**\n         * 计算 cacheSize和cacheCount\n         */\n        private void calculateCacheSizeAndCacheCount() {\n            new Thread(new Runnable() {\n                @Override\n                public void run() {\n                    int size = 0;\n                    int count = 0;\n                    File[] cachedFiles = cacheDir.listFiles();\n                    if (cachedFiles != null) {\n                        for (File cachedFile : cachedFiles) {\n                            size += calculateSize(cachedFile);\n                            count += 1;\n                            lastUsageDates.put(cachedFile, cachedFile.lastModified());\n                        }\n                        cacheSize.set(size);\n                        cacheCount.set(count);\n                    }\n                }\n            }).start();\n        }\n\n        private void put(File file) {\n            int curCacheCount = cacheCount.get();\n            while (curCacheCount + 1 > countLimit) {\n                long freedSize = removeNext();\n                cacheSize.addAndGet(-freedSize);\n\n                curCacheCount = cacheCount.addAndGet(-1);\n            }\n            cacheCount.addAndGet(1);\n\n            long valueSize = calculateSize(file);\n            long curCacheSize = cacheSize.get();\n            while (curCacheSize + valueSize > sizeLimit) {\n                long freedSize = removeNext();\n                curCacheSize = cacheSize.addAndGet(-freedSize);\n            }\n            cacheSize.addAndGet(valueSize);\n\n            Long currentTime = System.currentTimeMillis();\n            file.setLastModified(currentTime);\n            lastUsageDates.put(file, currentTime);\n        }\n\n        private File get(String key) {\n            File file = newFile(key);\n            Long currentTime = System.currentTimeMillis();\n            file.setLastModified(currentTime);\n            lastUsageDates.put(file, currentTime);\n\n            return file;\n        }\n\n        private File newFile(String key) {\n            return new File(cacheDir, key.hashCode() + \"\");\n        }\n\n        private boolean remove(String key) {\n            File image = get(key);\n            return image.delete();\n        }\n\n        private void clear() {\n            lastUsageDates.clear();\n            cacheSize.set(0);\n            File[] files = cacheDir.listFiles();\n            if (files != null) {\n                for (File f : files) {\n                    f.delete();\n                }\n            }\n        }\n\n        /**\n         * 移除旧的文件\n         *\n         * @return\n         */\n        private long removeNext() {\n            if (lastUsageDates.isEmpty()) {\n                return 0;\n            }\n\n            Long oldestUsage = null;\n            File mostLongUsedFile = null;\n            Set<Entry<File, Long>> entries = lastUsageDates.entrySet();\n            synchronized (lastUsageDates) {\n                for (Entry<File, Long> entry : entries) {\n                    if (mostLongUsedFile == null) {\n                        mostLongUsedFile = entry.getKey();\n                        oldestUsage = entry.getValue();\n                    } else {\n                        Long lastValueUsage = entry.getValue();\n                        if (lastValueUsage < oldestUsage) {\n                            oldestUsage = lastValueUsage;\n                            mostLongUsedFile = entry.getKey();\n                        }\n                    }\n                }\n            }\n\n            long fileSize = calculateSize(mostLongUsedFile);\n            if (mostLongUsedFile.delete()) {\n                lastUsageDates.remove(mostLongUsedFile);\n            }\n            return fileSize;\n        }\n\n        private long calculateSize(File file) {\n            return file.length();\n        }\n    }\n\n    /**\n     * @author 杨福海（michael） www.yangfuhai.com\n     * @version 1.0\n     * @title 时间计算工具类\n     */\n    private static class Utils {\n\n        /**\n         * 判断缓存的String数据是否到期\n         *\n         * @param str\n         * @return true：到期了 false：还没有到期\n         */\n        private static boolean isDue(String str) {\n            return isDue(str.getBytes());\n        }\n\n        /**\n         * 判断缓存的byte数据是否到期\n         *\n         * @param data\n         * @return true：到期了 false：还没有到期\n         */\n        private static boolean isDue(byte[] data) {\n            String[] strs = getDateInfoFromDate(data);\n            if (strs != null && strs.length == 2) {\n                String saveTimeStr = strs[0];\n                while (saveTimeStr.startsWith(\"0\")) {\n                    saveTimeStr = saveTimeStr.substring(1, saveTimeStr.length());\n                }\n                long saveTime = Long.valueOf(saveTimeStr);\n                long deleteAfter = Long.valueOf(strs[1]);\n                if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private static String newStringWithDateInfo(int second, String strInfo) {\n            return createDateInfo(second) + strInfo;\n        }\n\n        private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) {\n            byte[] data1 = createDateInfo(second).getBytes();\n            byte[] retdata = new byte[data1.length + data2.length];\n            System.arraycopy(data1, 0, retdata, 0, data1.length);\n            System.arraycopy(data2, 0, retdata, data1.length, data2.length);\n            return retdata;\n        }\n\n        private static String clearDateInfo(String strInfo) {\n            if (strInfo != null && hasDateInfo(strInfo.getBytes())) {\n                strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, strInfo.length());\n            }\n            return strInfo;\n        }\n\n        private static byte[] clearDateInfo(byte[] data) {\n            if (hasDateInfo(data)) {\n                return copyOfRange(data, indexOf(data, mSeparator) + 1, data.length);\n            }\n            return data;\n        }\n\n        private static boolean hasDateInfo(byte[] data) {\n            return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14;\n        }\n\n        private static String[] getDateInfoFromDate(byte[] data) {\n            if (hasDateInfo(data)) {\n                String saveDate = new String(copyOfRange(data, 0, 13));\n                String deleteAfter = new String(copyOfRange(data, 14, indexOf(data, mSeparator)));\n                return new String[]{saveDate, deleteAfter};\n            }\n            return null;\n        }\n\n        private static int indexOf(byte[] data, char c) {\n            for (int i = 0; i < data.length; i++) {\n                if (data[i] == c) {\n                    return i;\n                }\n            }\n            return -1;\n        }\n\n        private static byte[] copyOfRange(byte[] original, int from, int to) {\n            int newLength = to - from;\n            if (newLength < 0)\n                throw new IllegalArgumentException(from + \" > \" + to);\n            byte[] copy = new byte[newLength];\n            System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));\n            return copy;\n        }\n\n        private static final char mSeparator = ' ';\n\n        private static String createDateInfo(int second) {\n            String currentTime = System.currentTimeMillis() + \"\";\n            while (currentTime.length() < 13) {\n                currentTime = \"0\" + currentTime;\n            }\n            return currentTime + \"-\" + second + mSeparator;\n        }\n\n        /*\n         * Bitmap → byte[]\n         */\n        private static byte[] Bitmap2Bytes(Bitmap bm) {\n            if (bm == null) {\n                return null;\n            }\n            ByteArrayOutputStream baos = new ByteArrayOutputStream();\n            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);\n            return baos.toByteArray();\n        }\n\n        /*\n         * byte[] → Bitmap\n         */\n        private static Bitmap Bytes2Bimap(byte[] b) {\n            if (b.length == 0) {\n                return null;\n            }\n            return BitmapFactory.decodeByteArray(b, 0, b.length);\n        }\n\n        /*\n         * Drawable → Bitmap\n         */\n        private static Bitmap drawable2Bitmap(Drawable drawable) {\n            if (drawable == null) {\n                return null;\n            }\n            // 取 drawable 的长宽\n            int w = drawable.getIntrinsicWidth();\n            int h = drawable.getIntrinsicHeight();\n            // 取 drawable 的颜色格式\n            Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;\n            // 建立对应 bitmap\n            Bitmap bitmap = Bitmap.createBitmap(w, h, config);\n            // 建立对应 bitmap 的画布\n            Canvas canvas = new Canvas(bitmap);\n            drawable.setBounds(0, 0, w, h);\n            // 把 drawable 内容画到画布中\n            drawable.draw(canvas);\n            return bitmap;\n        }\n\n        /*\n         * Bitmap → Drawable\n         */\n        @SuppressWarnings(\"deprecation\")\n        private static Drawable bitmap2Drawable(Bitmap bm) {\n            if (bm == null) {\n                return null;\n            }\n            BitmapDrawable bd = new BitmapDrawable(bm);\n            bd.setTargetDensity(bm.getDensity());\n            return new BitmapDrawable(bm);\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/CommonUtils.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.utils;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n\nimport android.app.Activity;\nimport android.app.ActivityManager;\nimport android.app.ActivityManager.RunningTaskInfo;\nimport android.content.Context;\nimport android.graphics.drawable.ColorDrawable;\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\nimport android.text.Editable;\nimport android.text.TextUtils;\nimport android.text.TextWatcher;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.WindowManager;\nimport android.widget.AdapterView;\nimport android.widget.EditText;\nimport android.widget.ImageView;\nimport android.widget.ListView;\nimport android.widget.PopupWindow;\nimport android.widget.TextView;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.country.CountryCodeUtil;\nimport com.htmessage.yichatopen.activity.country.CountryComparator;\nimport com.htmessage.yichatopen.activity.country.CountrySortAdapter;\nimport com.htmessage.yichatopen.activity.country.CountrySortModel;\nimport com.htmessage.yichatopen.activity.country.GetCountryNameSort;\nimport com.htmessage.yichatopen.activity.country.SideBar;\nimport com.htmessage.yichatopen.HTConstant;\nimport com.htmessage.yichatopen.domain.User;\nimport com.github.promeg.pinyinhelper.Pinyin;\n\npublic class CommonUtils {\n\tprivate static final String TAG = \"CommonUtils\";\n\n\tpublic static User Json2User(JSONObject userJson) {\n\t\tUser user = new User(userJson.getString(HTConstant.JSON_KEY_HXID));\n\t\tuser.setNick(userJson.getString(HTConstant.JSON_KEY_NICK));\n\t\tuser.setAvatar(userJson.getString(HTConstant.JSON_KEY_AVATAR));\n\t\tuser.setUserInfo(userJson.toJSONString());\n\t\tCommonUtils.setUserInitialLetter(user);\n\t\treturn user;\n\t}\n\tpublic static boolean isNetWorkConnected(Context context) {\n\t\tif (context != null) {\n\t\t\tConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);\n\t\t\tNetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();\n\t\t\tif (mNetworkInfo != null) {\n\t\t\t\treturn mNetworkInfo.isAvailable() && mNetworkInfo.isConnected();\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * check if sdcard exist\n\t * \n\t * @return\n\t */\n\tpublic static boolean isSdcardExist() {\n\t\tif (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\t}\n\t\n\n\n    \n    static String getString(Context context, int resId){\n        return context.getResources().getString(resId);\n    }\n\t\n\t/**\n\t * get top activity\n\t * @param context\n\t * @return\n\t */\n\tpublic static String getTopActivity(Context context) {\n\t\tActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n\t\tList<RunningTaskInfo> runningTaskInfos = manager.getRunningTasks(1);\n\n\t\tif (runningTaskInfos != null)\n\t\t\treturn runningTaskInfos.get(0).topActivity.getClassName();\n\t\telse\n\t\t\treturn \"\";\n\t}\n\t\n\t/**\n     * set initial letter of according user's nickname( username if no nickname)\n     * \n     * @param\n     * @param user\n     */\n    public static void setUserInitialLetter(User user) {\n        final String DefaultLetter = \"#\";\n        String letter = DefaultLetter;\n        if ( !TextUtils.isEmpty(user.getNick()) ) {\n            letter = Pinyin.toPinyin(user.getNick().toCharArray()[0]);\n            user.setInitialLetter(letter.toUpperCase().substring(0,1));\n\t\t\tif (\"123456789\".contains(user.getInitialLetter())) {\n\t\t\t\tuser.setInitialLetter(\"#\");\n\t\t\t}\n            return;\n        } \n        if (letter == DefaultLetter && !TextUtils.isEmpty(user.getUsername())) {\n\t\t\tletter = Pinyin.toPinyin(user.getUsername().toCharArray()[0]);\n        }\n        user.setInitialLetter(letter.substring(0,1));\n\t\tif (\"123456789\".contains(user.getInitialLetter())) {\n\t\t\tuser.setInitialLetter(\"#\");\n\t\t}\n    }\n\n\t/**\n\t * 获取国家代码\n\t *\n\t * @param context     上下文对象\n\t * @param country     显示国家的textview\n\t * @param countryCode 显示国家代码的textview\n\t */\n\tpublic static void showPup(final Context context, final TextView country, final TextView countryCode) {\n\t\tfinal boolean cn = context.getResources().getConfiguration().locale.getCountry().equals(\"CN\");\n\t\tfinal List<CountrySortModel> countryList = CountryCodeUtil.getCountryList(context, cn);\n\t\t//获得pup的view\n\t\tView view = LayoutInflater.from(context).inflate(R.layout.layout_pup, null, false);\n\t\tfinal ImageView iv_back = (ImageView) view.findViewById(R.id.iv_back);\n\t\tfinal TextView tv_title = (TextView) view.findViewById(R.id.tv_title);\n\t\ttv_title.setText(R.string.country);\n\t\tfinal EditText country_et_search = (EditText) view.findViewById(R.id.country_et_search);\n\t\tfinal ImageView country_iv_cleartext = (ImageView) view.findViewById(R.id.country_iv_cleartext);\n\t\tfinal ListView ll_country = (ListView) view.findViewById(R.id.country_lv_list);\n\t\tfinal TextView country_dialog = (TextView) view.findViewById(R.id.country_dialog);\n\t\tfinal SideBar country_sidebar = (SideBar) view.findViewById(R.id.country_sidebar);\n\t\tcountry_sidebar.setTextView(country_dialog);\n\t\tfinal CountrySortAdapter adapter = new CountrySortAdapter(context, countryList);\n\t\tll_country.setAdapter(adapter);\n\t\tDisplayMetrics dm = new DisplayMetrics();\n\t\t//取得窗口属性\n\t\t((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);\n\t\t//窗口的宽度\n\t\tint screenWidth = dm.widthPixels;\n\t\t//窗口高度\n\t\tint screenHeight = dm.heightPixels / 2;\n\t\t//设置window的宽高   1 window的布局 2、window的宽  3、window的高  4、window是否获取焦点\n//        final PopupWindow window = new PopupWindow(view, WindowManager.LayoutParams.MATCH_PARENT, screenHeight, true);\n\t\tfinal PopupWindow window = new PopupWindow(view, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true);\n\t\t//设置window背景色\n\t\twindow.setBackgroundDrawable(new ColorDrawable(0x00000000));\n\t\t//设置可以获取焦点，否则弹出菜单中的EditText是无法获取输入的\n\t\twindow.setFocusable(true);\n\t\t//设置键盘不遮盖\n\t\twindow.setSoftInputMode(PopupWindow.INPUT_METHOD_NEEDED);\n\t\twindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);\n\t\t//设置window动画\n//        window.setAnimationStyle(R.style.custom_pup_style);\n\t\t//设置window在底部显示\n\t\twindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);\n\n\t\tcountry_iv_cleartext.setOnClickListener(new View.OnClickListener() {\n\n\t\t\t@Override\n\t\t\tpublic void onClick(View v) {\n\t\t\t\tcountry_et_search.setText(\"\");\n\t\t\t\tCollections.sort(countryList, new CountryComparator());\n\t\t\t\tadapter.updateListView(countryList);\n\t\t\t}\n\t\t});\n\n\t\tcountry_et_search.addTextChangedListener(new TextWatcher() {\n\n\t\t\t@Override\n\t\t\tpublic void onTextChanged(CharSequence s, int start, int before, int count) {\n\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void afterTextChanged(Editable s) {\n\t\t\t\tString searchContent = country_et_search.getText().toString();\n\t\t\t\tif (searchContent.equals(\"\")) {\n\t\t\t\t\tcountry_iv_cleartext.setVisibility(View.INVISIBLE);\n\t\t\t\t} else {\n\t\t\t\t\tcountry_iv_cleartext.setVisibility(View.VISIBLE);\n\t\t\t\t}\n\n\t\t\t\tif (searchContent.length() > 0) {\n\t\t\t\t\t// 按照输入内容进行匹配\n\t\t\t\t\tArrayList<CountrySortModel> fileterList = (ArrayList<CountrySortModel>) new GetCountryNameSort()\n\t\t\t\t\t\t\t.search(searchContent, countryList);\n\n\t\t\t\t\tadapter.updateListView(fileterList);\n\t\t\t\t} else {\n\t\t\t\t\tadapter.updateListView(countryList);\n\t\t\t\t}\n\t\t\t\tll_country.setSelection(0);\n\t\t\t}\n\t\t});\n\n\t\t// 右侧sideBar监听\n\t\tcountry_sidebar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {\n\n\t\t\t@Override\n\t\t\tpublic void onTouchingLetterChanged(String s) {\n\t\t\t\t// 该字母首次出现的位置\n\t\t\t\tint position = adapter.getPositionForSection(s.charAt(0));\n\t\t\t\tif (position != -1) {\n\t\t\t\t\tll_country.setSelection(position);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tll_country.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n\t\t\t@Override\n\t\t\tpublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {\n\t\t\t\twindow.dismiss();\n\t\t\t\tString countryName = null;\n\t\t\t\tString countryNumber = null;\n\t\t\t\tString searchContent = country_et_search.getText().toString();\n\t\t\t\tif (searchContent.length() > 0) {\n\t\t\t\t\t// 按照输入内容进行匹配\n\t\t\t\t\tArrayList<CountrySortModel> fileterList = (ArrayList<CountrySortModel>) new GetCountryNameSort()\n\t\t\t\t\t\t\t.search(searchContent, countryList);\n\t\t\t\t\t//获取国家名字及代码\n\t\t\t\t\tcountryName = fileterList.get(i).countryName;\n\t\t\t\t\tcountryNumber = fileterList.get(i).countryNumber;\n\t\t\t\t} else {\n\t\t\t\t\t//获取国家名字及代码\n\t\t\t\t\tcountryName = countryList.get(i).countryName;\n\t\t\t\t\tcountryNumber = countryList.get(i).countryNumber;\n\t\t\t\t}\n\t\t\t\tcountry.setText(countryName);\n\t\t\t\tcountryCode.setText(countryNumber);\n\t\t\t\tLog.e(TAG, \"countryName: + \" + countryName + \"countryNumber: \" + countryNumber);\n\t\t\t}\n\t\t});\n\t\tiv_back.setOnClickListener(new View.OnClickListener() {\n\t\t\t@Override\n\t\t\tpublic void onClick(View view) {\n\t\t\t\twindow.dismiss();\n\t\t\t}\n\t\t});\n\t}\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/DateUtils.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport com.htmessage.yichatopen.R;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.Locale;\n\n/**\n * Created by huangfangyi on 2016/12/24.\n * qq 84543217\n */\n\n\npublic class DateUtils {\n    private static final long INTERVAL_IN_MILLISECONDS = 30000L;\n\n    public DateUtils() {\n    }\n\n    /**\n     * 计算时间差\n     *\n     * @param starTime\n     *            开始时间\n     * @param endTime\n     *            结束时间\n     * @param type\n     *            返回类型 ==1----天，时，分。 ==2----时\n     * @return 返回时间差\n     */\n    public static String getTimeDifference(Context context, long starTime, long endTime) {\n        String timeString = \"\";\n        try {\n            Date parse = new Date(starTime);\n            Date parse1 = new Date(endTime);\n            long diff = parse1.getTime() - parse.getTime();\n\n            long day = diff / (24 * 60 * 60 * 1000);\n            long hour = (diff / (60 * 60 * 1000) - day * 24);\n            long min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);\n            long s = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);\n            long ms = (diff - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000\n                    - min * 60 * 1000 - s * 1000);\n            long hour1 = diff / (60 * 60 * 1000);\n            long min1 = ((diff / (60 * 1000)) - hour1 * 60);\n            if (day == 0){\n                if (hour1 == 0){\n                    if (0<=min1 && min1<=5){\n                        timeString = context.getString(R.string.just);\n                    }else if (min1>5 && min1<=15){\n                        timeString = context.getString(R.string.just_15);\n                    }else if (min1>15 && min1<=30){\n                        timeString = context.getString(R.string.just_30);\n                    }else{\n                        timeString = context.getString(R.string.just_1hour);\n                    }\n                }else{\n                    timeString = hour1+context.getString(R.string.An_hour_ago);\n                }\n            }else{\n                timeString = day+context.getString(R.string.Days_ago);\n            }\n\n//            timeString = hour1 + \"小时\" + min1 + \"分\";\n             Log.d(\"slj\",day + \"天\" + hour + \"小时\" + min + \"分\" + s + \"秒\");\n\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return timeString;\n\n    }\n\n\n    public static String getTimestampString(Date var0) {\n        String var1 = null;\n        String var2 = Locale.getDefault().getLanguage();\n        boolean var3 = var2.startsWith(\"zh\");\n        long var4 = var0.getTime();\n        if(isSameDay(var4)) {\n            if(var3) {\n                var1 = \"aa hh:mm\";\n            } else {\n                var1 = \"hh:mm aa\";\n            }\n        } else if(isYesterday(var4)) {\n            if(!var3) {\n                return \"Yesterday \" + (new SimpleDateFormat(\"hh:mm aa\", Locale.ENGLISH)).format(var0);\n            }\n\n            var1 = \"昨天aa hh:mm\";\n        } else if(var3) {\n            var1 = \"M月d日aa hh:mm\";\n        } else {\n            var1 = \"MMM dd hh:mm aa\";\n        }\n\n        return var3?(new SimpleDateFormat(var1, Locale.CHINESE)).format(var0):(new SimpleDateFormat(var1, Locale.ENGLISH)).format(var0);\n    }\n\n    public static boolean isCloseEnough(long var0, long var2) {\n        long var4 = var0 - var2;\n        if(var4 < 0L) {\n            var4 = -var4;\n        }\n\n        return var4 < 30000L;\n    }\n\n    private static boolean isSameDay(long var0) {\n        TimeInfo var2 = getTodayStartAndEndTime();\n        return var0 > var2.getStartTime() && var0 < var2.getEndTime();\n    }\n\n    private static boolean isYesterday(long var0) {\n        TimeInfo var2 = getYesterdayStartAndEndTime();\n        return var0 > var2.getStartTime() && var0 < var2.getEndTime();\n    }\n\n    public static Date StringToDate(String var0, String var1) {\n        SimpleDateFormat var2 = new SimpleDateFormat(var1);\n        Date var3 = null;\n\n        try {\n            var3 = var2.parse(var0);\n        } catch (ParseException var5) {\n            var5.printStackTrace();\n        }\n\n        return var3;\n    }\n\n    public static String toTime(int var0) {\n        var0 /= 1000;\n        int var1 = var0 / 60;\n        boolean var2 = false;\n        if(var1 >= 60) {\n            int var4 = var1 / 60;\n            var1 %= 60;\n        }\n\n        int var3 = var0 % 60;\n        return String.format(\"%02d:%02d\", new Object[]{Integer.valueOf(var1), Integer.valueOf(var3)});\n    }\n\n    public static String toTimeBySecond(int var0) {\n        int var1 = var0 / 60;\n        boolean var2 = false;\n        if(var1 >= 60) {\n            int var4 = var1 / 60;\n            var1 %= 60;\n        }\n\n        int var3 = var0 % 60;\n        return String.format(\"%02d:%02d\", new Object[]{Integer.valueOf(var1), Integer.valueOf(var3)});\n    }\n\n\n    public static TimeInfo getYesterdayStartAndEndTime() {\n        Calendar var0 = Calendar.getInstance();\n        var0.add(Calendar.DAY_OF_MONTH, -1);//5\n        var0.set(Calendar.HOUR_OF_DAY, 0);//11\n        var0.set(Calendar.MINUTE, 0);//12\n        var0.set(Calendar.SECOND, 0);//13\n        var0.set(Calendar.MILLISECOND, 0);//Calendar.MILLISECOND\n        Date var1 = var0.getTime();\n        long var2 = var1.getTime();\n        Calendar var4 = Calendar.getInstance();\n        var4.add(Calendar.DAY_OF_MONTH, -1);//5\n        var4.set(Calendar.HOUR_OF_DAY, 23);//11\n        var4.set(Calendar.MINUTE, 59);//12\n        var4.set(Calendar.SECOND, 59);//13\n        var4.set(Calendar.MILLISECOND, 999);//Calendar.MILLISECOND\n        Date var5 = var4.getTime();\n        long var6 = var5.getTime();\n        TimeInfo var8 = new TimeInfo();\n        var8.setStartTime(var2);\n        var8.setEndTime(var6);\n        return var8;\n    }\n\n    public static TimeInfo getTodayStartAndEndTime() {\n        Calendar var0 = Calendar.getInstance();\n        var0.set(Calendar.HOUR_OF_DAY, 0);\n        var0.set(Calendar.MINUTE, 0);\n        var0.set(Calendar.SECOND, 0);\n        var0.set(Calendar.MILLISECOND, 0);\n        Date var1 = var0.getTime();\n        long var2 = var1.getTime();\n        new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss S\");\n        Calendar var5 = Calendar.getInstance();\n        var5.set(Calendar.HOUR_OF_DAY, 23);\n        var5.set(Calendar.MINUTE, 59);\n        var5.set(Calendar.SECOND, 59);\n        var5.set(Calendar.MILLISECOND, 999);\n        Date var6 = var5.getTime();\n        long var7 = var6.getTime();\n        TimeInfo var9 = new TimeInfo();\n        var9.setStartTime(var2);\n        var9.setEndTime(var7);\n        return var9;\n    }\n\n    public static TimeInfo getBeforeYesterdayStartAndEndTime() {\n        Calendar var0 = Calendar.getInstance();\n        var0.add(Calendar.DAY_OF_MONTH, -2);\n        var0.set(Calendar.HOUR_OF_DAY, 0);\n        var0.set(Calendar.MINUTE, 0);\n        var0.set(Calendar.SECOND, 0);\n        var0.set(Calendar.MILLISECOND, 0);\n        Date var1 = var0.getTime();\n        long var2 = var1.getTime();\n        Calendar var4 = Calendar.getInstance();\n        var4.add(Calendar.DAY_OF_MONTH, -2);\n        var4.set(Calendar.HOUR_OF_DAY, 23);\n        var4.set(Calendar.MINUTE, 59);\n        var4.set(Calendar.SECOND, 59);\n        var4.set(Calendar.MILLISECOND, 999);\n        Date var5 = var4.getTime();\n        long var6 = var5.getTime();\n        TimeInfo var8 = new TimeInfo();\n        var8.setStartTime(var2);\n        var8.setEndTime(var6);\n        return var8;\n    }\n\n    public static TimeInfo getCurrentMonthStartAndEndTime() {\n        Calendar var0 = Calendar.getInstance();\n        var0.set(Calendar.DATE, 1);\n        var0.set(Calendar.HOUR_OF_DAY, 0);\n        var0.set(Calendar.MINUTE, 0);\n        var0.set(Calendar.SECOND, 0);\n        var0.set(Calendar.MILLISECOND, 0);\n        Date var1 = var0.getTime();\n        long var2 = var1.getTime();\n        Calendar var4 = Calendar.getInstance();\n        Date var5 = var4.getTime();\n        long var6 = var5.getTime();\n        TimeInfo var8 = new TimeInfo();\n        var8.setStartTime(var2);\n        var8.setEndTime(var6);\n        return var8;\n    }\n\n    public static TimeInfo getLastMonthStartAndEndTime() {\n        Calendar var0 = Calendar.getInstance();\n        var0.add(Calendar.MONTH, -1);\n        var0.set(Calendar.DATE, 1);\n        var0.set(Calendar.HOUR_OF_DAY, 0);\n        var0.set(Calendar.MINUTE, 0);\n        var0.set(Calendar.SECOND, 0);\n        var0.set(Calendar.MILLISECOND, 0);\n        Date var1 = var0.getTime();\n        long var2 = var1.getTime();\n        Calendar var4 = Calendar.getInstance();\n        var4.add(Calendar.MONTH, -1);\n        var4.set(Calendar.DATE, 1);\n        var4.set(Calendar.HOUR_OF_DAY, 23);\n        var4.set(Calendar.MINUTE, 59);\n        var4.set(Calendar.SECOND, 59);\n        var4.set(Calendar.MILLISECOND, 999);\n        var4.roll(Calendar.DATE, -1);\n        Date var5 = var4.getTime();\n        long var6 = var5.getTime();\n        TimeInfo var8 = new TimeInfo();\n        var8.setStartTime(var2);\n        var8.setEndTime(var6);\n        return var8;\n    }\n    public static String getStringTime(long time){\n        Date date = new Date(time);\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        String startTime = sdf.format(date);\n        return startTime;\n    }\n    public static String getTimestampStr() {\n        return Long.toString(System.currentTimeMillis());\n    }\n\n\n    public static class TimeInfo {\n        private long startTime;\n        private long endTime;\n\n        public TimeInfo() {\n        }\n\n        public long getStartTime() {\n            return this.startTime;\n        }\n\n        public void setStartTime(long var1) {\n            this.startTime = var1;\n        }\n\n        public long getEndTime() {\n            return this.endTime;\n        }\n\n        public void setEndTime(long var1) {\n            this.endTime = var1;\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/HTMessageUtils.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport android.app.Activity;\nimport android.app.ProgressDialog;\nimport android.content.ClipboardManager;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.widget.Toast;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.sdk.ChatType;\nimport com.htmessage.sdk.client.HTClient;\nimport com.htmessage.sdk.model.HTMessage;\nimport com.htmessage.sdk.model.HTMessageImageBody;\nimport com.htmessage.sdk.model.HTMessageTextBody;\nimport com.htmessage.sdk.model.HTMessageVoiceBody;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.HTClientHelper;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.activity.chat.activity.ChooseContactActivity;\nimport com.htmessage.yichatopen.HTConstant;\n\nimport java.io.File;\n\n/**\n * Created by huangfangyi on 2017/7/8.\n * qq 84543217\n */\n\npublic class HTMessageUtils {\n\n    public static HTMessage creatWithDrowMsg(HTMessage htMessage) {\n        String text = null;\n        JSONObject jsonObject = htMessage.getAttributes();\n        String userId = jsonObject.getString(HTConstant.JSON_KEY_HXID);\n        String nick = jsonObject.getString(HTConstant.JSON_KEY_NICK);\n        if (HTApp.getInstance().getUsername().equals(userId)) {\n            text = HTApp.getContext().getString(R.string.revoke_content);\n        } else {\n            text = String.format(HTApp.getContext().getString(R.string.revoke_content_someone), nick);\n        }\n        jsonObject.put(\"action\", 6001);\n        HTMessage message1 = HTMessage.createTextSendMessage(htMessage.getUsername(), text);\n        message1.setMsgId(htMessage.getMsgId());\n        message1.setChatType(htMessage.getChatType());\n        message1.setDirect(htMessage.getDirect());\n        message1.setAttributes(jsonObject.toJSONString());\n        message1.setTime(htMessage.getTime());\n        message1.setLocalTime(htMessage.getLocalTime());\n        message1.setFrom(htMessage.getFrom());\n        message1.setTo(htMessage.getTo());\n        message1.setStatus(htMessage.getStatus());\n        message1.setExt(htMessage.getExt());\n        HTClient.getInstance().messageManager().updateMessageInDB(message1);\n        return message1;\n    }\n\n\n    /**\n     * 获取copy的信息\n     *\n     * @param context\n     * @param message\n     */\n    public static void getCopyMsg(Activity context, HTMessage message, String toChatUserName) {\n        String copyType = \"\";\n        String fileName = \"\";\n        String localUrl = \"\";\n        String remotePath = \"\";\n        HTMessage.Type type = message.getType();\n        if (type == HTMessage.Type.IMAGE) {\n            copyType = \"image\";\n            HTMessageImageBody body = (HTMessageImageBody) message.getBody();\n            fileName = body.getFileName();\n            remotePath = body.getRemotePath();\n            localUrl = body.getLocalPath();\n        } else if (type == HTMessage.Type.VOICE) {\n            HTMessageVoiceBody body = (HTMessageVoiceBody) message.getBody();\n            copyType = \"voice\";\n            remotePath = body.getRemotePath();\n            fileName = body.getFileName();\n            localUrl = body.getLocalPath();\n        } else if (type == HTMessage.Type.TEXT) {\n            copyType = \"text\";\n            localUrl = ((HTMessageTextBody) message.getBody()).getContent();\n        }\n        String msgId = message.getMsgId();\n        if (!TextUtils.isEmpty(localUrl)) {\n            switch (copyType) {\n                case \"text\":\n                    showCopySendDialog(context, copyType, localUrl, message, null);\n                    break;\n                default:\n                    getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUserName, null);\n                    break;\n            }\n        } else {\n            switch (copyType) {\n                case \"text\":\n                    showCopySendDialog(context, copyType, localUrl, message, null);\n                    break;\n                default:\n                    getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUserName, null);\n                    break;\n            }\n        }\n    }\n\n    /**\n     * 下载copy文件并复制\n     *\n     * @param context\n     * @param copyType\n     * @param message\n     * @param msgId\n     * @param fileName\n     * @param remotePath\n     */\n    public static void getFilePath(final Activity context, final String copyType, final HTMessage message, String msgId, final String fileName, final String remotePath) {\n        String fileType = fileName.substring(fileName.lastIndexOf(\".\"));\n        if (!TextUtils.isEmpty(msgId) && !TextUtils.isEmpty(fileType) && !TextUtils.isEmpty(remotePath)) {\n//            final File file = new File(HTApp.getInstance().getDirFilePath() + msgId + fileType);\n            final File file = new File(HTApp.getInstance().getDirFilePath() + fileName);\n            if (file.exists()) {\n                switch (copyType) {\n                    case \"image\":\n                        showCopySendDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath());\n                        break;\n                    case \"voice\":\n                        showCopySendDialog(context, copyType, file.getAbsolutePath(), message, null);\n                        break;\n                }\n                return;\n            }\n            final ProgressDialog dialog = new ProgressDialog(context);\n            dialog.setMessage(context.getString(R.string.copying));\n            dialog.setCanceledOnTouchOutside(false);\n            dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);\n            final String path = HTApp.getInstance().getDirFilePath() + fileName;\n            dialog.show();\n            new OkHttpUtils(context).loadFile(remotePath, path, new OkHttpUtils.DownloadCallBack() {\n                @Override\n                public void onSuccess() {\n                    if (dialog != null && dialog.isShowing()) {\n                        dialog.dismiss();\n                    }\n                    File file1 = new File(path);\n                    switch (copyType) {\n                        case \"image\":\n                            showCopySendDialog(context, copyType, file1.getAbsolutePath(), message, file1.getAbsolutePath());\n                            break;\n                        case \"voice\":\n                            showCopySendDialog(context, copyType, file1.getAbsolutePath(), message, null);\n                            break;\n                    }\n                    ((Activity) context).runOnUiThread(new Runnable() {\n                        @Override\n                        public void run() {\n                            Toast.makeText(context, R.string.copy_success, Toast.LENGTH_SHORT).show();\n                        }\n                    });\n                }\n\n                @Override\n                public void onFailure(String message) {\n                    if (dialog != null && dialog.isShowing()) {\n                        dialog.dismiss();\n                    }\n                    ((Activity) context).runOnUiThread(new Runnable() {\n                        @Override\n                        public void run() {\n                            Toast.makeText(context, R.string.copy_failed, Toast.LENGTH_SHORT).show();\n                        }\n                    });\n                }\n            });\n        }\n    }\n\n    /**\n     * 复制并转发\n     *\n     * @param copyType\n     * @param localPath\n     * @param message1\n     */\n    public static void showCopySendDialog(Activity context, final String copyType, String localPath, final HTMessage message1, String imagePath) {\n        if (message1.getType() == HTMessage.Type.TEXT) {\n            ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);\n            // 将文本内容放到系统剪贴板里。\n            cm.setText(localPath);\n            ACache.get(context.getApplicationContext()).remove(\"myCopy\");\n        } else {\n            JSONObject jsonObject = new JSONObject();\n            jsonObject.put(\"copyType\", copyType);\n            jsonObject.put(\"localPath\", localPath);\n            jsonObject.put(\"msgId\", message1.getMsgId());\n            jsonObject.put(\"imagePath\", imagePath);\n            ACache.get(context.getApplicationContext()).put(\"myCopy\", jsonObject.toJSONString());\n        }\n    }\n\n    /**\n     * 获取copy的信息\n     *\n     * @param context\n     * @param message\n     */\n    public static void getForWordMessage(Activity context, HTMessage message, final String toChatUsername, final JSONObject userJson) {\n        String copyType = \"\";\n        String fileName = \"\";\n        String localUrl = \"\";\n        String remotePath = \"\";\n        HTMessage.Type type = message.getType();\n        if (type == HTMessage.Type.IMAGE) {\n            copyType = \"image\";\n            HTMessageImageBody body = (HTMessageImageBody) message.getBody();\n            fileName = body.getFileName();\n            remotePath = body.getRemotePath();\n            localUrl = body.getLocalPath();\n        } else if (type == HTMessage.Type.VOICE) {\n            HTMessageVoiceBody body = (HTMessageVoiceBody) message.getBody();\n            copyType = \"voice\";\n            remotePath = body.getRemotePath();\n            fileName = body.getFileName();\n            localUrl = body.getLocalPath();\n        } else if (type == HTMessage.Type.TEXT) {\n            copyType = \"text\";\n            localUrl = ((HTMessageTextBody) message.getBody()).getContent();\n        }\n        String msgId = message.getMsgId();\n        if (!TextUtils.isEmpty(localUrl)) {\n            switch (copyType) {\n                case \"text\":\n                    showForwordDialog(context, copyType, localUrl, message, null, toChatUsername, userJson);\n                    break;\n                default:\n                    getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUsername, userJson);\n                    break;\n            }\n        } else {\n            switch (copyType) {\n                case \"text\":\n                    showForwordDialog(context, copyType, localUrl, message, null, toChatUsername, userJson);\n                    break;\n                default:\n                    getFilePath(context, copyType, message, msgId, fileName, remotePath, toChatUsername, userJson);\n                    break;\n            }\n        }\n    }\n\n    /**\n     * 下载copy文件并复制\n     *\n     * @param context\n     * @param copyType\n     * @param message\n     * @param msgId\n     * @param fileName\n     * @param remotePath\n     */\n    public static void getFilePath(final Activity context, final String copyType, final HTMessage message, String msgId, final String fileName, final String remotePath, final String toChatUsername, final JSONObject userJson) {\n        String fileType = fileName.substring(fileName.lastIndexOf(\".\"));\n        String filePath = null;\n        if (!TextUtils.isEmpty(msgId) && !TextUtils.isEmpty(fileType) && !TextUtils.isEmpty(remotePath)) {\n            PathUtils pathUtils = new PathUtils(toChatUsername, context);\n            if (message.getType() == HTMessage.Type.VOICE) {\n                filePath = pathUtils.getVoicePath().getAbsolutePath() + \"/\" + fileName;\n            } else if (message.getType() == HTMessage.Type.IMAGE) {\n                filePath = pathUtils.getImagePath().getAbsolutePath() + \"/\" + fileName;\n            }\n            File file = new File(filePath);\n            if (file.exists()) {\n                switch (copyType) {\n                    case \"image\":\n                        if (userJson != null) {\n                            showForwordDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath(), toChatUsername, userJson);\n                        } else {\n                            showCopySendDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath());\n                        }\n                        break;\n                    case \"voice\":\n                        if (userJson != null) {\n                            showForwordDialog(context, copyType, file.getAbsolutePath(), message, null, toChatUsername, userJson);\n                        } else {\n                            showCopySendDialog(context, copyType, file.getAbsolutePath(), message, null);\n                        }\n                        break;\n                }\n                return;\n            }\n\n            loadMessageFile(message, toChatUsername, context, new CallBack() {\n                @Override\n                public void error() {\n                    if (userJson == null) {\n                        Toast.makeText(context, R.string.copy_failed, Toast.LENGTH_SHORT).show();\n                    }\n                }\n\n                @Override\n                public void completed(String localPath) {\n                    switch (copyType) {\n                        case \"image\":\n                            if (userJson != null) {\n                                showForwordDialog(context, copyType, localPath, message, localPath, toChatUsername, userJson);\n                            } else {\n                                showCopySendDialog(context, copyType,localPath, message, localPath);\n                            }\n                            break;\n                        case \"voice\":\n                            if (userJson != null) {\n                                showForwordDialog(context, copyType, localPath, message, null, toChatUsername, userJson);\n                            } else {\n                                Log.d(\"slj\",\"===复制:\"+userJson);\n                                showCopySendDialog(context, copyType, localPath, message, null);\n                            }\n                            break;\n                    }\n                    if (userJson == null) {\n                        Toast.makeText(context, R.string.copy_success, Toast.LENGTH_SHORT).show();\n                    }\n                }\n            });\n        }\n//        if (!TextUtils.isEmpty(msgId) && !TextUtils.isEmpty(fileType) && !TextUtils.isEmpty(remotePath)) {\n//            final File file = new File(HTApp.getInstance().getDirFilePath() + fileName);\n//            if (file.exists()) {\n//                switch (copyType) {\n//                    case \"image\":\n//                        showForwordDialog(context, copyType, file.getAbsolutePath(), message, file.getAbsolutePath(),toChatUsername,userJson);\n//                        break;\n//                    case \"voice\":\n//                        showForwordDialog(context, copyType, file.getAbsolutePath(), message, null,toChatUsername,userJson);\n//                        break;\n//                }\n//                return;\n//            }\n//            final ProgressDialog dialog = new ProgressDialog(context);\n//            dialog.setMessage(context.getString(R.string.forword_get));\n//            dialog.setCanceledOnTouchOutside(false);\n//            dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);\n////            final String path = HTApp.getInstance().getDirFilePath() + msgId + fileType;\n//            final String path = HTApp.getInstance().getDirFilePath() + fileName;\n//            dialog.show();\n//            new OkHttpUtils(context).loadFile(remotePath, path, new OkHttpUtils.DownloadCallBack() {\n//                @Override\n//                public void onSuccess() {\n//                    if (dialog != null && dialog.isShowing()) {\n//                        dialog.dismiss();\n//                    }\n//                    File file1 = new File(path);\n//                    switch (copyType) {\n//                        case \"image\":\n//                            showForwordDialog(context, copyType, file1.getAbsolutePath(), message, file1.getAbsolutePath(),toChatUsername,userJson);\n//                            break;\n//                        case \"voice\":\n//                            showForwordDialog(context, copyType, file1.getAbsolutePath(), message, null,toChatUsername,userJson);\n//                            break;\n//                    }\n//                 }\n//\n//                @Override\n//                public void onFailure(String message) {\n//                    if (dialog != null && dialog.isShowing()) {\n//                        dialog.dismiss();\n//                    }\n//                }\n//            });\n//        }\n    }\n\n\n    /**\n     * 转发\n     *\n     * @param forwordType\n     * @param localPath\n     * @param message1\n     * @param imagePath\n     * @param toChatUsername\n     * @param extJSON\n     */\n    private static void showForwordDialog(Activity context, final String forwordType, final String localPath, final HTMessage message1, String imagePath, String toChatUsername, JSONObject extJSON) {\n        JSONObject jsonObject = new JSONObject();\n        jsonObject.put(\"forwordType\", forwordType);\n        jsonObject.put(\"localPath\", localPath);\n        jsonObject.put(\"msgId\", message1.getMsgId());\n        jsonObject.put(\"imagePath\", imagePath);\n        jsonObject.put(\"toChatUsername\", toChatUsername);\n        jsonObject.put(\"exobj\", extJSON.toJSONString());\n        Intent intent = new Intent(context, ChooseContactActivity.class);\n        intent.putExtra(\"obj\", jsonObject.toJSONString());\n        context.startActivity(intent);\n    }\n\n\n    public static void loadMessageFile(HTMessage htMessage, String chatTo, final Activity context, final CallBack callBack) {\n\n        final ProgressDialog progressDialog = new ProgressDialog(context);\n        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);\n        progressDialog.setCanceledOnTouchOutside(false);\n        progressDialog.setMessage(context.getString(R.string.loading));\n        progressDialog.show();\n        PathUtils pathUtils = new PathUtils(chatTo, context);\n        String remotePath = \"\";\n\n        String fileName = \"\";\n        String filePath = null;\n        if (htMessage.getType() == HTMessage.Type.VOICE) {\n            HTMessageVoiceBody htMessageVoiceBody = (HTMessageVoiceBody) htMessage.getBody();\n            remotePath = htMessageVoiceBody.getRemotePath();\n            fileName = htMessageVoiceBody.getFileName();\n            filePath = pathUtils.getVoicePath().getAbsolutePath() + \"/\" + fileName;\n        } else if (htMessage.getType() == HTMessage.Type.IMAGE) {\n            HTMessageImageBody htMessageImageBody = (HTMessageImageBody) htMessage.getBody();\n            remotePath = htMessageImageBody.getRemotePath();\n            fileName = htMessageImageBody.getFileName();\n            filePath = pathUtils.getImagePath().getAbsolutePath() + \"/\" + fileName;\n        }\n        final String finalFilePath = filePath;\n        new OkHttpUtils(context).loadFile(remotePath, filePath, new OkHttpUtils.DownloadCallBack() {\n            @Override\n            public void onSuccess() {\n                context.runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        progressDialog.dismiss();\n                        callBack.completed(finalFilePath);\n                    }\n                });\n            }\n\n            @Override\n            public void onFailure(String message) {\n                context.runOnUiThread(new Runnable() {\n                    @Override\n                    public void run() {\n                        callBack.error();\n                        progressDialog.dismiss();\n                    }\n                });\n            }\n        });\n    }\n\n\n    public interface CallBack {\n        void error();\n\n        void completed(String localPath);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/ImageUtils.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.graphics.Canvas;\nimport android.graphics.Matrix;\nimport android.graphics.Paint;\nimport android.graphics.PorterDuff;\nimport android.graphics.PorterDuffXfermode;\nimport android.graphics.Rect;\nimport android.graphics.RectF;\nimport android.media.ExifInterface;\nimport android.media.ThumbnailUtils;\n\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\n\n/**\n * Created by huangfangyi on 2016/12/4.\n * qq 84543217\n */\n\npublic class ImageUtils {\n\n    public ImageUtils() {\n    }\n    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {\n        return getRoundedCornerBitmap(bitmap, 6);\n    }\n\n    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {\n        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),\n                bitmap.getHeight(), Bitmap.Config.ARGB_8888);\n        Canvas canvas = new Canvas(output);\n        final int color = 0xff424242;\n        final Paint paint = new Paint();\n        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());\n        final RectF rectF = new RectF(rect);\n        paint.setAntiAlias(true);\n        canvas.drawARGB(0, 0, 0, 0);\n        paint.setColor(color);\n        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);\n        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));\n        canvas.drawBitmap(bitmap, rect, rect, paint);\n        return output;\n    }\n\n    public static Bitmap getVideoThumbnail(String videoPath, int width, int height,\n                                           int kind) {\n        Bitmap bitmap = null;\n        // 获取视频的缩略图\n        bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, kind);\n        System.out.println(\"w\" + bitmap.getWidth());\n        System.out.println(\"h\" + bitmap.getHeight());\n        bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,\n                ThumbnailUtils.OPTIONS_RECYCLE_INPUT);\n        return bitmap;\n    }\n\n    public static Bitmap decodeScaleImage(String var0) {\n        BitmapFactory.Options var3 = getBitmapOptions(var0);\n        int var4 = calculateInSampleSize(var3, 420, 420);\n        var3.inSampleSize = var4;\n        var3.inJustDecodeBounds = false;\n        Bitmap var5 = BitmapFactory.decodeFile(var0, var3);\n        int var6 = readPictureDegree(var0);\n        Bitmap var7 = null;\n        if (var5 != null && var6 != 0) {\n            var7 = rotaingImageView(var6, var5);\n            var5.recycle();\n            var5 = null;\n            return var7;\n        } else {\n            return var5;\n        }\n    }\n\n\n    public static String getScaledImage(Context var0, String var1) {\n        File var2 = new File(var1);\n        if (!var2.exists()) {\n            return var1;\n        } else {\n            long var3 = var2.length();\n            if (var3 <= 102400L) {\n                return var1;\n            } else {\n                Bitmap var5 = decodeScaleImage(var1);\n\n                try {\n                    File var6 = File.createTempFile(\"image\", \".jpg\", var0.getFilesDir());\n                    FileOutputStream var7 = new FileOutputStream(var6);\n                    var5.compress(Bitmap.CompressFormat.JPEG, 70, var7);\n                    var7.close();\n                    return var6.getAbsolutePath();\n                } catch (Exception var8) {\n                    var8.printStackTrace();\n                    return var1;\n                }\n            }\n        }\n    }\n\n    public static String getScaledImage(Context var0, String var1, int var2) {\n        File var3 = new File(var1);\n        if (var3.exists()) {\n            long var4 = var3.length();\n            if (var4 > 102400L) {\n                Bitmap var6 = decodeScaleImage(var1);\n\n                try {\n                    File var7 = new File(var0.getExternalCacheDir(), \"eaemobTemp\" + var2 + \".jpg\");\n                    FileOutputStream var8 = new FileOutputStream(var7);\n                    var6.compress(Bitmap.CompressFormat.JPEG, 60, var8);\n                    var8.close();\n                    return var7.getAbsolutePath();\n                } catch (Exception var9) {\n                    var9.printStackTrace();\n                }\n            }\n        }\n\n        return var1;\n    }\n\n\n    public static Bitmap rotaingImageView(int var0, Bitmap var1) {\n        Matrix var2 = new Matrix();\n        var2.postRotate((float) var0);\n        Bitmap var3 = Bitmap.createBitmap(var1, 0, 0, var1.getWidth(), var1.getHeight(), var2, true);\n        return var3;\n    }\n\n\n    /* 获取缩略图\n     *\n             * @param path\n     * @param targetWidth\n     * @return\n             */\n    public static String getThumbnailImage(String path, int targetWidth, int targetHight) {\n        Bitmap scaleImage = decodeScaleImage(path);\n        try {\n            File file = File.createTempFile(\"image\", \".jpg\");\n            FileOutputStream fileOutputStream = new FileOutputStream(file);\n            scaleImage.compress(Bitmap.CompressFormat.JPEG, 60, fileOutputStream);\n            fileOutputStream.close();\n            return file.getAbsolutePath();\n        } catch (Exception e) {\n            e.printStackTrace();\n            return path;\n        }\n    }\n\n    /**\n     * 图片解析\n     *\n     * @param context\n     * @param resId\n     * @param targetWidth\n     * @param targetHeight\n     * @return\n     */\n    public static Bitmap decodeScaleImage(Context context, int resId, int targetWidth, int targetHeight) {\n        BitmapFactory.Options options = new BitmapFactory.Options();\n        options.inJustDecodeBounds = true;\n        BitmapFactory.decodeResource(context.getResources(), resId, options);\n        options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight);\n        options.inJustDecodeBounds = false;\n        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId, options);\n        return bitmap;\n    }\n\n    /**\n     * 计算样本大小\n     *\n     * @param options\n     * @param targetWidth\n     * @param targetHeight\n     * @return\n     */\n    public static int calculateInSampleSize(BitmapFactory.Options options, int targetWidth, int targetHeight) {\n        int height = options.outHeight;\n        int width = options.outWidth;\n        int scale = 1;\n        if (height > targetHeight || width > targetWidth) {\n            int heightScale = Math.round((float) height / (float) targetHeight);\n            int widthScale = Math.round((float) width / (float) targetWidth);\n            scale = heightScale > widthScale ? heightScale : widthScale;\n        }\n        return scale;\n    }\n\n\n    /**\n     * 获取BitmapFactory.Options\n     *\n     * @param pathName\n     * @return\n     */\n    public static BitmapFactory.Options getBitmapOptions(String pathName) {\n        BitmapFactory.Options opts = new BitmapFactory.Options();\n        opts.inJustDecodeBounds = true;\n        BitmapFactory.decodeFile(pathName, opts);\n        return opts;\n    }\n\n    /**\n     * 获取图片角度\n     *\n     * @param filename\n     * @return\n     */\n    public static int readPictureDegree(String filename) {\n        short degree = 0;\n        try {\n            ExifInterface exifInterface = new ExifInterface(filename);\n            int anInt = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);\n            switch (anInt) {\n                case ExifInterface.ORIENTATION_ROTATE_180:\n                    degree = 180;\n                case ExifInterface.ORIENTATION_FLIP_VERTICAL:\n                case ExifInterface.ORIENTATION_TRANSPOSE:\n                case ExifInterface.ORIENTATION_TRANSVERSE:\n                default:\n                    break;\n                case ExifInterface.ORIENTATION_ROTATE_90:\n                    degree = 90;\n                    break;\n                case ExifInterface.ORIENTATION_ROTATE_270:\n                    degree = 270;\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n\n        return degree;\n    }\n\n    /**\n     * 旋转ImageView\n     *\n     * @param degree\n     * @param source\n     * @return\n     */\n    public static Bitmap rotatingImageView(int degree, Bitmap source) {\n        Matrix matrix = new Matrix();\n        matrix.postRotate((float) degree);\n        return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);\n    }\n\n    /**\n     * 设置水印图片在左上角\n     *\n     * @param src\n     * @param watermark\n     * @param paddingLeft\n     * @param paddingTop\n     * @return\n     */\n    public static Bitmap createWaterMaskLeftTop(Context context, Bitmap src, Bitmap watermark, int paddingLeft, int paddingTop) {\n        return createWaterMaskBitmap(src, watermark, dp2px(context, paddingLeft), dp2px(context, paddingTop));\n    }\n\n    /**\n     * 创建水印图片\n     * @param src\n     * @param watermark\n     * @param paddingLeft\n     * @param paddingTop\n     * @return\n     */\n    private static Bitmap createWaterMaskBitmap(Bitmap src, Bitmap watermark, int paddingLeft, int paddingTop) {\n        if (src == null) {\n            return null;\n        }\n        int width = src.getWidth();\n        int height = src.getHeight();\n        //创建一个bitmap\n        Bitmap newb = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图\n        //将该图片作为画布\n        Canvas canvas = new Canvas(newb);\n        //在画布 0，0坐标上开始绘制原始图片\n        canvas.drawBitmap(src, 0, 0, null);\n        //在画布上绘制水印图片\n        canvas.drawBitmap(watermark, paddingLeft, paddingTop, null);\n        // 保存\n        canvas.save(Canvas.ALL_SAVE_FLAG);\n        // 存储\n        canvas.restore();\n        return newb;\n    }\n\n    /**\n     * 设置水印图片在右下角\n     *\n     * @param src\n     * @param watermark\n     * @param paddingRight\n     * @param paddingBottom\n     * @return\n     */\n    public static Bitmap createWaterMaskRightBottom(Context context, Bitmap src, Bitmap watermark, int paddingRight, int paddingBottom) {\n        return createWaterMaskBitmap(src, watermark, src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight),\n                src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom));\n    }\n\n    /**\n     * 设置水印图片到右上角\n     *\n     * @param src\n     * @param watermark\n     * @param paddingRight\n     * @param paddingTop\n     * @return\n     */\n    public static Bitmap createWaterMaskRightTop(Context context, Bitmap src, Bitmap watermark, int paddingRight, int paddingTop) {\n        return createWaterMaskBitmap(src, watermark, src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight), dp2px(context, paddingTop));\n    }\n\n    /**\n     * 设置水印图片到左下角\n     *\n     * @param src\n     * @param watermark\n     * @param paddingLeft\n     * @param paddingBottom\n     * @return\n     */\n    public static Bitmap createWaterMaskLeftBottom(Context context, Bitmap src, Bitmap watermark, int paddingLeft, int paddingBottom) {\n        return createWaterMaskBitmap(src, watermark, dp2px(context, paddingLeft), src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom));\n    }\n\n    /**\n     * 设置水印图片到中间\n     *\n     * @param src\n     * @param watermark\n     * @return\n     */\n    public static Bitmap createWaterMaskCenter(Bitmap src, Bitmap watermark) {\n        return createWaterMaskBitmap(src, watermark, (src.getWidth() - watermark.getWidth()) / 2, (src.getHeight() - watermark.getHeight()) / 2);\n    }\n\n    /**\n     * 给图片添加文字到左上角\n     *\n     * @param context\n     * @param bitmap\n     * @param text\n     * @return\n     */\n    public static Bitmap drawTextToLeftTop(Context context, Bitmap bitmap, String text, int size, int color, int paddingLeft, int paddingTop) {\n        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        paint.setColor(color);\n        paint.setTextSize(dp2px(context, size));\n        Rect bounds = new Rect();\n        paint.getTextBounds(text, 0, text.length(), bounds);\n        return drawTextToBitmap(context, bitmap, text, paint, bounds, dp2px(context, paddingLeft), dp2px(context, paddingTop) + bounds.height());\n    }\n\n    /**\n     * 绘制文字到右下角\n     *\n     * @param context\n     * @param bitmap\n     * @param text\n     * @param size\n     * @param color\n     * @param paddingRight\n     * @param paddingBottom\n     * @return\n     */\n    public static Bitmap drawTextToRightBottom(Context context, Bitmap bitmap, String text, int size, int color, int paddingRight, int paddingBottom) {\n        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        paint.setColor(color);\n        paint.setTextSize(dp2px(context, size));\n        Rect bounds = new Rect();\n        paint.getTextBounds(text, 0, text.length(), bounds);\n        return drawTextToBitmap(context, bitmap, text, paint, bounds, bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight), bitmap.getHeight() - dp2px(context, paddingBottom));\n    }\n\n    /**\n     * 绘制文字到右上方\n     *\n     * @param context\n     * @param bitmap\n     * @param text\n     * @param size\n     * @param color\n     * @param paddingRight\n     * @param paddingTop\n     * @return\n     */\n    public static Bitmap drawTextToRightTop(Context context, Bitmap bitmap, String text, int size, int color, int paddingRight, int paddingTop) {\n        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        paint.setColor(color);\n        paint.setTextSize(dp2px(context, size));\n        Rect bounds = new Rect();\n        paint.getTextBounds(text, 0, text.length(), bounds);\n        return drawTextToBitmap(context, bitmap, text, paint, bounds, bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight), dp2px(context, paddingTop) + bounds.height());\n    }\n\n    /**\n     * 绘制文字到左下方\n     *\n     * @param context\n     * @param bitmap\n     * @param text\n     * @param size\n     * @param color\n     * @param paddingLeft\n     * @param paddingBottom\n     * @return\n     */\n    public static Bitmap drawTextToLeftBottom(Context context, Bitmap bitmap, String text,\n                                              int size, int color, int paddingLeft, int paddingBottom) {\n        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        paint.setColor(color);\n        paint.setTextSize(dp2px(context, size));\n        Rect bounds = new Rect();\n        paint.getTextBounds(text, 0, text.length(), bounds);\n        return drawTextToBitmap(context, bitmap, text, paint, bounds, dp2px(context, paddingLeft), bitmap.getHeight() - dp2px(context, paddingBottom));\n    }\n\n    /**\n     * 绘制文字到中间\n     *\n     * @param context\n     * @param bitmap\n     * @param text\n     * @param size\n     * @param color\n     * @return\n     */\n    public static Bitmap drawTextToCenter(Context context, Bitmap bitmap, String text,\n                                          int size, int color) {\n        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        paint.setColor(color);\n        paint.setTextSize(dp2px(context, size));\n        Rect bounds = new Rect();\n        paint.getTextBounds(text, 0, text.length(), bounds);\n        return drawTextToBitmap(context, bitmap, text, paint, bounds, (bitmap.getWidth() - bounds.width()) / 2, (bitmap.getHeight() + bounds.height()) / 2);\n    }\n\n\n    /**\n     *  图片上绘制文字\n     * @param context\n     * @param bitmap\n     * @param text\n     * @param paint\n     * @param bounds\n     * @param paddingLeft\n     * @param paddingTop\n     * @return\n     */\n    private static Bitmap drawTextToBitmap(Context context, Bitmap bitmap, String text, Paint paint, Rect bounds, int paddingLeft, int paddingTop) {\n        android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();\n\n        paint.setDither(true); // 获取跟清晰的图像采样\n        paint.setFilterBitmap(true);// 过滤一些\n        if (bitmapConfig == null) {\n            bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;\n        }\n        bitmap = bitmap.copy(bitmapConfig, true);\n        Canvas canvas = new Canvas(bitmap);\n\n        canvas.drawText(text, paddingLeft, paddingTop, paint);\n        return bitmap;\n    }\n\n    /**\n     * 缩放图片\n     *\n     * @param src\n     * @param w\n     * @param h\n     * @return\n     */\n    public static Bitmap scaleWithWH(Bitmap src, double w, double h) {\n        if (w == 0 || h == 0 || src == null) {\n            return src;\n        } else {\n            // 记录src的宽高\n            int width = src.getWidth();\n            int height = src.getHeight();\n            // 创建一个matrix容器\n            Matrix matrix = new Matrix();\n            // 计算缩放比例\n            float scaleWidth = (float) (w / width);\n            float scaleHeight = (float) (h / height);\n            // 开始缩放\n            matrix.postScale(scaleWidth, scaleHeight);\n            // 创建缩放后的图片\n            return Bitmap.createBitmap(src, 0, 0, width, height, matrix, true);\n        }\n    }\n\n    /**\n     * dip转pix\n     *\n     * @param context\n     * @param dp\n     * @return\n     */\n    public static int dp2px(Context context, float dp) {\n        final float scale = context.getResources().getDisplayMetrics().density;\n        return (int) (dp * scale + 0.5f);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/OkHttpUtils.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport android.content.Context;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.util.Log;\nimport android.widget.Toast;\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.yichatopen.R;\nimport com.htmessage.yichatopen.HTConstant;\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.FileNameMap;\nimport java.net.URLConnection;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport okhttp3.Call;\nimport okhttp3.Callback;\nimport okhttp3.FormBody;\nimport okhttp3.Headers;\nimport okhttp3.MediaType;\nimport okhttp3.MultipartBody;\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport okhttp3.RequestBody;\nimport okhttp3.Response;\n\n/**\n * Created by huangfangyi on 2016/10/27.\n * qq 84543217\n */\n\npublic class OkHttpUtils {\n    private Context context;\n     private OkHttpClient okHttpClient;\n    private static final int RESULT_ERROR = 1000;\n    private static final int RESULT_SUCESS = 2000;\n    private HttpCallBack httpCallBack;\n\n    private Handler handler = new Handler() {\n        @Override\n        public void handleMessage(Message msg) {\n            super.handleMessage(msg);\n            int reusltCode = msg.what;\n            switch (reusltCode) {\n                case RESULT_ERROR:\n                    httpCallBack.onFailure((String) msg.obj);\n//                    Toast.makeText(context, \"服务器端无响应\", Toast.LENGTH_SHORT).show();\n                    Log.d(\"result----->\", (String) msg.obj);\n                    break;\n                case RESULT_SUCESS:\n                    String result = (String) msg.obj;\n                    Log.d(\"result----->\", result);\n                    try {\n                        JSONObject jsonObject = JSONObject.parseObject(result);\n                        httpCallBack.onResponse(jsonObject);\n                    } catch (JSONException e) {\n                        httpCallBack.onFailure((String) msg.obj);\n//                        Toast.makeText(context, \"响应数据解析错误\", Toast.LENGTH_SHORT).show();\n                    }\n\n                    break;\n            }\n\n        }\n    };\n\n    public OkHttpUtils(Context context) {\n        this.context = context;\n         okHttpClient = new OkHttpClient.Builder()\n                .connectTimeout(10000L, TimeUnit.MILLISECONDS)\n                .readTimeout(10000L, TimeUnit.MILLISECONDS)\n                .build();\n    }\n\n    \n \n\n    //纯粹键值对post请求\n    public   void post(List<Param> params, String url, HttpCallBack httpCallBack) {\n        Log.d(\"url----->>\", url);\n        this.httpCallBack = httpCallBack;\n        FormBody.Builder bodyBulder = new FormBody.Builder();\n        JSONObject userJson = HTApp.getInstance().getUserJson();\n        if (userJson!=null){\n            String session = userJson.getString(HTConstant.JSON_KEY_SESSION);\n            if (session!=null){\n                bodyBulder.add(\"session\",session);\n            }\n            Log.d(\"session----->>\", session);\n        }\n\n        for (Param param : params) {\n            bodyBulder.add(param.getKey(), param.getValue());\n            Log.d(\"param.getKey()----->>\", param.getKey());\n            Log.d(\"param.getValue()----->>\", param.getValue());\n        }\n        RequestBody requestBody = bodyBulder.build();\n        Request request = new Request.Builder()\n                .url(url)\n                .post(requestBody)\n                .build();\n\n        startRequest(request);\n\n    }\n\n    //键值对+文件 post请求\n    public void post(List<Param> params, List<File> files, String url, HttpCallBack httpCallBack) {\n        Log.d(\"url----->>\", url);\n        this.httpCallBack = httpCallBack;\n        MultipartBody.Builder builder = new MultipartBody.Builder();\n        builder.setType(MultipartBody.FORM);\n        for (Param param : params) {\n\n            builder.addPart(Headers.of(\"Content-Disposition\", \"form-data; name=\\\"\" + param.getKey() + \"\\\"\"), RequestBody.create(MediaType.parse(guessMimeType(param.getKey())), param.getValue()));\n            Log.d(\"param.getKey()----->>\", param.getKey());\n            Log.d(\"param.getValue()----->>\", param.getValue());\n        }\n        for (File file : files) {\n            if (file != null && file.exists()) {\n\n                //TODO-本项目固化文件的键名为“file”\n                builder.addPart(Headers.of(\"Content-Disposition\",\n                        \"form-data; name=\\\"\" + \"file\" + \"\\\"; filename=\\\"\" + file.getName()+ \"\\\"\"),\n                        RequestBody.create(MediaType.parse(guessMimeType(file.getName())), file));\n\n                Log.d(\"file.getName()----->>\", file.getName());\n            }\n\n        }\n        RequestBody requestBody = builder.build();\n        Request request = new Request.Builder()\n                .url(url)\n                .post(requestBody)\n                .build();\n\n        startRequest(request);\n\n    }\n\n\n    private void startRequest(Request request) {\n         if (CommonUtils.isNetWorkConnected(context)){\n            okHttpClient.newCall(request).enqueue(new Callback() {\n                @Override\n                public void onFailure(Call call, IOException e) {\n                    Message message = handler.obtainMessage();\n                    message.what = RESULT_ERROR;\n                    message.obj = e.getMessage().toString();\n                    message.sendToTarget();\n                }\n\n                @Override\n                public void onResponse(Call call, Response response) throws IOException {\n                    Message message = handler.obtainMessage();\n                    message.what = RESULT_SUCESS;\n                    message.obj = response.body().string();\n                    message.sendToTarget();\n                }\n            });\n        }else{\n            Toast.makeText(context, R.string.the_current_network, Toast.LENGTH_SHORT).show();\n        }\n    }\n\n    public interface HttpCallBack {\n\n        void onResponse(JSONObject jsonObject);\n\n        void onFailure(String errorMsg);\n    }\n    /**\n     * 下载不带进度\n     */\n    public interface DownloadCallBack {\n        void onSuccess();\n\n        void onFailure(String message);\n    }\n\n\n    private String guessMimeType(String path) {\n        FileNameMap fileNameMap = URLConnection.getFileNameMap();\n        String contentTypeFor = fileNameMap.getContentTypeFor(path);\n        if (contentTypeFor == null) {\n            contentTypeFor = \"application/octet-stream\";\n        }\n        return contentTypeFor;\n    }\n\n    public void loadFile(String url, final String savePath, final DownloadCallBack  callBack){\n        Request request = new Request.Builder()\n                //下载地址\n                .url(url)\n                .build();\n        okHttpClient.newCall(request).enqueue(new Callback() {\n            @Override\n            public void onFailure(Call call, IOException e) {\n                callBack.onFailure(e.getMessage());\n            }\n            @Override\n            public void onResponse(Call call, Response response) throws IOException {\n                int len;\n                byte[] buf = new byte[2048];\n                InputStream inputStream = response.body().byteStream();\n                //可以在这里自定义路径\n                File file1 = new File(savePath);\n                FileOutputStream fileOutputStream = new FileOutputStream(file1);\n                while ((len = inputStream.read(buf)) != -1) {\n                    fileOutputStream.write(buf, 0, len);\n                }\n                fileOutputStream.flush();\n                fileOutputStream.close();\n                inputStream.close();\n                callBack.onSuccess();\n            }\n        });\n    }\n    /**\n     * 下载的带进度的callback\n     */\n    public interface ProgressDownloadCallBack {\n        void onSuccess();\n\n        void onProgress(int progress);\n\n        void onFailure();\n    }\n    /**\n     * 下载文件带进度\n     *\n     * @param url      下载地址\n     * @param savePath 保存地址\n     * @param callBack ProgressDownloadCallBack\n     */\n    public void loadFileHasProgress(String url, final String savePath, final ProgressDownloadCallBack callBack) {\n        Request request = new Request.Builder()\n                //下载地址\n                .url(url)\n                .build();\n        okHttpClient.newCall(request).enqueue(new Callback() {\n            @Override\n            public void onFailure(Call call, IOException e) {\n                callBack.onFailure();\n            }\n\n            @Override\n            public void onResponse(Call call, Response response) throws IOException {\n                int len;\n                byte[] buf = new byte[2048];\n                InputStream inputStream = response.body().byteStream();\n                long requestLength = response.body().contentLength();\n                long total = 0;\n                //可以在这里自定义路径\n                File file1 = new File(savePath);\n                FileOutputStream fileOutputStream = new FileOutputStream(file1);\n                while ((len = inputStream.read(buf)) != -1) {\n                    total += len;\n                    // publishing the progress....\n                    if (requestLength > 0) // only if total length is known\n                        callBack.onProgress((int) (total * 100 / requestLength));\n                    fileOutputStream.write(buf, 0, len);\n                }\n                fileOutputStream.flush();\n                fileOutputStream.close();\n                inputStream.close();\n                callBack.onSuccess();\n            }\n        });\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/Param.java",
    "content": "package com.htmessage.yichatopen.utils;\n\n/**\n * Created by ustc on 2016/6/30.\n */\npublic class Param {\n\n\n    private String key;\n    private String value;\n\n    public Param(String key, String value) {\n        this.key = key;\n        this.value = value;\n\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/PathUtils.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport android.content.Context;\nimport android.os.Environment;\nimport android.util.Log;\n\nimport com.htmessage.yichatopen.HTApp;\nimport com.htmessage.sdk.model.HTMessage;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.InputStream;\n\n/**\n * Created by huangfangyi on 2016/12/4.\n * qq 84543217\n */\n\npublic class PathUtils {\n    private static PathUtils instance;\n    private static File storageDir = null;\n    private File voicePath = null;\n    private File imagePath = null;\n    private File videoPath = null;\n    private File filePath;\n\n   private static   String pathPrefix;\n\n    public PathUtils(String chatTo, Context context) {\n        String   username= HTApp.getInstance().getUsername();\n        String packageName = context.getPackageName();\n        pathPrefix = \"/Android/data/\" + packageName + \"/\";\n\n        this.voicePath = generateVoicePath(username,chatTo,context);\n        if(!this.voicePath.exists()) {\n            this.voicePath.mkdirs();\n        }\n        this.imagePath = generateImagePath(username, chatTo, context);\n        if(!this.imagePath.exists()) {\n            this.imagePath.mkdirs();\n        }\n\n        this.videoPath = generateVideoPath(username, chatTo, context);\n        if(!this.videoPath.exists()) {\n            this.videoPath.mkdirs();\n        }\n\n        this.filePath = generateFiePath(username, chatTo, context);\n        if(!this.filePath.exists()) {\n            this.filePath.mkdirs();\n        }\n\n    }\n\n    public File getImagePath() {\n        return this.imagePath;\n    }\n\n    public File getVoicePath() {\n        return this.voicePath;\n    }\n\n    public File getFilePath() {\n        return this.filePath;\n    }\n\n    public File getVideoPath() {\n        return this.videoPath;\n    }\n\n\n    private static File getStorageDir(Context context) {\n        if(storageDir == null) {\n            File file = Environment.getExternalStorageDirectory();\n            if(file.exists()) {\n                return file;\n            }\n            storageDir = context.getFilesDir();\n        }\n        return storageDir;\n    }\n\n\n    private static File generateImagePath(String username, String chatTo, Context context) {\n        String filePath = null;\n\n        if(username == null) {\n            filePath = pathPrefix + chatTo + \"/image/\";\n        } else {\n            filePath = pathPrefix + username + \"/\" + chatTo + \"/image/\";\n        }\n\n\n        return new File(getStorageDir(context), filePath);\n    }\n\n    private static File generateVoicePath(String username, String chatTo, Context context) {\n        String filePath = null;\n        if(username == null) {\n            filePath = pathPrefix + chatTo + \"/voice/\";\n        } else {\n            filePath = pathPrefix + username + \"/\" + chatTo + \"/voice/\";\n        }\n\n        return new File(getStorageDir(context), filePath);\n    }\n\n    private static File generateFiePath(String username, String chatTo, Context context) {\n        String filePath = null;\n        if(username == null) {\n            filePath = pathPrefix + chatTo + \"/file/\";\n        } else {\n            filePath = pathPrefix + username + \"/\" + chatTo + \"/file/\";\n        }\n\n        return new File(getStorageDir(context), filePath);\n    }\n\n    private static File generateVideoPath(String username, String chatTo, Context context) {\n        String filePath = null;\n        if(username == null) {\n            filePath = pathPrefix + chatTo + \"/video/\";\n        } else {\n            filePath = pathPrefix + username + \"/\" + chatTo + \"/video/\";\n        }\n\n        return new File(getStorageDir(context), filePath);\n    }\n\n\n    public void saveSendFileInDisk(final String filePath, final HTMessage.Type type, final NewFilePathCallBack newFilePathCallBack){\n        final String fileName=filePath.substring(filePath.lastIndexOf(\"/\")+1);\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                String finalPath=null;\n                if(type== HTMessage.Type.IMAGE){\n                      finalPath=getImagePath().getAbsolutePath()+fileName;\n\n                }else if(type== HTMessage.Type.VOICE){\n                      finalPath=getVoicePath().getAbsolutePath()+fileName;\n\n                }\n                else if(type== HTMessage.Type.VIDEO){\n                    finalPath=getVideoPath().getAbsolutePath()+fileName;\n\n                }\n                else if(type== HTMessage.Type.FILE){\n                    finalPath=getFilePath().getAbsolutePath()+fileName;\n\n                }\n                Log.d(\"filePath--->\",filePath);\n                Log.d(\"finalPath--->\",finalPath);\n                copyFile(filePath,finalPath,newFilePathCallBack);\n\n\n            }\n        }).start();\n\n\n    }\n\n    interface NewFilePathCallBack{\n\n        void  onSuccess(String filePath);\n    }\n\n    /**\n     * 复制单个文件\n     * @param oldPath String 原文件路径 如：c:/fqf.txt\n     * @param newPath String 复制后路径 如：f:/fqf.txt\n     * @return boolean\n     */\n    public void copyFile(String oldPath, String newPath,NewFilePathCallBack newFilePathCallBack) {\n        try {\n            int bytesum = 0;\n            int byteread = 0;\n            File oldfile = new File(oldPath);\n            if (oldfile.exists()) { //文件存在时\n                InputStream inStream = new FileInputStream(oldPath); //读入原文件\n                FileOutputStream fs = new FileOutputStream(newPath);\n                byte[] buffer = new byte[1444];\n                int length;\n                while ( (byteread = inStream.read(buffer)) != -1) {\n                    bytesum += byteread; //字节数 文件大小\n                    System.out.println(bytesum);\n                    fs.write(buffer, 0, byteread);\n                }\n                inStream.close();\n            }\n            newFilePathCallBack.onSuccess(newPath);\n\n        }\n        catch (Exception e) {\n            System.out.println(\"复制单个文件操作出错\");\n            e.printStackTrace();\n\n        }\n\n    }\n\n\n\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/UpdateLastLoginTimeUtils.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.htmessage.yichatopen.HTConstant;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 项目名称：yichat0504\n * 类描述：UpdateLocalLoginTimeUtils 描述:\n * 创建人：songlijie\n * 创建时间：2017/7/5 17:48\n * 邮箱:814326663@qq.com\n */\npublic class UpdateLastLoginTimeUtils {\n    private static String TAG = UpdateLastLoginTimeUtils.class.getSimpleName();\n    public static void sendLocalTimeToService(Context context){\n        List<Param> params = new ArrayList<>();\n        new OkHttpUtils(context).post(params, HTConstant.URL_SEND_LOCAL_LOGIN_TIME, new OkHttpUtils.HttpCallBack() {\n            @Override\n            public void onResponse(JSONObject jsonObject) {\n                int code = jsonObject.getIntValue(\"code\");\n                switch (code){\n                    case 1:\n                        Log.d(TAG,\"上传本地成功!\");\n                        break;\n                    default:\n                        Log.d(TAG,\"上传本地失败!\");\n                        break;\n                }\n            }\n\n            @Override\n            public void onFailure(String errorMsg) {\n                Log.d(TAG,\"上传本地失败!\"+errorMsg);\n            }\n        });\n\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/utils/Validator.java",
    "content": "package com.htmessage.yichatopen.utils;\n\nimport java.util.regex.Pattern;\n\n/**\n * 校验器：利用正则表达式校验邮箱、手机号等\n * \n * @author liujiduo\n * \n */\npublic class Validator {\n\t/**\n\t * 正则表达式：验证用户名\n\t */\n\tpublic static final String REGEX_USERNAME = \"^[a-zA-Z]\\\\w{5,17}$\";\n\n\t/**\n\t * 正则表达式：验证密码\n\t */\n\tpublic static final String REGEX_PASSWORD = \"^[a-zA-Z0-9]{6,16}$\";\n\n\t/**\n\t * 正则表达式：验证手机号  .matches(\"^[1][3578]\\\\d{9}\")\n\t */\n//\tpublic static final String REGEX_MOBILE = \"^((13[0-9])|(15[^4,\\\\D])|(18[0,5-9]))\\\\d{8}$\";//\n\tpublic static final String REGEX_MOBILE = \"^(13[0-9]|15[012356789]|17[03678]|18[0-9]|14[57])[0-9]{8}$\";\n\t/**\n\t * 正则表达式：验证邮箱\n\t */\n\tpublic static final String REGEX_EMAIL = \"^([a-z0-9A-Z]+[-|\\\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\\\.)+[a-zA-Z]{2,}$\";\n\n\t/**\n\t * 正则表达式：验证汉字\n\t */\n\tpublic static final String REGEX_CHINESE = \"^[\\u4e00-\\u9fa5],{0,}$\";\n\n\t/**\n\t * 正则表达式：验证身份证\n\t */\n\tpublic static final String REGEX_ID_CARD = \"(^\\\\d{18}$)|(^\\\\d{15}$)\";\n\n\t/**\n\t * 正则表达式：验证URL\n\t */\n\tpublic static final String REGEX_URL = \"http(s)?://([\\\\w-]+\\\\.)+[\\\\w-]+(/[\\\\w- ./?%&=]*)?\";\n\n\t/**\n\t * 正则表达式：验证IP地址\n\t */\n\tpublic static final String REGEX_IP_ADDR = \"(25[0-5]|2[0-4]\\\\d|[0-1]\\\\d{2}|[1-9]?\\\\d)\";\n\n\t/**\n\t * 校验用户名\n\t * \n\t * @param username\n\t * @return 校验通过返回true，否则返回false\n\t */\n\tpublic static boolean isUsername(String username) {\n\t\treturn Pattern.matches(REGEX_USERNAME, username);\n\t}\n\n\t/**\n\t * 校验密码\n\t * \n\t * @param password\n\t * @return 校验通过返回true，否则返回false\n\t */\n\tpublic static boolean isPassword(String password) {\n\t\treturn Pattern.matches(REGEX_PASSWORD, password);\n\t}\n\n\t/**\n\t * 校验手机号\n\t * \n\t * @param mobile\n\t * @return 校验通过返回true，否则返回false\n\t */\n\tpublic static boolean isMobile(String mobile) {\n\t\treturn Pattern.matches(REGEX_MOBILE, mobile);\n\t}\n\n\t/**\n\t * 校验邮箱\n\t * \n\t * @param email\n\t * @return 校验通过返回true，否则返回false\n\t */\n\tpublic static boolean isEmail(String email) {\n\t\treturn Pattern.matches(REGEX_EMAIL, email);\n\t}\n\n\t/**\n\t * 校验汉字\n\t * \n\t * @param chinese\n\t * @return 校验通过返回true，否则返回false\n\t */\n\tpublic static boolean isChinese(String chinese) {\n\t\treturn Pattern.matches(REGEX_CHINESE, chinese);\n\t}\n\n\t/**\n\t * 校验身份证\n\t * \n\t * @param idCard\n\t * @return 校验通过返回true，否则返回false\n\t */\n\tpublic static boolean isIDCard(String idCard) {\n\t\treturn Pattern.matches(REGEX_ID_CARD, idCard);\n\t}\n\n\t/**\n\t * 校验URL\n\t * \n\t * @param url\n\t * @return 校验通过返回true，否则返回false\n\t */\n\tpublic static boolean isUrl(String url) {\n\t\treturn Pattern.matches(REGEX_URL, url);\n\t}\n\n\t/**\n\t * 校验IP地址\n\t * \n\t * @param ipAddr\n\t * @return\n\t */\n\tpublic static boolean isIPAddr(String ipAddr) {\n\t\treturn Pattern.matches(REGEX_IP_ADDR, ipAddr);\n\t}\n\n\tpublic static void main(String[] args) {\n\t\tString username = \"fdsdfsdj\";\n\t\tSystem.out.println(Validator.isUsername(username));\n\t\tSystem.out.println(Validator.isChinese(username));\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/HTAlertDialog.java",
    "content": "package com.htmessage.yichatopen.widget;\n\nimport android.app.AlertDialog;\nimport android.content.Context;\nimport android.view.View;\nimport android.view.Window;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.htmessage.yichatopen.R;\n\n/**\n * Created by huangfangyi on 2016/7/3.\\\n * QQ:84543217\n */\npublic class HTAlertDialog {\n    private Context context;\n    private String title;\n    private String[] items;\n\n    public HTAlertDialog(Context context, String title, String[] items) {\n        this.context = context;\n        this.title = title;\n        this.items = items;\n    }\n    public void init(final OnItemClickListner onItemClickListner) {\n        final AlertDialog dlg = new AlertDialog.Builder(context).create();\n        dlg.show();\n        Window window = dlg.getWindow();\n        window.setContentView(R.layout.dialog_alert);\n        if (title != null) {\n            window.findViewById(R.id.ll_title).setVisibility(View.VISIBLE);\n            TextView tv_title = (TextView) window.findViewById(R.id.tv_title);\n            tv_title.setText(title);\n\n        }\n        //默认是2个item--最多支持5个，如需增加，请修改布局文件\n        LinearLayout[] linearLayouts=new LinearLayout[]{\n                (LinearLayout) window.findViewById(R.id.ll_content1),\n                (LinearLayout) window.findViewById(R.id.ll_content2),\n                (LinearLayout) window.findViewById(R.id.ll_content3),\n                (LinearLayout) window.findViewById(R.id.ll_content4),\n                (LinearLayout) window.findViewById(R.id.ll_content5)\n        };\n        TextView[] textViews=new TextView[]{\n                (TextView) window.findViewById(R.id.tv_content1),\n                (TextView) window.findViewById(R.id.tv_content2),\n                (TextView) window.findViewById(R.id.tv_content3),\n                (TextView) window.findViewById(R.id.tv_content4),\n                (TextView) window.findViewById(R.id.tv_content5),\n        };\n        for(int i=0;i<items.length;i++){\n            linearLayouts[i].setVisibility(View.VISIBLE);\n            textViews[i].setText(items[i]);\n            final int finalI = i;\n            linearLayouts[i].setOnClickListener(new View.OnClickListener() {\n                @Override\n                public void onClick(View v) {\n                    onItemClickListner.onClick(finalI);\n                    dlg.cancel();\n                }\n            });\n        }\n    }\n\n\n\n    public  interface  OnItemClickListner{\n        void onClick(int position);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/SwitchButton.java",
    "content": "package com.htmessage.yichatopen.widget;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.FrameLayout;\nimport android.widget.ImageView;\n\nimport com.htmessage.yichatopen.R;\n\n\npublic class SwitchButton extends FrameLayout{\n\n    private ImageView openImage;\n    private ImageView closeImage;\n\n    public SwitchButton(Context context, AttributeSet attrs, int defStyle) {\n        this(context, attrs);\n    }\n\n    public SwitchButton(Context context) {\n        this(context, null);\n    }\n    \n    public SwitchButton(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        \n        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SwitchButton);\n        Drawable openDrawable = ta.getDrawable(R.styleable.SwitchButton_switchOpenImage);\n        Drawable closeDrawable = ta.getDrawable(R.styleable.SwitchButton_switchCloseImage);\n        int switchStatus = ta.getInt(R.styleable.SwitchButton_switchStatus, 0);\n        ta.recycle();\n        \n        LayoutInflater.from(context).inflate(R.layout.widget_switch_button, this);\n        openImage = (ImageView) findViewById(R.id.iv_switch_open);\n        closeImage = (ImageView) findViewById(R.id.iv_switch_close);\n        if(openDrawable != null){\n            openImage.setImageDrawable(openDrawable);\n        }\n        if(closeDrawable != null){\n            closeImage.setImageDrawable(closeDrawable);\n        }\n        if(switchStatus == 1){\n            closeSwitch();\n        }\n        \n    }\n    \n    /**\n     * is switch open\n     */\n    public boolean isSwitchOpen(){\n        return openImage.getVisibility() == View.VISIBLE;\n    }\n\n    public void openSwitch(){\n    \topenImage.setVisibility(View.VISIBLE);\n    \tcloseImage.setVisibility(View.INVISIBLE);\n    }\n    \n    public void closeSwitch(){\n    \topenImage.setVisibility(View.INVISIBLE);\n    \tcloseImage.setVisibility(View.VISIBLE);\n    }\n    \n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/photoview/Compat.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.widget.photoview;\n\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.view.View;\n\nclass Compat {\n\t\n\tprivate static final int SIXTY_FPS_INTERVAL = 1000 / 60;\n\t\n\tpublic static void postOnAnimation(View view, Runnable runnable) {\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {\n\t\t\tSDK16.postOnAnimation(view, runnable);\n\t\t} else {\n\t\t\tview.postDelayed(runnable, SIXTY_FPS_INTERVAL);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/photoview/IPhotoView.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.htmessage.yichatopen.widget.photoview;\n\nimport android.graphics.RectF;\nimport android.view.View;\nimport android.widget.ImageView;\n\n\npublic interface IPhotoView {\n    /**\n     * Returns true if the PhotoView is set to allow zooming of Photos.\n     *\n     * @return true if the PhotoView allows zooming.\n     */\n    boolean canZoom();\n\n    /**\n     * Gets the Display Rectangle of the currently displayed Drawable. The\n     * Rectangle is relative to this View and includes all scaling and\n     * translations.\n     *\n     * @return - RectF of Displayed Drawable\n     */\n    RectF getDisplayRect();\n\n    /**\n     * @return The current minimum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.\n     */\n    float getMinScale();\n\n    /**\n     * @return The current middle scale level. What this value represents depends on the current {@link ImageView.ScaleType}.\n     */\n    float getMidScale();\n\n    /**\n     * @return The current maximum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.\n     */\n    float getMaxScale();\n\n    /**\n     * Returns the current scale value\n     *\n     * @return float - current scale value\n     */\n    float getScale();\n\n    /**\n     * Return the current scale type in use by the ImageView.\n     */\n    ImageView.ScaleType getScaleType();\n\n    /**\n     * Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll to it's horizontal edge.\n     */\n    void setAllowParentInterceptOnEdge(boolean allow);\n\n    /**\n     * Sets the minimum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.\n     */\n    void setMinScale(float minScale);\n\n    /**\n     * Sets the middle scale level. What this value represents depends on the current {@link ImageView.ScaleType}.\n     */\n    void setMidScale(float midScale);\n\n    /**\n     * Sets the maximum scale level. What this value represents depends on the current {@link ImageView.ScaleType}.\n     */\n    void setMaxScale(float maxScale);\n\n    /**\n     * Register a callback to be invoked when the Photo displayed by this view is long-pressed.\n     *\n     * @param listener - Listener to be registered.\n     */\n    void setOnLongClickListener(View.OnLongClickListener listener);\n\n    /**\n     * Register a callback to be invoked when the Matrix has changed for this\n     * View. An example would be the user panning or scaling the Photo.\n     *\n     * @param listener - Listener to be registered.\n     */\n    void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener);\n\n    /**\n     * Register a callback to be invoked when the Photo displayed by this View\n     * is tapped with a single tap.\n     *\n     * @param listener - Listener to be registered.\n     */\n    void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener);\n\n    /**\n     * Register a callback to be invoked when the View is tapped with a single\n     * tap.\n     *\n     * @param listener - Listener to be registered.\n     */\n    void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener);\n\n    /**\n     * Controls how the image should be resized or moved to match the size of\n     * the ImageView. Any scaling or panning will happen within the confines of\n     * this {@link ImageView.ScaleType}.\n     *\n     * @param scaleType - The desired scaling mode.\n     */\n    void setScaleType(ImageView.ScaleType scaleType);\n\n    /**\n     * Allows you to enable/disable the zoom functionality on the ImageView.\n     * When disable the ImageView reverts to using the FIT_CENTER matrix.\n     *\n     * @param zoomable - Whether the zoom functionality is enabled.\n     */\n    void setZoomable(boolean zoomable);\n\n    /**\n     * Zooms to the specified scale, around the focal point given.\n     *\n     * @param scale  - Scale to zoom to\n     * @param focalX - X Focus Point\n     * @param focalY - Y Focus Point\n     */\n    void zoomTo(float scale, float focalX, float focalY);\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/photoview/PhotoView.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.htmessage.yichatopen.widget.photoview;\n\nimport android.content.Context;\nimport android.graphics.RectF;\nimport android.graphics.drawable.Drawable;\nimport android.net.Uri;\nimport android.util.AttributeSet;\nimport android.widget.ImageView;\n\npublic class PhotoView extends ImageView implements IPhotoView {\n\n\tprivate final PhotoViewAttacher mAttacher;\n\n\tprivate ScaleType mPendingScaleType;\n\n\tpublic PhotoView(Context context) {\n\t\tthis(context, null);\n\t}\n\n\tpublic PhotoView(Context context, AttributeSet attr) {\n\t\tthis(context, attr, 0);\n\t}\n\t\n\tpublic PhotoView(Context context, AttributeSet attr, int defStyle) {\n\t\tsuper(context, attr, defStyle);\n\t\tsuper.setScaleType(ScaleType.MATRIX);\n\t\tmAttacher = new PhotoViewAttacher(this);\n\n\t\tif (null != mPendingScaleType) {\n\t\t\tsetScaleType(mPendingScaleType);\n\t\t\tmPendingScaleType = null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean canZoom() {\n\t\treturn mAttacher.canZoom();\n\t}\n\n\t@Override\n\tpublic RectF getDisplayRect() {\n\t\treturn mAttacher.getDisplayRect();\n\t}\n\n\t@Override\n\tpublic float getMinScale() {\n\t\treturn mAttacher.getMinScale();\n\t}\n\n\t@Override\n\tpublic float getMidScale() {\n\t\treturn mAttacher.getMidScale();\n\t}\n\n\t@Override\n\tpublic float getMaxScale() {\n\t\treturn mAttacher.getMaxScale();\n\t}\n\n\t@Override\n\tpublic float getScale() {\n\t\treturn mAttacher.getScale();\n\t}\n\n\t@Override\n\tpublic ScaleType getScaleType() {\n\t\treturn mAttacher.getScaleType();\n\t}\n\n    @Override\n    public void setAllowParentInterceptOnEdge(boolean allow) {\n        mAttacher.setAllowParentInterceptOnEdge(allow);\n    }\n\n    @Override\n\tpublic void setMinScale(float minScale) {\n\t\tmAttacher.setMinScale(minScale);\n\t}\n\n\t@Override\n\tpublic void setMidScale(float midScale) {\n\t\tmAttacher.setMidScale(midScale);\n\t}\n\n\t@Override\n\tpublic void setMaxScale(float maxScale) {\n\t\tmAttacher.setMaxScale(maxScale);\n\t}\n\n\t@Override\n\t// setImageBitmap calls through to this method\n\tpublic void setImageDrawable(Drawable drawable) {\n\t\tsuper.setImageDrawable(drawable);\n\t\tif (null != mAttacher) {\n\t\t\tmAttacher.update();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setImageResource(int resId) {\n\t\tsuper.setImageResource(resId);\n\t\tif (null != mAttacher) {\n\t\t\tmAttacher.update();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setImageURI(Uri uri) {\n\t\tsuper.setImageURI(uri);\n\t\tif (null != mAttacher) {\n\t\t\tmAttacher.update();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener) {\n\t\tmAttacher.setOnMatrixChangeListener(listener);\n\t}\n\n\t@Override\n\tpublic void setOnLongClickListener(OnLongClickListener l) {\n\t\tmAttacher.setOnLongClickListener(l);\n\t}\n\n\t@Override\n\tpublic void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener) {\n\t\tmAttacher.setOnPhotoTapListener(listener);\n\t}\n\n\t@Override\n\tpublic void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener) {\n\t\tmAttacher.setOnViewTapListener(listener);\n\t}\n\n\t@Override\n\tpublic void setScaleType(ScaleType scaleType) {\n\t\tif (null != mAttacher) {\n\t\t\tmAttacher.setScaleType(scaleType);\n\t\t} else {\n\t\t\tmPendingScaleType = scaleType;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setZoomable(boolean zoomable) {\n\t\tmAttacher.setZoomable(zoomable);\n\t}\n\n\t@Override\n\tpublic void zoomTo(float scale, float focalX, float focalY) {\n\t\tmAttacher.zoomTo(scale, focalX, focalY);\n\t}\n\n\t@Override\n\tprotected void onDetachedFromWindow() {\n\t\tmAttacher.cleanup();\n\t\tsuper.onDetachedFromWindow();\n\t}\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/photoview/PhotoViewAttacher.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.htmessage.yichatopen.widget.photoview;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.graphics.Matrix;\nimport android.graphics.Matrix.ScaleToFit;\nimport android.graphics.RectF;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.util.Log;\nimport android.view.GestureDetector;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.View.OnLongClickListener;\nimport android.view.ViewTreeObserver;\nimport android.widget.ImageView;\nimport android.widget.ImageView.ScaleType;\n\nimport java.lang.ref.WeakReference;\n\nclass PhotoViewAttacher implements IPhotoView, View.OnTouchListener, VersionedGestureDetector.OnGestureListener,\n\t\tGestureDetector.OnDoubleTapListener, ViewTreeObserver.OnGlobalLayoutListener {\n\n\tstatic final String LOG_TAG = \"PhotoViewAttacher\";\n\n\t// let debug flag be dynamic, but still Proguard can be used to remove from\n\t// release builds\n\tstatic final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);\n\n\tstatic final int EDGE_NONE = -1;\n\tstatic final int EDGE_LEFT = 0;\n\tstatic final int EDGE_RIGHT = 1;\n\tstatic final int EDGE_BOTH = 2;\n\n\tpublic static final float DEFAULT_MAX_SCALE = 2.0f;\n\t// public static final float DEFAULT_MID_SCALE = 1.75f;\n\tpublic static final float DEFAULT_MIN_SCALE = 1.0f;\n\n\tprivate float mMinScale = DEFAULT_MIN_SCALE;\n\t// private float mMidScale = DEFAULT_MID_SCALE;\n\tprivate float mMaxScale = DEFAULT_MAX_SCALE;\n\n\tprivate boolean mAllowParentInterceptOnEdge = true;\n\n\t// private static void checkZoomLevels(float minZoom, float midZoom,\n\t// float maxZoom) {\n\t// if (minZoom >= midZoom) {\n\t// throw new IllegalArgumentException(\n\t// \"MinZoom should be less than MidZoom\");\n\t// } else if (midZoom >= maxZoom) {\n\t// throw new IllegalArgumentException(\n\t// \"MidZoom should be less than MaxZoom\");\n\t// }\n\t// }\n\n\tprivate static void checkZoomLevels(float minZoom,float maxZoom) {\n\t\tif (minZoom >= maxZoom) {\n\t\t\tthrow new IllegalArgumentException(\"MinZoom should be less than maxZoom\");\n\t\t} /*else if (midZoom >= maxZoom) {\n\t\t\tthrow new IllegalArgumentException(\"MidZoom should be less than MaxZoom\");\n\t\t}*/\n\t}\n\n\t/**\n\t * @return true if the ImageView exists, and it's Drawable existss\n\t */\n\tprivate static boolean hasDrawable(ImageView imageView) {\n\t\treturn null != imageView && null != imageView.getDrawable();\n\t}\n\n\t/**\n\t * @return true if the ScaleType is supported.\n\t */\n\tprivate static boolean isSupportedScaleType(final ScaleType scaleType) {\n\t\tif (null == scaleType) {\n\t\t\treturn false;\n\t\t}\n\n\t\tswitch (scaleType) {\n\t\tcase MATRIX:\n\t\t\tthrow new IllegalArgumentException(scaleType.name() + \" is not supported in PhotoView\");\n\n\t\tdefault:\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * Set's the ImageView's ScaleType to Matrix.\n\t */\n\tprivate static void setImageViewScaleTypeMatrix(ImageView imageView) {\n\t\tif (null != imageView) {\n\t\t\tif (imageView instanceof PhotoView) {\n\t\t\t\t/**\n\t\t\t\t * PhotoView sets it's own ScaleType to Matrix, then diverts all\n\t\t\t\t * calls setScaleType to this.setScaleType. Basically we don't\n\t\t\t\t * need to do anything here\n\t\t\t\t */\n\t\t\t} else {\n\t\t\t\timageView.setScaleType(ScaleType.MATRIX);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate WeakReference<ImageView> mImageView;\n\tprivate ViewTreeObserver mViewTreeObserver;\n\n\t// Gesture Detectors\n\tprivate GestureDetector mGestureDetector;\n\tprivate VersionedGestureDetector mScaleDragDetector;\n\n\t// These are set so we don't keep allocating them on the heap\n\tprivate final Matrix mBaseMatrix = new Matrix();\n\tprivate final Matrix mDrawMatrix = new Matrix();\n\tprivate final Matrix mSuppMatrix = new Matrix();\n\tprivate final RectF mDisplayRect = new RectF();\n\tprivate final float[] mMatrixValues = new float[9];\n\n\t// Listeners\n\tprivate OnMatrixChangedListener mMatrixChangeListener;\n\tprivate OnPhotoTapListener mPhotoTapListener;\n\tprivate OnViewTapListener mViewTapListener;\n\tprivate OnLongClickListener mLongClickListener;\n\n\tprivate int mIvTop, mIvRight, mIvBottom, mIvLeft;\n\tprivate FlingRunnable mCurrentFlingRunnable;\n\tprivate int mScrollEdge = EDGE_BOTH;\n\n\tprivate boolean mZoomEnabled;\n\tprivate ScaleType mScaleType = ScaleType.FIT_CENTER;\n\n\tpublic PhotoViewAttacher(ImageView imageView) {\n\t\tmImageView = new WeakReference<ImageView>(imageView);\n\n\t\timageView.setOnTouchListener(this);\n\n\t\tmViewTreeObserver = imageView.getViewTreeObserver();\n\t\tmViewTreeObserver.addOnGlobalLayoutListener(this);\n\n\t\t// Make sure we using MATRIX Scale Type\n\t\tsetImageViewScaleTypeMatrix(imageView);\n\n\t\tif (!imageView.isInEditMode()) {\n\t\t\t// Create Gesture Detectors...\n\t\t\tmScaleDragDetector = VersionedGestureDetector.newInstance(imageView.getContext(), this);\n\n\t\t\tmGestureDetector = new GestureDetector(imageView.getContext(),\n\t\t\t\t\tnew GestureDetector.SimpleOnGestureListener() {\n\n\t\t\t\t\t\t// forward long click listener\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void onLongPress(MotionEvent e) {\n\t\t\t\t\t\t\tif (null != mLongClickListener) {\n\t\t\t\t\t\t\t\tmLongClickListener.onLongClick(mImageView.get());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\tmGestureDetector.setOnDoubleTapListener(this);\n\n\t\t\t// Finally, update the UI so that we're zoomable\n\t\t\tsetZoomable(true);\n\t\t}\n\t}\n\n\t@Override\n\tpublic final boolean canZoom() {\n\t\treturn mZoomEnabled;\n\t}\n\n\t/**\n\t * Clean-up the resources attached to this object. This needs to be called\n\t * when the ImageView is no longer used. A good example is from\n\t * {@link View#onDetachedFromWindow()} or from\n\t * {@link android.app.Activity#onDestroy()}. This is automatically called if\n\t * you are using {@link PhotoView.co.senab.photoview.PhotoView}.\n\t */\n\t@SuppressLint(\"NewApi\")\n\t@SuppressWarnings(\"deprecation\")\n\tpublic final void cleanup() {\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {\n\t\t\tif (null != mImageView) {\n\t\t\t\tmImageView.get().getViewTreeObserver().removeOnGlobalLayoutListener(this);\n\t\t\t}\n\n\t\t\tif (null != mViewTreeObserver && mViewTreeObserver.isAlive()) {\n\t\t\t\tmViewTreeObserver.removeOnGlobalLayoutListener(this);\n\n\t\t\t\tmViewTreeObserver = null;\n\n\t\t\t\t// Clear listeners too\n\t\t\t\tmMatrixChangeListener = null;\n\t\t\t\tmPhotoTapListener = null;\n\t\t\t\tmViewTapListener = null;\n\t\t\t\t// Finally, clear ImageView\n\t\t\t\tmImageView = null;\n\t\t\t}\n\n\t\t} else {\n\t\t\tif (null != mImageView) {\n\t\t\t\tmImageView.get().getViewTreeObserver().removeGlobalOnLayoutListener(this);\n\t\t\t}\n\n\t\t\tif (null != mViewTreeObserver && mViewTreeObserver.isAlive()) {\n\t\t\t\tmViewTreeObserver.removeGlobalOnLayoutListener(this);\n\n\t\t\t\tmViewTreeObserver = null;\n\n\t\t\t\t// Clear listeners too\n\t\t\t\tmMatrixChangeListener = null;\n\t\t\t\tmPhotoTapListener = null;\n\t\t\t\tmViewTapListener = null;\n\t\t\t\t// Finally, clear ImageView\n\t\t\t\tmImageView = null;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic final RectF getDisplayRect() {\n\t\tcheckMatrixBounds();\n\t\treturn getDisplayRect(getDisplayMatrix());\n\t}\n\n\tpublic final ImageView getImageView() {\n\t\tImageView imageView = null;\n\n\t\tif (null != mImageView) {\n\t\t\timageView = mImageView.get();\n\t\t}\n\n\t\t// If we don't have an ImageView, call cleanup()\n\t\tif (null == imageView) {\n\t\t\tcleanup();\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"ImageView no longer exists. You should not use this PhotoViewAttacher any more.\");\n\t\t}\n\n\t\treturn imageView;\n\t}\n\n\t@Override\n\tpublic float getMinScale() {\n\t\treturn mMinScale;\n\t}\n\n\t// @Override\n\t// public float getMidScale() {\n\t// return mMidScale;\n\t// }\n\n\t@Override\n\tpublic float getMaxScale() {\n\t\treturn mMaxScale;\n\t}\n\n\t@Override\n\tpublic final float getScale() {\n\t\treturn getValue(mSuppMatrix, Matrix.MSCALE_X);\n\t}\n\n\t@Override\n\tpublic final ScaleType getScaleType() {\n\t\treturn mScaleType;\n\t}\n\n\tpublic final boolean onDoubleTap(MotionEvent ev) {\n\t\ttry {\n\t\t\tfloat scale = getScale();\n\t\t\tfloat x = ev.getX();\n\t\t\tfloat y = ev.getY();\n\n\t\t\t/*\n\t\t\t * if (scale < mMidScale) { zoomTo(mMidScale, x, y); } else\n\t\t\t */if (/* scale >= mMidScale && */scale < mMaxScale) {\n\t\t\t\tzoomTo(mMaxScale, x, y);\n\t\t\t} else {\n\t\t\t\tzoomTo(mMinScale, x, y);\n\t\t\t}\n\t\t} catch (ArrayIndexOutOfBoundsException e) {\n\t\t\t// Can sometimes happen when getX() and getY() is called\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tpublic final boolean onDoubleTapEvent(MotionEvent e) {\n\t\t// Wait for the confirmed onDoubleTap() instead\n\t\treturn false;\n\t}\n\n\tpublic final void onDrag(float dx, float dy) {\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, String.format(\"onDrag: dx: %.2f. dy: %.2f\", dx, dy));\n\t\t}\n\n\t\tImageView imageView = getImageView();\n\n\t\tif (null != imageView && hasDrawable(imageView)) {\n\t\t\tmSuppMatrix.postTranslate(dx, dy);\n\t\t\tcheckAndDisplayMatrix();\n\n\t\t\t/**\n\t\t\t * Here we decide whether to let the ImageView's parent to start\n\t\t\t * taking over the touch event.\n\t\t\t * \n\t\t\t * First we check whether this function is enabled. We never want\n\t\t\t * the parent to take over if we're scaling. We then check the edge\n\t\t\t * we're on, and the direction of the scroll (i.e. if we're pulling\n\t\t\t * against the edge, aka 'overscrolling', let the parent take over).\n\t\t\t */\n\t\t\tif (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling()) {\n\t\t\t\tif (mScrollEdge == EDGE_BOTH || (mScrollEdge == EDGE_LEFT && dx >= 1f)\n\t\t\t\t\t\t|| (mScrollEdge == EDGE_RIGHT && dx <= -1f)) {\n\t\t\t\t\timageView.getParent().requestDisallowInterceptTouchEvent(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic final void onFling(float startX, float startY, float velocityX, float velocityY) {\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, \"onFling. sX: \" + startX + \" sY: \" + startY + \" Vx: \" + velocityX + \" Vy: \" + velocityY);\n\t\t}\n\n\t\tImageView imageView = getImageView();\n\t\tif (hasDrawable(imageView)) {\n\t\t\tmCurrentFlingRunnable = new FlingRunnable(imageView.getContext());\n\t\t\tmCurrentFlingRunnable.fling(imageView.getWidth(), imageView.getHeight(), (int) velocityX, (int) velocityY);\n\t\t\timageView.post(mCurrentFlingRunnable);\n\t\t}\n\t}\n\n\t@Override\n\tpublic final void onGlobalLayout() {\n\t\tImageView imageView = getImageView();\n\n\t\tif (null != imageView && mZoomEnabled) {\n\t\t\tfinal int top = imageView.getTop();\n\t\t\tfinal int right = imageView.getRight();\n\t\t\tfinal int bottom = imageView.getBottom();\n\t\t\tfinal int left = imageView.getLeft();\n\n\t\t\t/**\n\t\t\t * We need to check whether the ImageView's bounds have changed.\n\t\t\t * This would be easier if we targeted API 11+ as we could just use\n\t\t\t * View.OnLayoutChangeListener. Instead we have to replicate the\n\t\t\t * work, keeping track of the ImageView's bounds and then checking\n\t\t\t * if the values change.\n\t\t\t */\n\t\t\tif (top != mIvTop || bottom != mIvBottom || left != mIvLeft || right != mIvRight) {\n\t\t\t\t// Update our base matrix, as the bounds have changed\n\t\t\t\tupdateBaseMatrix(imageView.getDrawable());\n\n\t\t\t\t// Update values as something has changed\n\t\t\t\tmIvTop = top;\n\t\t\t\tmIvRight = right;\n\t\t\t\tmIvBottom = bottom;\n\t\t\t\tmIvLeft = left;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic final void onScale(float scaleFactor, float focusX, float focusY) {\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, String.format(\"onScale: scale: %.2f. fX: %.2f. fY: %.2f\", scaleFactor, focusX, focusY));\n\t\t}\n\n\t\tif (hasDrawable(getImageView()) && (getScale() < mMaxScale || scaleFactor < 1f)) {\n\t\t\tmSuppMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY);\n\t\t\tcheckAndDisplayMatrix();\n\t\t}\n\t}\n\n\tpublic final boolean onSingleTapConfirmed(MotionEvent e) {\n\t\tImageView imageView = getImageView();\n\n\t\tif (null != imageView) {\n\t\t\tif (null != mPhotoTapListener) {\n\t\t\t\tfinal RectF displayRect = getDisplayRect();\n\n\t\t\t\tif (null != displayRect) {\n\t\t\t\t\tfinal float x = e.getX(), y = e.getY();\n\n\t\t\t\t\t// Check to see if the user tapped on the photo\n\t\t\t\t\tif (displayRect.contains(x, y)) {\n\n\t\t\t\t\t\tfloat xResult = (x - displayRect.left) / displayRect.width();\n\t\t\t\t\t\tfloat yResult = (y - displayRect.top) / displayRect.height();\n\n\t\t\t\t\t\tmPhotoTapListener.onPhotoTap(imageView, xResult, yResult);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (null != mViewTapListener) {\n\t\t\t\tmViewTapListener.onViewTap(imageView, e.getX(), e.getY());\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic final boolean onTouch(View v, MotionEvent ev) {\n\t\tboolean handled = false;\n\n\t\tif (mZoomEnabled) {\n\t\t\tswitch (ev.getAction()) {\n\t\t\tcase MotionEvent.ACTION_DOWN:\n\t\t\t\t// First, disable the Parent from intercepting the touch\n\t\t\t\t// event\n\t\t\t\tv.getParent().requestDisallowInterceptTouchEvent(true);\n\n\t\t\t\t// If we're flinging, and the user presses down, cancel\n\t\t\t\t// fling\n\t\t\t\tcancelFling();\n\t\t\t\tbreak;\n\n\t\t\tcase MotionEvent.ACTION_CANCEL:\n\t\t\tcase MotionEvent.ACTION_UP:\n\t\t\t\t// If the user has zoomed less than min scale, zoom back\n\t\t\t\t// to min scale\n\t\t\t\tif (getScale() < mMinScale) {\n\t\t\t\t\tRectF rect = getDisplayRect();\n\t\t\t\t\tif (null != rect) {\n\t\t\t\t\t\tv.post(new AnimatedZoomRunnable(getScale(), mMinScale, rect.centerX(), rect.centerY()));\n\t\t\t\t\t\thandled = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Check to see if the user double tapped\n\t\t\tif (null != mGestureDetector && mGestureDetector.onTouchEvent(ev)) {\n\t\t\t\thandled = true;\n\t\t\t}\n\n\t\t\t// Finally, try the Scale/Drag detector\n\t\t\tif (null != mScaleDragDetector && mScaleDragDetector.onTouchEvent(ev)) {\n\t\t\t\thandled = true;\n\t\t\t}\n\t\t}\n\n\t\treturn handled;\n\t}\n\n\t@Override\n\tpublic void setAllowParentInterceptOnEdge(boolean allow) {\n\t\tmAllowParentInterceptOnEdge = allow;\n\t}\n\n\t@Override\n\tpublic void setMinScale(float minScale) {\n//\t\tcheckZoomLevels(minScale, mMidScale, mMaxScale);\n\t\tcheckZoomLevels(minScale, mMaxScale);\n\t\tmMinScale = minScale;\n\t}\n\n//\t@Override\n//\tpublic void setMidScale(float midScale) {\n//\t\tcheckZoomLevels(mMinScale, midScale, mMaxScale);\n//\t\tmMidScale = midScale;\n//\t}\n\n\t@Override\n\tpublic void setMaxScale(float maxScale) {\n//\t\tcheckZoomLevels(mMinScale, mMidScale, maxScale);\n\t\tcheckZoomLevels(mMinScale, maxScale);\n\t\tmMaxScale = maxScale;\n\t}\n\n\t@Override\n\tpublic final void setOnLongClickListener(OnLongClickListener listener) {\n\t\tmLongClickListener = listener;\n\t}\n\n\t@Override\n\tpublic final void setOnMatrixChangeListener(OnMatrixChangedListener listener) {\n\t\tmMatrixChangeListener = listener;\n\t}\n\n\t@Override\n\tpublic final void setOnPhotoTapListener(OnPhotoTapListener listener) {\n\t\tmPhotoTapListener = listener;\n\t}\n\n\t@Override\n\tpublic final void setOnViewTapListener(OnViewTapListener listener) {\n\t\tmViewTapListener = listener;\n\t}\n\n\t@Override\n\tpublic final void setScaleType(ScaleType scaleType) {\n\t\tif (isSupportedScaleType(scaleType) && scaleType != mScaleType) {\n\t\t\tmScaleType = scaleType;\n\n\t\t\t// Finally update\n\t\t\tupdate();\n\t\t}\n\t}\n\n\t@Override\n\tpublic final void setZoomable(boolean zoomable) {\n\t\tmZoomEnabled = zoomable;\n\t\tupdate();\n\t}\n\n\tpublic final void update() {\n\t\tImageView imageView = getImageView();\n\n\t\tif (null != imageView) {\n\t\t\tif (mZoomEnabled) {\n\t\t\t\t// Make sure we using MATRIX Scale Type\n\t\t\t\tsetImageViewScaleTypeMatrix(imageView);\n\n\t\t\t\t// Update the base matrix using the current drawable\n\t\t\t\tupdateBaseMatrix(imageView.getDrawable());\n\t\t\t} else {\n\t\t\t\t// Reset the Matrix...\n\t\t\t\tresetMatrix();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic final void zoomTo(float scale, float focalX, float focalY) {\n\t\tImageView imageView = getImageView();\n\n\t\tif (null != imageView) {\n\t\t\timageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));\n\t\t}\n\t}\n\n\tprotected Matrix getDisplayMatrix() {\n\t\tmDrawMatrix.set(mBaseMatrix);\n\t\tmDrawMatrix.postConcat(mSuppMatrix);\n\t\treturn mDrawMatrix;\n\t}\n\n\tprivate void cancelFling() {\n\t\tif (null != mCurrentFlingRunnable) {\n\t\t\tmCurrentFlingRunnable.cancelFling();\n\t\t\tmCurrentFlingRunnable = null;\n\t\t}\n\t}\n\n\t/**\n\t * Helper method that simply checks the Matrix, and then displays the result\n\t */\n\tprivate void checkAndDisplayMatrix() {\n\t\tcheckMatrixBounds();\n\t\tsetImageViewMatrix(getDisplayMatrix());\n\t}\n\n\tprivate void checkImageViewScaleType() {\n\t\tImageView imageView = getImageView();\n\n\t\t/**\n\t\t * PhotoView's getScaleType() will just divert to this.getScaleType() so\n\t\t * only call if we're not attached to a PhotoView.\n\t\t */\n\t\tif (null != imageView && !(imageView instanceof PhotoView)) {\n\t\t\tif (imageView.getScaleType() != ScaleType.MATRIX) {\n\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\"The ImageView's ScaleType has been changed since attaching a PhotoViewAttacher\");\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void checkMatrixBounds() {\n\t\tfinal ImageView imageView = getImageView();\n\t\tif (null == imageView) {\n\t\t\treturn;\n\t\t}\n\n\t\tfinal RectF rect = getDisplayRect(getDisplayMatrix());\n\t\tif (null == rect) {\n\t\t\treturn;\n\t\t}\n\n\t\tfinal float height = rect.height(), width = rect.width();\n\t\tfloat deltaX = 0, deltaY = 0;\n\n\t\tfinal int viewHeight = imageView.getHeight();\n\t\tif (height <= viewHeight) {\n\t\t\tswitch (mScaleType) {\n\t\t\tcase FIT_START:\n\t\t\t\tdeltaY = -rect.top;\n\t\t\t\tbreak;\n\t\t\tcase FIT_END:\n\t\t\t\tdeltaY = viewHeight - height - rect.top;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdeltaY = (viewHeight - height) / 2 - rect.top;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else if (rect.top > 0) {\n\t\t\tdeltaY = -rect.top;\n\t\t} else if (rect.bottom < viewHeight) {\n\t\t\tdeltaY = viewHeight - rect.bottom;\n\t\t}\n\n\t\tfinal int viewWidth = imageView.getWidth();\n\t\tif (width <= viewWidth) {\n\t\t\tswitch (mScaleType) {\n\t\t\tcase FIT_START:\n\t\t\t\tdeltaX = -rect.left;\n\t\t\t\tbreak;\n\t\t\tcase FIT_END:\n\t\t\t\tdeltaX = viewWidth - width - rect.left;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdeltaX = (viewWidth - width) / 2 - rect.left;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmScrollEdge = EDGE_BOTH;\n\t\t} else if (rect.left > 0) {\n\t\t\tmScrollEdge = EDGE_LEFT;\n\t\t\tdeltaX = -rect.left;\n\t\t} else if (rect.right < viewWidth) {\n\t\t\tdeltaX = viewWidth - rect.right;\n\t\t\tmScrollEdge = EDGE_RIGHT;\n\t\t} else {\n\t\t\tmScrollEdge = EDGE_NONE;\n\t\t}\n\n\t\t// Finally actually translate the matrix\n\t\tmSuppMatrix.postTranslate(deltaX, deltaY);\n\t}\n\n\t/**\n\t * Helper method that maps the supplied Matrix to the current Drawable\n\t * \n\t * @param matrix\n\t *            - Matrix to map Drawable against\n\t * @return RectF - Displayed Rectangle\n\t */\n\tprivate RectF getDisplayRect(Matrix matrix) {\n\t\tImageView imageView = getImageView();\n\n\t\tif (null != imageView) {\n\t\t\tDrawable d = imageView.getDrawable();\n\t\t\tif (null != d) {\n\t\t\t\tmDisplayRect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());\n\t\t\t\tmatrix.mapRect(mDisplayRect);\n\t\t\t\treturn mDisplayRect;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Helper method that 'unpacks' a Matrix and returns the required value\n\t * \n\t * @param matrix\n\t *            - Matrix to unpack\n\t * @param whichValue\n\t *            - Which value from Matrix.M* to return\n\t * @return float - returned value\n\t */\n\tprivate float getValue(Matrix matrix, int whichValue) {\n\t\tmatrix.getValues(mMatrixValues);\n\t\treturn mMatrixValues[whichValue];\n\t}\n\n\t/**\n\t * Resets the Matrix back to FIT_CENTER, and then displays it.s\n\t */\n\tprivate void resetMatrix() {\n\t\tmSuppMatrix.reset();\n\t\tsetImageViewMatrix(getDisplayMatrix());\n\t\tcheckMatrixBounds();\n\t}\n\n\tprivate void setImageViewMatrix(Matrix matrix) {\n\t\tImageView imageView = getImageView();\n\t\tif (null != imageView) {\n\n\t\t\tcheckImageViewScaleType();\n\t\t\timageView.setImageMatrix(matrix);\n\n\t\t\t// Call MatrixChangedListener if needed\n\t\t\tif (null != mMatrixChangeListener) {\n\t\t\t\tRectF displayRect = getDisplayRect(matrix);\n\t\t\t\tif (null != displayRect) {\n\t\t\t\t\tmMatrixChangeListener.onMatrixChanged(displayRect);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Calculate Matrix for FIT_CENTER\n\t * \n\t * @param d\n\t *            - Drawable being displayed\n\t */\n\tprivate void updateBaseMatrix(Drawable d) {\n\t\tImageView imageView = getImageView();\n\t\tif (null == imageView || null == d) {\n\t\t\treturn;\n\t\t}\n\n\t\tfinal float viewWidth = imageView.getWidth();\n\t\tfinal float viewHeight = imageView.getHeight();\n\t\tfinal int drawableWidth = d.getIntrinsicWidth();\n\t\tfinal int drawableHeight = d.getIntrinsicHeight();\n\n\t\tmBaseMatrix.reset();\n\n\t\tfinal float widthScale = viewWidth / drawableWidth;\n\t\tfinal float heightScale = viewHeight / drawableHeight;\n\n\t\tif (mScaleType == ScaleType.CENTER) {\n\t\t\tmBaseMatrix.postTranslate((viewWidth - drawableWidth) / 2F, (viewHeight - drawableHeight) / 2F);\n\n\t\t} else if (mScaleType == ScaleType.CENTER_CROP) {\n\t\t\tfloat scale = Math.max(widthScale, heightScale);\n\t\t\tmBaseMatrix.postScale(scale, scale);\n\t\t\tmBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,\n\t\t\t\t\t(viewHeight - drawableHeight * scale) / 2F);\n\n\t\t} else if (mScaleType == ScaleType.CENTER_INSIDE) {\n\t\t\tfloat scale = Math.min(1.0f, Math.min(widthScale, heightScale));\n\t\t\tmBaseMatrix.postScale(scale, scale);\n\t\t\tmBaseMatrix.postTranslate((viewWidth - drawableWidth * scale) / 2F,\n\t\t\t\t\t(viewHeight - drawableHeight * scale) / 2F);\n\n\t\t} else {\n\t\t\tRectF mTempSrc = new RectF(0, 0, drawableWidth, drawableHeight);\n\t\t\tRectF mTempDst = new RectF(0, 0, viewWidth, viewHeight);\n\n\t\t\tswitch (mScaleType) {\n\t\t\tcase FIT_CENTER:\n\t\t\t\tmBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.CENTER);\n\t\t\t\tbreak;\n\n\t\t\tcase FIT_START:\n\t\t\t\tmBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.START);\n\t\t\t\tbreak;\n\n\t\t\tcase FIT_END:\n\t\t\t\tmBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.END);\n\t\t\t\tbreak;\n\n\t\t\tcase FIT_XY:\n\t\t\t\tmBaseMatrix.setRectToRect(mTempSrc, mTempDst, ScaleToFit.FILL);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tresetMatrix();\n\t}\n\n\t/**\n\t * Interface definition for a callback to be invoked when the internal\n\t * Matrix has changed for this View.\n\t * \n\t * @author Chris Banes\n\t */\n\tpublic static interface OnMatrixChangedListener {\n\t\t/**\n\t\t * Callback for when the Matrix displaying the Drawable has changed.\n\t\t * This could be because the View's bounds have changed, or the user has\n\t\t * zoomed.\n\t\t * \n\t\t * @param rect\n\t\t *            - Rectangle displaying the Drawable's new bounds.\n\t\t */\n\t\tvoid onMatrixChanged(RectF rect);\n\t}\n\n\t/**\n\t * Interface definition for a callback to be invoked when the Photo is\n\t * tapped with a single tap.\n\t * \n\t * @author Chris Banes\n\t */\n\tpublic static interface OnPhotoTapListener {\n\n\t\t/**\n\t\t * A callback to receive where the user taps on a photo. You will only\n\t\t * receive a callback if the user taps on the actual photo, tapping on\n\t\t * 'whitespace' will be ignored.\n\t\t * \n\t\t * @param view\n\t\t *            - View the user tapped.\n\t\t * @param x\n\t\t *            - where the user tapped from the of the Drawable, as\n\t\t *            percentage of the Drawable width.\n\t\t * @param y\n\t\t *            - where the user tapped from the top of the Drawable, as\n\t\t *            percentage of the Drawable height.\n\t\t */\n\t\tvoid onPhotoTap(View view, float x, float y);\n\t}\n\n\t/**\n\t * Interface definition for a callback to be invoked when the ImageView is\n\t * tapped with a single tap.\n\t * \n\t * @author Chris Banes\n\t */\n\tpublic static interface OnViewTapListener {\n\n\t\t/**\n\t\t * A callback to receive where the user taps on a ImageView. You will\n\t\t * receive a callback if the user taps anywhere on the view, tapping on\n\t\t * 'whitespace' will not be ignored.\n\t\t * \n\t\t * @param view\n\t\t *            - View the user tapped.\n\t\t * @param x\n\t\t *            - where the user tapped from the left of the View.\n\t\t * @param y\n\t\t *            - where the user tapped from the top of the View.\n\t\t */\n\t\tvoid onViewTap(View view, float x, float y);\n\t}\n\n\tprivate class AnimatedZoomRunnable implements Runnable {\n\n\t\t// These are 'postScale' values, means they're compounded each iteration\n\t\tstatic final float ANIMATION_SCALE_PER_ITERATION_IN = 1.07f;\n\t\tstatic final float ANIMATION_SCALE_PER_ITERATION_OUT = 0.93f;\n\n\t\tprivate final float mFocalX, mFocalY;\n\t\tprivate final float mTargetZoom;\n\t\tprivate final float mDeltaScale;\n\n\t\tpublic AnimatedZoomRunnable(final float currentZoom, final float targetZoom, final float focalX,\n\t\t\t\tfinal float focalY) {\n\t\t\tmTargetZoom = targetZoom;\n\t\t\tmFocalX = focalX;\n\t\t\tmFocalY = focalY;\n\n\t\t\tif (currentZoom < targetZoom) {\n\t\t\t\tmDeltaScale = ANIMATION_SCALE_PER_ITERATION_IN;\n\t\t\t} else {\n\t\t\t\tmDeltaScale = ANIMATION_SCALE_PER_ITERATION_OUT;\n\t\t\t}\n\t\t}\n\n\t\tpublic void run() {\n\t\t\tImageView imageView = getImageView();\n\n\t\t\tif (null != imageView) {\n\t\t\t\tmSuppMatrix.postScale(mDeltaScale, mDeltaScale, mFocalX, mFocalY);\n\t\t\t\tcheckAndDisplayMatrix();\n\n\t\t\t\tfinal float currentScale = getScale();\n\n\t\t\t\tif ((mDeltaScale > 1f && currentScale < mTargetZoom)\n\t\t\t\t\t\t|| (mDeltaScale < 1f && mTargetZoom < currentScale)) {\n\t\t\t\t\t// We haven't hit our target scale yet, so post ourselves\n\t\t\t\t\t// again\n\t\t\t\t\tCompat.postOnAnimation(imageView, this);\n\n\t\t\t\t} else {\n\t\t\t\t\t// We've scaled past our target zoom, so calculate the\n\t\t\t\t\t// necessary scale so we're back at target zoom\n\t\t\t\t\tfinal float delta = mTargetZoom / currentScale;\n\t\t\t\t\tmSuppMatrix.postScale(delta, delta, mFocalX, mFocalY);\n\t\t\t\t\tcheckAndDisplayMatrix();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate class FlingRunnable implements Runnable {\n\n\t\tprivate final ScrollerProxy mScroller;\n\t\tprivate int mCurrentX, mCurrentY;\n\n\t\tpublic FlingRunnable(Context context) {\n\t\t\tmScroller = ScrollerProxy.getScroller(context);\n\t\t}\n\n\t\tpublic void cancelFling() {\n\t\t\tif (DEBUG) {\n\t\t\t\tLog.d(LOG_TAG, \"Cancel Fling\");\n\t\t\t}\n\t\t\tmScroller.forceFinished(true);\n\t\t}\n\n\t\tpublic void fling(int viewWidth, int viewHeight, int velocityX, int velocityY) {\n\t\t\tfinal RectF rect = getDisplayRect();\n\t\t\tif (null == rect) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfinal int startX = Math.round(-rect.left);\n\t\t\tfinal int minX, maxX, minY, maxY;\n\n\t\t\tif (viewWidth < rect.width()) {\n\t\t\t\tminX = 0;\n\t\t\t\tmaxX = Math.round(rect.width() - viewWidth);\n\t\t\t} else {\n\t\t\t\tminX = maxX = startX;\n\t\t\t}\n\n\t\t\tfinal int startY = Math.round(-rect.top);\n\t\t\tif (viewHeight < rect.height()) {\n\t\t\t\tminY = 0;\n\t\t\t\tmaxY = Math.round(rect.height() - viewHeight);\n\t\t\t} else {\n\t\t\t\tminY = maxY = startY;\n\t\t\t}\n\n\t\t\tmCurrentX = startX;\n\t\t\tmCurrentY = startY;\n\n\t\t\tif (DEBUG) {\n\t\t\t\tLog.d(LOG_TAG, \"fling. StartX:\" + startX + \" StartY:\" + startY + \" MaxX:\" + maxX + \" MaxY:\" + maxY);\n\t\t\t}\n\n\t\t\t// If we actually can move, fling the scroller\n\t\t\tif (startX != maxX || startY != maxY) {\n\t\t\t\tmScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, 0, 0);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tImageView imageView = getImageView();\n\t\t\tif (null != imageView && mScroller.computeScrollOffset()) {\n\n\t\t\t\tfinal int newX = mScroller.getCurrX();\n\t\t\t\tfinal int newY = mScroller.getCurrY();\n\n\t\t\t\tif (DEBUG) {\n\t\t\t\t\tLog.d(LOG_TAG, \"fling run(). CurrentX:\" + mCurrentX + \" CurrentY:\" + mCurrentY + \" NewX:\" + newX\n\t\t\t\t\t\t\t+ \" NewY:\" + newY);\n\t\t\t\t}\n\n\t\t\t\tmSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);\n\t\t\t\tsetImageViewMatrix(getDisplayMatrix());\n\n\t\t\t\tmCurrentX = newX;\n\t\t\t\tmCurrentY = newY;\n\n\t\t\t\t// Post On animation\n\t\t\t\tCompat.postOnAnimation(imageView, this);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic float getMidScale() {\n \t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void setMidScale(float midScale) {\n\n\t}\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/photoview/SDK16.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.htmessage.yichatopen.widget.photoview;\n\nimport android.annotation.TargetApi;\nimport android.view.View;\n\n@TargetApi(16)\nclass SDK16 {\n\n\tpublic static void postOnAnimation(View view, Runnable r) {\n\t\tview.postOnAnimation(r);\n\t}\n\t\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/photoview/ScrollerProxy.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.htmessage.yichatopen.widget.photoview;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.widget.OverScroller;\nimport android.widget.Scroller;\n\nabstract class ScrollerProxy {\n\n\tpublic static ScrollerProxy getScroller(Context context) {\n\t\tif (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) {\n\t\t\treturn new PreGingerScroller(context);\n\t\t} else {\n\t\t\treturn new GingerScroller(context);\n\t\t}\n\t}\n\n\tpublic abstract boolean computeScrollOffset();\n\n\tpublic abstract void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY,\n\t\t\tint maxY, int overX, int overY);\n\n\tpublic abstract void forceFinished(boolean finished);\n\n\tpublic abstract int getCurrX();\n\n\tpublic abstract int getCurrY();\n\n\t@TargetApi(9)\n\tprivate static class GingerScroller extends ScrollerProxy {\n\n\t\tprivate OverScroller mScroller;\n\n\t\tpublic GingerScroller(Context context) {\n\t\t\tmScroller = new OverScroller(context);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean computeScrollOffset() {\n\t\t\treturn mScroller.computeScrollOffset();\n\t\t}\n\n\t\t@Override\n\t\tpublic void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,\n\t\t\t\tint overX, int overY) {\n\t\t\tmScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY);\n\t\t}\n\n\t\t@Override\n\t\tpublic void forceFinished(boolean finished) {\n\t\t\tmScroller.forceFinished(finished);\n\t\t}\n\n\t\t@Override\n\t\tpublic int getCurrX() {\n\t\t\treturn mScroller.getCurrX();\n\t\t}\n\n\t\t@Override\n\t\tpublic int getCurrY() {\n\t\t\treturn mScroller.getCurrY();\n\t\t}\n\t}\n\n\tprivate static class PreGingerScroller extends ScrollerProxy {\n\n\t\tprivate Scroller mScroller;\n\n\t\tpublic PreGingerScroller(Context context) {\n\t\t\tmScroller = new Scroller(context);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean computeScrollOffset() {\n\t\t\treturn mScroller.computeScrollOffset();\n\t\t}\n\n\t\t@Override\n\t\tpublic void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,\n\t\t\t\tint overX, int overY) {\n\t\t\tmScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);\n\t\t}\n\n\t\t@Override\n\t\tpublic void forceFinished(boolean finished) {\n\t\t\tmScroller.forceFinished(finished);\n\t\t}\n\n\t\t@Override\n\t\tpublic int getCurrX() {\n\t\t\treturn mScroller.getCurrX();\n\t\t}\n\n\t\t@Override\n\t\tpublic int getCurrY() {\n\t\t\treturn mScroller.getCurrY();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/photoview/VersionedGestureDetector.java",
    "content": "/**\n * Copyright (C) 2016 Hyphenate Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *     http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.widget.photoview;\n\n/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build;\nimport android.view.MotionEvent;\nimport android.view.ScaleGestureDetector;\nimport android.view.ScaleGestureDetector.OnScaleGestureListener;\nimport android.view.VelocityTracker;\nimport android.view.ViewConfiguration;\n\nabstract class VersionedGestureDetector {\n\tstatic final String LOG_TAG = \"VersionedGestureDetector\";\n\tOnGestureListener mListener;\n\n\tpublic static VersionedGestureDetector newInstance(Context context, OnGestureListener listener) {\n\t\tfinal int sdkVersion = Build.VERSION.SDK_INT;\n\t\tVersionedGestureDetector detector = null;\n\n\t\tif (sdkVersion < Build.VERSION_CODES.ECLAIR) {\n\t\t\tdetector = new CupcakeDetector(context);\n\t\t} else if (sdkVersion < Build.VERSION_CODES.FROYO) {\n\t\t\tdetector = new EclairDetector(context);\n\t\t} else {\n\t\t\tdetector = new FroyoDetector(context);\n\t\t}\n\n\t\tdetector.mListener = listener;\n\n\t\treturn detector;\n\t}\n\n\tpublic abstract boolean onTouchEvent(MotionEvent ev);\n\n\tpublic abstract boolean isScaling();\n\n\tpublic static interface OnGestureListener {\n\t\tpublic void onDrag(float dx, float dy);\n\n\t\tpublic void onFling(float startX, float startY, float velocityX, float velocityY);\n\n\t\tpublic void onScale(float scaleFactor, float focusX, float focusY);\n\t}\n\n\tprivate static class CupcakeDetector extends VersionedGestureDetector {\n\n\t\tfloat mLastTouchX;\n\t\tfloat mLastTouchY;\n\t\tfinal float mTouchSlop;\n\t\tfinal float mMinimumVelocity;\n\n\t\tpublic CupcakeDetector(Context context) {\n\t\t\tfinal ViewConfiguration configuration = ViewConfiguration.get(context);\n\t\t\tmMinimumVelocity = configuration.getScaledMinimumFlingVelocity();\n\t\t\tmTouchSlop = configuration.getScaledTouchSlop();\n\t\t}\n\n\t\tprivate VelocityTracker mVelocityTracker;\n\t\tprivate boolean mIsDragging;\n\n\t\tfloat getActiveX(MotionEvent ev) {\n\t\t\treturn ev.getX();\n\t\t}\n\n\t\tfloat getActiveY(MotionEvent ev) {\n\t\t\treturn ev.getY();\n\t\t}\n\n\t\tpublic boolean isScaling() {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean onTouchEvent(MotionEvent ev) {\n\t\t\tswitch (ev.getAction()) {\n\t\t\t\tcase MotionEvent.ACTION_DOWN: {\n\t\t\t\t\tmVelocityTracker = VelocityTracker.obtain();\n\t\t\t\t\tmVelocityTracker.addMovement(ev);\n\n\t\t\t\t\tmLastTouchX = getActiveX(ev);\n\t\t\t\t\tmLastTouchY = getActiveY(ev);\n\t\t\t\t\tmIsDragging = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MotionEvent.ACTION_MOVE: {\n\t\t\t\t\tfinal float x = getActiveX(ev);\n\t\t\t\t\tfinal float y = getActiveY(ev);\n\t\t\t\t\tfinal float dx = x - mLastTouchX, dy = y - mLastTouchY;\n\n\t\t\t\t\tif (!mIsDragging) {\n\t\t\t\t\t\t// Use Pythagoras to see if drag length is larger than\n\t\t\t\t\t\t// touch slop\n\t\t\t\t\t\tmIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (mIsDragging) {\n\t\t\t\t\t\tmListener.onDrag(dx, dy);\n\t\t\t\t\t\tmLastTouchX = x;\n\t\t\t\t\t\tmLastTouchY = y;\n\n\t\t\t\t\t\tif (null != mVelocityTracker) {\n\t\t\t\t\t\t\tmVelocityTracker.addMovement(ev);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MotionEvent.ACTION_CANCEL: {\n\t\t\t\t\t// Recycle Velocity Tracker\n\t\t\t\t\tif (null != mVelocityTracker) {\n\t\t\t\t\t\tmVelocityTracker.recycle();\n\t\t\t\t\t\tmVelocityTracker = null;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MotionEvent.ACTION_UP: {\n\t\t\t\t\tif (mIsDragging) {\n\t\t\t\t\t\tif (null != mVelocityTracker) {\n\t\t\t\t\t\t\tmLastTouchX = getActiveX(ev);\n\t\t\t\t\t\t\tmLastTouchY = getActiveY(ev);\n\n\t\t\t\t\t\t\t// Compute velocity within the last 1000ms\n\t\t\t\t\t\t\tmVelocityTracker.addMovement(ev);\n\t\t\t\t\t\t\tmVelocityTracker.computeCurrentVelocity(1000);\n\n\t\t\t\t\t\t\tfinal float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker.getYVelocity();\n\n\t\t\t\t\t\t\t// If the velocity is greater than minVelocity, call\n\t\t\t\t\t\t\t// listener\n\t\t\t\t\t\t\tif (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {\n\t\t\t\t\t\t\t\tmListener.onFling(mLastTouchX, mLastTouchY, -vX, -vY);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Recycle Velocity Tracker\n\t\t\t\t\tif (null != mVelocityTracker) {\n\t\t\t\t\t\tmVelocityTracker.recycle();\n\t\t\t\t\t\tmVelocityTracker = null;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t@TargetApi(5)\n\tprivate static class EclairDetector extends CupcakeDetector {\n\t\tprivate static final int INVALID_POINTER_ID = -1;\n\t\tprivate int mActivePointerId = INVALID_POINTER_ID;\n\t\tprivate int mActivePointerIndex = 0;\n\n\t\tpublic EclairDetector(Context context) {\n\t\t\tsuper(context);\n\t\t}\n\n\t\t@Override\n\t\tfloat getActiveX(MotionEvent ev) {\n\t\t\ttry {\n\t\t\t\treturn ev.getX(mActivePointerIndex);\n\t\t\t} catch (Exception e) {\n\t\t\t\treturn ev.getX();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tfloat getActiveY(MotionEvent ev) {\n\t\t\ttry {\n\t\t\t\treturn ev.getY(mActivePointerIndex);\n\t\t\t} catch (Exception e) {\n\t\t\t\treturn ev.getY();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean onTouchEvent(MotionEvent ev) {\n\t\t\tfinal int action = ev.getAction();\n\t\t\tswitch (action & MotionEvent.ACTION_MASK) {\n\t\t\t\tcase MotionEvent.ACTION_DOWN:\n\t\t\t\t\tmActivePointerId = ev.getPointerId(0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase MotionEvent.ACTION_CANCEL:\n\t\t\t\tcase MotionEvent.ACTION_UP:\n\t\t\t\t\tmActivePointerId = INVALID_POINTER_ID;\n\t\t\t\t\tbreak;\n\t\t\t\tcase MotionEvent.ACTION_POINTER_UP:\n\t\t\t\t\tfinal int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;\n\t\t\t\t\tfinal int pointerId = ev.getPointerId(pointerIndex);\n\t\t\t\t\tif (pointerId == mActivePointerId) {\n\t\t\t\t\t\t// This was our active pointer going up. Choose a new\n\t\t\t\t\t\t// active pointer and adjust accordingly.\n\t\t\t\t\t\tfinal int newPointerIndex = pointerIndex == 0 ? 1 : 0;\n\t\t\t\t\t\tmActivePointerId = ev.getPointerId(newPointerIndex);\n\t\t\t\t\t\tmLastTouchX = ev.getX(newPointerIndex);\n\t\t\t\t\t\tmLastTouchY = ev.getY(newPointerIndex);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmActivePointerIndex = ev.findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId : 0);\n\t\t\treturn super.onTouchEvent(ev);\n\t\t}\n\t}\n\n\t@TargetApi(8)\n\tprivate static class FroyoDetector extends EclairDetector {\n\n\t\tprivate final ScaleGestureDetector mDetector;\n\n\t\t// Needs to be an inner class so that we don't hit\n\t\t// VerifyError's on API 4.\n\t\tprivate final OnScaleGestureListener mScaleListener = new OnScaleGestureListener() {\n\n\t\t\t@Override\n\t\t\tpublic boolean onScale(ScaleGestureDetector detector) {\n\t\t\t\tmListener.onScale(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY());\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean onScaleBegin(ScaleGestureDetector detector) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void onScaleEnd(ScaleGestureDetector detector) {\n\t\t\t\t// NO-OP\n\t\t\t}\n\t\t};\n\n\t\tpublic FroyoDetector(Context context) {\n\t\t\tsuper(context);\n\t\t\tmDetector = new ScaleGestureDetector(context, mScaleListener);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isScaling() {\n\t\t\treturn mDetector.isInProgress();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean onTouchEvent(MotionEvent ev) {\n\t\t\tmDetector.onTouchEvent(ev);\n\t\t\treturn super.onTouchEvent(ev);\n\t\t}\n\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/scan/CameraConfigurationManager.java",
    "content": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.widget.scan;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.graphics.Point;\nimport android.hardware.Camera;\nimport android.util.Log;\nimport android.view.Display;\nimport android.view.WindowManager;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.Iterator;\nimport java.util.List;\n\n/**\n *\n * 邮箱: 1076559197@qq.com | tauchen1990@gmail.com\n *\n * 作者: 陈涛\n *\n * 日期: 2014年8月20日\n *\n * 描述: 该类主要负责设置相机的参数信息，获取最佳的预览界面\n *\n */\npublic final class CameraConfigurationManager {\n\n\tprivate static final String TAG = \"CameraConfiguration\";\n\n\tprivate static final int MIN_PREVIEW_PIXELS = 480 * 320;\n\tprivate static final double MAX_ASPECT_DISTORTION = 0.15;\n\n\tprivate final Context context;\n\n\t// 屏幕分辨率\n\tprivate Point screenResolution;\n\t// 相机分辨率\n\tprivate Point cameraResolution;\n\n\tpublic CameraConfigurationManager(Context context) {\n\t\tthis.context = context;\n\t}\n\n\tpublic void initFromCameraParameters(Camera camera) {\n\t\tCamera.Parameters parameters = camera.getParameters();\n\t\tWindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);\n\t\tDisplay display = manager.getDefaultDisplay();\n\t\tPoint theScreenResolution = new Point();\n\t\ttheScreenResolution = getDisplaySize(display);\n\n\t\tscreenResolution = theScreenResolution;\n\t\tLog.i(TAG, \"Screen resolution: \" + screenResolution);\n\n\t\t/** 因为换成了竖屏显示，所以不替换屏幕宽高得出的预览图是变形的 */\n\t\tPoint screenResolutionForCamera = new Point();\n\t\tscreenResolutionForCamera.x = screenResolution.x;\n\t\tscreenResolutionForCamera.y = screenResolution.y;\n\n\t\tif (screenResolution.x < screenResolution.y) {\n\t\t\tscreenResolutionForCamera.x = screenResolution.y;\n\t\t\tscreenResolutionForCamera.y = screenResolution.x;\n\t\t}\n\n\t\tcameraResolution = findBestPreviewSizeValue(parameters, screenResolutionForCamera);\n\t\tLog.i(TAG, \"Camera resolution x: \" + cameraResolution.x);\n\t\tLog.i(TAG, \"Camera resolution y: \" + cameraResolution.y);\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\t@SuppressLint(\"NewApi\")\n\tprivate Point getDisplaySize(final Display display) {\n\t\tfinal Point point = new Point();\n\t\ttry {\n\t\t\tdisplay.getSize(point);\n\t\t} catch (NoSuchMethodError ignore) {\n\t\t\tpoint.x = display.getWidth();\n\t\t\tpoint.y = display.getHeight();\n\t\t}\n\t\treturn point;\n\t}\n\n\tpublic void setDesiredCameraParameters(Camera camera, boolean safeMode) {\n\t\tCamera.Parameters parameters = camera.getParameters();\n\n\t\tif (parameters == null) {\n\t\t\tLog.w(TAG, \"Device error: no camera parameters are available. Proceeding without configuration.\");\n\t\t\treturn;\n\t\t}\n\n\t\tLog.i(TAG, \"Initial camera parameters: \" + parameters.flatten());\n\n\t\tif (safeMode) {\n\t\t\tLog.w(TAG, \"In camera config safe mode -- most settings will not be honored\");\n\t\t}\n\n\t\tparameters.setPreviewSize(cameraResolution.x, cameraResolution.y);\n\t\tcamera.setParameters(parameters);\n\n\t\tCamera.Parameters afterParameters = camera.getParameters();\n\t\tCamera.Size afterSize = afterParameters.getPreviewSize();\n\t\tif (afterSize != null && (cameraResolution.x != afterSize.width || cameraResolution.y != afterSize.height)) {\n\t\t\tLog.w(TAG, \"Camera said it supported preview size \" + cameraResolution.x + 'x' + cameraResolution.y + \", but after setting it, preview size is \" + afterSize.width + 'x' + afterSize.height);\n\t\t\tcameraResolution.x = afterSize.width;\n\t\t\tcameraResolution.y = afterSize.height;\n\t\t}\n\n\t\t/** 设置相机预览为竖屏 */\n\t\tcamera.setDisplayOrientation(90);\n\t}\n\n\tpublic Point getCameraResolution() {\n\t\treturn cameraResolution;\n\t}\n\n\tpublic Point getScreenResolution() {\n\t\treturn screenResolution;\n\t}\n\n\t/**\n\t * 从相机支持的分辨率中计算出最适合的预览界面尺寸\n\t *\n\t * @param parameters\n\t * @param screenResolution\n\t * @return\n\t */\n\tprivate Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution) {\n\t\tList<Camera.Size> rawSupportedSizes = parameters.getSupportedPreviewSizes();\n\t\tif (rawSupportedSizes == null) {\n\t\t\tLog.w(TAG, \"Device returned no supported preview sizes; using default\");\n\t\t\tCamera.Size defaultSize = parameters.getPreviewSize();\n\t\t\treturn new Point(defaultSize.width, defaultSize.height);\n\t\t}\n\n\t\t// Sort by size, descending\n\t\tList<Camera.Size> supportedPreviewSizes = new ArrayList<Camera.Size>(rawSupportedSizes);\n\t\tCollections.sort(supportedPreviewSizes, new Comparator<Camera.Size>() {\n\t\t\t@Override\n\t\t\tpublic int compare(Camera.Size a, Camera.Size b) {\n\t\t\t\tint aPixels = a.height * a.width;\n\t\t\t\tint bPixels = b.height * b.width;\n\t\t\t\tif (bPixels < aPixels) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif (bPixels > aPixels) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t});\n\n\t\tif (Log.isLoggable(TAG, Log.INFO)) {\n\t\t\tStringBuilder previewSizesString = new StringBuilder();\n\t\t\tfor (Camera.Size supportedPreviewSize : supportedPreviewSizes) {\n\t\t\t\tpreviewSizesString.append(supportedPreviewSize.width).append('x').append(supportedPreviewSize.height).append(' ');\n\t\t\t}\n\t\t\tLog.i(TAG, \"Supported preview sizes: \" + previewSizesString);\n\t\t}\n\n\t\tdouble screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;\n\n\t\t// Remove sizes that are unsuitable\n\t\tIterator<Camera.Size> it = supportedPreviewSizes.iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tCamera.Size supportedPreviewSize = it.next();\n\t\t\tint realWidth = supportedPreviewSize.width;\n\t\t\tint realHeight = supportedPreviewSize.height;\n\t\t\tif (realWidth * realHeight < MIN_PREVIEW_PIXELS) {\n\t\t\t\tit.remove();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tboolean isCandidatePortrait = realWidth < realHeight;\n\t\t\tint maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;\n\t\t\tint maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;\n\n\t\t\tdouble aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;\n\t\t\tdouble distortion = Math.abs(aspectRatio - screenAspectRatio);\n\t\t\tif (distortion > MAX_ASPECT_DISTORTION) {\n\t\t\t\tit.remove();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {\n\t\t\t\tPoint exactPoint = new Point(realWidth, realHeight);\n\t\t\t\tLog.i(TAG, \"Found preview size exactly matching screen size: \" + exactPoint);\n\t\t\t\treturn exactPoint;\n\t\t\t}\n\t\t}\n\n\t\t// If no exact match, use largest preview size. This was not a great\n\t\t// idea on older devices because\n\t\t// of the additional computation needed. We're likely to get here on\n\t\t// newer Android 4+ devices, where\n\t\t// the CPU is much more powerful.\n\t\tif (!supportedPreviewSizes.isEmpty()) {\n\t\t\tCamera.Size largestPreview = supportedPreviewSizes.get(0);\n\t\t\tPoint largestSize = new Point(largestPreview.width, largestPreview.height);\n\t\t\tLog.i(TAG, \"Using largest suitable preview size: \" + largestSize);\n\t\t\treturn largestSize;\n\t\t}\n\n\t\t// If there is nothing at all suitable, return current preview size\n\t\tCamera.Size defaultPreview = parameters.getPreviewSize();\n\t\tPoint defaultSize = new Point(defaultPreview.width, defaultPreview.height);\n\t\tLog.i(TAG, \"No suitable preview sizes, using default: \" + defaultSize);\n\n\t\treturn defaultSize;\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/scan/CameraManager.java",
    "content": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.htmessage.yichatopen.widget.scan;\n\nimport android.content.Context;\nimport android.graphics.Point;\nimport android.hardware.Camera;\nimport android.util.Log;\n\nimport java.io.IOException;\n\n/**\n *\n * 邮箱: 1076559197@qq.com | tauchen1990@gmail.com\n *\n * 作者: 陈涛\n *\n * 日期: 2014年8月20日\n *\n * 描述: 该类主要负责对相机的操作\n *\n */\npublic final class CameraManager {\n\n\tprivate static final String TAG = CameraManager.class.getSimpleName();\n\n\tprivate final CameraConfigurationManager configManager;\n\n\tprivate Camera camera;\n\tprivate boolean initialized;\n\n\tpublic CameraManager(Context context) {\n\t\tthis.configManager = new CameraConfigurationManager(context);\n\t}\n\n\t/**\n\t * Opens the camera driver and initializes the hardware parameters.\n\t *\n\t * @param\n\t *            The surface object which the camera will draw preview frames\n\t *            into.\n\t * @throws IOException\n\t *             Indicates the camera driver failed to open.\n\t */\n\tpublic synchronized void openDriver() throws IOException {\n\t\tCamera theCamera = camera;\n\t\tif (theCamera == null) {\n\t\t\ttheCamera = Camera.open();\n\t\t\tif (theCamera == null) {\n\t\t\t\tthrow new IOException();\n\t\t\t}\n\t\t\tcamera = theCamera;\n\t\t}\n\n\t\tif (!initialized) {\n\t\t\tinitialized = true;\n\t\t\tconfigManager.initFromCameraParameters(theCamera);\n\t\t}\n\n\t\tCamera.Parameters parameters = theCamera.getParameters();\n\t\tString parametersFlattened = parameters == null ? null : parameters.flatten(); // Save\n\t\t// these,\n\t\t// temporarily\n\t\ttry {\n\t\t\tconfigManager.setDesiredCameraParameters(theCamera, false);\n\t\t} catch (RuntimeException re) {\n\t\t\t// Driver failed\n\t\t\tLog.w(TAG, \"Camera rejected parameters. Setting only minimal safe-mode parameters\");\n\t\t\tLog.i(TAG, \"Resetting to saved camera params: \" + parametersFlattened);\n\t\t\t// Reset:\n\t\t\tif (parametersFlattened != null) {\n\t\t\t\tparameters = theCamera.getParameters();\n\t\t\t\tparameters.unflatten(parametersFlattened);\n\t\t\t\ttry {\n\t\t\t\t\ttheCamera.setParameters(parameters);\n\t\t\t\t\tconfigManager.setDesiredCameraParameters(theCamera, true);\n\t\t\t\t} catch (RuntimeException re2) {\n\t\t\t\t\t// Well, darn. Give up\n\t\t\t\t\tLog.w(TAG, \"Camera rejected even safe-mode parameters! No configuration\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tpublic synchronized boolean isOpen() {\n\t\treturn camera != null;\n\t}\n\n\tpublic Camera getCamera(){\n\t\treturn camera;\n\t}\n\n\t/**\n\t * Closes the camera driver if still in use.\n\t */\n\tpublic synchronized void closeDriver() {\n\t\tif (camera != null) {\n\t\t\tcamera.release();\n\t\t\tcamera = null;\n\t\t}\n\t}\n\n\t/**\n\t * 获取相机分辨率\n\t *\n\t * @return\n\t */\n\tpublic Point getCameraResolution() {\n\t\treturn configManager.getCameraResolution();\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/scan/CameraPreview.java",
    "content": "/*\n * Barebones implementation of displaying camera preview.\n * \n * Created by lisah0 on 2012-02-24\n */\npackage com.htmessage.yichatopen.widget.scan;\n\nimport android.content.Context;\nimport android.hardware.Camera;\nimport android.hardware.Camera.AutoFocusCallback;\nimport android.hardware.Camera.PreviewCallback;\nimport android.util.Log;\nimport android.view.SurfaceHolder;\nimport android.view.SurfaceView;\n\nimport java.io.IOException;\n\n/** A basic Camera preview class */\npublic class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {\n\tprivate SurfaceHolder mHolder;\n\tprivate Camera mCamera;\n\tprivate PreviewCallback previewCallback;\n\tprivate AutoFocusCallback autoFocusCallback;\n\n\t@SuppressWarnings(\"deprecation\")\n\tpublic CameraPreview(Context context, Camera camera, PreviewCallback previewCb, AutoFocusCallback autoFocusCb) {\n\t\tsuper(context);\n\t\tmCamera = camera;\n\t\tpreviewCallback = previewCb;\n\t\tautoFocusCallback = autoFocusCb;\n\n\t\t/*\n\t\t * Set camera to continuous focus if supported, otherwise use software\n\t\t * auto-focus. Only works for API level >=9.\n\t\t */\n\t\t/*\n\t\t * Camera.Parameters parameters = camera.getParameters(); for (String f\n\t\t * : parameters.getSupportedFocusModes()) { if (f ==\n\t\t * Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {\n\t\t * mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);\n\t\t * autoFocusCallback = null; break; } }\n\t\t */\n\n\t\t// Install a SurfaceHolder.Callback so we get notified when the\n\t\t// underlying surface is created and destroyed.\n\t\tmHolder = getHolder();\n\t\tmHolder.addCallback(this);\n\n\t\t// deprecated setting, but required on Android versions prior to 3.0\n\t\tmHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);\n\t}\n\n\tpublic void surfaceCreated(SurfaceHolder holder) {\n\t\t// The Surface has been created, now tell the camera where to draw the\n\t\t// preview.\n\t\ttry {\n\t\t\tmCamera.setPreviewDisplay(holder);\n\t\t} catch (IOException e) {\n\t\t\tLog.d(\"DBG\", \"Error setting camera preview: \" + e.getMessage());\n\t\t}\n\t}\n\n\tpublic void surfaceDestroyed(SurfaceHolder holder) {\n\t\t// Camera preview released in activity\n\t}\n\n\tpublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {\n\t\t/*\n\t\t * If your preview can change or rotate, take care of those events here.\n\t\t * Make sure to stop the preview before resizing or reformatting it.\n\t\t */\n\t\tif (mHolder.getSurface() == null) {\n\t\t\t// preview surface does not exist\n\t\t\treturn;\n\t\t}\n\n\t\t// stop preview before making changes\n\t\ttry {\n\t\t\tmCamera.stopPreview();\n\t\t} catch (Exception e) {\n\t\t\t// ignore: tried to stop a non-existent preview\n\t\t}\n\n\t\ttry {\n\t\t\t// Hard code camera surface rotation 90 degs to match Activity view\n\t\t\t// in portrait\n\t\t\tmCamera.setDisplayOrientation(90);\n\n\t\t\tmCamera.setPreviewDisplay(mHolder);\n\t\t\tmCamera.setPreviewCallback(previewCallback);\n\t\t\tmCamera.startPreview();\n\t\t\tmCamera.autoFocus(autoFocusCallback);\n\t\t} catch (Exception e) {\n\t\t\tLog.d(\"DBG\", \"Error starting camera preview: \" + e.getMessage());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/CircleImageView.java",
    "content": "package com.htmessage.yichatopen.widget.swipyrefresh;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.graphics.RadialGradient;\nimport android.graphics.Shader;\nimport android.graphics.drawable.ShapeDrawable;\nimport android.graphics.drawable.shapes.OvalShape;\nimport android.support.v4.view.ViewCompat;\nimport android.view.animation.Animation;\nimport android.widget.ImageView;\n\n/**\n * Private class created to work around issues with AnimationListeners being\n * called before the animation is actually complete and support shadows on older\n * platforms.\n * \n * @hide\n */\nclass CircleImageView extends ImageView {\n\n\tprivate static final int KEY_SHADOW_COLOR = 0x1E000000;\n\tprivate static final int FILL_SHADOW_COLOR = 0x3D000000;\n\t// PX\n\tprivate static final float X_OFFSET = 0f;\n\tprivate static final float Y_OFFSET = 1.75f;\n\tprivate static final float SHADOW_RADIUS = 3.5f;\n\tprivate static final int SHADOW_ELEVATION = 4;\n\n\tprivate Animation.AnimationListener mListener;\n\tprivate int mShadowRadius;\n\n\tpublic CircleImageView(Context context, int color, final float radius) {\n\t\tsuper(context);\n\t\tfinal float density = getContext().getResources().getDisplayMetrics().density;\n\t\tfinal int diameter = (int) (radius * density * 2);\n\t\tfinal int shadowYOffset = (int) (density * Y_OFFSET);\n\t\tfinal int shadowXOffset = (int) (density * X_OFFSET);\n\n\t\tmShadowRadius = (int) (density * SHADOW_RADIUS);\n\n\t\tShapeDrawable circle;\n\t\tif (elevationSupported()) {\n\t\t\tcircle = new ShapeDrawable(new OvalShape());\n\t\t\tViewCompat.setElevation(this, SHADOW_ELEVATION * density);\n\t\t} else {\n\t\t\tOvalShape oval = new OvalShadow(mShadowRadius, diameter);\n\t\t\tcircle = new ShapeDrawable(oval);\n\t\t\tViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE,\n\t\t\t\t\tcircle.getPaint());\n\t\t\tcircle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset,\n\t\t\t\t\tshadowYOffset, KEY_SHADOW_COLOR);\n\t\t\tfinal int padding = (int) mShadowRadius;\n\t\t\t// set padding so the inner image sits correctly within the shadow.\n\t\t\tsetPadding(padding, padding, padding, padding);\n\t\t}\n\t\tcircle.getPaint().setColor(color);\n\t\tsetBackgroundDrawable(circle);\n\t}\n\n\tprivate boolean elevationSupported() {\n\t\treturn android.os.Build.VERSION.SDK_INT >= 21;\n\t}\n\n\t@Override\n\tprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n\t\tsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);\n\t\tif (!elevationSupported()) {\n\t\t\tsetMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2,\n\t\t\t\t\tgetMeasuredHeight() + mShadowRadius * 2);\n\t\t}\n\t}\n\n\tpublic void setAnimationListener(Animation.AnimationListener listener) {\n\t\tmListener = listener;\n\t}\n\n\t@Override\n\tpublic void onAnimationStart() {\n\t\tsuper.onAnimationStart();\n\t\tif (mListener != null) {\n\t\t\tmListener.onAnimationStart(getAnimation());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onAnimationEnd() {\n\t\tsuper.onAnimationEnd();\n\t\tif (mListener != null) {\n\t\t\tmListener.onAnimationEnd(getAnimation());\n\t\t}\n\t}\n\n\t/**\n\t * Update the background color of the circle image view.\n\t */\n\t@SuppressWarnings(\"ResourceType\")\n\tpublic void setBackgroundColor(int colorRes) {\n\t\tif (getBackground() instanceof ShapeDrawable) {\n\t\t\tfinal Resources res = getResources();\n\t\t\t((ShapeDrawable) getBackground()).getPaint().setColor(\n\t\t\t\t\tres.getColor(colorRes));\n\t\t}\n\t}\n\n\tprivate class OvalShadow extends OvalShape {\n\t\tprivate RadialGradient mRadialGradient;\n\t\tprivate int mShadowRadius;\n\t\tprivate Paint mShadowPaint;\n\t\tprivate int mCircleDiameter;\n\n\t\tpublic OvalShadow(int shadowRadius, int circleDiameter) {\n\t\t\tsuper();\n\t\t\tmShadowPaint = new Paint();\n\t\t\tmShadowRadius = shadowRadius;\n\t\t\tmCircleDiameter = circleDiameter;\n\t\t\tmRadialGradient = new RadialGradient(mCircleDiameter / 2,\n\t\t\t\t\tmCircleDiameter / 2, mShadowRadius, new int[] {\n\t\t\t\t\t\t\tFILL_SHADOW_COLOR, Color.TRANSPARENT }, null,\n\t\t\t\t\tShader.TileMode.CLAMP);\n\t\t\tmShadowPaint.setShader(mRadialGradient);\n\t\t}\n\n\t\t@Override\n\t\tpublic void draw(Canvas canvas, Paint paint) {\n\t\t\tfinal int viewWidth = CircleImageView.this.getWidth();\n\t\t\tfinal int viewHeight = CircleImageView.this.getHeight();\n\t\t\tcanvas.drawCircle(viewWidth / 2, viewHeight / 2,\n\t\t\t\t\t(mCircleDiameter / 2 + mShadowRadius), mShadowPaint);\n\t\t\tcanvas.drawCircle(viewWidth / 2, viewHeight / 2,\n\t\t\t\t\t(mCircleDiameter / 2), paint);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/MaterialProgressDrawable.java",
    "content": "package com.htmessage.yichatopen.widget.swipyrefresh;\n\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.ColorFilter;\nimport android.graphics.Paint;\nimport android.graphics.Paint.Style;\nimport android.graphics.Path;\nimport android.graphics.PixelFormat;\nimport android.graphics.Rect;\nimport android.graphics.RectF;\nimport android.graphics.drawable.Animatable;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.IntDef;\nimport android.support.annotation.NonNull;\nimport android.util.DisplayMetrics;\nimport android.view.View;\nimport android.view.animation.AccelerateDecelerateInterpolator;\nimport android.view.animation.Animation;\nimport android.view.animation.Interpolator;\nimport android.view.animation.LinearInterpolator;\nimport android.view.animation.Transformation;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.util.ArrayList;\n\n/**\n * Fancy progress indicator for Material theme.\n *\n * @hide \n */\nclass MaterialProgressDrawable extends Drawable implements Animatable {\n    private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();\n    private static final Interpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator();\n    private static final Interpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator();\n    private static final Interpolator EASE_INTERPOLATOR = new AccelerateDecelerateInterpolator();\n\n    @Retention(RetentionPolicy.CLASS)\n    @IntDef({LARGE, DEFAULT})\n    public @interface ProgressDrawableSize {}\n    // Maps to ProgressBar.Large style\n    static final int LARGE = 0;\n    // Maps to ProgressBar default style\n    static final int DEFAULT = 1;\n\n    // Maps to ProgressBar default style\n    private static final int CIRCLE_DIAMETER = 40;\n    private static final float CENTER_RADIUS = 8.75f; //should add up to 10 when + stroke_width\n    private static final float STROKE_WIDTH = 2.5f;\n\n    // Maps to ProgressBar.Large style\n    private static final int CIRCLE_DIAMETER_LARGE = 56;\n    private static final float CENTER_RADIUS_LARGE = 12.5f;\n    private static final float STROKE_WIDTH_LARGE = 3f;\n\n    private final int[] COLORS = new int[] {\n        Color.BLACK\n    };\n\n    /** The duration of a single progress spin in milliseconds. */\n    private static final int ANIMATION_DURATION = 1000 * 80 / 60;\n\n    /** The number of points in the progress \"star\". */\n    private static final float NUM_POINTS = 5f;\n    /** The list of animators operating on this drawable. */\n    private final ArrayList<Animation> mAnimators = new ArrayList<Animation>();\n\n    /** The indicator ring, used to manage animation state. */\n    private final Ring mRing;\n\n    /** Canvas rotation in degrees. */\n    private float mRotation;\n\n    /** Layout info for the arrowhead in dp */\n    private static final int ARROW_WIDTH = 10;\n    private static final int ARROW_HEIGHT = 5;\n    private static final float ARROW_OFFSET_ANGLE = 5;\n\n    /** Layout info for the arrowhead for the large spinner in dp */\n    private static final int ARROW_WIDTH_LARGE = 12;\n    private static final int ARROW_HEIGHT_LARGE = 6;\n    private static final float MAX_PROGRESS_ARC = .8f;\n\n    private Resources mResources;\n    private View mParent;\n    private Animation mAnimation;\n    private float mRotationCount;\n    private double mWidth;\n    private double mHeight;\n    private Animation mFinishAnimation;\n\n    public MaterialProgressDrawable(Context context, View parent) {\n        mParent = parent;\n        mResources = context.getResources();\n\n        mRing = new Ring(mCallback);\n        mRing.setColors(COLORS);\n\n        updateSizes(DEFAULT);\n        setupAnimators();\n    }\n\n    private void setSizeParameters(double progressCircleWidth, double progressCircleHeight,\n            double centerRadius, double strokeWidth, float arrowWidth, float arrowHeight) {\n        final Ring ring = mRing;\n        final DisplayMetrics metrics = mResources.getDisplayMetrics();\n        final float screenDensity = metrics.density;\n\n        mWidth = progressCircleWidth * screenDensity;\n        mHeight = progressCircleHeight * screenDensity;\n        ring.setStrokeWidth((float) strokeWidth * screenDensity);\n        ring.setCenterRadius(centerRadius * screenDensity);\n        ring.setColorIndex(0);\n        ring.setArrowDimensions(arrowWidth * screenDensity, arrowHeight * screenDensity);\n        ring.setInsets((int) mWidth, (int) mHeight);\n    }\n\n    /**\n     * Set the overall size for the progress spinner. This updates the radius\n     * and stroke width of the ring.\n     *\n     * @param size One of {@link com.orangegangsters.github.swiperefreshlayout.MaterialProgressDrawable.LARGE} or\n     *            {@link com.orangegangsters.github.swiperefreshlayout.MaterialProgressDrawable.DEFAULT}\n     */\n    public void updateSizes(@ProgressDrawableSize int size) {\n        if (size == LARGE) {\n            setSizeParameters(CIRCLE_DIAMETER_LARGE, CIRCLE_DIAMETER_LARGE, CENTER_RADIUS_LARGE,\n                    STROKE_WIDTH_LARGE, ARROW_WIDTH_LARGE, ARROW_HEIGHT_LARGE);\n        } else {\n            setSizeParameters(CIRCLE_DIAMETER, CIRCLE_DIAMETER, CENTER_RADIUS, STROKE_WIDTH,\n                    ARROW_WIDTH, ARROW_HEIGHT);\n        }\n    }\n\n    /**\n     * @param show Set to true to display the arrowhead on the progress spinner.\n     */\n    public void showArrow(boolean show) {\n        mRing.setShowArrow(show);\n    }\n\n    /**\n     * @param scale Set the scale of the arrowhead for the spinner.\n     */\n    public void setArrowScale(float scale) {\n        mRing.setArrowScale(scale);\n    }\n\n    /**\n     * Set the start and end trim for the progress spinner arc.\n     *\n     * @param startAngle start angle\n     * @param endAngle end angle\n     */\n    public void setStartEndTrim(float startAngle, float endAngle) {\n        mRing.setStartTrim(startAngle);\n        mRing.setEndTrim(endAngle);\n    }\n\n    /**\n     * Set the amount of rotation to apply to the progress spinner.\n     *\n     * @param rotation Rotation is from [0..1]\n     */\n    public void setProgressRotation(float rotation) {\n        mRing.setRotation(rotation);\n    }\n\n    /**\n     * Update the background color of the circle image view.\n     */\n    public void setBackgroundColor(int color) {\n        mRing.setBackgroundColor(color);\n     }\n\n    /**\n     * Set the colors used in the progress animation from color resources.\n     * The first color will also be the color of the bar that grows in response\n     * to a user swipe gesture.\n     *\n     * @param colors\n     */\n    public void setColorSchemeColors(int... colors) {\n        mRing.setColors(colors);\n        mRing.setColorIndex(0);\n    }\n\n    @Override\n    public int getIntrinsicHeight() {\n        return (int) mHeight;\n    }\n\n    @Override\n    public int getIntrinsicWidth() {\n        return (int) mWidth;\n    }\n\n    @Override\n    public void draw(Canvas c) {\n        final Rect bounds = getBounds();\n        final int saveCount = c.save();\n        c.rotate(mRotation, bounds.exactCenterX(), bounds.exactCenterY());\n        mRing.draw(c, bounds);\n        c.restoreToCount(saveCount);\n    }\n\n    @Override\n    public void setAlpha(int alpha) {\n        mRing.setAlpha(alpha);\n    }\n\n    public int getAlpha() {\n        return mRing.getAlpha();\n    }\n\n    @Override\n    public void setColorFilter(ColorFilter colorFilter) {\n        mRing.setColorFilter(colorFilter);\n    }\n\n    @SuppressWarnings(\"unused\")\n    void setRotation(float rotation) {\n        mRotation = rotation;\n        invalidateSelf();\n    }\n\n    @SuppressWarnings(\"unused\")\n    private float getRotation() {\n        return mRotation;\n    }\n\n    @Override\n    public int getOpacity() {\n        return PixelFormat.TRANSLUCENT;\n    }\n\n    @Override\n    public boolean isRunning() {\n        final ArrayList<Animation> animators = mAnimators;\n        final int N = animators.size();\n        for (int i = 0; i < N; i++) {\n            final Animation animator = animators.get(i);\n            if (animator.hasStarted() && !animator.hasEnded()) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public void start() {\n        mAnimation.reset();\n        mRing.storeOriginals();\n        // Already showing some part of the ring\n        if (mRing.getEndTrim() != mRing.getStartTrim()) {\n            mParent.startAnimation(mFinishAnimation);\n        } else {\n            mRing.setColorIndex(0);\n            mRing.resetOriginals();\n            mParent.startAnimation(mAnimation);\n        }\n    }\n\n    @Override\n    public void stop() {\n        mParent.clearAnimation();\n        setRotation(0);\n        mRing.setShowArrow(false);\n        mRing.setColorIndex(0);\n        mRing.resetOriginals();\n    }\n\n    private void setupAnimators() {\n        final Ring ring = mRing;\n        final Animation finishRingAnimation = new Animation() {\n            public void applyTransformation(float interpolatedTime, Transformation t) {\n                // shrink back down and complete a full rotation before starting other circles\n                // Rotation goes between [0..1].\n                float targetRotation = (float) (Math.floor(ring.getStartingRotation()\n                        / MAX_PROGRESS_ARC) + 1f);\n                final float startTrim = ring.getStartingStartTrim()\n                        + (ring.getStartingEndTrim() - ring.getStartingStartTrim())\n                        * interpolatedTime;\n                ring.setStartTrim(startTrim);\n                final float rotation = ring.getStartingRotation()\n                        + ((targetRotation - ring.getStartingRotation()) * interpolatedTime);\n                ring.setRotation(rotation);\n                ring.setArrowScale(1 - interpolatedTime);\n            }\n        };\n        finishRingAnimation.setInterpolator(EASE_INTERPOLATOR);\n        finishRingAnimation.setDuration(ANIMATION_DURATION/2);\n        finishRingAnimation.setAnimationListener(new Animation.AnimationListener() {\n\n            @Override\n            public void onAnimationStart(Animation animation) {\n            }\n\n            @Override\n            public void onAnimationEnd(Animation animation) {\n                ring.goToNextColor();\n                ring.storeOriginals();\n                ring.setShowArrow(false);\n                mParent.startAnimation(mAnimation);\n            }\n\n            @Override\n            public void onAnimationRepeat(Animation animation) {\n            }\n        });\n        final Animation animation = new Animation() {\n            @Override\n            public void applyTransformation(float interpolatedTime, Transformation t) {\n                // The minProgressArc is calculated from 0 to create an angle that\n                // matches the stroke width.\n                final float minProgressArc = (float) Math.toRadians(ring.getStrokeWidth()\n                        / (2 * Math.PI * ring.getCenterRadius()));\n                final float startingEndTrim = ring.getStartingEndTrim();\n                final float startingTrim = ring.getStartingStartTrim();\n                final float startingRotation = ring.getStartingRotation();\n\n                // Offset the minProgressArc to where the endTrim is located.\n                final float minArc = MAX_PROGRESS_ARC - minProgressArc;\n                final float endTrim = startingEndTrim\n                        + (minArc * START_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));\n                ring.setEndTrim(endTrim);\n\n                final float startTrim = startingTrim\n                        + (MAX_PROGRESS_ARC * END_CURVE_INTERPOLATOR\n                                .getInterpolation(interpolatedTime));\n                ring.setStartTrim(startTrim);\n\n                final float rotation = startingRotation + (0.25f * interpolatedTime);\n                ring.setRotation(rotation);\n\n                float groupRotation = ((720.0f / NUM_POINTS) * interpolatedTime)\n                        + (720.0f * (mRotationCount / NUM_POINTS));\n                setRotation(groupRotation);\n            }\n        };\n        animation.setRepeatCount(Animation.INFINITE);\n        animation.setRepeatMode(Animation.RESTART);\n        animation.setInterpolator(LINEAR_INTERPOLATOR);\n        animation.setDuration(ANIMATION_DURATION);\n        animation.setAnimationListener(new Animation.AnimationListener() {\n\n            @Override\n            public void onAnimationStart(Animation animation) {\n                mRotationCount = 0;\n            }\n\n            @Override\n            public void onAnimationEnd(Animation animation) {\n                // do nothing\n            }\n\n            @Override\n            public void onAnimationRepeat(Animation animation) {\n                ring.storeOriginals();\n                ring.goToNextColor();\n                ring.setStartTrim(ring.getEndTrim());\n                mRotationCount = (mRotationCount + 1) % (NUM_POINTS);\n            }\n        });\n        mFinishAnimation = finishRingAnimation;\n        mAnimation = animation;\n    }\n\n    private final Callback mCallback = new Callback() {\n        @Override\n        public void invalidateDrawable(Drawable d) {\n            invalidateSelf();\n        }\n\n        @Override\n        public void scheduleDrawable(Drawable d, Runnable what, long when) {\n            scheduleSelf(what, when);\n        }\n\n        @Override\n        public void unscheduleDrawable(Drawable d, Runnable what) {\n            unscheduleSelf(what);\n        }\n    };\n\n    private static class Ring {\n        private final RectF mTempBounds = new RectF();\n        private final Paint mPaint = new Paint();\n        private final Paint mArrowPaint = new Paint();\n\n        private final Callback mCallback;\n\n        private float mStartTrim = 0.0f;\n        private float mEndTrim = 0.0f;\n        private float mRotation = 0.0f;\n        private float mStrokeWidth = 5.0f;\n        private float mStrokeInset = 2.5f;\n\n        private int[] mColors;\n        // mColorIndex represents the offset into the available mColors that the\n        // progress circle should currently display. As the progress circle is\n        // animating, the mColorIndex moves by one to the next available color.\n        private int mColorIndex;\n        private float mStartingStartTrim;\n        private float mStartingEndTrim;\n        private float mStartingRotation;\n        private boolean mShowArrow;\n        private Path mArrow;\n        private float mArrowScale;\n        private double mRingCenterRadius;\n        private int mArrowWidth;\n        private int mArrowHeight;\n        private int mAlpha;\n        private final Paint mCirclePaint = new Paint();\n        private int mBackgroundColor;\n\n        public Ring(Callback callback) {\n            mCallback = callback;\n\n            mPaint.setStrokeCap(Paint.Cap.SQUARE);\n            mPaint.setAntiAlias(true);\n            mPaint.setStyle(Style.STROKE);\n\n            mArrowPaint.setStyle(Style.FILL);\n            mArrowPaint.setAntiAlias(true);\n        }\n\n        public void setBackgroundColor(int color) {\n            mBackgroundColor = color;\n        }\n\n        /**\n         * Set the dimensions of the arrowhead.\n         *\n         * @param width Width of the hypotenuse of the arrow head\n         * @param height Height of the arrow point\n         */\n        public void setArrowDimensions(float width, float height) {\n            mArrowWidth = (int) width;\n            mArrowHeight = (int) height;\n        }\n\n        /**\n         * Draw the progress spinner\n         */\n        public void draw(Canvas c, Rect bounds) {\n            final RectF arcBounds = mTempBounds;\n            arcBounds.set(bounds);\n            arcBounds.inset(mStrokeInset, mStrokeInset);\n\n            final float startAngle = (mStartTrim + mRotation) * 360;\n            final float endAngle = (mEndTrim + mRotation) * 360;\n            float sweepAngle = endAngle - startAngle;\n\n            mPaint.setColor(mColors[mColorIndex]);\n            c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);\n\n            drawTriangle(c, startAngle, sweepAngle, bounds);\n\n            if (mAlpha < 255) {\n                mCirclePaint.setColor(mBackgroundColor);\n                mCirclePaint.setAlpha(255 - mAlpha);\n                c.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), bounds.width() / 2,\n                        mCirclePaint);\n            }\n        }\n\n        private void drawTriangle(Canvas c, float startAngle, float sweepAngle, Rect bounds) {\n            if (mShowArrow) {\n                if (mArrow == null) {\n                    mArrow = new Path();\n                    mArrow.setFillType(Path.FillType.EVEN_ODD);\n                } else {\n                    mArrow.reset();\n                }\n\n                // Adjust the position of the triangle so that it is inset as\n                // much as the arc, but also centered on the arc.\n                float inset = (int) mStrokeInset / 2 * mArrowScale;\n                float x = (float) (mRingCenterRadius * Math.cos(0) + bounds.exactCenterX());\n                float y = (float) (mRingCenterRadius * Math.sin(0) + bounds.exactCenterY());\n\n                // Update the path each time. This works around an issue in SKIA\n                // where concatenating a rotation matrix to a scale matrix\n                // ignored a starting negative rotation. This appears to have\n                // been fixed as of API 21.\n                mArrow.moveTo(0, 0);\n                mArrow.lineTo(mArrowWidth * mArrowScale, 0);\n                mArrow.lineTo((mArrowWidth * mArrowScale / 2), (mArrowHeight\n                        * mArrowScale));\n                mArrow.offset(x - inset, y);\n                mArrow.close();\n                // draw a triangle\n                mArrowPaint.setColor(mColors[mColorIndex]);\n                c.rotate(startAngle + sweepAngle - ARROW_OFFSET_ANGLE, bounds.exactCenterX(),\n                        bounds.exactCenterY());\n                c.drawPath(mArrow, mArrowPaint);\n            }\n        }\n\n        /**\n         * Set the colors the progress spinner alternates between.\n         *\n         * @param colors Array of integers describing the colors. Must be non-<code>null</code>.\n         */\n        public void setColors(@NonNull int[] colors) {\n            mColors = colors;\n            // if colors are reset, make sure to reset the color index as well\n            setColorIndex(0);\n        }\n\n        /**\n         * @param index Index into the color array of the color to display in\n         *            the progress spinner.\n         */\n        public void setColorIndex(int index) {\n            mColorIndex = index;\n        }\n\n        /**\n         * Proceed to the next available ring color. This will automatically\n         * wrap back to the beginning of colors.\n         */\n        public void goToNextColor() {\n            mColorIndex = (mColorIndex + 1) % (mColors.length);\n        }\n\n        public void setColorFilter(ColorFilter filter) {\n            mPaint.setColorFilter(filter);\n            invalidateSelf();\n        }\n\n        /**\n         * @param alpha Set the alpha of the progress spinner and associated arrowhead.\n         */\n        public void setAlpha(int alpha) {\n            mAlpha = alpha;\n        }\n\n        /**\n         * @return Current alpha of the progress spinner and arrowhead.\n         */\n        public int getAlpha() {\n            return mAlpha;\n        }\n\n        /**\n         * @param strokeWidth Set the stroke width of the progress spinner in pixels.\n         */\n        public void setStrokeWidth(float strokeWidth) {\n            mStrokeWidth = strokeWidth;\n            mPaint.setStrokeWidth(strokeWidth);\n            invalidateSelf();\n        }\n\n        @SuppressWarnings(\"unused\")\n        public float getStrokeWidth() {\n            return mStrokeWidth;\n        }\n\n        @SuppressWarnings(\"unused\")\n        public void setStartTrim(float startTrim) {\n            mStartTrim = startTrim;\n            invalidateSelf();\n        }\n\n        @SuppressWarnings(\"unused\")\n        public float getStartTrim() {\n            return mStartTrim;\n        }\n\n        public float getStartingStartTrim() {\n            return mStartingStartTrim;\n        }\n\n        public float getStartingEndTrim() {\n            return mStartingEndTrim;\n        }\n\n        @SuppressWarnings(\"unused\")\n        public void setEndTrim(float endTrim) {\n            mEndTrim = endTrim;\n            invalidateSelf();\n        }\n\n        @SuppressWarnings(\"unused\")\n        public float getEndTrim() {\n            return mEndTrim;\n        }\n\n        @SuppressWarnings(\"unused\")\n        public void setRotation(float rotation) {\n            mRotation = rotation;\n            invalidateSelf();\n        }\n\n        @SuppressWarnings(\"unused\")\n        public float getRotation() {\n            return mRotation;\n        }\n\n        public void setInsets(int width, int height) {\n            final float minEdge = (float) Math.min(width, height);\n            float insets;\n            if (mRingCenterRadius <= 0 || minEdge < 0) {\n                insets = (float) Math.ceil(mStrokeWidth / 2.0f);\n            } else {\n                insets = (float) (minEdge / 2.0f - mRingCenterRadius);\n            }\n            mStrokeInset = insets;\n        }\n\n        @SuppressWarnings(\"unused\")\n        public float getInsets() {\n            return mStrokeInset;\n        }\n\n        /**\n         * @param centerRadius Inner radius in px of the circle the progress\n         *            spinner arc traces.\n         */\n        public void setCenterRadius(double centerRadius) {\n            mRingCenterRadius = centerRadius;\n        }\n\n        public double getCenterRadius() {\n            return mRingCenterRadius;\n        }\n\n        /**\n         * @param show Set to true to show the arrow head on the progress spinner.\n         */\n        public void setShowArrow(boolean show) {\n            if (mShowArrow != show) {\n                mShowArrow = show;\n                invalidateSelf();\n            }\n        }\n\n        /**\n         * @param scale Set the scale of the arrowhead for the spinner.\n         */\n        public void setArrowScale(float scale) {\n            if (scale != mArrowScale) {\n                mArrowScale = scale;\n                invalidateSelf();\n            }\n        }\n\n        /**\n         * @return The amount the progress spinner is currently rotated, between [0..1].\n         */\n        public float getStartingRotation() {\n            return mStartingRotation;\n        }\n\n        /**\n         * If the start / end trim are offset to begin with, store them so that\n         * animation starts from that offset.\n         */\n        public void storeOriginals() {\n            mStartingStartTrim = mStartTrim;\n            mStartingEndTrim = mEndTrim;\n            mStartingRotation = mRotation;\n        }\n\n        /**\n         * Reset the progress spinner to default rotation, start and end angles.\n         */\n        public void resetOriginals() {\n            mStartingStartTrim = 0;\n            mStartingEndTrim = 0;\n            mStartingRotation = 0;\n            setStartTrim(0);\n            setEndTrim(0);\n            setRotation(0);\n        }\n\n        private void invalidateSelf() {\n            mCallback.invalidateDrawable(null);\n        }\n    }\n\n    /**\n     * Squishes the interpolation curve into the second half of the animation.\n     */\n    private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator {\n        @Override\n        public float getInterpolation(float input) {\n            return super.getInterpolation(Math.max(0, (input - 0.5f) * 2.0f));\n        }\n    }\n\n    /**\n     * Squishes the interpolation curve into the first half of the animation.\n     */\n    private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator {\n        @Override\n        public float getInterpolation(float input) {\n            return super.getInterpolation(Math.min(1, input * 2.0f));\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/SwipyRefreshLayout.java",
    "content": "package com.htmessage.yichatopen.widget.swipyrefresh;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.content.res.TypedArray;\nimport android.os.Build;\nimport android.support.v4.view.MotionEventCompat;\nimport android.support.v4.view.ViewCompat;\nimport android.util.AttributeSet;\nimport android.util.DisplayMetrics;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.ViewConfiguration;\nimport android.view.ViewGroup;\nimport android.view.animation.Animation;\nimport android.view.animation.Animation.AnimationListener;\nimport android.view.animation.DecelerateInterpolator;\nimport android.view.animation.Transformation;\nimport android.widget.AbsListView;\n\nimport com.htmessage.yichatopen.R;\n\n/**\n * The SwipeRefreshLayout should be used whenever the user can refresh the\n * contents of a view via a vertical swipe gesture. The activity that\n * instantiates this view should add an OnRefreshListener to be notified\n * whenever the swipe to refresh gesture is completed. The SwipeRefreshLayout\n * will notify the listener each and every time the gesture is completed again;\n * the listener is responsible for correctly determining when to actually\n * initiate a refresh of its content. If the listener determines there should\n * not be a refresh, it must call setRefreshing(false) to cancel any visual\n * indication of a refresh. If an activity wishes to show just the progress\n * animation, it should call setRefreshing(true). To disable the gesture and\n * progress animation, call setEnabled(false) on the view.\n * <p>\n * This layout should be made the parent of the view that will be refreshed as a\n * result of the gesture and can only support one direct child. This view will\n * also be made the target of the gesture and will be forced to match both the\n * width and the height supplied in this layout. The SwipeRefreshLayout does not\n * provide accessibility events; instead, a menu item must be provided to allow\n * refresh of the content wherever this gesture is used.\n * </p>\n */\n\n/**\n * 下拉刷新、加载更多、分页索引\n * @author xutao\n *\n */\npublic class SwipyRefreshLayout extends ViewGroup {\n\t\n\t/** 是不是下拉 **/\n\tpublic boolean isTop;\n\t\n\t/** 第一页 **/\n\tpublic int firstIndex = 0;\n\t\n\t/** 页数索引 **/\n\tpublic int index = firstIndex;\n\t\n    // Maps to ProgressBar.Large style\n    public static final int LARGE = MaterialProgressDrawable.LARGE;\n    // Maps to ProgressBar default style\n    public static final int DEFAULT = MaterialProgressDrawable.DEFAULT;\n\n    private static final String LOG_TAG = SwipyRefreshLayout.class.getSimpleName();\n\n    private static final int MAX_ALPHA = 255;\n    private static final int STARTING_PROGRESS_ALPHA = (int) (.3f * MAX_ALPHA);\n\n    private static final int CIRCLE_DIAMETER = 40;\n    private static final int CIRCLE_DIAMETER_LARGE = 56;\n\n    private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;\n    private static final int INVALID_POINTER = -1;\n    private static final float DRAG_RATE = .5f;\n\n    // Max amount of circle that can be filled by progress during swipe gesture,\n    // where 1.0 is a full circle\n    private static final float MAX_PROGRESS_ANGLE = .8f;\n\n    private static final int SCALE_DOWN_DURATION = 150;\n\n    private static final int ALPHA_ANIMATION_DURATION = 300;\n\n    private static final int ANIMATE_TO_TRIGGER_DURATION = 200;\n\n    private static final int ANIMATE_TO_START_DURATION = 200;\n\n    // Default background for the progress spinner\n    private static final int CIRCLE_BG_LIGHT = 0xFFFAFAFA;\n    // Default offset in dips from the top of the view to where the progress spinner should stop\n    private static final int DEFAULT_CIRCLE_TARGET = 64;\n\n    private View mTarget; // the target of the gesture\n    private SwipyRefreshLayoutDirection mDirection;\n    private boolean mBothDirection;\n    private OnRefreshListener mListener;\n    private boolean mRefreshing = false;\n    private int mTouchSlop;\n    private float mTotalDragDistance = -1;\n    private int mMediumAnimationDuration;\n    private int mCurrentTargetOffsetTop;\n    // Whether or not the starting offset has been determined.\n    private boolean mOriginalOffsetCalculated = false;\n\n    private float mInitialMotionY;\n    private boolean mIsBeingDragged;\n    private int mActivePointerId = INVALID_POINTER;\n    // Whether this item is scaled up rather than clipped\n    private boolean mScale;\n\n    // Target is returning to its start offset because it was cancelled or a\n    // refresh was triggered.\n    private boolean mReturningToStart;\n    private final DecelerateInterpolator mDecelerateInterpolator;\n    private static final int[] LAYOUT_ATTRS = new int[]{\n            android.R.attr.enabled\n    };\n\n    private CircleImageView mCircleView;\n    private int mCircleViewIndex = -1;\n\n    protected int mFrom;\n\n    private float mStartingScale;\n\n    protected int mOriginalOffsetTop;\n\n    private MaterialProgressDrawable mProgress;\n\n    private Animation mScaleAnimation;\n\n    private Animation mScaleDownAnimation;\n\n    private Animation mAlphaStartAnimation;\n\n    private Animation mAlphaMaxAnimation;\n\n    private Animation mScaleDownToStartAnimation;\n\n    private float mSpinnerFinalOffset;\n\n    private boolean mNotify;\n\n    private int mCircleWidth;\n\n    private int mCircleHeight;\n\n    // Whether the client has set a custom starting position;\n    private boolean mUsingCustomStart;\n\n    private AnimationListener mRefreshListener = new AnimationListener() {\n        @Override\n        public void onAnimationStart(Animation animation) {\n        }\n\n        @Override\n        public void onAnimationRepeat(Animation animation) {\n        }\n\n        @Override\n        public void onAnimationEnd(Animation animation) {\n            if (mRefreshing) {\n                // Make sure the progress view is fully visible\n                mProgress.setAlpha(MAX_ALPHA);\n                mProgress.start();\n                if (mNotify) {\n                    if (mListener != null) {\n                        if (isTop) {\n                        \tindex = firstIndex;\n                        \tmListener.onRefresh(index);\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tindex ++;\n\t\t\t\t\t\t\tmListener.onLoad(index);\n\t\t\t\t\t\t}\n                    }\n                }\n            } else {\n                mProgress.stop();\n                mCircleView.setVisibility(View.GONE);\n                setColorViewAlpha(MAX_ALPHA);\n                // Return the circle to its start position\n                if (mScale) {\n                    setAnimationProgress(0 /* animation complete and view is hidden */);\n                } else {\n                    setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCurrentTargetOffsetTop,\n                            true /* requires update */);\n                }\n            }\n            mCurrentTargetOffsetTop = mCircleView.getTop();\n        }\n    };\n\n    private void setColorViewAlpha(int targetAlpha) {\n        mCircleView.getBackground().setAlpha(targetAlpha);\n        mProgress.setAlpha(targetAlpha);\n    }\n\n    /**\n     * The refresh indicator starting and resting position is always positioned\n     * near the top of the refreshing content. This position is a consistent\n     * location, but can be adjusted in either direction based on whether or not\n     * there is a toolbar or actionbar present.\n     *\n     * @param scale Set to true if there is no view at a higher z-order than\n     *            where the progress spinner is set to appear.\n     * @param start The offset in pixels from the top of this view at which the\n     *            progress spinner should appear.\n     * @param end The offset in pixels from the top of this view at which the\n     *            progress spinner should come to rest after a successful swipe\n     *            gesture.\n     */\n    /*\n    public void setProgressViewOffset(boolean scale, int start, int end) {\n        mScale = scale;\n        mCircleView.setVisibility(View.GONE);\n        mOriginalOffsetTop = mCurrentTargetOffsetTop = start;\n        mSpinnerFinalOffset = end;\n        mUsingCustomStart = true;\n        mCircleView.invalidate();\n    }*/\n\n    /**\n     * The refresh indicator resting position is always positioned near the top\n     * of the refreshing content. This position is a consistent location, but\n     * can be adjusted in either direction based on whether or not there is a\n     * toolbar or actionbar present.\n     *\n     * @param scale Set to true if there is no view at a higher z-order than\n     *            where the progress spinner is set to appear.\n     * @param end The offset in pixels from the top of this view at which the\n     *            progress spinner should come to rest after a successful swipe\n     *            gesture.\n     */\n    /*\n    public void setProgressViewEndTarget(boolean scale, int end) {\n        mSpinnerFinalOffset = end;\n        mScale = scale;\n        mCircleView.invalidate();\n    }*/\n\n    /**\n     * One of DEFAULT, or LARGE.\n     */\n    public void setSize(int size) {\n        if (size != MaterialProgressDrawable.LARGE && size != MaterialProgressDrawable.DEFAULT) {\n            return;\n        }\n        final DisplayMetrics metrics = getResources().getDisplayMetrics();\n        if (size == MaterialProgressDrawable.LARGE) {\n            mCircleHeight = mCircleWidth = (int) (CIRCLE_DIAMETER_LARGE * metrics.density);\n        } else {\n            mCircleHeight = mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);\n        }\n        // force the bounds of the progress circle inside the circle view to\n        // update by setting it to null before updating its size and then\n        // re-setting it\n        mCircleView.setImageDrawable(null);\n        mProgress.updateSizes(size);\n        mCircleView.setImageDrawable(mProgress);\n    }\n\n    /**\n     * Simple constructor to use when creating a SwipeRefreshLayout from code.\n     *\n     * @param context\n     */\n    public SwipyRefreshLayout(Context context) {\n        this(context, null);\n    }\n\n    /**\n     * Constructor that is called when inflating SwipeRefreshLayout from XML.\n     *\n     * @param context\n     * @param attrs\n     */\n    @TargetApi(Build.VERSION_CODES.CUPCAKE)\n    public SwipyRefreshLayout(Context context, AttributeSet attrs) {\n        super(context, attrs);\n\n        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();\n\n        mMediumAnimationDuration = getResources().getInteger(\n                android.R.integer.config_mediumAnimTime);\n\n        setWillNotDraw(false);\n        mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);\n\n        final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);\n        setEnabled(a.getBoolean(0, true));\n        a.recycle();\n\n        final TypedArray a2 = context.obtainStyledAttributes(attrs, R.styleable.SwipyRefreshLayout);\n        SwipyRefreshLayoutDirection direction\n                = SwipyRefreshLayoutDirection.getFromInt(a2.getInt(R.styleable.SwipyRefreshLayout_direction, 0));\n        if (direction != SwipyRefreshLayoutDirection.BOTH) {\n            mDirection = direction;\n            mBothDirection = false;\n        } else {\n            mDirection = SwipyRefreshLayoutDirection.TOP;\n            mBothDirection = true;\n        }\n        a2.recycle();\n\n        final DisplayMetrics metrics = getResources().getDisplayMetrics();\n        mCircleWidth = (int) (CIRCLE_DIAMETER * metrics.density);\n        mCircleHeight = (int) (CIRCLE_DIAMETER * metrics.density);\n\n        createProgressView();\n        ViewCompat.setChildrenDrawingOrderEnabled(this, true);\n        // the absolute offset has to take into account that the circle starts at an offset\n        mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;\n        mTotalDragDistance = mSpinnerFinalOffset;\n        \n        //设置刷新动画颜色\n        setColorSchemeResources(android.R.color.holo_blue_light, \n        \t\tandroid.R.color.holo_red_light, \n        \t\tandroid.R.color.holo_orange_light, \n        \t\tandroid.R.color.holo_green_light);\n    }\n\n    protected int getChildDrawingOrder(int childCount, int i) {\n        if (mCircleViewIndex < 0) {\n            return i;\n        } else if (i == childCount - 1) {\n            // Draw the selected child last\n            return mCircleViewIndex;\n        } else if (i >= mCircleViewIndex) {\n            // Move the children after the selected child earlier one\n            return i + 1;\n        } else {\n            // Keep the children before the selected child the same\n            return i;\n        }\n    }\n\n    private void createProgressView() {\n        mCircleView = new CircleImageView(getContext(), CIRCLE_BG_LIGHT, CIRCLE_DIAMETER / 2);\n        mProgress = new MaterialProgressDrawable(getContext(), this);\n        mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);\n        mCircleView.setImageDrawable(mProgress);\n        mCircleView.setVisibility(View.GONE);\n        addView(mCircleView);\n    }\n\n    /**\n     * Set the listener to be notified when a refresh is triggered via the swipe\n     * gesture.\n     */\n    public void setOnRefreshListener(OnRefreshListener listener) {\n        mListener = listener;\n    }\n\n    /**\n     * Pre API 11, alpha is used to make the progress circle appear instead of scale.\n     */\n    private boolean isAlphaUsedForScale() {\n        return Build.VERSION.SDK_INT < 11;\n    }\n\n    /**\n     * Notify the widget that refresh state has changed. Do not call this when\n     * refresh is triggered by a swipe gesture.\n     *\n     * @param refreshing Whether or not the view should show refresh progress.\n     */\n    public void setRefreshing(boolean refreshing) {\n        if (refreshing && mRefreshing != refreshing) {\n            // scale and show\n            mRefreshing = refreshing;\n            int endTarget = 0;\n            if (!mUsingCustomStart) {\n                endTarget = (int) (mSpinnerFinalOffset + mOriginalOffsetTop);\n            } else {\n                endTarget = (int) mSpinnerFinalOffset;\n            }\n            setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop,\n                    true /* requires update */);\n            mNotify = false;\n            startScaleUpAnimation(mRefreshListener);\n        } else {\n            setRefreshing(refreshing, false /* notify */);\n        }\n    }\n\n    private void startScaleUpAnimation(AnimationListener listener) {\n        mCircleView.setVisibility(View.VISIBLE);\n        if (Build.VERSION.SDK_INT >= 11) {\n            // Pre API 11, alpha is used in place of scale up to show the\n            // progress circle appearing.\n            // Don't adjust the alpha during appearance otherwise.\n            mProgress.setAlpha(MAX_ALPHA);\n        }\n        mScaleAnimation = new Animation() {\n            @Override\n            public void applyTransformation(float interpolatedTime, Transformation t) {\n                setAnimationProgress(interpolatedTime);\n            }\n        };\n        mScaleAnimation.setDuration(mMediumAnimationDuration);\n        if (listener != null) {\n            mCircleView.setAnimationListener(listener);\n        }\n        mCircleView.clearAnimation();\n        mCircleView.startAnimation(mScaleAnimation);\n    }\n\n    /**\n     * Pre API 11, this does an alpha animation.\n     *\n     * @param progress\n     */\n    private void setAnimationProgress(float progress) {\n        if (isAlphaUsedForScale()) {\n            setColorViewAlpha((int) (progress * MAX_ALPHA));\n        } else {\n            ViewCompat.setScaleX(mCircleView, progress);\n            ViewCompat.setScaleY(mCircleView, progress);\n        }\n    }\n\n    private void setRefreshing(boolean refreshing, final boolean notify) {\n        if (mRefreshing != refreshing) {\n            mNotify = notify;\n            ensureTarget();\n            mRefreshing = refreshing;\n            if (mRefreshing) {\n                animateOffsetToCorrectPosition(mCurrentTargetOffsetTop, mRefreshListener);\n            } else {\n                startScaleDownAnimation(mRefreshListener);\n            }\n        }\n    }\n\n    private void startScaleDownAnimation(AnimationListener listener) {\n        mScaleDownAnimation = new Animation() {\n            @Override\n            public void applyTransformation(float interpolatedTime, Transformation t) {\n                setAnimationProgress(1 - interpolatedTime);\n            }\n        };\n        mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION);\n        mCircleView.setAnimationListener(listener);\n        mCircleView.clearAnimation();\n        mCircleView.startAnimation(mScaleDownAnimation);\n    }\n\n    @SuppressLint(\"NewApi\") private void startProgressAlphaStartAnimation() {\n        mAlphaStartAnimation = startAlphaAnimation(mProgress.getAlpha(), STARTING_PROGRESS_ALPHA);\n    }\n\n    @SuppressLint(\"NewApi\") private void startProgressAlphaMaxAnimation() {\n        mAlphaMaxAnimation = startAlphaAnimation(mProgress.getAlpha(), MAX_ALPHA);\n    }\n\n    private Animation startAlphaAnimation(final int startingAlpha, final int endingAlpha) {\n        // Pre API 11, alpha is used in place of scale. Don't also use it to\n        // show the trigger point.\n        if (mScale && isAlphaUsedForScale()) {\n            return null;\n        }\n        Animation alpha = new Animation() {\n            @Override\n            public void applyTransformation(float interpolatedTime, Transformation t) {\n                mProgress\n                        .setAlpha((int) (startingAlpha + ((endingAlpha - startingAlpha)\n                                * interpolatedTime)));\n            }\n        };\n        alpha.setDuration(ALPHA_ANIMATION_DURATION);\n        // Clear out the previous animation listeners.\n        mCircleView.setAnimationListener(null);\n        mCircleView.clearAnimation();\n        mCircleView.startAnimation(alpha);\n        return alpha;\n    }\n\n    /**\n     * Set the background color of the progress spinner disc.\n     *\n     * @param colorRes Resource id of the color.\n     */\n    public void setProgressBackgroundColor(int colorRes) {\n        mCircleView.setBackgroundColor(colorRes);\n        mProgress.setBackgroundColor(getResources().getColor(colorRes));\n    }\n\n    /**\n     * @deprecated Use {@link #setColorSchemeResources(int...)}\n     */\n    @Deprecated\n    public void setColorScheme(int... colors) {\n        setColorSchemeResources(colors);\n    }\n\n    /**\n     * Set the color resources used in the progress animation from color resources.\n     * The first color will also be the color of the bar that grows in response\n     * to a user swipe gesture.\n     *\n     * @param colorResIds\n     */\n    public void setColorSchemeResources(int... colorResIds) {\n        final Resources res = getResources();\n        int[] colorRes = new int[colorResIds.length];\n        for (int i = 0; i < colorResIds.length; i++) {\n            colorRes[i] = res.getColor(colorResIds[i]);\n        }\n        setColorSchemeColors(colorRes);\n    }\n\n    /**\n     * Set the colors used in the progress animation. The first\n     * color will also be the color of the bar that grows in response to a user\n     * swipe gesture.\n     *\n     * @param colors\n     */\n    public void setColorSchemeColors(int... colors) {\n        ensureTarget();\n        mProgress.setColorSchemeColors(colors);\n    }\n\n    /**\n     * @return Whether the SwipeRefreshWidget is actively showing refresh\n     * progress.\n     */\n    public boolean isRefreshing() {\n        return mRefreshing;\n    }\n\n    private void ensureTarget() {\n        // Don't bother getting the parent height if the parent hasn't been laid\n        // out yet.\n        if (mTarget == null) {\n            for (int i = 0; i < getChildCount(); i++) {\n                View child = getChildAt(i);\n                if (!child.equals(mCircleView)) {\n                    mTarget = child;\n                    break;\n                }\n            }\n        }\n    }\n\n    /**\n     * Set the distance to trigger a sync in dips\n     *\n     * @param distance\n     */\n    public void setDistanceToTriggerSync(int distance) {\n        mTotalDragDistance = distance;\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        final int width = getMeasuredWidth();\n        final int height = getMeasuredHeight();\n        if (getChildCount() == 0) {\n            return;\n        }\n        if (mTarget == null) {\n            ensureTarget();\n        }\n        if (mTarget == null) {\n            return;\n        }\n        final View child = mTarget;\n        final int childLeft = getPaddingLeft();\n        final int childTop = getPaddingTop();\n        final int childWidth = width - getPaddingLeft() - getPaddingRight();\n        final int childHeight = height - getPaddingTop() - getPaddingBottom();\n        child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);\n        int circleWidth = mCircleView.getMeasuredWidth();\n        int circleHeight = mCircleView.getMeasuredHeight();\n        mCircleView.layout((width / 2 - circleWidth / 2), mCurrentTargetOffsetTop,\n                (width / 2 + circleWidth / 2), mCurrentTargetOffsetTop + circleHeight);\n    }\n\n    @Override\n    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        if (mTarget == null) {\n            ensureTarget();\n        }\n        if (mTarget == null) {\n            return;\n        }\n        mTarget.measure(MeasureSpec.makeMeasureSpec(\n                getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),\n                MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(\n                getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));\n        mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleWidth, MeasureSpec.EXACTLY),\n                MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY));\n        if (!mUsingCustomStart && !mOriginalOffsetCalculated) {\n            mOriginalOffsetCalculated = true;\n\n            switch (mDirection) {\n                case BOTTOM:\n                    mCurrentTargetOffsetTop = mOriginalOffsetTop = getMeasuredHeight() - mCircleView.getMeasuredHeight();\n                    break;\n                case TOP:\n                default:  \n                    mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();\n                    break;\n            }\n        }\n        mCircleViewIndex = -1;\n        // Get the index of the circleview.\n        for (int index = 0; index < getChildCount(); index++) {\n            if (getChildAt(index) == mCircleView) {\n                mCircleViewIndex = index;\n                break;\n            }\n        }\n    }\n\n    /**\n     * @return Whether it is possible for the child view of this layout to\n     * scroll up. Override this if the child view is a custom view.\n     */\n    public boolean canChildScrollUp() {\n        if (Build.VERSION.SDK_INT < 14) {\n            if (mTarget instanceof AbsListView) {\n                final AbsListView absListView = (AbsListView) mTarget;\n                return absListView.getChildCount() > 0\n                        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)\n                        .getTop() < absListView.getPaddingTop());\n            } else {\n                return mTarget.getScrollY() > 0;\n            }\n        } else {\n            return ViewCompat.canScrollVertically(mTarget, -1);\n        }\n    }\n//    public boolean canChildScrollUp() {\n//        if (android.os.Build.VERSION.SDK_INT < 14) {\n//            if (mTarget instanceof AbsListView) {\n//                final AbsListView absListView = (AbsListView) mTarget;\n//                if (absListView.getLastVisiblePosition() + 1 == absListView.getCount()) {\n//                    int lastIndex = absListView.getLastVisiblePosition() - absListView.getFirstVisiblePosition();\n//\n//                    boolean res = absListView.getChildAt(lastIndex).getBottom() == absListView.getPaddingBottom();\n//\n//                    return res;\n//                }\n//                return true;\n//            } else {\n//                return mTarget.getScrollY() > 0;\n//            }\n//        } else {\n//            return ViewCompat.canScrollVertically(mTarget, 1);\n//        }\n//    }\n\n\n    public boolean canChildScrollDown() {\n        if (Build.VERSION.SDK_INT < 14) {\n            if (mTarget instanceof AbsListView) {\n                final AbsListView absListView = (AbsListView) mTarget;\n                try {\n                    if (absListView.getCount() > 0) {\n                        if (absListView.getLastVisiblePosition() + 1 == absListView.getCount()) {\n                            int lastIndex = absListView.getLastVisiblePosition() - absListView.getFirstVisiblePosition();\n                            return absListView.getChildAt(lastIndex).getBottom() == absListView.getPaddingBottom();\n                        }\n                    }\n                } catch (Exception e) {\n                    e.printStackTrace();\n                }\n                return true;\n            } else {\n                return true;\n            }\n        } else {\n            return ViewCompat.canScrollVertically(mTarget, 1);\n        }\n    }\n\n    @Override\n    public boolean onInterceptTouchEvent(MotionEvent ev) {\n        ensureTarget();\n\n        final int action = MotionEventCompat.getActionMasked(ev);\n\n        if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {\n            mReturningToStart = false;\n        }\n\n        switch (mDirection) {\n            case BOTTOM:\n                if (!isEnabled() || mReturningToStart || (!mBothDirection && canChildScrollDown()) || mRefreshing) {\n                    // Fail fast if we're not in a state where a swipe is possible\n                    return false;\n                }\n                break;\n            case TOP:\n            default:\n                if (!isEnabled() || mReturningToStart || (!mBothDirection && canChildScrollUp()) || mRefreshing) {\n                    // Fail fast if we're not in a state where a swipe is possible\n                    return false;\n                }\n                break;\n        }\n\n        switch (action) {\n            case MotionEvent.ACTION_DOWN:\n                setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true);\n                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);\n                mIsBeingDragged = false;\n                final float initialMotionY = getMotionEventY(ev, mActivePointerId);\n                if (initialMotionY == -1) {\n                    return false;\n                }\n                mInitialMotionY = initialMotionY;\n\n            case MotionEvent.ACTION_MOVE:\n                if (mActivePointerId == INVALID_POINTER) {\n                    return false;\n                }\n\n                final float y = getMotionEventY(ev, mActivePointerId);\n                if (y == -1) {\n                    return false;\n                }\n                if (mBothDirection) {\n                    if (y > mInitialMotionY) {\n                        setRawDirection(SwipyRefreshLayoutDirection.TOP);\n                    } else if (y < mInitialMotionY) {\n                        setRawDirection(SwipyRefreshLayoutDirection.BOTTOM);\n                    }\n                    if ((mDirection == SwipyRefreshLayoutDirection.BOTTOM && canChildScrollDown())\n                            || (mDirection == SwipyRefreshLayoutDirection.TOP && canChildScrollUp())) {\n                        return false;\n                    }\n                }\n                float yDiff;\n                switch (mDirection) {\n                    case BOTTOM:\n                        yDiff = mInitialMotionY - y;\n                        break;\n                    case TOP:\n                    default:\n                        yDiff = y - mInitialMotionY;\n                        break;\n                }\n                if (yDiff > mTouchSlop && !mIsBeingDragged) {\n                    mIsBeingDragged = true;\n                    mProgress.setAlpha(STARTING_PROGRESS_ALPHA);\n                }\n                break;\n\n            case MotionEventCompat.ACTION_POINTER_UP:\n                onSecondaryPointerUp(ev);\n                break;\n\n            case MotionEvent.ACTION_UP:\n            case MotionEvent.ACTION_CANCEL:\n                mIsBeingDragged = false;\n                mActivePointerId = INVALID_POINTER;\n                break;\n        }\n\n        return mIsBeingDragged;\n    }\n\n    private float getMotionEventY(MotionEvent ev, int activePointerId) {\n        final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);\n        if (index < 0) {\n            return -1;\n        }\n        return MotionEventCompat.getY(ev, index);\n    }\n\n    @Override\n    public void requestDisallowInterceptTouchEvent(boolean b) {\n        // Nope.\n    }\n\n    private boolean isAnimationRunning(Animation animation) {\n        return animation != null && animation.hasStarted() && !animation.hasEnded();\n    }\n\n    @SuppressLint(\"NewApi\") @Override\n    public boolean onTouchEvent(MotionEvent ev) {\n        final int action = MotionEventCompat.getActionMasked(ev);\n\n        if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {\n            mReturningToStart = false;\n        }\n\n        switch (mDirection) {\n            case BOTTOM:\n                if (!isEnabled() || mReturningToStart || canChildScrollDown() || mRefreshing) {\n                    // Fail fast if we're not in a state where a swipe is possible\n                    return false;\n                }\n                break;\n            case TOP:\n            default:\n                if (!isEnabled() || mReturningToStart || canChildScrollUp() || mRefreshing) {\n                    // Fail fast if we're not in a state where a swipe is possible\n                    return false;\n                }\n                break;\n        }\n\n        switch (action) {\n            case MotionEvent.ACTION_DOWN:\n                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);\n                mIsBeingDragged = false;\n                break;\n\n            case MotionEvent.ACTION_MOVE: {\n                final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);\n                if (pointerIndex < 0) {\n                    return false;\n                }\n\n                final float y = MotionEventCompat.getY(ev, pointerIndex);\n\n                float overscrollTop;\n                switch (mDirection) {\n                    case BOTTOM:\n                        overscrollTop = (mInitialMotionY - y) * DRAG_RATE;\n                        break;\n                    case TOP:\n                    default:\n                        overscrollTop = (y - mInitialMotionY) * DRAG_RATE;\n                        break;\n                }\n                if (mIsBeingDragged) {\n                    mProgress.showArrow(true);\n                    float originalDragPercent = overscrollTop / mTotalDragDistance;\n                    if (originalDragPercent < 0) {\n                        return false;\n                    }\n                    float dragPercent = Math.min(1f, Math.abs(originalDragPercent));\n                    float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;\n                    float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;\n                    float slingshotDist = mUsingCustomStart ? mSpinnerFinalOffset\n                            - mOriginalOffsetTop : mSpinnerFinalOffset;\n                    float tensionSlingshotPercent = Math.max(0,\n                            Math.min(extraOS, slingshotDist * 2) / slingshotDist);\n                    float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow(\n                            (tensionSlingshotPercent / 4), 2)) * 2f;\n                    float extraMove = (slingshotDist) * tensionPercent * 2;\n\n                    // int targetY = mOriginalOffsetTop + (int) ((slingshotDist * dragPercent) + extraMove);\n                    int targetY;\n                    if (mDirection == SwipyRefreshLayoutDirection.TOP) {\n                        targetY = mOriginalOffsetTop + (int) ((slingshotDist * dragPercent) + extraMove);\n                    } else {\n                        targetY = mOriginalOffsetTop - (int) ((slingshotDist * dragPercent) + extraMove);\n                    }\n                    // where 1.0f is a full circle\n                    if (mCircleView.getVisibility() != View.VISIBLE) {\n                        mCircleView.setVisibility(View.VISIBLE);\n                    }\n                    if (!mScale) {\n                        ViewCompat.setScaleX(mCircleView, 1f);\n                        ViewCompat.setScaleY(mCircleView, 1f);\n                    }\n                    if (overscrollTop < mTotalDragDistance) {\n                        if (mScale) {\n                            setAnimationProgress(overscrollTop / mTotalDragDistance);\n                        }\n                        if (mProgress.getAlpha() > STARTING_PROGRESS_ALPHA\n                                && !isAnimationRunning(mAlphaStartAnimation)) {\n                            // Animate the alpha\n                            startProgressAlphaStartAnimation();\n                        }\n                        float strokeStart = (float) (adjustedPercent * .8f);\n                        mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));\n                        mProgress.setArrowScale(Math.min(1f, adjustedPercent));\n                    } else {\n                        if (mProgress.getAlpha() < MAX_ALPHA\n                                && !isAnimationRunning(mAlphaMaxAnimation)) {\n                            // Animate the alpha\n                            startProgressAlphaMaxAnimation();\n                        }\n                    }\n                    float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;\n                    mProgress.setProgressRotation(rotation);\n                    setTargetOffsetTopAndBottom(targetY - mCurrentTargetOffsetTop,\n                            true /* requires update */);\n                }\n                break;\n            }\n            case MotionEventCompat.ACTION_POINTER_DOWN: {\n                final int index = MotionEventCompat.getActionIndex(ev);\n                mActivePointerId = MotionEventCompat.getPointerId(ev, index);\n                break;\n            }\n\n            case MotionEventCompat.ACTION_POINTER_UP:\n                onSecondaryPointerUp(ev);\n                break;\n\n            case MotionEvent.ACTION_UP:\n            case MotionEvent.ACTION_CANCEL: {\n                if (mActivePointerId == INVALID_POINTER) {\n                    if (action == MotionEvent.ACTION_UP) {\n                    }\n                    return false;\n                }\n                final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);\n                final float y = MotionEventCompat.getY(ev, pointerIndex);\n\n                float overscrollTop;\n                switch (mDirection) {\n                    case BOTTOM:\n                        overscrollTop = (mInitialMotionY - y) * DRAG_RATE;\n                        isTop = false;\n                        break;\n                    case TOP:\n                    default:\n                        overscrollTop = (y - mInitialMotionY) * DRAG_RATE;\n                        isTop = true;\n                        break;\n                }\n                mIsBeingDragged = false;\n                if (overscrollTop > mTotalDragDistance) {\n                    setRefreshing(true, true /* notify */);\n                } else {\n                    // cancel refresh\n                    mRefreshing = false;\n                    mProgress.setStartEndTrim(0f, 0f);\n                    AnimationListener listener = null;\n                    if (!mScale) {\n                        listener = new AnimationListener() {\n\n                            @Override\n                            public void onAnimationStart(Animation animation) {\n                            }\n\n                            @Override\n                            public void onAnimationEnd(Animation animation) {\n                                if (!mScale) {\n                                    startScaleDownAnimation(null);\n                                }\n                            }\n\n                            @Override\n                            public void onAnimationRepeat(Animation animation) {\n                            }\n\n                        };\n                    }\n                    animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener);\n                    mProgress.showArrow(false);\n                }\n                mActivePointerId = INVALID_POINTER;\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    private void animateOffsetToCorrectPosition(int from, AnimationListener listener) {\n        mFrom = from;\n        mAnimateToCorrectPosition.reset();\n        mAnimateToCorrectPosition.setDuration(ANIMATE_TO_TRIGGER_DURATION);\n        mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator);\n        if (listener != null) {\n            mCircleView.setAnimationListener(listener);\n        }\n        mCircleView.clearAnimation();\n        mCircleView.startAnimation(mAnimateToCorrectPosition);\n    }\n\n    private void animateOffsetToStartPosition(int from, AnimationListener listener) {\n        if (mScale) {\n            // Scale the item back down\n            startScaleDownReturnToStartAnimation(from, listener);\n        } else {\n            mFrom = from;\n            mAnimateToStartPosition.reset();\n            mAnimateToStartPosition.setDuration(ANIMATE_TO_START_DURATION);\n            mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);\n            if (listener != null) {\n                mCircleView.setAnimationListener(listener);\n            }\n            mCircleView.clearAnimation();\n            mCircleView.startAnimation(mAnimateToStartPosition);\n        }\n    }\n\n    private final Animation mAnimateToCorrectPosition = new Animation() {\n        @Override\n        public void applyTransformation(float interpolatedTime, Transformation t) {\n            int targetTop = 0;\n            int endTarget = 0;\n            if (!mUsingCustomStart) {\n                switch (mDirection) {\n                    case BOTTOM:\n                        endTarget = getMeasuredHeight() - (int) (mSpinnerFinalOffset);\n                        break;\n                    case TOP:\n                    default:\n                        endTarget = (int) (mSpinnerFinalOffset - Math.abs(mOriginalOffsetTop));\n                        break;\n                }\n            } else {\n                endTarget = (int) mSpinnerFinalOffset;\n            }\n            targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime));\n            int offset = targetTop - mCircleView.getTop();\n            setTargetOffsetTopAndBottom(offset, false /* requires update */);\n        }\n    };\n\n    private void moveToStart(float interpolatedTime) {\n        int targetTop = 0;\n        targetTop = (mFrom + (int) ((mOriginalOffsetTop - mFrom) * interpolatedTime));\n        int offset = targetTop - mCircleView.getTop();\n        setTargetOffsetTopAndBottom(offset, false /* requires update */);\n    }\n\n    private final Animation mAnimateToStartPosition = new Animation() {\n        @Override\n        public void applyTransformation(float interpolatedTime, Transformation t) {\n            moveToStart(interpolatedTime);\n        }\n    };\n\n    @SuppressLint(\"NewApi\") private void startScaleDownReturnToStartAnimation(int from,\n                                                                              AnimationListener listener) {\n        mFrom = from;\n        if (isAlphaUsedForScale()) {\n            mStartingScale = mProgress.getAlpha();\n        } else {\n            mStartingScale = ViewCompat.getScaleX(mCircleView);\n        }\n        mScaleDownToStartAnimation = new Animation() {\n            @Override\n            public void applyTransformation(float interpolatedTime, Transformation t) {\n                float targetScale = (mStartingScale + (-mStartingScale * interpolatedTime));\n                setAnimationProgress(targetScale);\n                moveToStart(interpolatedTime);\n            }\n        };\n        mScaleDownToStartAnimation.setDuration(SCALE_DOWN_DURATION);\n        if (listener != null) {\n            mCircleView.setAnimationListener(listener);\n        }\n        mCircleView.clearAnimation();\n        mCircleView.startAnimation(mScaleDownToStartAnimation);\n    }\n\n    private void setTargetOffsetTopAndBottom(int offset, boolean requiresUpdate) {\n        mCircleView.bringToFront();\n        mCircleView.offsetTopAndBottom(offset);\n        mCurrentTargetOffsetTop = mCircleView.getTop();\n        if (requiresUpdate && Build.VERSION.SDK_INT < 11) {\n            invalidate();\n        }\n    }\n\n    private void onSecondaryPointerUp(MotionEvent ev) {\n        final int pointerIndex = MotionEventCompat.getActionIndex(ev);\n        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);\n        if (pointerId == mActivePointerId) {\n            // This was our active pointer going up. Choose a new\n            // active pointer and adjust accordingly.\n            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;\n            mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);\n        }\n    }\n\n    /**\n     * Classes that wish to be notified when the swipe gesture correctly\n     * triggers a refresh should implement this interface.\n     */\n    public interface OnRefreshListener {\n        public void onRefresh(int index);\n        public void onLoad(int index);\n    }\n\n    public SwipyRefreshLayoutDirection getDirection() {\n        return mBothDirection ? SwipyRefreshLayoutDirection.BOTH : mDirection;\n    }\n\n    public void setDirection(SwipyRefreshLayoutDirection direction) {\n        if (direction == SwipyRefreshLayoutDirection.BOTH) {\n            mBothDirection = true;\n        } else {\n            mBothDirection = false;\n            mDirection = direction;\n        }\n\n        switch (mDirection) {\n            case BOTTOM:\n                mCurrentTargetOffsetTop = mOriginalOffsetTop = getMeasuredHeight() - mCircleView.getMeasuredHeight();\n                break;\n            case TOP:\n            default:\n                mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();\n                break;\n        }\n    }\n\n    // only TOP or Bottom\n    private void setRawDirection(SwipyRefreshLayoutDirection direction) {\n        if (mDirection == direction) {\n            return;\n        }\n\n        mDirection = direction;\n        switch (mDirection) {\n            case BOTTOM:\n                mCurrentTargetOffsetTop = mOriginalOffsetTop = getMeasuredHeight() - mCircleView.getMeasuredHeight();\n                break;\n            case TOP:\n            default:\n                mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();\n                break;\n        }\n    }\n\n    /**\n     * @return 获得从第一页开始索引\n     */\n\tpublic int getFirstIndex() {\n\t\treturn firstIndex;\n\t}\n\n\t/**\n\t * 设置从第几页开始（默认值为0）\n\t * @param firstIndex 第几页\n\t */\n\tpublic void setFirstIndex(int firstIndex) {\n\t\tthis.firstIndex = firstIndex;\n\t}\n\n\t/**\n\t * @return 获得当前索引\n\t */\n\tpublic int getIndex() {\n\t\treturn index;\n\t}\n\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/swipyrefresh/SwipyRefreshLayoutDirection.java",
    "content": "package com.htmessage.yichatopen.widget.swipyrefresh;\n\n/**\n * \n * @author xutao\n * \n */\npublic enum SwipyRefreshLayoutDirection {\n\n\tTOP(0), // 只有下拉刷新\n\tBOTTOM(1), // 只有加载更多\n\tBOTH(2);// 全都有\n\n\tprivate int mValue;\n\n\tSwipyRefreshLayoutDirection(int value) {\n\t\tthis.mValue = value;\n\t}\n\n\tpublic static SwipyRefreshLayoutDirection getFromInt(int value) {\n\t\tfor (SwipyRefreshLayoutDirection direction : SwipyRefreshLayoutDirection\n\t\t\t\t.values()) {\n\t\t\tif (direction.mValue == value) {\n\t\t\t\treturn direction;\n\t\t\t}\n\t\t}\n\t\treturn BOTH;\n\t}\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/activity/CaptureActivity.java",
    "content": "package com.htmessage.yichatopen.widget.zxing.activity;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.content.res.AssetFileDescriptor;\nimport android.graphics.Bitmap;\nimport android.media.AudioManager;\nimport android.media.MediaPlayer;\nimport android.media.MediaPlayer.OnCompletionListener;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.Vibrator;\nimport android.view.SurfaceHolder;\nimport android.view.SurfaceHolder.Callback;\nimport android.view.SurfaceView;\nimport android.widget.Toast;\n\nimport com.htmessage.yichatopen.widget.zxing.camera.CameraManager;\nimport com.htmessage.yichatopen.widget.zxing.decoding.CaptureActivityHandler;\nimport com.htmessage.yichatopen.widget.zxing.decoding.InactivityTimer;\nimport com.htmessage.yichatopen.widget.zxing.view.ViewfinderView;\nimport com.google.zxing.BarcodeFormat;\nimport com.google.zxing.Result;\n\nimport java.io.IOException;\nimport java.util.Vector;\n\n\npublic class CaptureActivity extends Activity implements Callback {\n\n\tprivate CaptureActivityHandler handler;\n\tprivate ViewfinderView viewfinderView;\n\tprivate boolean hasSurface;\n\tprivate Vector<BarcodeFormat> decodeFormats;\n\tprivate String characterSet;\n\tprivate InactivityTimer inactivityTimer;\n\tprivate MediaPlayer mediaPlayer;\n\tprivate boolean playBeep;\n\tprivate static final float BEEP_VOLUME = 0.10f;\n\tprivate boolean vibrate;\n \n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n//\t\tsetContentView(R.layout.activity_camera);\n//\t\t//ViewUtil.addTopView(getApplicationContext(), this, R.string.scan_card);\n//\t\tCameraManager.init(getApplication(),false);\n//\t\tviewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);\n\t\t \n\t\thasSurface = false;\n\t\tinactivityTimer = new InactivityTimer(this);\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\t@Override\n\tprotected void onResume() {\n\t\tsuper.onResume();\n\t\tSurfaceView surfaceView = null;\n\t\tSurfaceHolder surfaceHolder = surfaceView.getHolder();\n\t\tif (hasSurface) {\n\t\t\tinitCamera(surfaceHolder);\n\t\t} else {\n\t\t\tsurfaceHolder.addCallback(this);\n\t\t\tsurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);\n\t\t}\n\t\tdecodeFormats = null;\n\t\tcharacterSet = null;\n\n\t\tplayBeep = true;\n\t\tAudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);\n\t\tif (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {\n\t\t\tplayBeep = false;\n\t\t}\n\t\tinitBeepSound();\n\t\tvibrate = true;\n\t\t\n\t \n\t}\n\n\t@Override\n\tprotected void onPause() {\n\t\tsuper.onPause();\n\t\tif (handler != null) {\n\t\t\thandler.quitSynchronously();\n\t\t\thandler = null;\n\t\t}\n\t\tCameraManager.get().closeDriver();\n\t}\n\n\t@Override\n\tprotected void onDestroy() {\n\t\tinactivityTimer.shutdown();\n\t\tsuper.onDestroy();\n\t}\n\t\n\t/**\n\t * Handler scan result\n\t * @param result\n\t * @param barcode\n\t */\n\tpublic void handleDecode(Result result, Bitmap barcode) {\n\t\tinactivityTimer.onActivity();\n\t\tplayBeepSoundAndVibrate();\n\t\tString resultString = result.getText();\n\t\t//FIXME\n\t\tif (resultString.equals(\"\")) {\n\t\t\tToast.makeText(CaptureActivity.this, \"Scan failed!\", Toast.LENGTH_SHORT).show();\n\t\t}else {\n//\t\t\tSystem.out.println(\"Result:\"+resultString);\n\t\t//\tIntent resultIntent = new Intent();\n\t\t//\tBundle bundle = new Bundle();\n\t\t//\tbundle.putString(\"result\", resultString);\n\t\t//\tresultIntent.putExtras(bundle);\n\t\t\t//this.setResult(RESULT_OK, resultIntent);\n             viewfinderView.drawResultBitmap(barcode);\n\t         \n\t         String Qruid =result.getText().toString().trim();\n\t         //传值 gongfan\n             Intent intent = new Intent();\n             intent.putExtra(\"address\", Qruid);\n             setResult(RESULT_OK,intent);\n           \n//             intent.setClass(CaptureActivity.this,\n// AddFriendsTwoActivity.class);\n//             startActivity(intent);\n\t         \n\t         //查询用户\n\t       //         \n\t       //  searchUser(uid);\n\t\t}\n\t\t  CaptureActivity.this.finish();\n\t}\n\t\n\t /*  public void handleDecode(Result obj, Bitmap barcode) {\n\t        inactivityTimer.onActivity();\n\t        viewfinderView.drawResultBitmap(barcode);\n\t         playBeepSoundAndVibrate();\n\t        txtResult.setText(obj.getBarcodeFormat().toString() + \":\"\n\t                + obj.getText());\n\t    }*/\n\tprivate void initCamera(SurfaceHolder surfaceHolder) {\n\t\ttry {\n\t\t\tCameraManager.get().openDriver(surfaceHolder);\n\t\t} catch (IOException ioe) {\n\t\t\treturn;\n\t\t} catch (RuntimeException e) {\n\t\t\treturn;\n\t\t}\n\t\tif (handler == null) {\n\t\t\thandler = new CaptureActivityHandler(this, decodeFormats,\n\t\t\t\t\tcharacterSet);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void surfaceChanged(SurfaceHolder holder, int format, int width,\n\t\t\tint height) {\n\n\t}\n\n\t@Override\n\tpublic void surfaceCreated(SurfaceHolder holder) {\n\t\tif (!hasSurface) {\n\t\t\thasSurface = true;\n\t\t\tinitCamera(holder);\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic void surfaceDestroyed(SurfaceHolder holder) {\n\t\thasSurface = false;\n\n\t}\n\n\tpublic ViewfinderView getViewfinderView() {\n\t\treturn viewfinderView;\n\t}\n\n\tpublic Handler getHandler() {\n\t\treturn handler;\n\t}\n\n\tpublic void drawViewfinder() {\n\t\tviewfinderView.drawViewfinder();\n\n\t}\n\n\tprivate void initBeepSound() {\n\t\tif (playBeep && mediaPlayer == null) {\n\t\t\t// The volume on STREAM_SYSTEM is not adjustable, and users found it\n\t\t\t// too loud,\n\t\t\t// so we now play on the music stream.\n\t\t\tsetVolumeControlStream(AudioManager.STREAM_MUSIC);\n\t\t\tmediaPlayer = new MediaPlayer();\n\t\t\tmediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);\n\t\t\tmediaPlayer.setOnCompletionListener(beepListener);\n\n\t\t\tAssetFileDescriptor file =null;\n\t\t\ttry {\n\t\t\t\tmediaPlayer.setDataSource(file.getFileDescriptor(),\n\t\t\t\t\t\tfile.getStartOffset(), file.getLength());\n\t\t\t\tfile.close();\n\t\t\t\tmediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);\n\t\t\t\tmediaPlayer.prepare();\n\t\t\t} catch (IOException e) {\n\t\t\t\tmediaPlayer = null;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static final long VIBRATE_DURATION = 200L;\n\n\tprivate void playBeepSoundAndVibrate() {\n\t\tif (playBeep && mediaPlayer != null) {\n\t\t\tmediaPlayer.start();\n\t\t}\n\t\tif (vibrate) {\n\t\t\tVibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);\n\t\t\tvibrator.vibrate(VIBRATE_DURATION);\n\t\t}\n\t}\n\n\t/**\n\t * When the beep has finished playing, rewind to queue up another one.\n\t */\n\tprivate final OnCompletionListener beepListener = new OnCompletionListener() {\n\t\tpublic void onCompletion(MediaPlayer mediaPlayer) {\n\t\t\tmediaPlayer.seekTo(0);\n\t\t}\n\t};\n\n}"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/activity/DensityUtil.java",
    "content": "package com.htmessage.yichatopen.widget.zxing.activity;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.util.DisplayMetrics;\n\n/*\n * 屏幕分辨率获取的类\n */\npublic class DensityUtil {\n\tprivate static int[] deviceWidthHeight = new int[2];\n\tpublic static int[] getDeviceInfo(Context context) {\n\t\tif ((deviceWidthHeight[0] == 0) && (deviceWidthHeight[1] == 0)) {\n\t\t\tDisplayMetrics metrics = new DisplayMetrics();\n\t\t\t((Activity) context).getWindowManager().getDefaultDisplay()\n\t\t\t\t\t.getMetrics(metrics);\n\n\t\t\tdeviceWidthHeight[0] = metrics.widthPixels;\n\t\t\tdeviceWidthHeight[1] = metrics.heightPixels;\n\t\t}\n\t\treturn deviceWidthHeight;\n\t}\n\t/**\n\t * 根据手机的分辨率从 dp 的单位 转成为 px(像素)\n\t */\n\tpublic static int dip2px(Context context, float dpValue) {\n\t\tfinal float scale = context.getResources().getDisplayMetrics().density;\n\t\treturn (int) (dpValue * scale + 0.5f);\n\t}\n\n\t/**\n\t * 根据手机的分辨率从 px(像素) 的单位 转成为 dp\n\t */\n\tpublic static int px2dip(Context context, float pxValue) {\n\t\tfinal float scale = context.getResources().getDisplayMetrics().density;\n\t\treturn (int) (pxValue / scale + 0.5f);\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/AutoFocusCallback.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.camera;\n\nimport android.hardware.Camera;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.util.Log;\n\nfinal class AutoFocusCallback implements Camera.AutoFocusCallback {\n\n  private static final String TAG = AutoFocusCallback.class.getSimpleName();\n\n  private static final long AUTOFOCUS_INTERVAL_MS = 1500L;\n\n  private Handler autoFocusHandler;\n  private int autoFocusMessage;\n  public boolean isFocusing;\n  void setHandler(Handler autoFocusHandler, int autoFocusMessage) {\n    this.autoFocusHandler = autoFocusHandler;\n    this.autoFocusMessage = autoFocusMessage;\n  }\n\n  public void onAutoFocus(boolean success, Camera camera) {\n\t  isFocusing = true;  \n    if (autoFocusHandler != null) {\n      Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);\n      autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);\n      autoFocusHandler = null;\n    } else {\n      Log.d(TAG, \"Got auto-focus callback, but no handler for it\");\n    }\n   \n    \n    isFocusing = false;  \n    \n    \n  }\n  \n  \n  \n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/CameraConfigurationManager.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.camera;\n\nimport android.content.Context;\nimport android.graphics.Point;\nimport android.hardware.Camera;\nimport android.os.Build;\nimport android.util.Log;\nimport android.view.Display;\nimport android.view.WindowManager;\n\nimport java.util.regex.Pattern;\n\nfinal class CameraConfigurationManager {\n\n  private static final String TAG = CameraConfigurationManager.class.getSimpleName();\n\n  private static final int TEN_DESIRED_ZOOM = 27;\n  private static final int DESIRED_SHARPNESS = 30;\n\n  private static final Pattern COMMA_PATTERN = Pattern.compile(\",\");\n\n  private final Context context;\n  private Point screenResolution;\n  private Point cameraResolution;\n  private int previewFormat;\n  private String previewFormatString;\n\n  CameraConfigurationManager(Context context) {\n    this.context = context;\n  }\n\n  /**\n   * Reads, one time, values from the camera that are needed by the app.\n   */\n  @SuppressWarnings(\"deprecation\")\nvoid initFromCameraParameters(Camera camera) {\n    Camera.Parameters parameters = camera.getParameters();\n    previewFormat = parameters.getPreviewFormat();\n    previewFormatString = parameters.get(\"preview-format\");\n    Log.d(TAG, \"Default preview format: \" + previewFormat + '/' + previewFormatString);\n    WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);\n    Display display = manager.getDefaultDisplay();\n    screenResolution = new Point(display.getWidth(), display.getHeight());\n    Log.d(TAG, \"Screen resolution: \" + screenResolution);\n    cameraResolution = getCameraResolution(parameters, screenResolution);\n    Log.d(TAG, \"Camera resolution: \" + screenResolution);\n  }\n\n  /**\n   * Sets the camera up to take preview images which are used for both preview and decoding.\n   * We detect the preview format here so that buildLuminanceSource() can build an appropriate\n   * LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,\n   * and the planar Y can be used for barcode scanning without a copy in some cases.\n   */\n  void setDesiredCameraParameters(Camera camera) {\n    Camera.Parameters parameters = camera.getParameters();\n    Log.d(TAG, \"Setting preview size: \" + cameraResolution);\n    parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);\n    setFlash(parameters);\n    setZoom(parameters);\n    //setSharpness(parameters);\n    //modify here\n    camera.setDisplayOrientation(90);\n    camera.setParameters(parameters);\n  }\n\n  Point getCameraResolution() {\n    return cameraResolution;\n  }\n\n  Point getScreenResolution() {\n    return screenResolution;\n  }\n\n  int getPreviewFormat() {\n    return previewFormat;\n  }\n\n  String getPreviewFormatString() {\n    return previewFormatString;\n  }\n\n  private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {\n\n    String previewSizeValueString = parameters.get(\"preview-size-values\");\n    // saw this on Xperia\n    if (previewSizeValueString == null) {\n      previewSizeValueString = parameters.get(\"preview-size-value\");\n    }\n\n    Point cameraResolution = null;\n\n    if (previewSizeValueString != null) {\n      Log.d(TAG, \"preview-size-values parameter: \" + previewSizeValueString);\n      cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);\n    }\n\n    if (cameraResolution == null) {\n      // Ensure that the camera resolution is a multiple of 8, as the screen may not be.\n      cameraResolution = new Point(\n          (screenResolution.x >> 3) << 3,\n          (screenResolution.y >> 3) << 3);\n    }\n\n    return cameraResolution;\n  }\n\n  private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {\n    int bestX = 0;\n    int bestY = 0;\n    int diff = Integer.MAX_VALUE;\n    for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {\n\n      previewSize = previewSize.trim();\n      int dimPosition = previewSize.indexOf('x');\n      if (dimPosition < 0) {\n        Log.w(TAG, \"Bad preview-size: \" + previewSize);\n        continue;\n      }\n\n      int newX;\n      int newY;\n      try {\n        newX = Integer.parseInt(previewSize.substring(0, dimPosition));\n        newY = Integer.parseInt(previewSize.substring(dimPosition + 1));\n      } catch (NumberFormatException nfe) {\n        Log.w(TAG, \"Bad preview-size: \" + previewSize);\n        continue;\n      }\n\n      int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);\n      if (newDiff == 0) {\n        bestX = newX;\n        bestY = newY;\n        break;\n      } else if (newDiff < diff) {\n        bestX = newX;\n        bestY = newY;\n        diff = newDiff;\n      }\n\n    }\n\n    if (bestX > 0 && bestY > 0) {\n      return new Point(bestX, bestY);\n    }\n    return null;\n  }\n\n  private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {\n    int tenBestValue = 0;\n    for (String stringValue : COMMA_PATTERN.split(stringValues)) {\n      stringValue = stringValue.trim();\n      double value;\n      try {\n        value = Double.parseDouble(stringValue);\n      } catch (NumberFormatException nfe) {\n        return tenDesiredZoom;\n      }\n      int tenValue = (int) (10.0 * value);\n      if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {\n        tenBestValue = tenValue;\n      }\n    }\n    return tenBestValue;\n  }\n\n  private void setFlash(Camera.Parameters parameters) {\n    // FIXME: This is a hack to turn the flash off on the Samsung Galaxy.\n    // And this is a hack-hack to work around a different value on the Behold II\n    // Restrict Behold II check to Cupcake, per Samsung's advice\n    //if (Build.MODEL.contains(\"Behold II\") &&\n    //    CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {\n    if (Build.MODEL.contains(\"Behold II\") && CameraManager.SDK_INT == 3) { // 3 = Cupcake\n      parameters.set(\"flash-value\", 1);\n    } else {\n      parameters.set(\"flash-value\", 2);\n    }\n    // This is the standard setting to turn the flash off that all devices should honor.\n    parameters.set(\"flash-mode\", \"off\");\n  }\n\n  private void setZoom(Camera.Parameters parameters) {\n\n    String zoomSupportedString = parameters.get(\"zoom-supported\");\n    if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {\n      return;\n    }\n\n    int tenDesiredZoom = TEN_DESIRED_ZOOM;\n\n    String maxZoomString = parameters.get(\"max-zoom\");\n    if (maxZoomString != null) {\n      try {\n        int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));\n        if (tenDesiredZoom > tenMaxZoom) {\n          tenDesiredZoom = tenMaxZoom;\n        }\n      } catch (NumberFormatException nfe) {\n        Log.w(TAG, \"Bad max-zoom: \" + maxZoomString);\n      }\n    }\n\n    String takingPictureZoomMaxString = parameters.get(\"taking-picture-zoom-max\");\n    if (takingPictureZoomMaxString != null) {\n      try {\n        int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);\n        if (tenDesiredZoom > tenMaxZoom) {\n          tenDesiredZoom = tenMaxZoom;\n        }\n      } catch (NumberFormatException nfe) {\n        Log.w(TAG, \"Bad taking-picture-zoom-max: \" + takingPictureZoomMaxString);\n      }\n    }\n\n    String motZoomValuesString = parameters.get(\"mot-zoom-values\");\n    if (motZoomValuesString != null) {\n      tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);\n    }\n\n    String motZoomStepString = parameters.get(\"mot-zoom-step\");\n    if (motZoomStepString != null) {\n      try {\n        double motZoomStep = Double.parseDouble(motZoomStepString.trim());\n        int tenZoomStep = (int) (10.0 * motZoomStep);\n        if (tenZoomStep > 1) {\n          tenDesiredZoom -= tenDesiredZoom % tenZoomStep;\n        }\n      } catch (NumberFormatException nfe) {\n        // continue\n      }\n    }\n\n    // Set zoom. This helps encourage the user to pull back.\n    // Some devices like the Behold have a zoom parameter\n    if (maxZoomString != null || motZoomValuesString != null) {\n      parameters.set(\"zoom\", String.valueOf(tenDesiredZoom / 10.0));\n    }\n\n    // Most devices, like the Hero, appear to expose this zoom parameter.\n    // It takes on values like \"27\" which appears to mean 2.7x zoom\n    if (takingPictureZoomMaxString != null) {\n      parameters.set(\"taking-picture-zoom\", tenDesiredZoom);\n    }\n  }\n\n\tpublic static int getDesiredSharpness() {\n\t\treturn DESIRED_SHARPNESS;\n\t}\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/CameraManager.java",
    "content": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.camera;\n\nimport android.content.Context;\nimport android.graphics.PixelFormat;\nimport android.graphics.Point;\nimport android.graphics.Rect;\nimport android.hardware.Camera;\nimport android.os.Build;\nimport android.os.Handler;\nimport android.util.Log;\nimport android.view.SurfaceHolder;\n\nimport com.htmessage.yichatopen.widget.zxing.activity.DensityUtil;\n\nimport java.io.IOException;\n\n/**\n * This object wraps the Camera service object and expects to be the only one talking to it. The\n * implementation encapsulates the steps needed to take preview-sized images, which are used for\n * both preview and decoding.\n *\n */\n@SuppressWarnings(\"deprecation\")\npublic final class CameraManager {\n\n  private static final String TAG = CameraManager.class.getSimpleName();\n\n  private static final int MIN_FRAME_WIDTH = 340;\n  private static final int MIN_FRAME_HEIGHT = 340;\n  private static final int MAX_FRAME_WIDTH = 580;\n  private static final int MAX_FRAME_HEIGHT = 460;\n\n  private static CameraManager cameraManager;\n\n  static final int SDK_INT; // Later we can use Build.VERSION.SDK_INT\n  static {\n    int sdkInt;\n    try {\n      sdkInt = Integer.parseInt(Build.VERSION.SDK);\n    } catch (NumberFormatException nfe) {\n      // Just to be safe\n      sdkInt = 10000;\n    }\n    SDK_INT = sdkInt;\n  }\n\n  private final Context context;\n  private final CameraConfigurationManager configManager;\n  private Camera camera;\n  private Rect framingRect;\n  private Rect framingRectInPreview;\n  private boolean initialized;\n  private boolean previewing;\n  private final boolean useOneShotPreviewCallback;\n  private boolean is_top=false;\n  /**\n   * Preview frames are delivered here, which we pass on to the registered handler. Make sure to\n   * clear the handler so it will only receive one message.\n   */\n  private final PreviewCallback previewCallback;\n  /** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */\n  private final AutoFocusCallback autoFocusCallback;\n\n  /**\n   * Initializes this static object with the Context of the calling Activity.\n   *\n   * @param context The Activity which wants to use the camera.\n   */\n  public static void init(Context context,boolean is_top) {\n//    if (cameraManager == null) {\n      cameraManager = new CameraManager(context,is_top);\n     \n//    }\n  }\n\n  /**\n   * Gets the CameraManager singleton instance.\n   *\n   * @return A reference to the CameraManager singleton.\n   */\n  public static CameraManager get() {\n    return cameraManager;\n  }\n\n  private CameraManager(Context context,boolean is_top) {\n\t  this.is_top=is_top;\n    this.context = context;\n    this.configManager = new CameraConfigurationManager(context);\n\n    // Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older\n    // Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use\n    // the more efficient one shot callback, as the older one can swamp the system and cause it\n    // to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.\n    //useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.CUPCAKE;\n    useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = Cupcake\n\n    previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);\n    autoFocusCallback = new AutoFocusCallback();\n  }\n\n  /**\n   * Opens the camera driver and initializes the hardware parameters.\n   *\n   * @param holder The surface object which the camera will draw preview frames into.\n   * @throws IOException Indicates the camera driver failed to open.\n   */\n  public void openDriver(SurfaceHolder holder) throws IOException {\n    if (camera == null) {\n      camera = Camera.open();\n      if (camera == null) {\n        throw new IOException();\n      }\n      camera.setPreviewDisplay(holder);\n\n      if (!initialized) {\n        initialized = true;\n        configManager.initFromCameraParameters(camera);\n      }\n      configManager.setDesiredCameraParameters(camera);\n\n      //FIXME\n //     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);\n      //�Ƿ�ʹ��ǰ��\n//      if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {\n//        FlashlightManager.enableFlashlight();\n//      }\n      FlashlightManager.enableFlashlight();\n    }\n  }\n\n  /**\n   * Closes the camera driver if still in use.\n   */\n  public void closeDriver() {\n    if (camera != null) {\n      FlashlightManager.disableFlashlight();\n      camera.release();\n      camera = null;\n    }\n  }\n\n  /**\n   * Asks the camera hardware to begin drawing preview frames to the screen.\n   */\n  public void startPreview() {\n    if (camera != null && !previewing) {\n      camera.startPreview();\n      previewing = true;\n    }\n  }\n\n  /**\n   * Tells the camera to stop drawing preview frames.\n   */\n  public void stopPreview() {\n    if (camera != null && previewing) {\n      if (!useOneShotPreviewCallback) {\n        camera.setPreviewCallback(null);\n      }\n      camera.stopPreview();\n      previewCallback.setHandler(null, 0);\n      autoFocusCallback.setHandler(null, 0);\n      previewing = false;\n    }\n  }\n\n  /**\n   * A single preview frame will be returned to the handler supplied. The data will arrive as byte[]\n   * in the message.obj field, with width and height encoded as message.arg1 and message.arg2,\n   * respectively.\n   *\n   * @param handler The handler to send the message to.\n   * @param message The what field of the message to be sent.\n   */\n  public void requestPreviewFrame(Handler handler, int message) {\n    if (camera != null && previewing) {\n      previewCallback.setHandler(handler, message);\n      if (useOneShotPreviewCallback) {\n        camera.setOneShotPreviewCallback(previewCallback);\n      } else {\n        camera.setPreviewCallback(previewCallback);\n      }\n    }\n  }\n\n  /**\n   * Asks the camera hardware to perform an autofocus.\n   *\n   * @param handler The Handler to notify when the autofocus completes.\n   * @param message The message to deliver.\n   */\n  public void requestAutoFocus(Handler handler, int message) {\n    if (camera != null && previewing ) {\n      autoFocusCallback.setHandler(handler, message);\n      //Log.d(TAG, \"Requesting auto-focus callback\");\n      try {\n      camera.autoFocus(autoFocusCallback); \n      } catch (Exception e) {\n          \n      }\n    }\n  }\n  \n  \n\n  /**\n   * Calculates the framing rect which the UI should draw to show the user where to place the\n   * barcode. This target helps with alignment as well as forces the user to hold the device\n   * far enough away to ensure the image will be in focus.\n   *\n   * @return The rectangle to draw on screen in window coordinates.\n   */\n  public Rect getFramingRect() {\n    Point screenResolution = configManager.getScreenResolution();\n    if (framingRect == null) {\n      if (camera == null) {\n        return null;\n      }\n      int width = screenResolution.x * 3 / 4;\n      if (width < MIN_FRAME_WIDTH) {\n        width = MIN_FRAME_WIDTH;\n      } else if (width > MAX_FRAME_WIDTH) {\n        width = MAX_FRAME_WIDTH;\n      }\n      int height = screenResolution.y * 3 / 4;\n      if (height < MIN_FRAME_HEIGHT) {\n        height = MIN_FRAME_HEIGHT;\n      } else if (height > MAX_FRAME_HEIGHT) {\n        height = MAX_FRAME_HEIGHT;\n      }\n      int leftOffset = (screenResolution.x - width) / 2;\n      int topOffset=(screenResolution.y - height) / 2;\n      if(is_top){\n    \t  topOffset= DensityUtil.dip2px(getContext(),80);\n      }\n       \n      framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);\n      Log.d(TAG, \"Calculated framing rect: \" + framingRect);\n    }\n    return framingRect;\n  }\n\n  /**\n   * Like {@link #getFramingRect} but coordinates are in terms of the preview frame,\n   * not UI / screen.\n   */\n  public Rect getFramingRectInPreview() {\n    if (framingRectInPreview == null) {\n      Rect rect = new Rect(getFramingRect());\n      Point cameraResolution = configManager.getCameraResolution();\n      Point screenResolution = configManager.getScreenResolution();\n      //modify here\n//      rect.left = rect.left * cameraResolution.x / screenResolution.x;\n//      rect.right = rect.right * cameraResolution.x / screenResolution.x;\n//      rect.top = rect.top * cameraResolution.y / screenResolution.y;\n//      rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;\n      rect.left = rect.left * cameraResolution.y / screenResolution.x;\n      rect.right = rect.right * cameraResolution.y / screenResolution.x;\n      rect.top = rect.top * cameraResolution.x / screenResolution.y;\n      rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;\n      framingRectInPreview = rect;\n    }\n    return framingRectInPreview;\n  }\n\n  /**\n   * Converts the result points from still resolution coordinates to screen coordinates.\n   *\n   * @param points The points returned by the Reader subclass through Result.getResultPoints().\n   * @return An array of Points scaled to the size of the framing rect and offset appropriately\n   *         so they can be drawn in screen coordinates.\n   */\n  /*\n  public Point[] convertResultPoints(ResultPoint[] points) {\n    Rect frame = getFramingRectInPreview();\n    int count = points.length;\n    Point[] output = new Point[count];\n    for (int x = 0; x < count; x++) {\n      output[x] = new Point();\n      output[x].x = frame.left + (int) (points[x].getX() + 0.5f);\n      output[x].y = frame.top + (int) (points[x].getY() + 0.5f);\n    }\n    return output;\n  }\n   */\n\n  /**\n   * A factory method to build the appropriate LuminanceSource object based on the format\n   * of the preview buffers, as described by Camera.Parameters.\n   *\n   * @param data A preview frame.\n   * @param width The width of the image.\n   * @param height The height of the image.\n   * @return A PlanarYUVLuminanceSource instance.\n   */\n  public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {\n    Rect rect = getFramingRectInPreview();\n    int previewFormat = configManager.getPreviewFormat();\n    String previewFormatString = configManager.getPreviewFormatString();\n    switch (previewFormat) {\n      // This is the standard Android format which all devices are REQUIRED to support.\n      // In theory, it's the only one we should ever care about.\n      case PixelFormat.YCbCr_420_SP:\n      // This format has never been seen in the wild, but is compatible as we only care\n      // about the Y channel, so allow it.\n      case PixelFormat.YCbCr_422_SP:\n        return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,\n            rect.width(), rect.height());\n      default:\n        // The Samsung Moment incorrectly uses this variant instead of the 'sp' version.\n        // Fortunately, it too has all the Y data up front, so we can read it.\n        if (\"yuv420p\".equals(previewFormatString)) {\n          return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,\n            rect.width(), rect.height());\n        }\n    }\n    throw new IllegalArgumentException(\"Unsupported picture format: \" +\n        previewFormat + '/' + previewFormatString);\n  }\n\n\tpublic Context getContext() {\n\t\treturn context;\n\t}\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/FlashlightManager.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.camera;\n\nimport android.os.IBinder;\nimport android.util.Log;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\n/**\n * This class is used to activate the weak light on some camera phones (not flash)\n * in order to illuminate surfaces for scanning. There is no official way to do this,\n * but, classes which allow access to this function still exist on some devices.\n * This therefore proceeds through a great deal of reflection.\n *\n * See <a href=\"http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/\">\n * http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/</a> and\n * <a href=\"http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java\">\n * http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java</a>.\n * Thanks to Ryan Alford for pointing out the availability of this class.\n */\nfinal class FlashlightManager {\n\n  private static final String TAG = FlashlightManager.class.getSimpleName();\n\n  private static final Object iHardwareService;\n  private static final Method setFlashEnabledMethod;\n  static {\n    iHardwareService = getHardwareService();\n    setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);\n    if (iHardwareService == null) {\n      Log.v(TAG, \"This device does supports control of a flashlight\");\n    } else {\n      Log.v(TAG, \"This device does not support control of a flashlight\");\n    }\n  }\n\n  private FlashlightManager() {\n  }\n\n\n  //FIXME\n  static void enableFlashlight() {\n    setFlashlight(false);\n  }\n\n  static void disableFlashlight() {\n    setFlashlight(false);\n  }\n\n  private static Object getHardwareService() {\n    Class<?> serviceManagerClass = maybeForName(\"android.os.ServiceManager\");\n    if (serviceManagerClass == null) {\n      return null;\n    }\n\n    Method getServiceMethod = maybeGetMethod(serviceManagerClass, \"getService\", String.class);\n    if (getServiceMethod == null) {\n      return null;\n    }\n\n    Object hardwareService = invoke(getServiceMethod, null, \"hardware\");\n    if (hardwareService == null) {\n      return null;\n    }\n\n    Class<?> iHardwareServiceStubClass = maybeForName(\"android.os.IHardwareService$Stub\");\n    if (iHardwareServiceStubClass == null) {\n      return null;\n    }\n\n    Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, \"asInterface\", IBinder.class);\n    if (asInterfaceMethod == null) {\n      return null;\n    }\n\n    return invoke(asInterfaceMethod, null, hardwareService);\n  }\n\n  private static Method getSetFlashEnabledMethod(Object iHardwareService) {\n    if (iHardwareService == null) {\n      return null;\n    }\n    Class<?> proxyClass = iHardwareService.getClass();\n    return maybeGetMethod(proxyClass, \"setFlashlightEnabled\", boolean.class);\n  }\n\n  private static Class<?> maybeForName(String name) {\n    try {\n      return Class.forName(name);\n    } catch (ClassNotFoundException cnfe) {\n      // OK\n      return null;\n    } catch (RuntimeException re) {\n      Log.w(TAG, \"Unexpected error while finding class \" + name, re);\n      return null;\n    }\n  }\n\n  private static Method maybeGetMethod(Class<?> clazz, String name, Class<?>... argClasses) {\n    try {\n      return clazz.getMethod(name, argClasses);\n    } catch (NoSuchMethodException nsme) {\n      // OK\n      return null;\n    } catch (RuntimeException re) {\n      Log.w(TAG, \"Unexpected error while finding method \" + name, re);\n      return null;\n    }\n  }\n\n  private static Object invoke(Method method, Object instance, Object... args) {\n    try {\n      return method.invoke(instance, args);\n    } catch (IllegalAccessException e) {\n      Log.w(TAG, \"Unexpected error while invoking \" + method, e);\n      return null;\n    } catch (InvocationTargetException e) {\n      Log.w(TAG, \"Unexpected error while invoking \" + method, e.getCause());\n      return null;\n    } catch (RuntimeException re) {\n      Log.w(TAG, \"Unexpected error while invoking \" + method, re);\n      return null;\n    }\n  }\n\n  private static void setFlashlight(boolean active) {\n    if (iHardwareService != null) {\n      invoke(setFlashEnabledMethod, iHardwareService, active);\n    }\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/PlanarYUVLuminanceSource.java",
    "content": "/*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.camera;\n\nimport android.graphics.Bitmap;\n\nimport com.google.zxing.LuminanceSource;\n\n/**\n * This object extends LuminanceSource around an array of YUV data returned from the camera driver,\n * with the option to crop to a rectangle within the full data. This can be used to exclude\n * superfluous pixels around the perimeter and speed up decoding.\n *\n * It works for any pixel format where the Y channel is planar and appears first, including\n * YCbCr_420_SP and YCbCr_422_SP.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\npublic final class PlanarYUVLuminanceSource extends LuminanceSource {\n  private final byte[] yuvData;\n  private final int dataWidth;\n  private final int dataHeight;\n  private final int left;\n  private final int top;\n\n  public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,\n      int width, int height) {\n    super(width, height);\n\n    if (left + width > dataWidth || top + height > dataHeight) {\n      throw new IllegalArgumentException(\"Crop rectangle does not fit within image data.\");\n    }\n\n    this.yuvData = yuvData;\n    this.dataWidth = dataWidth;\n    this.dataHeight = dataHeight;\n    this.left = left;\n    this.top = top;\n  }\n\n  @Override\n  public byte[] getRow(int y, byte[] row) {\n    if (y < 0 || y >= getHeight()) {\n      throw new IllegalArgumentException(\"Requested row is outside the image: \" + y);\n    }\n    int width = getWidth();\n    if (row == null || row.length < width) {\n      row = new byte[width];\n    }\n    int offset = (y + top) * dataWidth + left;\n    System.arraycopy(yuvData, offset, row, 0, width);\n    return row;\n  }\n\n  @Override\n  public byte[] getMatrix() {\n    int width = getWidth();\n    int height = getHeight();\n\n    // If the caller asks for the entire underlying image, save the copy and give them the\n    // original data. The docs specifically warn that result.length must be ignored.\n    if (width == dataWidth && height == dataHeight) {\n      return yuvData;\n    }\n\n    int area = width * height;\n    byte[] matrix = new byte[area];\n    int inputOffset = top * dataWidth + left;\n\n    // If the width matches the full width of the underlying data, perform a single copy.\n    if (width == dataWidth) {\n      System.arraycopy(yuvData, inputOffset, matrix, 0, area);\n      return matrix;\n    }\n\n    // Otherwise copy one cropped row at a time.\n    byte[] yuv = yuvData;\n    for (int y = 0; y < height; y++) {\n      int outputOffset = y * width;\n      System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);\n      inputOffset += dataWidth;\n    }\n    return matrix;\n  }\n\n  @Override\n  public boolean isCropSupported() {\n    return true;\n  }\n\n  public int getDataWidth() {\n    return dataWidth;\n  }\n\n  public int getDataHeight() {\n    return dataHeight;\n  }\n\n  public Bitmap renderCroppedGreyscaleBitmap() {\n    int width = getWidth();\n    int height = getHeight();\n    int[] pixels = new int[width * height];\n    byte[] yuv = yuvData;\n    int inputOffset = top * dataWidth + left;\n\n    for (int y = 0; y < height; y++) {\n      int outputOffset = y * width;\n      for (int x = 0; x < width; x++) {\n        int grey = yuv[inputOffset + x] & 0xff;\n        pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);\n      }\n      inputOffset += dataWidth;\n    }\n\n    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);\n    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);\n    return bitmap;\n  }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/camera/PreviewCallback.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.camera;\n\nimport android.graphics.Point;\nimport android.hardware.Camera;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.util.Log;\n\nfinal class PreviewCallback implements Camera.PreviewCallback {\n\n  private static final String TAG = PreviewCallback.class.getSimpleName();\n\n  private final CameraConfigurationManager configManager;\n  private final boolean useOneShotPreviewCallback;\n  private Handler previewHandler;\n  private int previewMessage;\n\n  PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {\n    this.configManager = configManager;\n    this.useOneShotPreviewCallback = useOneShotPreviewCallback;\n  }\n\n  void setHandler(Handler previewHandler, int previewMessage) {\n    this.previewHandler = previewHandler;\n    this.previewMessage = previewMessage;\n  }\n\n  public void onPreviewFrame(byte[] data, Camera camera) {\n    Point cameraResolution = configManager.getCameraResolution();\n    if (!useOneShotPreviewCallback) {\n      camera.setPreviewCallback(null);\n    }\n    if (previewHandler != null) {\n      Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,\n          cameraResolution.y, data);\n      message.sendToTarget();\n      previewHandler = null;\n    } else {\n      Log.d(TAG, \"Got preview callback, but no handler for it\");\n    }\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/CaptureActivityHandler.java",
    "content": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.decoding;\n\nimport android.os.Handler;\nimport android.os.Message;\n\nimport com.htmessage.yichatopen.widget.zxing.activity.CaptureActivity;\nimport com.htmessage.yichatopen.widget.zxing.camera.CameraManager;\nimport com.htmessage.yichatopen.widget.zxing.view.ViewfinderResultPointCallback;\nimport com.google.zxing.BarcodeFormat;\n\nimport java.util.Vector;\n\n/**\n * This class handles all the messaging which comprises the state machine for capture.\n */\npublic final class CaptureActivityHandler extends Handler {\n\n  private static final String TAG = CaptureActivityHandler.class.getSimpleName();\n\n  private final CaptureActivity activity;\n  private final DecodeThread decodeThread;\n  private State state;\n\n  private enum State {\n    PREVIEW,\n    SUCCESS,\n    DONE\n  }\n\n  public CaptureActivityHandler(CaptureActivity activity, Vector<BarcodeFormat> decodeFormats,\n                                String characterSet) {\n    this.activity = activity;\n    decodeThread = new DecodeThread(activity, decodeFormats, characterSet,\n        new ViewfinderResultPointCallback(activity.getViewfinderView()));\n    decodeThread.start();\n    state = State.SUCCESS;\n    // Start ourselves capturing previews and decoding.\n    CameraManager.get().startPreview();\n    restartPreviewAndDecode();\n  }\n\n  @Override\n  public void handleMessage(Message message) {\n    switch (message.what) {\n      \n         \n      \n        \n    }\n  }\n\n  public void quitSynchronously() {\n    state = State.DONE;\n    CameraManager.get().stopPreview();\n    Message quit = null;\n    quit.sendToTarget();\n    try {\n      decodeThread.join();\n    } catch (InterruptedException e) {\n      // continue\n    }\n\n    // Be absolutely sure we don't send any queued up messages\n//    removeMessages(R.id.decode_succeeded);\n//    removeMessages(R.id.decode_failed);\n  }\n\n  private void restartPreviewAndDecode() {\n    if (state == State.SUCCESS) {\n      state = State.PREVIEW;\n//      CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);\n//      CameraManager.get().requestAutoFocus(this, R.id.auto_focus);\n      activity.drawViewfinder();\n    }\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/DecodeFormatManager.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.decoding;\n\nimport android.content.Intent;\nimport android.net.Uri;\n\nimport com.google.zxing.BarcodeFormat;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Vector;\nimport java.util.regex.Pattern;\n\nfinal class DecodeFormatManager {\n\n  private static final Pattern COMMA_PATTERN = Pattern.compile(\",\");\n\n  static final Vector<BarcodeFormat> PRODUCT_FORMATS;\n  static final Vector<BarcodeFormat> ONE_D_FORMATS;\n  static final Vector<BarcodeFormat> QR_CODE_FORMATS;\n  static final Vector<BarcodeFormat> DATA_MATRIX_FORMATS;\n  static {\n    PRODUCT_FORMATS = new Vector<BarcodeFormat>(5);\n    PRODUCT_FORMATS.add(BarcodeFormat.UPC_A);\n    PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);\n    PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);\n    PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);\n    PRODUCT_FORMATS.add(BarcodeFormat.RSS14);\n    ONE_D_FORMATS = new Vector<BarcodeFormat>(PRODUCT_FORMATS.size() + 4);\n    ONE_D_FORMATS.addAll(PRODUCT_FORMATS);\n    ONE_D_FORMATS.add(BarcodeFormat.CODE_39);\n    ONE_D_FORMATS.add(BarcodeFormat.CODE_93);\n    ONE_D_FORMATS.add(BarcodeFormat.CODE_128);\n    ONE_D_FORMATS.add(BarcodeFormat.ITF);\n    QR_CODE_FORMATS = new Vector<BarcodeFormat>(1);\n    QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);\n    DATA_MATRIX_FORMATS = new Vector<BarcodeFormat>(1);\n    DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);\n  }\n\n  private DecodeFormatManager() {}\n\n  static Vector<BarcodeFormat> parseDecodeFormats(Intent intent) {\n    List<String> scanFormats = null;\n    String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS);\n    if (scanFormatsString != null) {\n      scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString));\n    }\n    return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE));\n  }\n\n  static Vector<BarcodeFormat> parseDecodeFormats(Uri inputUri) {\n    List<String> formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS);\n    if (formats != null && formats.size() == 1 && formats.get(0) != null){\n      formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0)));\n    }\n    return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE));\n  }\n\n  private static Vector<BarcodeFormat> parseDecodeFormats(Iterable<String> scanFormats,\n                                                          String decodeMode) {\n    if (scanFormats != null) {\n      Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();\n      try {\n        for (String format : scanFormats) {\n          formats.add(BarcodeFormat.valueOf(format));\n        }\n        return formats;\n      } catch (IllegalArgumentException iae) {\n        // ignore it then\n      }\n    }\n    if (decodeMode != null) {\n      if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) {\n        return PRODUCT_FORMATS;\n      }\n      if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) {\n        return QR_CODE_FORMATS;\n      }\n      if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) {\n        return DATA_MATRIX_FORMATS;\n      }\n      if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) {\n        return ONE_D_FORMATS;\n      }\n    }\n    return null;\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/DecodeHandler.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.decoding;\n\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.util.Log;\n\nimport com.htmessage.yichatopen.widget.zxing.activity.CaptureActivity;\nimport com.htmessage.yichatopen.widget.zxing.camera.CameraManager;\nimport com.htmessage.yichatopen.widget.zxing.camera.PlanarYUVLuminanceSource;\nimport com.google.zxing.BinaryBitmap;\nimport com.google.zxing.DecodeHintType;\nimport com.google.zxing.MultiFormatReader;\nimport com.google.zxing.ReaderException;\nimport com.google.zxing.Result;\nimport com.google.zxing.common.HybridBinarizer;\n\nimport java.util.Hashtable;\n\nfinal class DecodeHandler extends Handler {\n\n  private static final String TAG = DecodeHandler.class.getSimpleName();\n\n  private final CaptureActivity activity;\n  private final MultiFormatReader multiFormatReader;\n\n  DecodeHandler(CaptureActivity activity, Hashtable<DecodeHintType, Object> hints) {\n    multiFormatReader = new MultiFormatReader();\n    multiFormatReader.setHints(hints);\n    this.activity = activity;\n  }\n\n  @Override\n  public void handleMessage(Message message) {\n    switch (message.what) {\n      \n    }\n  }\n\n  /**\n   * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,\n   * reuse the same reader objects from one decode to the next.\n   *\n   * @param data   The YUV preview frame.\n   * @param width  The width of the preview frame.\n   * @param height The height of the preview frame.\n   */\n  private void decode(byte[] data, int width, int height) {\n    long start = System.currentTimeMillis();\n    Result rawResult = null;\n    \n    //modify here\n    byte[] rotatedData = new byte[data.length];\n    for (int y = 0; y < height; y++) {\n        for (int x = 0; x < width; x++)\n            rotatedData[x * height + height - y - 1] = data[x + y * width];\n    }\n    int tmp = width; // Here we are swapping, that's the difference to #11\n    width = height;\n    height = tmp;\n    \n    PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);\n    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));\n    try {\n      rawResult = multiFormatReader.decodeWithState(bitmap);\n    } catch (ReaderException re) {\n      // continue\n    } finally {\n      multiFormatReader.reset();\n    }\n\n    if (rawResult != null) {\n      long end = System.currentTimeMillis();\n      Log.d(TAG, \"Found barcode (\" + (end - start) + \" ms):\\n\" + rawResult.toString());\n      Message message =null;\n      Bundle bundle = new Bundle();\n      bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());\n      message.setData(bundle);\n      //Log.d(TAG, \"Sending decode succeeded message...\");\n      message.sendToTarget();\n    } else {\n      Message message = Message.obtain(activity.getHandler(),null);\n      message.sendToTarget();\n    }\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/DecodeThread.java",
    "content": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.decoding;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport com.htmessage.yichatopen.widget.zxing.activity.CaptureActivity;\nimport com.google.zxing.BarcodeFormat;\nimport com.google.zxing.DecodeHintType;\nimport com.google.zxing.ResultPointCallback;\n\nimport java.util.Hashtable;\nimport java.util.Vector;\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * This thread does all the heavy lifting of decoding the images.\n */\nfinal class DecodeThread extends Thread {\n\n  public static final String BARCODE_BITMAP = \"barcode_bitmap\";\n  private final CaptureActivity activity;\n  private final Hashtable<DecodeHintType, Object> hints;\n  private Handler handler;\n  private final CountDownLatch handlerInitLatch;\n\n  DecodeThread(CaptureActivity activity,\n               Vector<BarcodeFormat> decodeFormats,\n               String characterSet,\n               ResultPointCallback resultPointCallback) {\n\n    this.activity = activity;\n    handlerInitLatch = new CountDownLatch(1);\n\n    hints = new Hashtable<DecodeHintType, Object>(3);\n\n    if (decodeFormats == null || decodeFormats.isEmpty()) {\n    \t decodeFormats = new Vector<BarcodeFormat>();\n    \t decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);\n    \t decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);\n    \t decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);\n    }\n    \n    hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);\n\n    if (characterSet != null) {\n      hints.put(DecodeHintType.CHARACTER_SET, characterSet);\n    }\n\n    hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);\n  }\n\n  Handler getHandler() {\n    try {\n      handlerInitLatch.await();\n    } catch (InterruptedException ie) {\n      // continue?\n    }\n    return handler;\n  }\n\n  @Override\n  public void run() {\n    Looper.prepare();\n    handler = new DecodeHandler(activity, hints);\n    handlerInitLatch.countDown();\n    Looper.loop();\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/FinishListener.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.decoding;\n\nimport android.app.Activity;\nimport android.content.DialogInterface;\n\n/**\n * Simple listener used to exit the app in a few cases.\n *\n */\npublic final class FinishListener\n    implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {\n\n  private final Activity activityToFinish;\n\n  public FinishListener(Activity activityToFinish) {\n    this.activityToFinish = activityToFinish;\n  }\n\n  public void onCancel(DialogInterface dialogInterface) {\n    run();\n  }\n\n  public void onClick(DialogInterface dialogInterface, int i) {\n    run();\n  }\n\n  public void run() {\n    activityToFinish.finish();\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/InactivityTimer.java",
    "content": "/*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.decoding;\n\nimport android.app.Activity;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Finishes an activity after a period of inactivity.\n */\npublic final class InactivityTimer {\n\n  private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;\n\n  private final ScheduledExecutorService inactivityTimer =\n      Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());\n  private final Activity activity;\n  private ScheduledFuture<?> inactivityFuture = null;\n\n  public InactivityTimer(Activity activity) {\n    this.activity = activity;\n    onActivity();\n  }\n\n  public void onActivity() {\n    cancel();\n    inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),\n                                                INACTIVITY_DELAY_SECONDS,\n                                                TimeUnit.SECONDS);\n  }\n\n  private void cancel() {\n    if (inactivityFuture != null) {\n      inactivityFuture.cancel(true);\n      inactivityFuture = null;\n    }\n  }\n\n  public void shutdown() {\n    cancel();\n    inactivityTimer.shutdown();\n  }\n\n  private static final class DaemonThreadFactory implements ThreadFactory {\n    public Thread newThread(Runnable runnable) {\n      Thread thread = new Thread(runnable);\n      thread.setDaemon(true);\n      return thread;\n    }\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/decoding/Intents.java",
    "content": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.decoding;\n\n/**\n * This class provides the constants to use when sending an Intent to Barcode Scanner.\n * These strings are effectively API and cannot be changed.\n */\npublic final class Intents {\n  private Intents() {\n  }\n\n  public static final class Scan {\n    /**\n     * Send this intent to open the Barcodes app in scanning mode, find a barcode, and return\n     * the results.\n     */\n    public static final String ACTION = \"com.google.zxing.client.android.SCAN\";\n\n    /**\n     * By default, sending Scan.ACTION will decode all barcodes that we understand. However it\n     * may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with\n     * one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}).\n     * Optional.\n     *\n     * Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}.\n     * It is overridden by that setting.\n     */\n    public static final String MODE = \"SCAN_MODE\";\n\n    /**\n     * Comma-separated list of formats to scan for. The values must match the names of\n     * {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}.\n     * Example: \"EAN_13,EAN_8,QR_CODE\"\n     *\n     * This overrides {@link #MODE}.\n     */\n    public static final String SCAN_FORMATS = \"SCAN_FORMATS\";\n\n    /**\n     * @see com.google.zxing.DecodeHintType#CHARACTER_SET\n     */\n    public static final String CHARACTER_SET = \"CHARACTER_SET\";\n\n    /**\n     * Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get\n     * prices, reviews, etc. for products.\n     */\n    public static final String PRODUCT_MODE = \"PRODUCT_MODE\";\n\n    /**\n     * Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).\n     */\n    public static final String ONE_D_MODE = \"ONE_D_MODE\";\n\n    /**\n     * Decode only QR codes.\n     */\n    public static final String QR_CODE_MODE = \"QR_CODE_MODE\";\n\n    /**\n     * Decode only Data Matrix codes.\n     */\n    public static final String DATA_MATRIX_MODE = \"DATA_MATRIX_MODE\";\n\n    /**\n     * If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which\n     * requested the scan via startSubActivity(). The barcodes contents can be retrieved with\n     * intent.getStringExtra(RESULT). If the user presses Back, the result code will be\n     * RESULT_CANCELED.\n     */\n    public static final String RESULT = \"SCAN_RESULT\";\n\n    /**\n     * Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.\n     * See Contents.Format for possible values.\n     */\n    public static final String RESULT_FORMAT = \"SCAN_RESULT_FORMAT\";\n\n    /**\n     * Setting this to false will not save scanned codes in the history.\n     */\n    public static final String SAVE_HISTORY = \"SAVE_HISTORY\";\n\n    private Scan() {\n    }\n  }\n\n  public static final class Encode {\n    /**\n     * Send this intent to encode a piece of data as a QR code and display it full screen, so\n     * that another person can scan the barcode from your screen.\n     */\n    public static final String ACTION = \"com.google.zxing.client.android.ENCODE\";\n\n    /**\n     * The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a\n     * Bundle, depending on the type and format specified. Non-QR Code formats should\n     * just use a String here. For QR Code, see Contents for details.\n     */\n    public static final String DATA = \"ENCODE_DATA\";\n\n    /**\n     * The type of data being supplied if the format is QR Code. Use\n     * Intent.putExtra(TYPE, type) with one of Contents.Type.\n     */\n    public static final String TYPE = \"ENCODE_TYPE\";\n    \n    /**\n     * The barcode format to be displayed. If this isn't specified or is blank, \n     * it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where\n     * format is one of Contents.Format. \n     */\n    public static final String FORMAT = \"ENCODE_FORMAT\";\n\n    private Encode() {\n    }\n  }\n\n  public static final class SearchBookContents {\n    /**\n     * Use Google Book Search to search the contents of the book provided.\n     */\n    public static final String ACTION = \"com.google.zxing.client.android.SEARCH_BOOK_CONTENTS\";\n\n    /**\n     * The book to search, identified by ISBN number.\n     */\n    public static final String ISBN = \"ISBN\";\n\n    /**\n     * An optional field which is the text to search for.\n     */\n    public static final String QUERY = \"QUERY\";\n\n    private SearchBookContents() {\n    }\n  }\n\n  public static final class WifiConnect {\n\t    /**\n\t     * Internal intent used to trigger connection to a wi-fi network.\n\t     */\n\t    public static final String ACTION = \"com.google.zxing.client.android.WIFI_CONNECT\";\n\n\t    /**\n\t     * The network to connect to, all the configuration provided here.\n\t     */\n\t    public static final String SSID = \"SSID\";\n\n\t    /**\n\t     * The network to connect to, all the configuration provided here.\n\t     */\n\t    public static final String TYPE = \"TYPE\";\n\n\t    /**\n\t     * The network to connect to, all the configuration provided here.\n\t     */\n\t    public static final String PASSWORD = \"PASSWORD\";\n\n\t    private WifiConnect() {\n\t    }\n\t  }\n\n\n  public static final class Share {\n    /**\n     * Give the user a choice of items to encode as a barcode, then render it as a QR Code and\n     * display onscreen for a friend to scan with their phone.\n     */\n    public static final String ACTION = \"com.google.zxing.client.android.SHARE\";\n\n    private Share() {\n    }\n  }\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/encoding/EncodingHandler.java",
    "content": "package com.htmessage.yichatopen.widget.zxing.encoding;\n\nimport android.graphics.Bitmap;\n\nimport com.google.zxing.BarcodeFormat;\nimport com.google.zxing.EncodeHintType;\nimport com.google.zxing.MultiFormatWriter;\nimport com.google.zxing.WriterException;\nimport com.google.zxing.common.BitMatrix;\n\nimport java.util.Hashtable;\n\n/**\n * @author Ryan Tang\n *\n */\npublic final class EncodingHandler {\n\tprivate static final int BLACK = 0xff000000;\n\t\n\tpublic static Bitmap createQRCode(String str,int widthAndHeight) throws WriterException {\n\t\tHashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();  \n        hints.put(EncodeHintType.CHARACTER_SET, \"utf-8\"); \n\t\tBitMatrix matrix = new MultiFormatWriter().encode(str,\n\t\t\t\tBarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);\n\t\tint width = matrix.getWidth();\n\t\tint height = matrix.getHeight();\n\t\tint[] pixels = new int[width * height];\n\t\t\n\t\tfor (int y = 0; y < height; y++) {\n\t\t\tfor (int x = 0; x < width; x++) {\n\t\t\t\tif (matrix.get(x, y)) {\n\t\t\t\t\tpixels[y * width + x] = BLACK;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tBitmap bitmap = Bitmap.createBitmap(width, height,\n\t\t\t\tBitmap.Config.ARGB_8888);\n\t\tbitmap.setPixels(pixels, 0, width, 0, 0, width, height);\n\t\treturn bitmap;\n\t}\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/view/ViewfinderResultPointCallback.java",
    "content": "/*\n * Copyright (C) 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.view;\n\nimport com.google.zxing.ResultPoint;\nimport com.google.zxing.ResultPointCallback;\n\npublic final class ViewfinderResultPointCallback implements ResultPointCallback {\n\n  private final ViewfinderView viewfinderView;\n\n  public ViewfinderResultPointCallback(ViewfinderView viewfinderView) {\n    this.viewfinderView = viewfinderView;\n  }\n\n  public void foundPossibleResultPoint(ResultPoint point) {\n    viewfinderView.addPossibleResultPoint(point);\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/htmessage/yichatopen/widget/zxing/view/ViewfinderView.java",
    "content": "/*\n * Copyright (C) 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.htmessage.yichatopen.widget.zxing.view;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.graphics.Bitmap;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.graphics.Rect;\nimport android.util.AttributeSet;\nimport android.view.View;\n\nimport com.htmessage.yichatopen.widget.zxing.camera.CameraManager;\nimport com.google.zxing.ResultPoint;\n\nimport java.util.Collection;\nimport java.util.HashSet;\n\n/**\n * This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial\n * transparency outside it, as well as the laser scanner animation and result points.\n * �Զ����View������ʱ�м���ʾ��\n */\npublic final class ViewfinderView extends View {\n\n  private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};\n  private static final long ANIMATION_DELAY = 100L;\n  private static final int OPAQUE = 0xFF;\n\n  private final Paint paint;\n  private Bitmap resultBitmap;\n  private final int maskColor;\n  private final int resultColor;\n  private final int frameColor;\n  private final int laserColor;\n  private final int resultPointColor;\n  private int scannerAlpha;\n  private Collection<ResultPoint> possibleResultPoints;\n  private Collection<ResultPoint> lastPossibleResultPoints;\n\n  // This constructor is used when the class is built from an XML resource.\n  public ViewfinderView(Context context, AttributeSet attrs) {\n    super(context, attrs);\n\n    // Initialize these once for performance rather than calling them every time in onDraw().\n    paint = new Paint();\n    Resources resources = getResources();\n    maskColor = 0;\n    resultColor =0;\n    frameColor = 0;\n    laserColor = 0;\n    resultPointColor =0;\n    scannerAlpha = 0;\n    possibleResultPoints = new HashSet<ResultPoint>(5);\n  }\n\n  @Override\n  public void onDraw(Canvas canvas) {\n    Rect frame = CameraManager.get().getFramingRect();\n    if (frame == null) {\n      return;\n    }\n    int width = canvas.getWidth();\n    int height = canvas.getHeight();\n\n    // Draw the exterior (i.e. outside the framing rect) darkened\n    paint.setColor(resultBitmap != null ? resultColor : maskColor);\n    canvas.drawRect(0, 0, width, frame.top, paint);\n    canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);\n    canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);\n    canvas.drawRect(0, frame.bottom + 1, width, height, paint);\n\n    if (resultBitmap != null) {\n      // Draw the opaque result bitmap over the scanning rectangle\n      paint.setAlpha(OPAQUE);\n      canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);\n    } else {\n\n      // Draw a two pixel solid black border inside the framing rect\n      paint.setColor(frameColor);\n      canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);\n      canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);\n      canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);\n      canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);\n\n      // Draw a red \"laser scanner\" line through the middle to show decoding is active\n      paint.setColor(laserColor);\n      paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);\n      scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;\n      int middle = frame.height() / 2 + frame.top;\n      canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);\n\n      Collection<ResultPoint> currentPossible = possibleResultPoints;\n      Collection<ResultPoint> currentLast = lastPossibleResultPoints;\n      if (currentPossible.isEmpty()) {\n        lastPossibleResultPoints = null;\n      } else {\n        possibleResultPoints = new HashSet<ResultPoint>(5);\n        lastPossibleResultPoints = currentPossible;\n        paint.setAlpha(OPAQUE);\n        paint.setColor(resultPointColor);\n        for (ResultPoint point : currentPossible) {\n          canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);\n        }\n      }\n      if (currentLast != null) {\n        paint.setAlpha(OPAQUE / 2);\n        paint.setColor(resultPointColor);\n        for (ResultPoint point : currentLast) {\n          canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);\n        }\n      }\n\n      // Request another update at the animation interval, but only repaint the laser line,\n      // not the entire viewfinder mask.\n      postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);\n    }\n  }\n\n  public void drawViewfinder() {\n    resultBitmap = null;\n    invalidate();\n  }\n\n  /**\n   * Draw a bitmap with the result points highlighted instead of the live scanning display.\n   *\n   * @param barcode An image of the decoded barcode.\n   */\n  public void drawResultBitmap(Bitmap barcode) {\n    resultBitmap = barcode;\n    invalidate();\n  }\n\n  public void addPossibleResultPoint(ResultPoint point) {\n    possibleResultPoints.add(point);\n  }\n\n}\n"
  },
  {
    "path": "app/src/main/res/anim/fade_in.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<alpha xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:interpolator=\"@android:anim/accelerate_interpolator\"\n    android:fromAlpha=\"0.0\" android:toAlpha=\"1.0\"\n    android:duration=\"300\" />"
  },
  {
    "path": "app/src/main/res/anim/fade_out.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<alpha xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:interpolator=\"@android:anim/accelerate_interpolator\"\n    android:fromAlpha=\"1.0\" android:toAlpha=\"0.0\"\n    android:duration=\"300\" />"
  },
  {
    "path": "app/src/main/res/anim/head_in.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- 左上角扩大-->\n  <scale   xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:interpolator=\"@android:anim/accelerate_decelerate_interpolator\"  \n        android:fromXScale=\"0.001\"   \n        android:toXScale=\"1.0\"   \n        android:fromYScale=\"0.001\"   \n        android:toYScale=\"1.0\"   \n        android:pivotX=\"15%\"  \n        android:pivotY=\"25%\"  \n        android:duration=\"200\" />  \n   "
  },
  {
    "path": "app/src/main/res/anim/head_out.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- 左上角缩小 -->\n  <scale   xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:interpolator=\"@android:anim/accelerate_decelerate_interpolator\"  \n        android:fromXScale=\"1.0\"   \n        android:toXScale=\"0.001\"   \n        android:fromYScale=\"1.0\"   \n        android:toYScale=\"0.001\"   \n        android:pivotX=\"15%\"  \n        android:pivotY=\"25%\"  \n        android:duration=\"200\" />  \n   "
  },
  {
    "path": "app/src/main/res/anim/hold.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?> \n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n       android:interpolator=\"@android:anim/accelerate_interpolator\"\n       android:fromXDelta=\"0\" android:toXDelta=\"0\"\n       android:duration=\"300\" />"
  },
  {
    "path": "app/src/main/res/anim/loading_animation.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <rotate\n        android:interpolator=\"@android:anim/linear_interpolator\"\n        android:pivotX=\"50%\"\n        android:pivotY=\"50%\"\n        android:fromDegrees=\"0\"\n        android:toDegrees=\"+360\"\n        android:duration=\"1500\"\n        android:startOffset=\"-1\"\n        android:repeatMode=\"restart\"\n        android:repeatCount=\"-1\"/>\n</set>"
  },
  {
    "path": "app/src/main/res/anim/push_bottom_in.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- 上下滑入式 -->\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <translate\n        android:duration=\"200\"\n        android:fromYDelta=\"50%p\"\n        android:toYDelta=\"0\" />\n\n</set>"
  },
  {
    "path": "app/src/main/res/anim/push_bottom_out.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- 上下滑入式 -->\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    \n    <translate\n        android:duration=\"200\"\n        android:fromYDelta=\"0\"\n        android:toYDelta=\"50%p\" />\n\n    \n\n</set>"
  },
  {
    "path": "app/src/main/res/anim/push_top_in.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- 上下滑入式 -->\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <translate\n        android:duration=\"200\"\n        android:fromYDelta=\"-50%p\"\n        android:toYDelta=\"0\" />   \n</set>"
  },
  {
    "path": "app/src/main/res/anim/push_top_in2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- 上下滑入式 -->\n<scale   xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:interpolator=\"@android:anim/accelerate_decelerate_interpolator\"  \n        android:fromXScale=\"1.0\"   \n        android:toXScale=\"1.0\"   \n        android:fromYScale=\"0\"   \n        android:toYScale=\"1.0\"   \n        android:pivotX=\"0\"  \n        android:pivotY=\"10%\"  \n        android:duration=\"200\" /> "
  },
  {
    "path": "app/src/main/res/anim/push_top_out.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- 上下滑入式 -->\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <translate\n        android:duration=\"200\"\n        android:fromYDelta=\"0\"\n        android:toYDelta=\"-50%p\" />   \n</set>"
  },
  {
    "path": "app/src/main/res/anim/push_top_out2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<scale   xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:interpolator=\"@android:anim/accelerate_decelerate_interpolator\"  \n        android:fromXScale=\"1.0\"   \n        android:toXScale=\"1.0\"   \n        android:fromYScale=\"1.0\"   \n        android:toYScale=\"0\"   \n        android:pivotX=\"0\"  \n        android:pivotY=\"10%\"  \n        android:duration=\"200\" /> "
  },
  {
    "path": "app/src/main/res/anim/slide_in_from_left.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <translate\n        android:duration=\"200\"\n        android:fromXDelta=\"-100%p\"\n        android:toXDelta=\"0\" />\n\n</set>"
  },
  {
    "path": "app/src/main/res/anim/slide_in_from_right.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <translate\n        android:duration=\"200\"\n        android:fromXDelta=\"100%p\"\n        android:toXDelta=\"0\" />\n\n</set>"
  },
  {
    "path": "app/src/main/res/anim/slide_out_to_left.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <translate\n        android:duration=\"200\"\n        android:fromXDelta=\"0\"\n        android:toXDelta=\"-100%p\" />\n\n</set>"
  },
  {
    "path": "app/src/main/res/anim/slide_out_to_right.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <translate\n        android:duration=\"200\"\n        android:fromXDelta=\"0\"\n        android:toXDelta=\"100%p\" />\n\n</set>"
  },
  {
    "path": "app/src/main/res/anim/voice_from_icon.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<animation-list xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:oneshot=\"false\">\n    <item\n        android:drawable=\"@drawable/chatfrom_voice_playing_f1\"\n        android:duration=\"200\" />\n    <item\n        android:drawable=\"@drawable/chatfrom_voice_playing_f2\"\n        android:duration=\"200\" />\n    <item\n        android:drawable=\"@drawable/chatfrom_voice_playing_f3\"\n        android:duration=\"200\" />\n</animation-list>"
  },
  {
    "path": "app/src/main/res/anim/voice_to_icon.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<animation-list xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:oneshot=\"false\">\n    <item\n        android:drawable=\"@drawable/chatto_voice_playing_f1\"\n        android:duration=\"200\" />\n    <item\n        android:drawable=\"@drawable/chatto_voice_playing_f2\"\n        android:duration=\"200\" />\n    <item\n        android:drawable=\"@drawable/chatto_voice_playing_f3\"\n        android:duration=\"200\" />\n</animation-list>"
  },
  {
    "path": "app/src/main/res/color/login_btn_text_color.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_enabled=\"false\" android:color=\"@color/white\" />\n    <item android:color=\"@android:color/white\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/color/main_botton_text_color.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_selected=\"true\" android:color=\"@color/icon_press\" />\n    <item android:color=\"#666666\" />\n</selector>\n"
  },
  {
    "path": "app/src/main/res/drawable/bg_btn_gray.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <solid android:color=\"#F1F1F1\" />\n\n    <corners\n        android:bottomLeftRadius=\"1dp\"\n        android:bottomRightRadius=\"1dp\"\n        android:topLeftRadius=\"1dp\"\n        android:topRightRadius=\"1dp\" />\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/bg_btn_green.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:drawable=\"@color/icon_press\" android:state_pressed=\"true\"/>\n \n    <item android:drawable=\"@color/icon_press\" android:state_enabled=\"false\"/>\n    <item android:drawable=\"@color/icon_press\" android:state_enabled=\"true\"/>\n    <item android:drawable=\"@color/icon_press\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/bg_dialog.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:drawable=\"@drawable/icon_gray\" android:state_pressed=\"true\"/>\n    <item android:drawable=\"@drawable/icon_white\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/bg_et.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item android:drawable=\"@drawable/bg_et_f\" android:state_focused=\"true\"/>\n    <item android:drawable=\"@drawable/bg_et_n\"/>\n  \n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/btn_bottom_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n      <item android:drawable=\"@color/btn_pressed_green_solid\" android:state_pressed=\"true\"/>\n    <item android:drawable=\"@color/btn_pressed_green_solid\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@color/white\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/btn_more_type_msg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/type_select_btn_pressed\" />\n    <item android:state_selected=\"true\" android:drawable=\"@drawable/type_select_btn_pressed\" />\n    <item android:state_focused=\"true\" android:drawable=\"@drawable/type_select_btn_pressed\" />\n    <item android:drawable=\"@drawable/type_select_btn_nor\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chat_error_item_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/mm_listitem_pressed\"/>\n    <item android:drawable=\"@color/error_item_color\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chat_image_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item android:drawable=\"@drawable/pictures\" android:state_pressed=\"true\"/>\n    <item android:drawable=\"@drawable/pictures\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@drawable/pictures\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chat_press_speak_btn.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:state_pressed=\"true\">\n        <shape>\n            <corners android:radius=\"3dp\" />\n\n            <padding android:bottom=\"5dp\" android:left=\"5dp\" android:right=\"5dp\" android:top=\"5dp\" />\n\n            <solid android:color=\"#d3d3d3\" />\n\n            <stroke android:width=\"0.5dp\" android:color=\"#999999\" />\n        </shape>\n    </item>\n    <item>\n        <shape>\n            <corners android:radius=\"3dp\" />\n\n            <padding android:bottom=\"5dp\" android:left=\"5dp\" android:right=\"5dp\" android:top=\"5dp\" />\n\n            <solid android:color=\"#00000000\" />\n\n            <stroke android:width=\"0.5dp\" android:color=\"#999999\" />\n        </shape>\n    </item>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chat_takepic_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item android:drawable=\"@drawable/takephoto\" android:state_pressed=\"true\"/>\n    <item android:drawable=\"@drawable/takephoto\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chatfrom_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/chatfrom_bg_focused\" />\n    <item android:drawable=\"@drawable/chatfrom_bg_normal\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chatting_setmode_keyboard_btn.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/chatting_setmode_keyboard_btn_pressed\" />\n    <item android:state_selected=\"true\" android:drawable=\"@drawable/chatting_setmode_keyboard_btn_pressed\" />\n    <item android:drawable=\"@drawable/chatting_setmode_keyboard_btn_normal\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chatting_setmode_voice_btn.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/chatting_setmode_voice_btn_pressed\" />\n    <item android:state_selected=\"true\" android:drawable=\"@drawable/chatting_setmode_voice_btn_pressed\" />\n    <item android:state_focused=\"true\" android:drawable=\"@drawable/chatting_setmode_voice_btn_pressed\" />\n    <item android:drawable=\"@drawable/chatting_setmode_voice_btn_normal\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/chatto_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/chatto_bg_focused\" />\n    <item android:drawable=\"@drawable/chatto_bg_normal\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/divider_horizontal.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <solid android:color=\"#d4d4d4\"/>\n    <size android:height=\"1dp\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/divider_vertical.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <solid android:color=\"#d4d4d4\"/>\n    <size android:width=\"1dp\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/dot_emoji.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <item android:drawable=\"@drawable/dot_emojicon_selected\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@drawable/dot_emojicon_unselected\" android:state_selected=\"false\"/>\n </selector>"
  },
  {
    "path": "app/src/main/res/drawable/edit_text_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item >\n        <shape android:shape=\"rectangle\">\n            <stroke android:width=\"2.0px\" android:color=\"@color/divider_list\"/>\n            <solid android:color=\"@android:color/white\"/>\n        </shape>\n    </item>\n\t<item android:bottom=\"4.0dip\">\n\t    <shape android:shape=\"rectangle\">\n\t        <solid android:color=\"@android:color/white\"/>\n\t        \n\t    </shape>\n\t    \n\t</item>\n\t \n</layer-list>\n"
  },
  {
    "path": "app/src/main/res/drawable/emoji_bottom_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:state_selected=\"true\">\n        <color android:color=\"#d4d4d4\" />\n    </item>\n    <item android:state_selected=\"false\">\n        <color android:color=\"#f4f4f4\" />\n    </item>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/item_pre_videocall_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@drawable/nim_picker_image_selected\" android:state_checked=\"true\"></item>\n    <item android:drawable=\"@drawable/nim_picker_image_selected\" android:state_selected=\"true\"></item>\n    <item android:drawable=\"@drawable/nim_picker_image_selected\" android:state_pressed=\"true\"></item>\n    <item android:drawable=\"@drawable/nim_picker_image_normal\"></item>\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/list_item_bg_gray.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:state_pressed=\"true\"><color android:color=\"#dddddd\" />\n    </item>\n    <item android:state_pressed=\"false\"><color android:color=\"#f0f0f0\" />\n    </item>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/list_item_bg_white.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:state_pressed=\"true\"><color android:color=\"#dddddd\" />\n    </item>\n    <item android:state_pressed=\"false\"><color android:color=\"#ffffff\" />\n    </item>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/msg_state_failed_resend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/msg_state_fail_resend_pressed\" />\n    <item android:state_selected=\"true\" android:drawable=\"@drawable/msg_state_fail_resend_pressed\" />\n    <item android:drawable=\"@drawable/msg_state_fail_resend\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/progressbar_white.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rotate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:drawable=\"@drawable/loadingicon\"\n    android:fromDegrees=\"0\"\n    android:pivotX=\"50%\"\n    android:pivotY=\"50%\"\n    android:toDegrees=\"360\" />"
  },
  {
    "path": "app/src/main/res/drawable/recording_hint_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <corners android:radius=\"5dp\" />\n\n    <solid android:color=\"#55000000\" />\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/recording_text_hint_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <corners android:radius=\"5dp\" />\n\n    <solid android:color=\"#55FF0000\" />\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/register_phone_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <corners android:radius=\"0.0dip\" />\n    <solid android:color=\"@color/white\" />\n    <stroke android:width=\"1px\" android:color=\"@color/gray_pressed\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/sidebar_background_pressed.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <corners android:radius=\"8dp\" />\n\n    <solid android:color=\"#50000000\" />\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/sign_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <corners android:radius=\"10dip\" />\n    <solid android:color=\"@color/main_bottom_split\" />\n    <stroke android:width=\"1.0dip\" android:color=\"@color/main_bottom_split\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/tab_chat_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:drawable=\"@drawable/chat_press\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@drawable/chat_numal\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/tab_contact_list_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:drawable=\"@drawable/contact_press\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@drawable/contact_numal\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/tab_find_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:drawable=\"@drawable/find_press\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@drawable/find_numal\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/tab_profile_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:drawable=\"@drawable/me_press\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@drawable/me_numal\"/>\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/timestampe_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <corners android:radius=\"3dp\" />\n\n    <solid android:color=\"#dcdddd\" />\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/top_bar_back.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/icon_back_p\" />\n    <item android:drawable=\"@drawable/icon_back_n\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/topbar_back.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector\n  xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"true\" android:drawable=\"@drawable/icon_p\" />\n    <item android:state_selected=\"true\" android:drawable=\"@drawable/icon_p\" />\n    <item android:drawable=\"@drawable/icon_back_n\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/layout/activity_addfriends_final.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#fff\"\n    android:orientation=\"vertical\" >\n\n    <RelativeLayout\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\" >\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/top_bar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:id=\"@+id/tv_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toRightOf=\"@+id/view_temp\"\n            android:layout_marginLeft=\"10dp\"\n            android:text=\"@string/add_friend\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_send\"\n            android:layout_width=\"48dp\"\n            android:layout_height=\"32dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"8dp\"\n            android:background=\"@drawable/bg_btn_green\"\n            android:gravity=\"center\"\n            android:text=\"@string/str_send\"\n            android:textColor=\"#fff\"\n            android:textSize=\"14sp\" />\n    </RelativeLayout>\n  <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"16dp\"\n        android:text=\"@string/pass_or_no_by_send\"\n        android:textColor=\"#AAAAAA\"\n        android:textSize=\"14sp\" />\n    <EditText\n        android:id=\"@+id/et_reason\"\n        android:paddingLeft=\"5dp\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"36dp\"\n        android:layout_marginLeft=\"16dp\"\n        android:layout_marginRight=\"16dp\"\n        android:background=\"@drawable/bg_et\"\n        android:singleLine=\"true\"\n        android:text=\"@string/i_am\"\n        android:textColor=\"#353535\"\n        android:textSize=\"16sp\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_addfriends_next.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#ffffff\" >\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\" >\n\n        <RelativeLayout\n            android:id=\"@+id/title\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"@dimen/height_top_bar\"\n            android:background=\"@color/common_top_bar\" >\n\n            <ImageView\n                android:id=\"@+id/iv_back\"\n                android:layout_width=\"40dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_alignParentLeft=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:onClick=\"back\"\n                android:paddingBottom=\"5dp\"\n                android:paddingLeft=\"5dp\"\n                android:paddingRight=\"5dp\"\n                android:paddingTop=\"5dp\"\n                android:scaleType=\"centerInside\"\n                android:src=\"@drawable/top_bar_back\" />\n\n            <EditText\n                android:id=\"@+id/et_search\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginBottom=\"8dp\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginRight=\"12dp\"\n                android:layout_toRightOf=\"@+id/iv_back\"\n                android:background=\"@drawable/bg_et\"\n                android:gravity=\"bottom\"\n                android:textColor=\"#fff\"\n                android:hint=\"@string/secret_signal_or_phone_number\"\n                android:paddingBottom=\"10dp\"\n                android:paddingLeft=\"46dp\"\n                android:singleLine=\"true\"\n                android:textColorHint=\"#484c4c\"\n                android:textSize=\"16sp\" />\n\n            <ImageView\n                android:layout_width=\"22dp\"\n                android:layout_height=\"22dp\"\n                android:layout_alignBottom=\"@id/et_search\"\n                android:layout_alignLeft=\"@id/et_search\"\n                android:layout_margin=\"8dp\"\n                android:src=\"@drawable/search_white\" />\n\n            <View\n                android:id=\"@+id/view_temp\"\n                android:layout_width=\"1dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_marginBottom=\"8dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_toRightOf=\"@id/iv_back\"\n                android:background=\"#14191A\" />\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:visibility=\"gone\"\n            android:id=\"@+id/re_search\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"64dp\"\n            android:background=\"@drawable/list_item_bg_white\"\n            android:clickable=\"true\"\n            android:paddingBottom=\"14dp\"\n            android:paddingLeft=\"12dp\"\n            android:paddingRight=\"12dp\"\n            android:paddingTop=\"14dp\" >\n\n            <ImageView\n                android:id=\"@+id/iv_find\"\n                android:layout_width=\"48dp\"\n                android:layout_height=\"48dp\"\n                android:layout_alignParentLeft=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:src=\"@drawable/icon_search_green_0\" />\n\n            <TextView\n                android:id=\"@+id/tv_temp\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"16dp\"\n                android:layout_toRightOf=\"@id/iv_find\"\n                android:text=\"@string/search\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:singleLine=\"true\"\n                android:ellipsize=\"end\"\n                android:id=\"@+id/tv_search\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_toRightOf=\"@id/tv_temp\"\n                android:text=\"\"\n                android:textColor=\"@color/icon_press\"\n                android:textSize=\"16sp\" />\n        </RelativeLayout>\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#DBDBDB\" />\n    </LinearLayout>\n\n</ScrollView>"
  },
  {
    "path": "app/src/main/res/layout/activity_addfriends_pre.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#ebebeb\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\">\n\n        <RelativeLayout\n            android:id=\"@+id/title\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"@dimen/height_top_bar\"\n            android:background=\"@color/common_top_bar\">\n\n            <ImageView\n                android:id=\"@+id/iv_back\"\n                android:layout_width=\"40dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_alignParentLeft=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:onClick=\"back\"\n                android:paddingBottom=\"5dp\"\n                android:paddingLeft=\"5dp\"\n                android:paddingRight=\"5dp\"\n                android:paddingTop=\"5dp\"\n                android:scaleType=\"centerInside\"\n                android:src=\"@drawable/top_bar_back\" />\n\n            <View\n                android:id=\"@+id/view_temp\"\n                android:layout_width=\"1dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_marginBottom=\"8dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_toRightOf=\"@id/iv_back\"\n                android:background=\"#14191A\" />\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_toRightOf=\"@+id/view_temp\"\n                android:layout_marginLeft=\"10dp\"\n                android:text=\"@string/add_friend\"\n                android:textColor=\"#ffffff\"\n                android:textSize=\"18sp\" />\n\n\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"52dp\"\n            android:layout_marginTop=\"20dp\"\n            android:background=\"#fff\">\n\n            <TextView\n                android:id=\"@+id/tv_search\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginBottom=\"8dp\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginRight=\"12dp\"\n                android:background=\"@drawable/bg_et\"\n                android:gravity=\"bottom\"\n                android:paddingBottom=\"10dp\"\n                android:paddingLeft=\"46dp\"\n                android:singleLine=\"true\"\n                android:hint=\"@string/secret_signal_or_phone_number\"\n                android:textColor=\"#C5C5C5\"\n                android:textSize=\"14sp\" />\n\n            <ImageView\n                android:layout_width=\"21dp\"\n                android:layout_height=\"22dp\"\n                android:layout_alignBottom=\"@id/tv_search\"\n                android:layout_alignLeft=\"@id/tv_search\"\n                android:layout_margin=\"6dp\"\n                android:src=\"@drawable/icon_search_gray\" />\n        </RelativeLayout>\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\"\n            android:layout_marginBottom=\"10dp\"\n            android:gravity=\"center\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:id=\"@+id/tv_fxid\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/me_yichat_number\"\n                android:textColor=\"#888888\"\n                android:textSize=\"14sp\" />\n\n            <ImageView\n                android:id=\"@+id/iv_scode\"\n                android:layout_width=\"18dp\"\n                android:layout_height=\"18dp\"\n                android:layout_marginLeft=\"5dp\"\n                android:layout_marginRight=\"20dp\"\n                android:src=\"@drawable/icon_qrcode\" />\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"#fff\"\n            android:orientation=\"vertical\">\n\n\n            <RelativeLayout\n                android:visibility=\"gone\"\n                android:id=\"@+id/rl_leida\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"64dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingBottom=\"14dp\"\n                android:paddingLeft=\"12dp\"\n                android:paddingRight=\"12dp\"\n                android:paddingTop=\"14dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_leida\"\n                    android:layout_width=\"36dp\"\n                    android:layout_height=\"36dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:src=\"@drawable/icon_scan\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentTop=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_leida\"\n                    android:text=\"雷达加朋友\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_leida\"\n                    android:text=\"添加身边的朋友\"\n                    android:textColor=\"#BBBBBB\"\n                    android:textSize=\"12sp\" />\n            </RelativeLayout>\n\n            <View\n                android:visibility=\"gone\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginRight=\"12dp\"\n                android:background=\"#DBDBDB\" />\n\n            <RelativeLayout\n                android:visibility=\"gone\"\n                android:id=\"@+id/rl_jianqun\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"64dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingBottom=\"14dp\"\n                android:paddingLeft=\"12dp\"\n                android:paddingRight=\"12dp\"\n                android:paddingTop=\"14dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_jianqun\"\n                    android:layout_width=\"36dp\"\n                    android:layout_height=\"36dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:src=\"@drawable/icon_face2face\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentTop=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_jianqun\"\n                    android:text=\"面对面建群\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_jianqun\"\n                    android:text=\"与身边的朋友进入同一个群聊\"\n                    android:textColor=\"#BBBBBB\"\n                    android:textSize=\"12sp\" />\n            </RelativeLayout>\n\n            <View\n                android:visibility=\"gone\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginRight=\"12dp\"\n                android:background=\"#DBDBDB\" />\n\n            <RelativeLayout\n                android:visibility=\"gone\"\n                android:id=\"@+id/rl_sacn\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"64dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingBottom=\"14dp\"\n                android:paddingLeft=\"12dp\"\n                android:paddingRight=\"12dp\"\n                android:paddingTop=\"14dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_saoyisao\"\n                    android:layout_width=\"36dp\"\n                    android:layout_height=\"36dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:src=\"@drawable/icon_scan\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentTop=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_saoyisao\"\n                    android:text=\"@string/scanning\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_saoyisao\"\n                    android:text=\"@string/scanning_image\"\n                    android:textColor=\"#BBBBBB\"\n                    android:textSize=\"12sp\" />\n            </RelativeLayout>\n\n            <View\n                android:visibility=\"gone\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginRight=\"12dp\"\n                android:background=\"#DBDBDB\" />\n\n            <RelativeLayout\n                android:visibility=\"gone\"\n                android:id=\"@+id/rl_lianxiren\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"64dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingBottom=\"14dp\"\n                android:paddingLeft=\"12dp\"\n                android:paddingRight=\"12dp\"\n                android:paddingTop=\"14dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_lianxiren\"\n                    android:layout_width=\"36dp\"\n                    android:layout_height=\"36dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:src=\"@drawable/icon_contacts\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentTop=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_lianxiren\"\n                    android:text=\"手机联系人\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_lianxiren\"\n                    android:text=\"邀请或添加通讯录中的朋友\"\n                    android:textColor=\"#BBBBBB\"\n                    android:textSize=\"12sp\" />\n            </RelativeLayout>\n\n            <View\n                android:visibility=\"gone\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginLeft=\"12dp\"\n                android:layout_marginRight=\"12dp\"\n                android:background=\"#DBDBDB\" />\n\n            <RelativeLayout\n                android:visibility=\"gone\"\n                android:id=\"@+id/rl_ggh\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"64dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingBottom=\"14dp\"\n                android:paddingLeft=\"12dp\"\n                android:paddingRight=\"12dp\"\n                android:paddingTop=\"14dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_ggh\"\n                    android:layout_width=\"36dp\"\n                    android:layout_height=\"36dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:src=\"@drawable/default_avatar\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentTop=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_ggh\"\n                    android:text=\"公共号\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:layout_toRightOf=\"@id/iv_ggh\"\n                    android:text=\"获取更多资讯和服务\"\n                    android:textColor=\"#BBBBBB\"\n                    android:textSize=\"12sp\" />\n            </RelativeLayout>\n        </LinearLayout>\n    </LinearLayout>\n\n</ScrollView>"
  },
  {
    "path": "app/src/main/res/layout/activity_base.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n     android:orientation=\"vertical\">\n\n    <RelativeLayout\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\">\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/topbar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#2E2E32\" />\n        <ImageView\n            android:id=\"@+id/iv_right\"\n            android:padding=\"8dp\"\n            android:layout_height=\"@dimen/height_top_bar\"\n            android:layout_width=\"@dimen/height_top_bar\"\n            android:layout_alignParentRight=\"true\"\n            android:visibility=\"gone\" />\n        <TextView\n            android:layout_toLeftOf=\"@id/iv_right\"\n            android:id=\"@+id/tv_title\"\n            android:layout_width=\"wrap_content\"\n            android:maxLines=\"1\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"10dp\"\n            android:gravity=\"left\"\n            android:layout_toRightOf=\"@id/view_temp\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n        <TextView\n            android:visibility=\"gone\"\n            android:background=\"@android:color/transparent\"\n            android:maxLines=\"1\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\"\n            android:text=\"@string/str_connect_hoster\"\n            android:id=\"@+id/btn_rtc\"\n            android:layout_marginRight=\"5dp\"\n            android:layout_centerVertical=\"true\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_width=\"60dp\"\n            android:gravity=\"center\"\n            android:layout_height=\"match_parent\" />\n    </RelativeLayout>\n\n    <FrameLayout\n        android:id=\"@+id/contentFrame\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_base_input.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\" android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <FrameLayout\n        android:id=\"@+id/contentFrame\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_base_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n     <android.support.v7.widget.Toolbar\n         android:id=\"@+id/toolbar\"\n         android:layout_width=\"match_parent\"\n         android:layout_height=\"@dimen/height_top_bar\"\n         android:background=\"@color/common_top_bar\"\n         android:theme=\"@style/Theme.ToolBar.Menu\"\n         app:titleTextColor=\"@color/white\"\n          />\n\n     <android.support.v4.view.ViewPager\n        android:id=\"@+id/viewPager\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0dp\"\n        android:layout_weight=\"1\"\n        android:background=\"@color/main_bottom_split\"\n         android:paddingBottom=\"1dp\"\n        android:scrollbars=\"none\"></android.support.v4.view.ViewPager>\n\n    <android.support.design.widget.TabLayout\n        android:id=\"@+id/tabLayout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"50dp\"\n        app:tabBackground=\"@color/main_bottom_bg\"\n        app:tabGravity=\"fill\"\n        app:tabIndicatorHeight=\"0dp\"\n         app:tabMode=\"fixed\"\n       >\n\n    </android.support.design.widget.TabLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_chat_setting_single.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#ebebeb\"\n    android:orientation=\"vertical\" >\n\n    <RelativeLayout\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\" >\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/top_bar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:id=\"@+id/tv_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toRightOf=\"@+id/view_temp\"\n            android:layout_marginLeft=\"10dp\"\n            android:text=\"@string/chat_msg\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n    </RelativeLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"100dp\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"#ffffff\"\n        android:orientation=\"horizontal\"\n        android:weightSum=\"4\" >\n\n        <RelativeLayout\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_weight=\"1\"\n            android:background=\"#ffffff\" >\n\n            <ImageView\n                android:id=\"@+id/iv_avatar\"\n                android:layout_width=\"56dp\"\n                android:layout_height=\"56dp\"\n                android:layout_centerHorizontal=\"true\"\n                android:layout_marginTop=\"12dp\"\n                android:src=\"@drawable/default_avatar\" />\n\n            <TextView\n                android:id=\"@+id/tv_username\"\n                android:layout_width=\"56dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_below=\"@+id/iv_avatar\"\n                android:layout_centerHorizontal=\"true\"\n                android:gravity=\"center\"\n                android:singleLine=\"true\"\n                android:textColor=\"#AAAAAA\"\n                android:textSize=\"12sp\" />\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:visibility=\"gone\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_weight=\"1\"\n            android:background=\"#ffffff\" >\n\n            <ImageView\n                android:id=\"@+id/iv_avatar2\"\n                android:layout_width=\"56dp\"\n                android:layout_height=\"56dp\"\n                android:layout_centerHorizontal=\"true\"\n                android:layout_marginTop=\"12dp\"\n                android:src=\"@drawable/icon_add\" />\n\n            <TextView\n                android:layout_width=\"56dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_below=\"@+id/iv_avatar2\"\n                android:layout_centerHorizontal=\"true\"\n                android:layout_marginBottom=\"10dp\"\n                android:gravity=\"center\"\n                android:singleLine=\"true\"\n                android:textSize=\"14sp\" />\n        </RelativeLayout>\n    </LinearLayout>\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n\n        android:id=\"@+id/rl_switch_chattotop\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\"\n        android:padding=\"10dip\" >\n\n        <TextView\n\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:text=\"置顶聊天\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\"\n            android:typeface=\"serif\" />\n\n        <ImageView\n            android:id=\"@+id/iv_switch_chattotop\"\n            android:layout_width=\"70dp\"\n            android:layout_height=\"22dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:background=\"@drawable/icon_open\"\n            android:visibility=\"invisible\" />\n\n        <ImageView\n            android:id=\"@+id/iv_switch_unchattotop\"\n            android:layout_width=\"70dp\"\n            android:layout_height=\"22dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:background=\"@drawable/icon_close\"\n            android:visibility=\"visible\" />\n    </RelativeLayout>\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0.1dp\"\n        android:background=\"#dadada\" />\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n\n        android:id=\"@+id/rl_switch_block_groupmsg\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\"\n        android:padding=\"10dip\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:text=\"免打扰\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\"\n            android:typeface=\"serif\" />\n\n        <ImageView\n            android:id=\"@+id/iv_switch_block_groupmsg\"\n            android:layout_width=\"70dp\"\n            android:layout_height=\"22dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:background=\"@drawable/icon_open\"\n            android:visibility=\"invisible\" />\n\n        <ImageView\n            android:id=\"@+id/iv_switch_unblock_groupmsg\"\n            android:layout_width=\"70dp\"\n            android:layout_height=\"22dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:background=\"@drawable/icon_close\"\n            android:visibility=\"visible\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:id=\"@+id/re_clear\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\"\n        android:padding=\"10dp\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:text=\"清空聊天记录\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\"\n            android:typeface=\"serif\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_check_people.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@color/white\"\n    android:orientation=\"vertical\" >\n    <include layout=\"@layout/layout_title_bar\"/>\n    <TextView\n        android:visibility=\"gone\"\n        android:id=\"@+id/tv_group_check\"\n        android:background=\"@color/white\"\n        android:text=\"@string/group_chat\"\n        android:layout_gravity=\"center|left\"\n        android:textSize=\"16sp\"\n        android:gravity=\"center|left\"\n        android:padding=\"10dp\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\" />\n    <View\n        android:background=\"@color/divider_list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"1dp\"/>\n\n        <ListView\n            android:id=\"@+id/list\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:cacheColorHint=\"#00000000\"\n            android:background=\"@android:color/transparent\"\n            android:divider=\"#D4D4D4\"\n            android:descendantFocusability=\"afterDescendants\"\n            android:dividerHeight=\"1px\"\n            android:fastScrollEnabled=\"true\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_new_friends.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#ebebeb\"\n    android:orientation=\"vertical\" >\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\" >\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/top_bar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:id=\"@+id/tv_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_centerInParent=\"true\"\n            android:text=\"@string/new_friend\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_add\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"8dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/add_friend\"\n            android:textColor=\"#fff\"\n            android:textSize=\"16sp\" />\n\n        <View\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginRight=\"5dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toLeftOf=\"@id/tv_add\"\n            android:background=\"#14191A\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"#fff\" >\n\n        <TextView\n            android:id=\"@+id/et_search\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"@drawable/bg_et_f\"\n            android:gravity=\"bottom\"\n            android:paddingBottom=\"10dp\"\n            android:paddingLeft=\"46dp\"\n            android:singleLine=\"true\"\n            android:text=\"@string/secret_signal_or_phone_number\"\n            android:textColor=\"#484c4c\"\n            android:textSize=\"16sp\" />\n\n        <ImageView\n            android:layout_width=\"22dp\"\n            android:layout_height=\"22dp\"\n            android:layout_alignBottom=\"@id/et_search\"\n            android:layout_alignLeft=\"@id/et_search\"\n            android:layout_margin=\"8dp\"\n            android:src=\"@drawable/icon_search_gray\" />\n    </RelativeLayout>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"36dp\"\n        android:gravity=\"bottom\"\n        android:paddingBottom=\"4dp\"\n        android:paddingLeft=\"12dp\"\n        android:text=\"@string/new_friend\"\n        android:textSize=\"12sp\" />\n\n    <ListView\n        android:id=\"@+id/listview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"#fff\"\n        android:divider=\"#DADADA\"\n        android:dividerHeight=\"0.1dp\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_people_recently.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <com.htmessage.yichatopen.widget.swipyrefresh.SwipyRefreshLayout\n        android:id=\"@+id/swipyrefresh\"\n        app:direction=\"both\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n        <ListView\n            android:scrollbars=\"none\"\n            android:id=\"@+id/listview_people_recently\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"></ListView>\n    </com.htmessage.yichatopen.widget.swipyrefresh.SwipyRefreshLayout>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_psw_reset.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@color/white\"\n    android:orientation=\"vertical\">\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:layout_marginBottom=\"33dp\"\n        android:background=\"@color/common_top_bar\">\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/topbar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:id=\"@+id/tv_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_toRightOf=\"@id/view_temp\"\n            android:text=\"@string/resetPassword\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n    </RelativeLayout>\n    <ScrollView\n        android:scrollbars=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n        <LinearLayout\n            android:orientation=\"vertical\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n            <RelativeLayout\n                android:id=\"@+id/rl_country\"\n                android:layout_marginRight=\"13dp\"\n                android:layout_marginLeft=\"13dp\"\n                android:layout_marginTop=\"10dp\"\n                android:layout_marginBottom=\"10dp\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\" >\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:text=\"@string/countries_and_regions\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:id=\"@+id/tv_country\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentRight=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginRight=\"10dp\"\n                    android:text=\"@string/china\"\n                    android:textColor=\"@color/icon_press\"\n                    android:textSize=\"16sp\" />\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"0.1dp\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:background=\"#dbdbdb\" />\n            </RelativeLayout>\n            <RelativeLayout\n                android:layout_marginRight=\"13dp\"\n                android:layout_marginLeft=\"13dp\"\n                android:layout_marginTop=\"10dp\"\n                android:layout_marginBottom=\"10dp\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\">\n\n                <EditText\n                    android:id=\"@+id/et_usertel\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_centerVertical=\"true\"\n                    android:background=\"@drawable/bg_et\"\n                    android:hint=\"@string/you_mobile\"\n                    android:inputType=\"phone\"\n                    android:paddingLeft=\"90dp\"\n                    android:maxLines=\"1\"\n                    android:singleLine=\"true\"\n                    android:textColorHint=\"#DDDDDD\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:id=\"@+id/tv_country_code\"\n                    android:layout_width=\"90dp\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_alignLeft=\"@id/et_usertel\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"@string/country_code\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/rl_smscode\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:layout_marginRight=\"13dp\"\n                android:layout_marginLeft=\"13dp\"\n                android:layout_marginTop=\"10dp\"\n                android:layout_marginBottom=\"10dp\">\n\n                <Button\n                    android:id=\"@+id/btn_code\"\n                    android:layout_width=\"120dp\"\n                    android:layout_height=\"40dp\"\n                    android:layout_alignParentRight=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:background=\"@drawable/bg_btn_green\"\n                    android:gravity=\"center\"\n                    android:text=\"@string/has_code\"\n                    android:textColor=\"#fff\"\n                    android:textSize=\"14sp\" />\n\n                <EditText\n                    android:id=\"@+id/et_code\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"42dp\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginRight=\"40dp\"\n                    android:layout_toLeftOf=\"@+id/btn_code\"\n                    android:background=\"@drawable/bg_et\"\n                    android:hint=\"@string/Verification_Code\"\n                    android:inputType=\"number\"\n                    android:paddingLeft=\"10dp\"\n                    android:singleLine=\"true\"\n                    android:textColorHint=\"#DDDDDD\"\n                    android:textSize=\"16sp\" />\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:layout_marginRight=\"13dp\"\n                android:layout_marginLeft=\"13dp\"\n                android:layout_marginTop=\"10dp\"\n                android:layout_marginBottom=\"10dp\">\n\n\n                <EditText\n                    android:id=\"@+id/et_password\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_alignBottom=\"@+id/tv_password\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_alignParentStart=\"true\"\n                    android:background=\"@drawable/bg_et\"\n                    android:hint=\"@string/input_pwd\"\n                    android:inputType=\"textPassword\"\n                    android:paddingLeft=\"90dp\"\n                    android:singleLine=\"true\"\n                    android:textColorHint=\"#DDDDDD\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:id=\"@+id/tv_password\"\n                    android:layout_width=\"90dp\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_alignLeft=\"@id/et_password\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"@string/new_password\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:layout_marginRight=\"13dp\"\n                android:layout_marginLeft=\"13dp\"\n                android:layout_marginTop=\"10dp\"\n                android:layout_marginBottom=\"10dp\">\n\n                <EditText\n                    android:id=\"@+id/et_password_confire\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"match_parent\"\n                    android:inputType=\"textPassword\"\n                    android:layout_centerVertical=\"true\"\n                    android:background=\"@drawable/bg_et\"\n                    android:hint=\"@string/input_pwd\"\n                    android:paddingLeft=\"90dp\"\n                    android:singleLine=\"true\"\n                    android:textColorHint=\"#DDDDDD\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    android:layout_width=\"90dp\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_alignLeft=\"@id/et_password_confire\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"@string/confirmpassword\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n\n            </RelativeLayout>\n\n            <Button\n                android:id=\"@+id/btn_ok\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_margin=\"13dp\"\n                android:layout_marginTop=\"24dp\"\n                android:background=\"@drawable/bg_btn_green\"\n                android:text=\"@string/resetPassword\"\n                android:textColor=\"@android:color/white\"\n                android:textSize=\"18sp\" />\n\n        </LinearLayout>\n    </ScrollView>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_qrcode_generate.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:background=\"#fff\"\n    android:layout_height=\"match_parent\" >\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:layout_alignParentTop=\"true\"\n        android:background=\"@color/common_top_bar\" >\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/top_bar_back\" />\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n        <TextView\n            android:id=\"@+id/tv_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_toRightOf=\"@+id/view_temp\"\n            android:layout_centerVertical=\"true\"\n            android:text=\"@string/me_qrcode\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n    </RelativeLayout>\n\n    <ImageView\n        android:id=\"@+id/code_image\"\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"250dp\"\n        android:layout_height=\"250dp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_region.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:baselineAligned=\"false\"\n    android:orientation=\"vertical\">\n\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\">\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/topbar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toRightOf=\"@+id/view_temp\"\n            android:layout_marginLeft=\"10dp\"\n            android:text=\"@string/region\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:visibility=\"gone\"\n            android:id=\"@+id/tv_all\"\n            android:layout_width=\"60dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:gravity=\"center\"\n            android:text=\"全部\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n    </RelativeLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:baselineAligned=\"false\"\n        android:orientation=\"horizontal\">\n\n        <ListView\n            android:id=\"@+id/list_province\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_weight=\"1\"\n            android:background=\"#999999\"\n            android:scrollbars=\"none\" />\n\n        <ListView\n            android:id=\"@+id/list_city\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_weight=\"2\"\n            android:background=\"#ffffff\"\n            android:scrollbars=\"none\" />\n    </LinearLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_show_big_image.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#000\"\n    android:orientation=\"vertical\" >\n    <com.htmessage.yichatopen.widget.photoview.PhotoView\n        android:id=\"@+id/image\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:scaleType=\"fitCenter\" />\n    <RelativeLayout\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/transparent\">\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/topbar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:visibility=\"gone\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:visibility=\"gone\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_toRightOf=\"@id/view_temp\"\n            android:text=\"@string/login_by_mobile\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n    </RelativeLayout>\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_splash.xml",
    "content": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/splash_root\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@color/splash_bg\" >\n    <TextView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/app_name\"\n        android:layout_centerInParent=\"true\"\n        android:textColor=\"#fff\"\n        android:textSize=\"68sp\"\n\n        />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_update_info.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#fff\"\n    android:orientation=\"vertical\" >\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\" >\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/top_bar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:id=\"@+id/tv_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toRightOf=\"@+id/view_temp\"\n            android:layout_marginLeft=\"10dp\"\n            android:text=\"@string/modify_name\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_save\"\n            android:layout_width=\"48dp\"\n            android:layout_height=\"32dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"8dp\"\n            android:background=\"@drawable/bg_btn_green\"\n            android:gravity=\"center\"\n            android:text=\"@string/save\"\n            android:textColor=\"#fff\"\n            android:textSize=\"14sp\" />\n    </RelativeLayout>\n\n    <EditText\n        android:paddingLeft=\"5dp\"\n        android:id=\"@+id/et_info\"\n        android:layout_marginTop=\"20dp\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:minHeight=\"48dp\"\n       android:layout_marginLeft=\"16dp\"\n        android:layout_marginRight=\"16dp\"\n        android:background=\"@drawable/bg_et\"\n        android:textColor=\"#353535\"\n        android:textSize=\"16sp\" />\n\n    <TextView\n        android:visibility=\"gone\"\n        android:layout_marginTop=\"10dp\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginLeft=\"20dp\"\n        android:layout_marginRight=\"20dp\"\n        android:text=\"@string/good_name\"\n        android:textColor=\"#AAAAAA\"\n        android:textSize=\"14sp\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_userinfo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#ebebeb\"\n    android:orientation=\"vertical\">\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\">\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/top_bar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toRightOf=\"@+id/view_temp\"\n            android:layout_marginLeft=\"10dp\"\n            android:text=\"@string/Detailed_information\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n\n        <ImageView\n            android:visibility=\"gone\"\n            android:layout_width=\"56dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/icon_top_more\" />\n    </RelativeLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\">\n\n        <RelativeLayout\n            android:background=\"#ffffff\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"80dp\"\n            android:layout_marginBottom=\"20dp\"\n            android:layout_marginTop=\"20dp\">\n\n            <ImageView\n                android:layout_centerVertical=\"true\"\n                android:id=\"@+id/iv_avatar\"\n                android:layout_width=\"75dp\"\n                android:padding=\"5dp\"\n                android:layout_height=\"75dp\"\n                android:layout_marginLeft=\"15dp\"\n                android:src=\"@drawable/default_avatar\" />\n            <LinearLayout\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"16dp\"\n                android:layout_marginTop=\"12dp\"\n                android:layout_toRightOf=\"@id/iv_avatar\"\n                android:layout_width=\"wrap_content\"\n                android:orientation=\"vertical\"\n                android:layout_height=\"wrap_content\">\n            <LinearLayout\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <TextView\n                    android:id=\"@+id/tv_name\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_gravity=\"center|left\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/not_set\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <ImageView\n                    android:layout_gravity=\"center\"\n                    android:id=\"@+id/iv_sex\"\n                    android:layout_width=\"20dp\"\n                    android:layout_height=\"20dp\"\n                    android:layout_marginLeft=\"8dp\"\n                    android:src=\"@drawable/icon_male\" />\n            </LinearLayout>\n            <TextView\n                android:layout_gravity=\"center|left\"\n                android:id=\"@+id/tv_mixin\"\n                android:text=\"@string/not_set\"\n                android:textColor=\"@color/light_grey\"\n                android:textSize=\"14sp\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\" />\n            </LinearLayout>\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:id=\"@+id/rl_region\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\"\n            android:background=\"#ffffff\"\n            android:paddingLeft=\"12dp\"\n            android:paddingRight=\"12dp\">\n\n            <TextView\n                android:id=\"@+id/tv_region_temp\"\n                android:layout_width=\"96dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentLeft=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:paddingLeft=\"8dp\"\n                android:text=\"@string/region\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_region\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_toRightOf=\"@+id/tv_region_temp\"\n                android:text=\"@string/not_set\"\n                android:textColor=\"#AAAAAA\"\n                android:textSize=\"14sp\" />\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:background=\"#DBDBDB\" />\n        </RelativeLayout>\n        <RelativeLayout\n            android:id=\"@+id/rl_yichat_id\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\"\n            android:background=\"#ffffff\"\n            android:paddingLeft=\"12dp\"\n            android:paddingRight=\"12dp\">\n\n            <TextView\n                android:id=\"@+id/tv_mobile_number\"\n                android:layout_width=\"96dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentLeft=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:paddingLeft=\"8dp\"\n                android:text=\"@string/Personal_signature\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_yichat_number\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_toRightOf=\"@+id/tv_mobile_number\"\n                android:text=\"@string/not_set\"\n                android:textColor=\"#AAAAAA\"\n                android:textSize=\"14sp\" />\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:background=\"#DBDBDB\" />\n        </RelativeLayout>\n        <RelativeLayout\n            android:id=\"@+id/re_mobile\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\"\n            android:background=\"#ffffff\"\n            android:paddingLeft=\"12dp\"\n            android:paddingRight=\"12dp\">\n\n            <TextView\n                android:id=\"@+id/tv_mobile_temp\"\n                android:layout_width=\"96dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentLeft=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:paddingLeft=\"8dp\"\n                android:text=\"@string/mobile\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_mobile\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_toRightOf=\"@+id/tv_mobile_temp\"\n                android:text=\"@string/not_set\"\n                android:textColor=\"#AAAAAA\"\n                android:textSize=\"14sp\" />\n        </RelativeLayout>\n        <Button\n            android:id=\"@+id/btn_msg\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:layout_marginTop=\"32dp\"\n            android:background=\"@drawable/bg_btn_green\"\n            android:paddingBottom=\"7dp\"\n            android:paddingTop=\"7dp\"\n            android:text=\"@string/send_msg\"\n            android:textColor=\"@android:color/white\"\n            android:textSize=\"18sp\" />\n\n        <Button\n            android:visibility=\"gone\"\n            android:id=\"@+id/btn_add\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:layout_marginTop=\"32dp\"\n            android:background=\"@drawable/bg_btn_green\"\n            android:paddingBottom=\"7dp\"\n            android:paddingTop=\"7dp\"\n            android:text=\"@string/add_to_contacts\"\n            android:textColor=\"@android:color/white\"\n            android:textSize=\"18sp\" />\n    </LinearLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/chat_menu_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\" >\n\n    <RelativeLayout\n        android:layout_width=\"64dp\"\n        android:layout_height=\"64dp\" >\n\n        <ImageView\n            android:id=\"@+id/image\"\n            android:layout_width=\"56dp\"\n            android:layout_height=\"56dp\"\n            android:layout_centerInParent=\"true\"\n            android:scaleType=\"fitCenter\" />\n    </RelativeLayout>\n\n    <TextView\n        android:id=\"@+id/text\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:text=\"@string/attach_take_pic\"\n        android:textColor=\"#727171\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/chat_neterror_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"50dp\"\n    android:background=\"@drawable/chat_error_item_bg\"\n    android:clickable=\"true\"\n    android:orientation=\"vertical\">\n\n    <ImageView\n        android:layout_marginLeft=\"9dp\"\n        android:id=\"@+id/iv_neterror\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:src=\"@drawable/login_error_icon\"\n        android:layout_centerVertical=\"true\" />\n\n    <TextView\n        android:id=\"@+id/tv_connect_errormsg\"\n        android:layout_marginLeft=\"4dp\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"不能连接到服务器\"\n        android:textColor=\"#000\"\n        android:layout_centerVertical=\"true\"\n        android:layout_toRightOf=\"@id/iv_neterror\" />\n\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/coogame_country_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"#fff\"\n    android:gravity=\"center_vertical\"\n    android:orientation=\"vertical\" >\n\n    <TextView\n        android:id=\"@+id/country_catalog\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"#f0f0f0\"\n        android:gravity=\"center_vertical\"\n        android:paddingBottom=\"5dip\"\n        android:paddingLeft=\"8dip\"\n        android:paddingTop=\"5dip\"\n        android:textColor=\"#000\" />\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"10dip\" >\n\n        <TextView\n            android:id=\"@+id/country_name\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_marginLeft=\"20dip\"\n            android:singleLine=\"true\"\n            android:textColor=\"#000\"\n            android:textSize=\"15sp\" />\n\n        <TextView\n            android:id=\"@+id/country_number\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_marginRight=\"20dip\"\n            android:singleLine=\"true\"\n            android:textColor=\"#333\"\n            android:textSize=\"12sp\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/dialog_alert.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\" >\n\n    <LinearLayout\n        android:layout_width=\"280dp\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:background=\"#ffffff\"\n        android:orientation=\"vertical\"\n        android:paddingLeft=\"10dp\"\n        android:paddingRight=\"10dp\" >\n\n        <LinearLayout\n            android:id=\"@+id/ll_title\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:visibility=\"gone\" >\n\n            <TextView\n                android:id=\"@+id/tv_title\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"64dp\"\n                android:background=\"@drawable/bg_dialog\"\n                android:gravity=\"center_vertical\"\n                android:paddingLeft=\"10dp\"\n                android:textColor=\"@color/icon_press\"\n                android:textSize=\"18sp\" />\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"1dp\"\n                android:background=\"#BCBCBC\" />\n        </LinearLayout>\n\n\n        <LinearLayout\n            android:visibility=\"gone\"\n            android:id=\"@+id/ll_content1\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            >\n\n            <TextView\n                android:id=\"@+id/tv_content1\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/bg_dialog\"\n                android:gravity=\"center_vertical\"\n                android:paddingLeft=\"10dp\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </LinearLayout>\n\n        <LinearLayout\n            android:visibility=\"gone\"\n            android:id=\"@+id/ll_content2\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n              >\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:background=\"#d7d7d7\" />\n\n            <TextView\n                android:id=\"@+id/tv_content2\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/bg_dialog\"\n                android:gravity=\"center_vertical\"\n                android:paddingLeft=\"10dp\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </LinearLayout>\n\n        <LinearLayout\n            android:id=\"@+id/ll_content3\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:visibility=\"gone\" >\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:background=\"#d7d7d7\" />\n\n            <TextView\n                android:id=\"@+id/tv_content3\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/bg_dialog\"\n                android:gravity=\"center_vertical\"\n                android:paddingLeft=\"10dp\"\n     \n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </LinearLayout>\n\n        <LinearLayout\n            android:id=\"@+id/ll_content4\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:visibility=\"gone\" >\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:background=\"#d7d7d7\" />\n\n            <TextView\n                android:id=\"@+id/tv_content4\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/bg_dialog\"\n                android:gravity=\"center_vertical\"\n                android:paddingLeft=\"10dp\"\n            \n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </LinearLayout>\n\n        <LinearLayout\n            android:id=\"@+id/ll_content5\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:visibility=\"gone\" >\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:background=\"#d7d7d7\" />\n\n            <TextView\n                android:id=\"@+id/tv_content5\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/bg_dialog\"\n                android:gravity=\"center_vertical\"\n                android:paddingLeft=\"10dp\"\n          \n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </LinearLayout>\n    </LinearLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/emoji_gridview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\" >\n    \n    <GridView\n        android:id=\"@+id/gridview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:scrollbars=\"none\"\n        android:verticalSpacing=\"6dp\"\n        android:gravity=\"center\"\n        android:layout_gravity=\"center\"\n        android:layout_marginTop=\"8dp\"\n        android:fadingEdge=\"none\"\n        android:cacheColorHint=\"@android:color/transparent\"\n        />\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_chat.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:animateLayoutChanges=\"true\"\n    android:background=\"#EBEBEB\"\n    android:descendantFocusability=\"afterDescendants\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n\n\n        <com.htmessage.yichatopen.activity.chat.weight.loadmore.PullToLoadMoreListView\n            android:id=\"@+id/list\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"#EBEBEB\"\n            android:divider=\"@null\"\n            android:listSelector=\"#EBEBEB\"\n\n            />\n\n        <com.htmessage.yichatopen.activity.chat.weight.ChatInputView\n            android:id=\"@+id/inputView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\" />\n\n\n    </LinearLayout>\n\n    <com.htmessage.yichatopen.activity.chat.weight.VoiceRecorderView\n        android:id=\"@+id/voice_recorder\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:visibility=\"invisible\" />\n</RelativeLayout>\n\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_contactlist.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#EBEBEB\"\n    android:orientation=\"vertical\" >\n\n    <FrameLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" >\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\" >\n\n            <LinearLayout\n                android:id=\"@+id/ll_loading\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginLeft=\"10dp\"\n                android:layout_marginTop=\"2dp\"\n                android:gravity=\"center_vertical\"\n                android:visibility=\"gone\" >\n\n                <ProgressBar\n                    style=\"@style/mProgress_circle\"\n                    android:layout_width=\"28dp\"\n                    android:layout_height=\"28dp\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginLeft=\"6dp\"\n                    android:text=\"@string/loading\" />\n            </LinearLayout>\n\n            <ListView\n                android:id=\"@+id/list\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_below=\"@id/ll_loading\"\n                android:background=\"@android:color/transparent\"\n                android:divider=\"@null\"\n                android:footerDividersEnabled=\"false\"\n                android:descendantFocusability=\"afterDescendants\"\n                android:fastScrollEnabled=\"false\" />\n \t\t\t<com.htmessage.yichatopen.activity.main.contacts.Sidebar\n                android:visibility=\"gone\"\n                android:id=\"@+id/sidebar\"\n                android:layout_width=\"25dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_alignParentRight=\"true\"\n                android:background=\"@android:color/transparent\"\n                android:clickable=\"true\" />\n\n            <TextView\n                android:id=\"@+id/floating_header\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerInParent=\"true\"\n                android:background=\"@drawable/show_head_toast_bg\"\n                android:gravity=\"center\"\n                android:paddingLeft=\"25dp\"\n                android:paddingRight=\"25dp\"\n                android:textColor=\"@android:color/white\"\n                android:textSize=\"40sp\"\n                android:visibility=\"invisible\" />\n\n        </RelativeLayout>\n    </FrameLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_conversation_settings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <RelativeLayout\n        android:id=\"@+id/title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/height_top_bar\"\n        android:background=\"@color/common_top_bar\">\n\n        <ImageView\n            android:id=\"@+id/iv_back\"\n            android:layout_width=\"40dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:onClick=\"back\"\n            android:paddingBottom=\"5dp\"\n            android:paddingLeft=\"5dp\"\n            android:paddingRight=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:scaleType=\"centerInside\"\n            android:src=\"@drawable/top_bar_back\" />\n\n        <View\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_toRightOf=\"@id/iv_back\"\n            android:background=\"#14191A\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_toRightOf=\"@+id/view_temp\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_centerVertical=\"true\"\n            android:text=\"@string/set\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"18sp\" />\n    </RelativeLayout>\n\n    <ScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:fadingEdge=\"none\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:orientation=\"vertical\">\n\n            <TextView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"1dip\"\n                android:layout_marginLeft=\"10dip\"\n                android:layout_marginRight=\"10dip\"\n                android:background=\"#E6E6E6\"\n                android:visibility=\"gone\" />\n\n            <RelativeLayout\n                android:id=\"@+id/rl_switch_chatroom_owner_leave\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"@drawable/btn_bottom_selector\"\n                android:padding=\"10dip\"\n                android:visibility=\"gone\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/chatroom_allow_owner_leave\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\"\n                    android:typeface=\"serif\" />\n\n                <com.htmessage.yichatopen.widget.SwitchButton\n                    android:id=\"@+id/switch_owner_leave\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentRight=\"true\"\n                    android:layout_centerVertical=\"true\" />\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/rl_switch_auto_accept_group_invitation\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"@drawable/btn_bottom_selector\"\n                android:padding=\"10dip\"\n                android:visibility=\"gone\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/auto_accept_group_invitation\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\"\n                    android:typeface=\"serif\" />\n\n                <com.htmessage.yichatopen.widget.SwitchButton\n                    android:id=\"@+id/switch_auto_accept_group_invitation\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentRight=\"true\"\n                    android:layout_centerVertical=\"true\" />\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/rl_switch_adaptive_video_encode\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"@drawable/btn_bottom_selector\"\n                android:padding=\"10dip\"\n                android:visibility=\"gone\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/adaptive_video_encode\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\"\n                    android:typeface=\"serif\" />\n\n                <com.htmessage.yichatopen.widget.SwitchButton\n                    android:id=\"@+id/switch_adaptive_video_encode\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentRight=\"true\"\n                    android:layout_centerVertical=\"true\" />\n            </RelativeLayout>\n\n            <LinearLayout\n                android:id=\"@+id/ll_numal_set\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginLeft=\"10dip\"\n                android:layout_marginRight=\"10dip\"\n                android:layout_marginTop=\"10dip\"\n                android:orientation=\"vertical\"\n                android:visibility=\"gone\">\n\n                <TextView\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"30dip\"\n                    android:gravity=\"bottom|left\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/numal_set\"\n                    android:textColor=\"@color/btn_gray_pressed\" />\n\n                <TextView\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"1dip\"\n                    android:background=\"@color/btn_gray_normal\" />\n            </LinearLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/re_resetpassword\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"#ffffff\"\n                android:padding=\"10dip\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/resetPassword\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\"\n                    android:typeface=\"serif\" />\n            </RelativeLayout>\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.5px\"\n                android:layout_marginLeft=\"10dp\"\n                android:layout_marginRight=\"10dp\"\n                android:background=\"@color/btn_gray_normal\" />\n\n            <RelativeLayout\n                android:id=\"@+id/rl_update\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"#ffffff\"\n                android:padding=\"10dip\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/check_update\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\"\n                    android:typeface=\"serif\" />\n            </RelativeLayout>\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.5px\"\n                android:layout_marginLeft=\"10dp\"\n                android:layout_marginRight=\"10dp\"\n                android:background=\"@color/btn_gray_normal\" />\n\n            <RelativeLayout\n                android:visibility=\"gone\"\n                android:id=\"@+id/rl_keep_live\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"#ffffff\"\n                android:padding=\"10dip\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/keep_live_setting\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\"\n                    android:typeface=\"serif\" />\n            </RelativeLayout>\n\n            <View\n                android:visibility=\"gone\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.5px\"\n                android:layout_marginLeft=\"10dp\"\n                android:layout_marginRight=\"10dp\"\n                android:background=\"@color/btn_gray_normal\" />\n\n            <LinearLayout\n                android:visibility=\"gone\"\n                android:id=\"@+id/ll_change\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"@drawable/btn_bottom_selector\"\n                android:padding=\"10dip\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_gravity=\"center_vertical\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"@string/notify_set\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\" />\n            </LinearLayout>\n\n            <View\n                android:visibility=\"gone\"\n                android:id=\"@+id/view_devider\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"1dip\"\n                android:layout_marginLeft=\"10dp\"\n                android:layout_marginRight=\"10dp\"\n                android:background=\"@color/btn_gray_normal\" />\n\n            <LinearLayout\n                android:id=\"@+id/ll_new_msg\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\"\n                android:visibility=\"gone\">\n\n                <LinearLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginLeft=\"10dip\"\n                    android:layout_marginRight=\"10dip\"\n                    android:layout_marginTop=\"10dip\"\n                    android:orientation=\"vertical\">\n\n                    <TextView\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"30dip\"\n                        android:gravity=\"bottom|left\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/notify\"\n                        android:textColor=\"@color/btn_gray_pressed\" />\n\n                    <TextView\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"1dip\"\n                        android:background=\"@color/btn_gray_normal\" />\n                </LinearLayout>\n\n                <RelativeLayout\n                    android:id=\"@+id/rl_switch_notification\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_centerVertical=\"true\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/newnotify\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\"\n                        android:typeface=\"serif\" />\n\n                    <com.htmessage.yichatopen.widget.SwitchButton\n                        android:id=\"@+id/switch_notification\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_alignParentRight=\"true\"\n                        android:layout_centerVertical=\"true\" />\n                </RelativeLayout>\n\n                <TextView\n                    android:id=\"@+id/textview1\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"1dip\"\n                    android:layout_marginLeft=\"10dip\"\n                    android:layout_marginRight=\"10dip\"\n                    android:background=\"#E6E6E6\" />\n\n                <RelativeLayout\n                    android:id=\"@+id/rl_switch_sound\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_centerVertical=\"true\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/voice\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\"\n                        android:typeface=\"serif\" />\n\n                    <com.htmessage.yichatopen.widget.SwitchButton\n                        android:id=\"@+id/switch_sound\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_alignParentRight=\"true\"\n                        android:layout_centerVertical=\"true\" />\n                </RelativeLayout>\n\n                <TextView\n                    android:id=\"@+id/textview2\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"1dip\"\n                    android:layout_marginLeft=\"10dip\"\n                    android:layout_marginRight=\"10dip\"\n                    android:background=\"#E6E6E6\" />\n\n                <RelativeLayout\n                    android:id=\"@+id/rl_switch_vibrate\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_centerVertical=\"true\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/shake\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\"\n                        android:typeface=\"serif\" />\n\n                    <com.htmessage.yichatopen.widget.SwitchButton\n                        android:id=\"@+id/switch_vibrate\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_alignParentRight=\"true\"\n                        android:layout_centerVertical=\"true\" />\n                </RelativeLayout>\n\n                <LinearLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginLeft=\"10dip\"\n                    android:layout_marginRight=\"10dip\"\n                    android:layout_marginTop=\"10dip\"\n                    android:orientation=\"vertical\">\n\n                    <TextView\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"30dip\"\n                        android:gravity=\"bottom|left\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/chatset\"\n                        android:textColor=\"@color/btn_gray_pressed\" />\n\n                    <TextView\n                        android:layout_width=\"match_parent\"\n                        android:layout_height=\"1dip\"\n                        android:background=\"@color/btn_gray_normal\" />\n                </LinearLayout>\n\n                <RelativeLayout\n                    android:id=\"@+id/rl_switch_speaker\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_centerVertical=\"true\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/yangshengqi\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\"\n                        android:typeface=\"serif\" />\n\n                    <com.htmessage.yichatopen.widget.SwitchButton\n                        android:id=\"@+id/switch_speaker\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_alignParentRight=\"true\"\n                        android:layout_centerVertical=\"true\" />\n                </RelativeLayout>\n\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"1dip\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:layout_marginRight=\"10dp\"\n                    android:background=\"@color/btn_gray_normal\" />\n\n                <RelativeLayout\n                    android:id=\"@+id/rl_switch_delete_msg_when_exit_group\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_centerVertical=\"true\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/delete_msg_when_exit_group\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\"\n                        android:typeface=\"serif\" />\n\n                    <com.htmessage.yichatopen.widget.SwitchButton\n                        android:id=\"@+id/switch_delete_msg_when_exit_group\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_alignParentRight=\"true\"\n                        android:layout_centerVertical=\"true\" />\n                </RelativeLayout>\n\n                <LinearLayout\n                    android:id=\"@+id/ll_black_list\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\"\n                    android:visibility=\"gone\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/book_black\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\" />\n                </LinearLayout>\n\n                <LinearLayout\n                    android:id=\"@+id/ll_user_profile\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\"\n                    android:visibility=\"gone\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/title_user_profile\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\" />\n                </LinearLayout>\n\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"1dip\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:layout_marginRight=\"10dp\"\n                    android:background=\"@color/btn_gray_normal\"\n                    android:visibility=\"gone\" />\n\n                <LinearLayout\n                    android:id=\"@+id/ll_diagnose\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\"\n                    android:visibility=\"gone\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/diagnose\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\" />\n                </LinearLayout>\n\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"1dip\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:layout_marginRight=\"10dp\"\n                    android:background=\"@color/btn_gray_normal\"\n                    android:visibility=\"gone\" />\n\n                <LinearLayout\n                    android:id=\"@+id/ll_set_push_nick\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"50dip\"\n                    android:background=\"@drawable/btn_bottom_selector\"\n                    android:padding=\"10dip\"\n                    android:visibility=\"gone\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:paddingLeft=\"10dip\"\n                        android:text=\"@string/push_nick\"\n                        android:textColor=\"@android:color/black\"\n                        android:textSize=\"14sp\" />\n                </LinearLayout>\n            </LinearLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/rl_about_us\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"#ffffff\"\n                android:padding=\"10dip\"\n                android:visibility=\"gone\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:paddingLeft=\"10dip\"\n                    android:text=\"关于我们\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\"\n                    android:typeface=\"serif\" />\n            </RelativeLayout>\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"1dip\"\n                android:layout_marginLeft=\"10dp\"\n                android:layout_marginRight=\"10dp\"\n                android:background=\"@color/btn_gray_normal\"\n                android:visibility=\"gone\" />\n\n            <RelativeLayout\n                android:id=\"@+id/rl_logout\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"50dip\"\n                android:background=\"#ffffff\"\n                android:padding=\"10dp\"\n                android:orientation=\"vertical\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:typeface=\"serif\"\n                    android:paddingLeft=\"10dp\"\n                    android:layout_centerVertical=\"true\"\n                    android:text=\"@string/button_logout\"\n                    android:textColor=\"@android:color/black\"\n                    android:textSize=\"14sp\" />\n            </RelativeLayout>\n\n        </LinearLayout>\n    </ScrollView>\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_emoji.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n\n    android:layout_height=\"match_parent\"\n     android:orientation=\"vertical\">\n\n    <android.support.v4.view.ViewPager\n        android:id=\"@+id/viewpager_emoji\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0dp\"\n        android:layout_weight=\"1\">\n\n    </android.support.v4.view.ViewPager>\n\n    <android.support.design.widget.TabLayout\n        android:id=\"@+id/tabLayout_dot\"\n        app:tabGravity=\"center\"\n        app:tabIndicatorHeight=\"0dp\"\n        app:tabMode=\"fixed\"\n\n        app:tabMaxWidth=\"30dp\"\n         android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n    </android.support.design.widget.TabLayout>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_find.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#EBEBEB\"\n    android:orientation=\"vertical\" >\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/rl_friends\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\"\n        android:layout_marginTop=\"16dp\"\n        android:paddingLeft=\"12dp\" >\n\n        <ImageView\n            android:id=\"@+id/iv_friends\"\n            android:layout_width=\"24dp\"\n            android:layout_height=\"24dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/friend_icon\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:layout_toRightOf=\"@id/iv_friends\"\n            android:text=\"@string/Circle_of_friends\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:layout_marginTop=\"16dp\"\n         android:id=\"@+id/re_qrcode\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\"\n        android:paddingLeft=\"12dp\" >\n\n        <ImageView\n            android:id=\"@+id/iv_qrcode\"\n            android:layout_width=\"24dp\"\n            android:layout_height=\"24dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/scan_icon\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:layout_toRightOf=\"@id/iv_qrcode\"\n            android:text=\"@string/scanning\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <View\n            android:visibility=\"gone\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n\n    <RelativeLayout\n        android:layout_marginTop=\"16dp\"\n        android:id=\"@+id/rl_near\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\"\n        android:paddingLeft=\"12dp\" >\n\n        <ImageView\n            android:id=\"@+id/iv_fujin\"\n            android:layout_width=\"24dp\"\n            android:layout_height=\"24dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/people_time\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:layout_toRightOf=\"@id/iv_fujin\"\n            android:text=\"@string/people_time\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <View\n            android:visibility=\"gone\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n\n\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_home.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#fff\"\n    android:orientation=\"vertical\">\n\n    <include\n        android:id=\"@+id/rl_error_item\"\n        android:visibility=\"gone\"\n        layout=\"@layout/chat_neterror_item\" />\n\n    <ListView\n        android:id=\"@+id/list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@android:color/transparent\"\n         android:dividerHeight=\"0.1dp\"\n        android:divider=\"#d4d4d4\" />\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_login.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:padding=\"12dp\">\n\n        <RelativeLayout\n            android:id=\"@+id/rl_country\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"10dp\"\n                android:text=\"@string/countries_and_regions\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_country\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentRight=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginRight=\"10dp\"\n                android:text=\"@string/china\"\n                android:textColor=\"@color/icon_press\"\n                android:textSize=\"16sp\" />\n\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:background=\"#dbdbdb\" />\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\">\n\n            <EditText\n                android:id=\"@+id/et_usertel\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_centerVertical=\"true\"\n                android:background=\"@drawable/bg_et\"\n                android:hint=\"@string/you_mobile\"\n                android:inputType=\"phone\"\n                android:maxLines=\"1\"\n                android:paddingLeft=\"90dp\"\n                android:singleLine=\"true\"\n                android:textColorHint=\"#DDDDDD\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_country_code\"\n                android:layout_width=\"90dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignLeft=\"@id/et_usertel\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"10dp\"\n                android:text=\"@string/country_code\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\">\n\n            <EditText\n                android:id=\"@+id/et_password\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_centerVertical=\"true\"\n                android:background=\"@drawable/bg_et\"\n                android:hint=\"@string/input_pwd\"\n                android:inputType=\"textPassword\"\n                android:paddingLeft=\"90dp\"\n                android:singleLine=\"true\"\n                android:textColorHint=\"#DDDDDD\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:layout_width=\"90dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignLeft=\"@id/et_password\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"10dp\"\n                android:text=\"@string/password\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </RelativeLayout>\n\n        <Button\n            android:id=\"@+id/btn_login\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"24dp\"\n            android:background=\"@drawable/bg_btn_green\"\n            android:enabled=\"false\"\n            android:paddingBottom=\"7dp\"\n            android:paddingTop=\"7dp\"\n            android:text=\"@string/login\"\n            android:textColor=\"@color/login_btn_text_color\"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_find_password\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"35dp\"\n            android:layout_gravity=\"right\"\n            android:layout_marginTop=\"10dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/find_pwd\"\n            android:textColor=\"#576B95\"\n            android:textSize=\"14sp\" />\n    </LinearLayout>\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:gravity=\"center\"\n            android:text=\"----------------------------   第三方登录   ----------------------------\"\n            android:textColor=\"@color/icon_numal\"\n            android:textSize=\"15sp\"\n            android:visibility=\"gone\" />\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_centerHorizontal=\"true\"\n            android:layout_marginTop=\"40dp\"\n            android:gravity=\"center\"\n            android:orientation=\"horizontal\"\n            android:visibility=\"invisible\">\n\n            <ImageView\n                android:layout_width=\"50dp\"\n                android:layout_height=\"50dp\"\n                android:layout_marginLeft=\"15dp\"\n                android:layout_marginRight=\"15dp\"\n                android:background=\"@drawable/qqlogin\" />\n\n            <ImageView\n                android:layout_width=\"50dp\"\n                android:layout_height=\"50dp\"\n                android:layout_marginLeft=\"15dp\"\n                android:layout_marginRight=\"15dp\"\n                android:background=\"@drawable/wblogin\" />\n\n            <ImageView\n                android:layout_width=\"50dp\"\n                android:layout_height=\"50dp\"\n                android:layout_marginLeft=\"15dp\"\n                android:layout_marginRight=\"15dp\"\n                android:background=\"@drawable/wxlogin\" />\n        </LinearLayout>\n\n        <Button\n            android:id=\"@+id/btn_qtlogin\"\n            android:layout_width=\"120dp\"\n            android:layout_height=\"36dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_centerHorizontal=\"true\"\n            android:layout_margin=\"33dp\"\n            android:background=\"@drawable/bg_btn_gray\"\n            android:gravity=\"center\"\n            android:text=\"@string/register\"\n            android:textColor=\"#353535\"\n            android:textSize=\"15sp\" />\n\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_profile.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n\n    <ScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"#ebebeb\"\n        android:scrollbars=\"none\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:orientation=\"vertical\"\n            android:paddingBottom=\"40dp\">\n\n            <RelativeLayout\n                android:id=\"@+id/re_myinfo\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"80dp\"\n                android:layout_marginBottom=\"20dp\"\n                android:layout_marginTop=\"20dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingBottom=\"8dp\"\n                android:paddingTop=\"8dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_avatar\"\n                    android:layout_width=\"64dp\"\n                    android:layout_height=\"64dp\"\n                    android:layout_marginLeft=\"15dp\"\n                    android:src=\"@drawable/default_avatar\" />\n\n\n                <TextView\n                    android:id=\"@+id/tv_name\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginLeft=\"16dp\"\n                    android:layout_marginTop=\"8dp\"\n                    android:layout_toRightOf=\"@id/iv_avatar\"\n                    android:text=\"@string/not_set\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n\n                <TextView\n                    android:id=\"@+id/tv_fxid\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginBottom=\"10dp\"\n                    android:layout_marginLeft=\"16dp\"\n                    android:layout_toRightOf=\"@id/iv_avatar\"\n                    android:text=\"\"\n                    android:textColor=\"#AAAAAA\"\n                    android:textSize=\"14sp\" />\n\n\n                <ImageView\n                    android:layout_width=\"18dp\"\n                    android:layout_height=\"18dp\"\n                    android:layout_alignParentRight=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginRight=\"32dp\"\n                    android:src=\"@drawable/icon_qrcode\" />\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/re_xiangce\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingLeft=\"12dp\"\n                android:visibility=\"gone\">\n\n                <ImageView\n                    android:id=\"@+id/iv_xiangce\"\n                    android:layout_width=\"24dp\"\n                    android:layout_height=\"24dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:src=\"@drawable/pbotos_icon\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"20dp\"\n                    android:layout_toRightOf=\"@id/iv_xiangce\"\n                    android:text=\"@string/image_manager\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"0.1dp\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginRight=\"12dp\"\n                    android:background=\"#dadada\" />\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/rl_qrcode\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingLeft=\"12dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_qrcode\"\n                    android:layout_width=\"24dp\"\n                    android:layout_height=\"24dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:src=\"@drawable/myid\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"20dp\"\n                    android:layout_toRightOf=\"@id/iv_qrcode\"\n                    android:text=\"@string/me_qrcode\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"0.1dp\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginRight=\"12dp\"\n                    android:background=\"#dadada\"\n                    android:visibility=\"gone\" />\n            </RelativeLayout>\n\n\n            <RelativeLayout\n                android:id=\"@+id/re_setting\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:layout_marginTop=\"10dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingLeft=\"12dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_setting\"\n                    android:layout_width=\"24dp\"\n                    android:layout_height=\"24dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:src=\"@drawable/setting_icon\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"20dp\"\n                    android:layout_toRightOf=\"@id/iv_setting\"\n                    android:text=\"@string/set\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n            </RelativeLayout>\n            <RelativeLayout\n                android:id=\"@+id/re_github\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:layout_marginTop=\"20dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingLeft=\"12dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_github\"\n                    android:layout_width=\"24dp\"\n                    android:layout_height=\"24dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:src=\"@drawable/github\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"20dp\"\n                    android:layout_toRightOf=\"@id/iv_github\"\n                    android:text=\"@string/donation_git\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"0.1dp\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginRight=\"12dp\"\n                    android:background=\"#dadada\" />\n            </RelativeLayout>\n            <RelativeLayout\n                android:id=\"@+id/re_oschina\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingLeft=\"12dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_oschina\"\n                    android:layout_width=\"24dp\"\n                    android:layout_height=\"24dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:src=\"@drawable/oschina\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"20dp\"\n                    android:layout_toRightOf=\"@id/iv_oschina\"\n                    android:text=\"@string/donation_kaiyuan\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n                <View\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"0.1dp\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_marginRight=\"12dp\"\n                    android:background=\"#dadada\" />\n            </RelativeLayout>\n            <RelativeLayout\n                android:id=\"@+id/re_pro_test\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:background=\"@drawable/list_item_bg_white\"\n                android:clickable=\"true\"\n                android:paddingLeft=\"12dp\">\n\n                <ImageView\n                    android:id=\"@+id/iv_pro_test\"\n                    android:layout_width=\"24dp\"\n                    android:layout_height=\"24dp\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"12dp\"\n                    android:src=\"@drawable/fire\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginLeft=\"20dp\"\n                    android:layout_toRightOf=\"@id/iv_pro_test\"\n                    android:text=\"@string/keep_live_setting\"\n                    android:textColor=\"#353535\"\n                    android:textSize=\"16sp\" />\n            </RelativeLayout>\n        </LinearLayout>\n    </ScrollView>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_profile_info.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\" android:layout_width=\"match_parent\"\n    android:background=\"#ebebeb\"\n    android:layout_height=\"match_parent\">\n    <RelativeLayout\n        android:id=\"@+id/re_avatar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"80dp\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <ImageView\n            android:id=\"@+id/iv_avatar\"\n            android:layout_width=\"64dp\"\n            android:layout_height=\"64dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"12dp\"\n            android:src=\"@drawable/default_avatar\"/>\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"@string/Head_portrait\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:id=\"@+id/re_name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <TextView\n            android:id=\"@+id/tv_temp_name\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"@string/nickname\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_name\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"20dp\"\n            android:layout_toRightOf=\"@id/tv_temp_name\"\n            android:ellipsize=\"end\"\n            android:gravity=\"right\"\n            android:singleLine=\"true\"\n            android:textColor=\"#AAAAAA\"\n            android:textSize=\"16sp\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:id=\"@+id/re_fxid\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <TextView\n            android:id=\"@+id/tv_temp_fxid\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"@string/yichat_number\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_fxid\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"20dp\"\n            android:layout_toRightOf=\"@id/tv_temp_fxid\"\n            android:ellipsize=\"end\"\n            android:gravity=\"right\"\n            android:singleLine=\"true\"\n            android:text=\"\"\n            android:textColor=\"#AAAAAA\"\n            android:textSize=\"14sp\" />\n\n        <View\n            android:visibility=\"gone\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/re_qrcode\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"@string/me_qrcode\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <ImageView\n            android:layout_width=\"18dp\"\n            android:layout_height=\"18dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"20dp\"\n            android:src=\"@drawable/icon_qrcode\" />\n\n        <View\n            android:visibility=\"gone\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"我的地址\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:id=\"@+id/re_sex\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <TextView\n            android:id=\"@+id/tv_temp_sex\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"@string/sex\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_sex\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"20dp\"\n            android:layout_toRightOf=\"@id/tv_temp_sex\"\n            android:ellipsize=\"end\"\n            android:gravity=\"right\"\n            android:singleLine=\"true\"\n            android:text=\"@string/male\"\n            android:textColor=\"#AAAAAA\"\n            android:textSize=\"14sp\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:id=\"@+id/re_region\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <TextView\n            android:id=\"@+id/tv_temp_region\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"@string/region\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_region\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"20dp\"\n            android:layout_toRightOf=\"@id/tv_temp_region\"\n            android:ellipsize=\"end\"\n            android:gravity=\"right\"\n            android:singleLine=\"true\"\n            android:text=\"@string/not_set\"\n            android:textColor=\"#AAAAAA\"\n            android:textSize=\"14sp\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#dadada\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:id=\"@+id/re_sign\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <TextView\n            android:id=\"@+id/tv_temp_sign\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"20dp\"\n            android:text=\"@string/Personal_signature\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <TextView\n            android:gravity=\"right\"\n            android:layout_marginLeft=\"13dp\"\n            android:id=\"@+id/tv_sign\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"20dp\"\n            android:layout_toRightOf=\"@id/tv_temp_sign\"\n            android:ellipsize=\"end\"\n            android:textColor=\"#AAAAAA\"\n            android:textSize=\"14sp\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_register.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#ffffff\"\n    android:orientation=\"vertical\" >\n\n\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:padding=\"12dp\" >\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"64dp\" >\n\n            <ImageView\n                android:id=\"@+id/iv_photo\"\n                android:layout_width=\"64dp\"\n                android:layout_height=\"64dp\"\n                android:layout_alignParentRight=\"true\"\n                android:src=\"@drawable/icon_camera\" />\n\n            <EditText\n                android:id=\"@+id/et_usernick\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"48dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginRight=\"10dp\"\n                android:layout_toLeftOf=\"@id/iv_photo\"\n                android:background=\"@drawable/bg_et\"\n                android:gravity=\"center_vertical\"\n                android:hint=\"@string/example\"\n                android:paddingLeft=\"90dp\"\n                android:singleLine=\"true\"\n                android:textColorHint=\"#DDDDDD\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:layout_width=\"90dp\"\n                android:layout_height=\"48dp\"\n                android:layout_alignLeft=\"@id/et_usernick\"\n                android:layout_alignParentBottom=\"true\"\n                android:layout_marginLeft=\"10dp\"\n                android:gravity=\"center_vertical\"\n                android:text=\"@string/nickname\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:id=\"@+id/rl_country\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\" >\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"10dp\"\n                android:text=\"@string/countries_and_regions\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_country\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentRight=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginRight=\"10dp\"\n                android:text=\"@string/china\"\n                android:textColor=\"@color/icon_press\"\n                android:textSize=\"16sp\" />\n            <View\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0.1dp\"\n                android:layout_alignParentBottom=\"true\"\n                android:background=\"#dbdbdb\" />\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\" >\n\n            <EditText\n                android:id=\"@+id/et_usertel\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_centerVertical=\"true\"\n                android:background=\"@drawable/bg_et\"\n                android:hint=\"@string/you_mobile\"\n                android:inputType=\"phone\"\n                android:paddingLeft=\"90dp\"\n                android:maxLines=\"1\"\n                android:singleLine=\"true\"\n                android:textColorHint=\"#DDDDDD\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_country_code\"\n                android:layout_width=\"90dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignLeft=\"@id/et_usertel\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"10dp\"\n                android:text=\"@string/country_code\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n        </RelativeLayout>\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"48dp\" >\n\n            <EditText\n                android:id=\"@+id/et_password\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:layout_centerVertical=\"true\"\n                android:background=\"@drawable/bg_et\"\n                android:hint=\"@string/input_pwd\"\n                android:paddingLeft=\"90dp\"\n                android:password=\"true\"\n                android:singleLine=\"true\"\n                android:textColorHint=\"#DDDDDD\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:layout_width=\"90dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignLeft=\"@id/et_password\"\n                android:layout_centerVertical=\"true\"\n                android:layout_marginLeft=\"10dp\"\n                android:text=\"@string/password\"\n                android:textColor=\"#353535\"\n                android:textSize=\"16sp\" />\n\n            <LinearLayout\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"44dp\"\n                android:layout_alignParentRight=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:orientation=\"horizontal\" >\n\n                <ImageView\n                    android:id=\"@+id/iv_hide\"\n                    android:layout_width=\"44dp\"\n                    android:layout_height=\"44dp\"\n                    android:padding=\"10dp\"\n                    android:src=\"@drawable/show_numal\" />\n\n                <ImageView\n                    android:id=\"@+id/iv_show\"\n                    android:layout_width=\"44dp\"\n                    android:layout_height=\"44dp\"\n                    android:padding=\"10dp\"\n                    android:src=\"@drawable/show1\"\n                    android:visibility=\"gone\" />\n            </LinearLayout>\n        </RelativeLayout>\n\n        <Button\n            android:id=\"@+id/btn_register\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"24dp\"\n            android:background=\"@drawable/bg_btn_green\"\n            android:enabled=\"false\"\n            android:paddingBottom=\"7dp\"\n            android:paddingTop=\"7dp\"\n            android:text=\"@string/register\"\n            android:textColor=\"@android:color/white\"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_xieyi\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"10dp\"\n            android:textSize=\"14sp\" />\n    </LinearLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_contact_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <TextView\n        android:id=\"@+id/header\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"22dp\"\n        android:background=\"#ebebeb\"\n        android:gravity=\"center_vertical\"\n        android:paddingLeft=\"12dp\"\n        android:textColor=\"#888888\"\n        android:textSize=\"14sp\"\n        android:visibility=\"gone\" />\n\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"52dp\"\n        android:background=\"@drawable/list_item_bg_white\">\n\n        <ImageView\n            android:id=\"@+id/iv_avatar\"\n            android:layout_width=\"36dp\"\n            android:layout_height=\"36dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/default_avatar\" />\n\n        <TextView\n            android:id=\"@+id/tv_name\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_toRightOf=\"@id/iv_avatar\"\n            android:text=\"@string/app_name\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n        <View\n            android:layout_alignParentBottom=\"true\"\n            android:id=\"@+id/view_temp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#d9d9d9\"\n            />\n\n    </RelativeLayout>\n\n\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_contact_list_footer.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\" >\n\n    <TextView\n        android:id=\"@+id/tv_total\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"56dp\"\n        android:background=\"#ebebeb\"\n        android:gravity=\"center\"\n        android:text=\"0位联系人\"\n        android:textColor=\"#888888\"\n        android:textSize=\"16sp\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_contact_list_header.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"#ffffff\"\n    android:orientation=\"vertical\" >\n\n    <RelativeLayout\n        android:id=\"@+id/re_newfriends\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"52dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <ImageView\n            android:id=\"@+id/iv_avatar\"\n            android:layout_width=\"36dp\"\n            android:layout_height=\"36dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/newfriend\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_toRightOf=\"@id/iv_avatar\"\n            android:text=\"新的朋友\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_unread\"\n            android:layout_width=\"10dp\"\n            android:layout_height=\"10dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"30dp\"\n            android:background=\"@drawable/unread_count_bg\"\n            android:gravity=\"center\"\n            android:textColor=\"#ffffff\"\n            android:textSize=\"12sp\"\n            android:visibility=\"gone\" />\n    </RelativeLayout>\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0.1dp\"\n        android:layout_marginLeft=\"12dp\"\n        android:layout_marginRight=\"12dp\"\n        android:background=\"#d9d9d9\" />\n\n    <RelativeLayout\n        android:id=\"@+id/re_chatroom\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"52dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <ImageView\n            android:id=\"@+id/iv_avatar2\"\n            android:layout_width=\"36dp\"\n            android:layout_height=\"36dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/groupchat\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_toRightOf=\"@id/iv_avatar2\"\n            android:text=\"群聊\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n        <View\n            android:visibility=\"gone\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#d9d9d9\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/re_tag\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"52dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <ImageView\n            android:id=\"@+id/iv_avatar3\"\n            android:layout_width=\"36dp\"\n            android:layout_height=\"36dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/watchlive\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_toRightOf=\"@id/iv_avatar3\"\n            android:text=\"看直播\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n        <View\n            android:visibility=\"gone\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0.1dp\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginRight=\"12dp\"\n            android:background=\"#d9d9d9\" />\n    </RelativeLayout>\n\n    <RelativeLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/re_public\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"52dp\"\n        android:background=\"@drawable/list_item_bg_white\"\n        android:clickable=\"true\" >\n\n        <ImageView\n            android:id=\"@+id/iv_avatar4\"\n            android:layout_width=\"36dp\"\n            android:layout_height=\"36dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/live\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_toRightOf=\"@id/iv_avatar4\"\n            android:text=\"进行直播\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_conversation_single.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"64dp\"\n    android:id=\"@+id/re_main\"\n    android:background=\"@drawable/list_item_bg_white\"\n    android:gravity=\"center_vertical\" >\n\n    <RelativeLayout\n        android:id=\"@+id/avatar_container\"\n        android:layout_width=\"72dp\"\n        android:layout_height=\"64dp\"\n        android:layout_alignParentLeft=\"true\" >\n\n        <ImageView\n            android:id=\"@+id/avatar\"\n            android:layout_width=\"48dp\"\n            android:layout_height=\"48dp\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"13dp\"\n            android:scaleType=\"fitXY\"\n            android:src=\"@drawable/default_avatar\" />\n\n        <TextView\n            android:id=\"@+id/unread_msg_number\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_marginRight=\"2dp\"\n            android:layout_marginTop=\"3dp\"\n            android:background=\"@drawable/unread_dot\"\n            android:gravity=\"center\"\n            android:text=\"7\"\n            android:textColor=\"@android:color/white\"\n            android:textSize=\"10sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_group_tag\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"群\"\n            android:textSize=\"12sp\"\n            android:textColor=\"#FFF\"\n            android:layout_alignBottom=\"@id/avatar\"\n            android:layout_alignRight=\"@id/avatar\"\n            android:layout_marginRight=\"3dp\"/>\n    </RelativeLayout>\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n         android:layout_marginTop=\"10dp\"\n        android:layout_toRightOf=\"@id/avatar_container\"\n        android:textColor=\"#353535\"\n        android:textSize=\"17sp\" />\n\n    <TextView\n        android:id=\"@+id/time\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_marginRight=\"7dp\"\n        android:layout_marginTop=\"12dp\"\n        android:textColor=\"#AAAAAA\"\n        android:textSize=\"12sp\" />\n\n    <ImageView\n        android:id=\"@+id/msg_state\"\n        android:layout_width=\"20dp\"\n        android:layout_height=\"20dp\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginBottom=\"5dp\"\n         android:layout_toRightOf=\"@id/avatar_container\"\n        android:src=\"@drawable/msg_state_fail_resend\"\n        android:visibility=\"gone\" />\n\n    <TextView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:textSize=\"14sp\"\n        android:text=\"@string/were_mentioned\"\n        android:textColor=\"#e84e40\"\n        android:id=\"@+id/mentioned\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_toRightOf=\"@id/msg_state\"\n        android:paddingTop=\"7dp\"\n        android:paddingBottom=\"7dp\"\n         android:visibility=\"gone\"\n        />\n\n    <TextView\n        android:id=\"@+id/message\"\n        android:layout_toLeftOf=\"@id/time\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_toRightOf=\"@id/mentioned\"\n        android:maxLines=\"1\"\n        android:ellipsize=\"end\"\n        android:paddingBottom=\"11dp\"\n        android:textColor=\"#AAAAAA\"\n        android:textSize=\"13sp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_dialog_gridview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@drawable/register_phone_bg\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n\n        <TextView\n            android:id=\"@+id/tv_forward\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/forward\"\n            android:textSize=\"16sp\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"1dp\"\n            android:background=\"@color/divider_list\" />\n\n        <TextView\n            android:id=\"@+id/textView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:layout_margin=\"10dp\"\n            android:gravity=\"center\"\n            android:minHeight=\"48dp\"\n            android:text=\"@string/forward\"\n            android:textSize=\"14sp\" />\n\n        <ImageView\n            android:id=\"@+id/imageView\"\n            android:layout_width=\"100dp\"\n            android:layout_height=\"100dp\"\n            android:layout_centerInParent=\"true\"\n            android:layout_gravity=\"center\"\n            android:layout_margin=\"10dp\"\n            android:src=\"@drawable/default_avatar\"\n            android:visibility=\"gone\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"1dp\"\n            android:background=\"@color/divider_list\" />\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:id=\"@+id/tv_ok\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_gravity=\"center\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\"\n                android:text=\"@string/ok\"\n                android:textSize=\"16sp\" />\n\n            <View\n                android:layout_width=\"1dp\"\n                android:layout_height=\"match_parent\"\n                android:background=\"@color/divider_list\" />\n\n            <TextView\n                android:id=\"@+id/tv_cancel\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_gravity=\"center\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\"\n                android:text=\"@string/cancel\"\n                android:textSize=\"16sp\" />\n        </LinearLayout>\n    </LinearLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_diaolog_gridview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n\n        <TextView\n            android:id=\"@+id/tv_forward\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            android:gravity=\"center\"\n            android:text=\"@string/forward\"\n            android:textSize=\"16sp\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"1dp\"\n            android:background=\"@color/divider_list\" />\n\n        <TextView\n            android:id=\"@+id/textView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:layout_margin=\"10dp\"\n            android:gravity=\"center\"\n            android:minHeight=\"48dp\"\n            android:text=\"@string/forward\"\n            android:textSize=\"14sp\" />\n\n        <ImageView\n            android:id=\"@+id/imageView\"\n            android:layout_width=\"100dp\"\n            android:layout_height=\"100dp\"\n            android:layout_centerInParent=\"true\"\n            android:layout_gravity=\"center\"\n            android:layout_margin=\"10dp\"\n            android:src=\"@drawable/default_avatar\"\n            android:visibility=\"gone\" />\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"1dp\"\n            android:background=\"@color/divider_list\" />\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:id=\"@+id/tv_ok\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_gravity=\"center\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\"\n                android:text=\"@string/ok\"\n                android:textSize=\"16sp\" />\n\n            <View\n                android:layout_width=\"1dp\"\n                android:layout_height=\"match_parent\"\n                android:background=\"@color/divider_list\" />\n\n            <TextView\n                android:id=\"@+id/tv_cancel\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_gravity=\"center\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\"\n                android:text=\"@string/cancel\"\n                android:textSize=\"16sp\" />\n        </LinearLayout>\n    </LinearLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_newfriend_msg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <RelativeLayout\n        android:id=\"@+id/rl_item_add\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"64dp\"\n        android:background=\"#ffffff\">\n\n        <ImageView\n            android:id=\"@+id/iv_avatar\"\n            android:layout_width=\"48dp\"\n            android:layout_height=\"48dp\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:src=\"@drawable/default_avatar\" />\n\n        <TextView\n            android:id=\"@+id/tv_name\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_marginTop=\"14dp\"\n            android:layout_toRightOf=\"@id/iv_avatar\"\n            android:textColor=\"#353535\"\n            android:textSize=\"16sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_reason\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginBottom=\"14dp\"\n            android:layout_marginLeft=\"12dp\"\n            android:layout_toRightOf=\"@id/iv_avatar\"\n            android:text=\"@string/request_add_friend\"\n            android:textColor=\"#aaaaaa\"\n            android:textSize=\"14sp\" />\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"\n            android:layout_marginRight=\"8dp\"\n            android:gravity=\"center\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:id=\"@+id/tv_added\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:paddingRight=\"20dp\"\n                android:text=\"@string/Already_added\"\n                android:textColor=\"#AAAAAA\"\n                android:textSize=\"12sp\" />\n\n            <Button\n                android:id=\"@+id/btn_add\"\n                android:layout_width=\"48dp\"\n                android:layout_height=\"32dp\"\n                android:background=\"@drawable/bg_btn_green\"\n                android:text=\"@string/accept\"\n                android:textColor=\"#fff\"\n                android:textSize=\"12sp\" />\n        </LinearLayout>\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_people_recently.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"horizontal\">\n\n    <ImageView\n        android:id=\"@+id/iv_avatar\"\n        android:layout_width=\"50dp\"\n        android:layout_height=\"50dp\"\n        android:layout_gravity=\"center\"\n        android:layout_margin=\"10dp\"\n        android:src=\"@drawable/default_avatar\" />\n\n    <RelativeLayout\n        android:layout_width=\"0dp\"\n        android:layout_height=\"50dp\"\n        android:layout_gravity=\"center\"\n        android:layout_weight=\"1\">\n\n        <TextView\n            android:id=\"@+id/tv_name\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginTop=\"5dp\"\n            android:text=\"@string/accept\"\n            android:textColor=\"@color/black\"\n            android:textSize=\"16sp\" />\n\n        <ImageView\n            android:id=\"@+id/iv_sex\"\n            android:layout_marginLeft=\"5dp\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginTop=\"3dp\"\n            android:layout_toRightOf=\"@+id/tv_name\"\n            android:src=\"@drawable/icon_male\" />\n\n        <TextView\n            android:id=\"@+id/tv_time\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_marginBottom=\"3dp\"\n            android:text=\"@string/accept\"\n            android:textSize=\"14sp\" />\n    </RelativeLayout>\n\n    <LinearLayout\n        android:id=\"@+id/ll_sign\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:padding=\"8dp\"\n        android:layout_marginRight=\"10dp\"\n        android:background=\"@drawable/sign_bg\">\n\n        <TextView\n            android:id=\"@+id/tv_sign\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:ellipsize=\"end\"\n            android:maxLines=\"2\"\n            android:textSize=\"12sp\"\n            android:textColor=\"@color/gray\"\n            android:maxWidth=\"80dp\"\n            android:text=\"@string/accept\" />\n    </LinearLayout>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_region.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\" >\n\n    <TextView\n        android:id=\"@+id/tv_name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:padding=\"10dp\" />\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/latout_pre_videocall_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\" android:layout_width=\"match_parent\"\n    android:background=\"@color/white\"\n    android:layout_height=\"wrap_content\">\n    <ImageView\n        android:id=\"@+id/iv_game_avatar\"\n        android:src=\"@drawable/default_avatar\"\n        android:layout_margin=\"10dp\"\n        android:layout_width=\"40dp\"\n        android:layout_centerVertical=\"true\"\n        android:layout_height=\"40dp\" />\n        <TextView\n            android:layout_toRightOf=\"@+id/iv_game_avatar\"\n            android:layout_centerVertical=\"true\"\n            android:text=\"@string/accept\"\n            android:layout_marginLeft=\"10dp\"\n            android:id=\"@+id/tv_username\"\n            android:textSize=\"14sp\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\" />\n    <CheckBox\n        android:id=\"@+id/checkbox\"\n        android:layout_marginRight=\"20dp\"\n        android:focusable=\"false\"\n        android:clickable=\"false\"\n        android:focusableInTouchMode=\"false\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:button=\"@null\"\n        android:textColor=\"@color/black_deep\"\n        android:layout_marginBottom=\"10dp\"\n        android:drawableLeft=\"@drawable/item_pre_videocall_selector\"\n        android:layout_width=\"25dp\"\n        android:layout_height=\"25dp\" />\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_alert_dialog_delete.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <TextView\n        android:id=\"@+id/tv_delete_title\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\"\n        android:layout_gravity=\"center\"\n        android:layout_marginTop=\"5dp\"\n        android:gravity=\"center\"\n        android:text=\"@string/prompt\"\n        android:textSize=\"18sp\" />\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"2px\"\n        android:layout_marginTop=\"5dp\"\n        android:background=\"@color/gray_pressed\" />\n\n    <TextView\n        android:id=\"@+id/tv_delete_people\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:layout_marginBottom=\"20dp\"\n        android:layout_marginTop=\"20dp\"\n        android:gravity=\"center\"\n        android:text=\"@string/Delete_the_contact\"\n        android:textSize=\"16sp\" />\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"2px\"\n        android:layout_marginTop=\"10dp\"\n        android:background=\"@color/gray_pressed\" />\n    <LinearLayout\n        android:orientation=\"horizontal\"\n        android:gravity=\"center\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\">\n        <TextView\n            android:id=\"@+id/tv_cancle\"\n            android:text=\"@string/cancel\"\n            android:gravity=\"center\"\n            android:layout_width=\"0dp\"\n            android:layout_weight=\"1\"\n            android:textSize=\"16sp\"\n            android:layout_height=\"match_parent\" />\n        <View\n            android:id=\"@+id/view_line_dialog\"\n            android:layout_width=\"1dp\"\n            android:layout_height=\"match_parent\"\n            android:background=\"@color/gray_pressed\" />\n        <TextView\n            android:id=\"@+id/tv_ok\"\n            android:text=\"@string/ok\"\n            android:gravity=\"center\"\n            android:textSize=\"16sp\"\n            android:layout_weight=\"1\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"match_parent\" />\n    </LinearLayout>\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"2px\"\n        android:background=\"@color/gray_pressed\" />\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_pup.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\" android:layout_width=\"match_parent\"\n    android:background=\"@color/white\"\n    android:layout_height=\"match_parent\">\n    <include layout=\"@layout/layout_title_bar\"/>\n    <FrameLayout\n        android:visibility=\"gone\"\n        android:layout_marginTop=\"10dp\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:layout_marginLeft=\"20dip\"\n        android:layout_marginRight=\"20dip\"\n        android:padding=\"2dp\" >\n\n        <EditText\n            android:id=\"@+id/country_et_search\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:background=\"@drawable/register_phone_bg\"\n            android:drawableLeft=\"@drawable/icon_search_gray\"\n            android:drawablePadding=\"4dp\"\n            android:hint=\"@string/search\"\n            android:paddingLeft=\"10dp\"\n            android:paddingRight=\"40dp\"\n            android:singleLine=\"true\"\n            android:textSize=\"14sp\" />\n\n        <ImageView\n            android:id=\"@+id/country_iv_cleartext\"\n            android:layout_width=\"35dp\"\n            android:layout_height=\"35dp\"\n            android:layout_gravity=\"right|center_vertical\"\n            android:padding=\"6dp\"\n            android:src=\"@drawable/clear\"\n            android:visibility=\"invisible\"/>\n    </FrameLayout>\n\n    <FrameLayout\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\" >\n\n        <ListView\n            android:id=\"@+id/country_lv_list\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:cacheColorHint=\"#000000\"\n            android:divider=\"#e3e3e3\"\n            android:dividerHeight=\"1.0dp\"\n            android:fadingEdge=\"none\"\n            android:scrollbars=\"none\"\n            android:scrollingCache=\"false\"\n            android:visibility=\"visible\" />\n\n        <TextView\n            android:visibility=\"invisible\"\n            android:id=\"@+id/country_dialog\"\n            android:layout_width=\"80.0dip\"\n            android:layout_height=\"80.0dip\"\n            android:layout_gravity=\"center\"\n            android:background=\"@color/holo_green_light\"\n            android:gravity=\"center\"\n            android:textColor=\"#ffffffff\"\n            android:textSize=\"30.0dip\" />\n\n        <com.htmessage.yichatopen.activity.country.SideBar\n            android:id=\"@+id/country_sidebar\"\n            android:layout_width=\"30dp\"\n            android:paddingBottom=\"5dp\"\n            android:background=\"@color/transparent\"\n            android:layout_height=\"match_parent\"\n            android:layout_gravity=\"right|center\" />\n    </FrameLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_title_bar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/title\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"48dp\"\n    android:layout_alignParentTop=\"true\"\n    android:background=\"@color/common_top_bar\">\n\n    <ImageView\n        android:id=\"@+id/iv_back\"\n        android:layout_width=\"40dp\"\n        android:layout_height=\"match_parent\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_centerVertical=\"true\"\n        android:onClick=\"back\"\n        android:paddingBottom=\"5dp\"\n        android:paddingLeft=\"5dp\"\n        android:paddingRight=\"5dp\"\n        android:paddingTop=\"5dp\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/top_bar_back\" />\n\n    <View\n        android:id=\"@+id/view_temp\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"match_parent\"\n        android:layout_marginBottom=\"8dp\"\n        android:layout_marginTop=\"8dp\"\n        android:layout_toRightOf=\"@id/iv_back\"\n        android:background=\"#14191A\" />\n\n    <TextView\n        android:id=\"@+id/tv_title\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerVertical=\"true\"\n        android:layout_toRightOf=\"@+id/view_temp\"\n        android:layout_marginLeft=\"10dp\"\n        android:maxLines=\"1\"\n        android:maxLength=\"20\"\n        android:ellipsize=\"end\"\n        android:text=\"@string/app_name\"\n        android:textColor=\"#ffffff\"\n        android:textSize=\"18sp\" />\n    <Button\n        android:visibility=\"gone\"\n        android:background=\"@android:color/transparent\"\n        android:maxLines=\"1\"\n        android:maxLength=\"20\"\n        android:ellipsize=\"end\"\n        android:textColor=\"#ffffff\"\n        android:textSize=\"18sp\"\n        android:text=\"@string/str_connect_hoster\"\n        android:id=\"@+id/btn_rtc\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_marginRight=\"3dp\"\n        android:padding=\"13dp\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n    <ImageView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerVertical=\"true\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_marginRight=\"10dp\"\n        android:padding=\"13dp\" />\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/loading_dialog.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/dialog_view\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:minHeight=\"60dp\"\n    android:minWidth=\"180dp\"\n    android:gravity=\"center\"\n    android:padding=\"10dp\"\n    android:background=\"@android:color/transparent\">\n    <ImageView\n        android:id=\"@+id/img\"\n        android:layout_gravity=\"center\"\n        android:layout_width=\"40dp\"\n        android:layout_height=\"40dp\"\n        android:src=\"@drawable/loadingicon\"\n        />\n\n    <TextView\n        android:layout_marginTop=\"10dp\"\n        android:layout_marginLeft=\"5dp\"\n        android:layout_gravity=\"center\"\n        android:id=\"@+id/tipTextView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/logining\" />\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_big_expression.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\" >\n\n    <ImageView\n        android:id=\"@+id/iv_expression\"\n        android:layout_width=\"48dp\"\n        android:layout_height=\"48dp\"\n        android:scaleType=\"centerInside\" />\n    \n    <TextView \n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:id=\"@+id/tv_name\"\n        android:textSize=\"11sp\"\n        android:textColor=\"@color/gray_normal\"\n        />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_expression.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\" >\n\n    <ImageView\n        android:id=\"@+id/iv_expression\"\n        android:layout_width=\"46dp\"\n        android:layout_height=\"46dp\"\n        android:padding=\"8dp\"\n        android:scaleType=\"fitXY\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_received_message.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\"\n    android:paddingTop=\"13dp\" >\n\n    <TextView\n        android:id=\"@+id/timestamp\"\n        style=\"@style/chat_text_date_style\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\" />\n\n    <RelativeLayout\n        android:id=\"@+id/re_main\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/margin_chat_activity\" >\n\n        <ImageView\n            android:id=\"@+id/iv_userhead\"\n            android:layout_width=\"@dimen/size_avatar\"\n            android:layout_height=\"@dimen/size_avatar\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginLeft=\"@dimen/margin_chat_activity\"\n            android:background=\"@drawable/default_avatar\"\n            android:scaleType=\"fitXY\" />\n\n        <RelativeLayout\n            android:id=\"@+id/bubble\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_below=\"@+id/tv_userid\"\n            android:layout_marginLeft=\"@dimen/margin_chat_activity\"\n            android:layout_toRightOf=\"@id/iv_userhead\"\n            android:background=\"@drawable/chatfrom_bg\"\n             >\n\n            <TextView\n                android:id=\"@+id/tv_chatcontent\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:autoLink=\"web\"\n                android:layout_centerInParent=\"true\"\n                android:gravity=\"center|left\"\n                android:paddingLeft=\"6dp\"\n                android:paddingRight=\"1dp\"\n                android:lineSpacingExtra=\"2dp\"\n                android:minHeight=\"38dp\"\n                android:maxWidth=\"225.0dip\"\n                android:textColor=\"#ff000000\"\n                android:textSize=\"15sp\" />\n        </RelativeLayout>\n\n        <TextView\n            android:id=\"@+id/tv_userid\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"@dimen/chat_nick_margin_left\"\n            android:textSize=\"@dimen/chat_nick_text_size\"\n            android:layout_toRightOf=\"@id/iv_userhead\"\n            android:visibility=\"gone\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_received_picture.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\"\n    android:paddingTop=\"13dp\" >\n\n    <TextView\n        android:id=\"@+id/timestamp\"\n        style=\"@style/chat_text_date_style\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/margin_chat_activity\" >\n\n        <ImageView\n            android:id=\"@+id/iv_userhead\"\n            android:layout_width=\"@dimen/size_avatar\"\n            android:layout_height=\"@dimen/size_avatar\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginLeft=\"@dimen/margin_chat_activity\"\n            android:src=\"@drawable/default_avatar\"\n            android:scaleType=\"fitXY\" />\n\n        <RelativeLayout\n            android:id=\"@+id/bubble\"\n            android:layout_width=\"wrap_content\" \n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"@dimen/margin_chat_activity\"\n            android:layout_toRightOf=\"@id/iv_userhead\"\n            android:layout_below=\"@+id/tv_userid\"\n            android:background=\"@drawable/chatfrom_bg\"\n             >\n\n            <ImageView\n                android:id=\"@+id/image\"\n                android:adjustViewBounds=\"true\"\n                android:maxWidth=\"240dp\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"150dp\"\n                android:scaleType=\"fitCenter\" />\n\n            <LinearLayout\n                android:id=\"@+id/ll_loading\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerInParent=\"true\"\n                android:gravity=\"center_horizontal\"\n                android:orientation=\"vertical\" >\n\n                <ProgressBar\n                    android:id=\"@+id/progress_bar\"\n                    android:layout_width=\"28dp\"\n                    android:layout_height=\"28dp\"\n                    android:visibility=\"gone\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"0%\"\n                    android:textColor=\"@android:color/white\"\n                    android:visibility=\"gone\" />\n            </LinearLayout>\n        </RelativeLayout>\n\n         <TextView\n            android:id=\"@+id/tv_userid\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"@dimen/chat_nick_margin_left\"\n            android:textSize=\"@dimen/chat_nick_text_size\"\n            android:layout_toRightOf=\"@id/iv_userhead\"\n            android:visibility=\"gone\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_received_voice.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\"\n    android:paddingTop=\"13dp\" >\n\n    <TextView\n        android:id=\"@+id/timestamp\"\n        style=\"@style/chat_text_date_style\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/margin_chat_activity\" >\n\n        <ImageView\n            android:id=\"@+id/iv_userhead\"\n            android:layout_width=\"@dimen/size_avatar\"\n            android:layout_height=\"@dimen/size_avatar\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginLeft=\"@dimen/margin_chat_activity\"\n            android:background=\"@drawable/default_avatar\"\n            android:scaleType=\"fitXY\" />\n\n        <RelativeLayout\n            android:id=\"@+id/bubble\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\" \n            android:layout_toRightOf=\"@id/iv_userhead\"\n            android:layout_marginLeft=\"@dimen/margin_chat_activity\"\n            android:layout_below=\"@+id/tv_userid\"\n            android:background=\"@drawable/chatfrom_bg\"\n            >\n\n            <ImageView\n                android:id=\"@+id/iv_voice\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:paddingLeft=\"10dp\"\n\t            android:paddingRight=\"12dp\"\n\t            android:layout_centerInParent=\"true\"\n                android:src=\"@drawable/chatfrom_voice_playing\" />\n        </RelativeLayout>\n\n        <TextView\n            android:id=\"@+id/tv_length\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_toRightOf=\"@id/bubble\"\n            android:layout_alignTop=\"@id/bubble\"\n            android:gravity=\"center\"\n            android:text=\"3&apos;&apos;\" />\n\n        <ImageView\n            android:id=\"@+id/iv_unread_voice\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_alignTop=\"@id/bubble\"\n            android:layout_toRightOf=\"@id/tv_length\"\n            android:src=\"@drawable/voice_unread\" />\n\n        <ProgressBar\n            android:id=\"@+id/progress_bar\"\n            style=\"@style/mProgress_circle\"\n            android:layout_width=\"30dp\"\n            android:layout_height=\"30dp\"\n            android:layout_marginTop=\"5dp\"\n            android:layout_toRightOf=\"@id/iv_unread_voice\"\n            android:visibility=\"invisible\" />\n\n         <TextView\n            android:id=\"@+id/tv_userid\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"@dimen/chat_nick_margin_left\"\n            android:textSize=\"@dimen/chat_nick_text_size\"\n            android:layout_toRightOf=\"@id/iv_userhead\"\n            android:visibility=\"gone\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_sent_message.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\"\n    android:paddingTop=\"13dp\" >\n\n    <TextView\n        android:id=\"@+id/timestamp\"\n        style=\"@style/chat_text_date_style\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <RelativeLayout\n        android:id=\"@+id/re_main\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/margin_chat_activity\" >\n\n        <ImageView\n            android:id=\"@+id/iv_userhead\"\n            android:layout_width=\"@dimen/size_avatar\"\n            android:layout_height=\"@dimen/size_avatar\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginRight=\"@dimen/margin_chat_activity\"\n            android:background=\"@drawable/default_avatar\"\n            android:scaleType=\"fitXY\" />\n\n        <RelativeLayout\n            android:id=\"@+id/bubble\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\" \n            android:layout_marginRight=\"@dimen/margin_chat_activity\"\n            android:layout_toLeftOf=\"@id/iv_userhead\"\n            android:layout_below=\"@+id/tv_userid\"\n             android:background=\"@drawable/chatto_bg\"\n            >\n\n            <TextView\n                 android:id=\"@+id/tv_chatcontent\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:autoLink=\"web\"\n                android:layout_centerInParent=\"true\"\n                android:gravity=\"center|left\"\n                android:paddingRight=\"6dp\"\n                android:paddingLeft=\"1dp\"\n                android:minHeight=\"38dp\"\n                android:lineSpacingExtra=\"2dp\"\n              \tandroid:textColor=\"#000000\"\n                android:maxWidth=\"225.0dip\"\n                android:textSize=\"15sp\" />\n        </RelativeLayout>\n        \n       <!--  <TextView\n            android:id=\"@+id/tv_userid\"\n            android:visibility=\"gone\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginRight=\"15dp\"\n            android:layout_toLeftOf=\"@id/iv_userhead\"\n            android:text=\"xxx\" /> -->\n\n        <ImageView\n            android:id=\"@+id/msg_status\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:clickable=\"true\"\n            android:src=\"@drawable/msg_state_failed_resend\"\n            android:visibility=\"gone\" />\n\n        <TextView\n            android:id=\"@+id/tv_ack_msg\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:text=\"@string/text_ack_msg\"\n            android:textSize=\"12sp\"\n            android:visibility=\"invisible\" />\n\n        <TextView\n            android:id=\"@+id/tv_delivered\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:text=\"@string/text_delivered_msg\"\n            android:textSize=\"12sp\"\n            android:visibility=\"invisible\" />\n        <ProgressBar\n            android:id=\"@+id/progress_bar\"\n            android:layout_width=\"28dp\"\n            android:layout_height=\"28dp\"\n            style=\"@style/mProgress_circle\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:visibility=\"invisible\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_sent_picture.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\"\n    android:paddingTop=\"13dp\" >\n\n    <TextView\n        android:id=\"@+id/timestamp\"\n        style=\"@style/chat_text_date_style\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/margin_chat_activity\" >\n\n        <ImageView\n            android:id=\"@+id/iv_userhead\"\n            android:layout_width=\"@dimen/size_avatar\"\n            android:layout_height=\"@dimen/size_avatar\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginRight=\"@dimen/margin_chat_activity\"\n            android:background=\"@drawable/default_avatar\"\n            android:scaleType=\"fitXY\" />\n\n        <RelativeLayout\n            android:id=\"@+id/bubble\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginRight=\"@dimen/margin_chat_activity\"\n            android:background=\"@drawable/chatto_bg\"\n            android:layout_toLeftOf=\"@id/iv_userhead\" >\n\n            <ImageView\n                android:id=\"@+id/image\"\n                android:maxWidth=\"240dp\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"150dp\"\n                android:adjustViewBounds=\"true\"\n                android:scaleType=\"fitCenter\"\n                />\n        </RelativeLayout>\t\n        <LinearLayout\n            android:id=\"@+id/ll_loading\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerInParent=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:gravity=\"center\"\n            android:orientation=\"vertical\" >\n\n            <ProgressBar\n                android:id=\"@+id/progress_bar\"\n                style=\"@style/mProgress_circle\"\n                android:layout_width=\"28dp\"\n                android:layout_height=\"28dp\"\n                android:visibility=\"visible\" />\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"0%\"\n                android:textColor=\"@android:color/black\"\n                android:visibility=\"gone\" />\n        </LinearLayout>\n\n        <ImageView\n            android:id=\"@+id/msg_status\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:clickable=\"true\"\n            android:src=\"@drawable/msg_state_failed_resend\"\n            android:visibility=\"gone\" />\n        <TextView\n            android:id=\"@+id/tv_ack_msg\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:text=\"@string/text_ack_msg\"\n            android:textSize=\"12sp\"\n            android:visibility=\"invisible\" />\n\n        <TextView\n            android:id=\"@+id/tv_delivered\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:text=\"@string/text_delivered_msg\"\n            android:textSize=\"12sp\"\n            android:visibility=\"invisible\" />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_sent_voice.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\"\n    android:paddingTop=\"13dp\" >\n\n    <TextView\n        android:id=\"@+id/timestamp\"\n        style=\"@style/chat_text_date_style\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/margin_chat_activity\" >\n\n        <ImageView\n            android:id=\"@+id/iv_userhead\"\n            android:layout_width=\"@dimen/size_avatar\"\n            android:layout_height=\"@dimen/size_avatar\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_marginRight=\"@dimen/margin_chat_activity\"\n            android:background=\"@drawable/default_avatar\"\n            android:scaleType=\"fitXY\" />\n\n        <RelativeLayout \n            android:id=\"@+id/bubble\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_toLeftOf=\"@id/iv_userhead\"\n            android:layout_marginRight=\"10dp\"\n             android:background=\"@drawable/chatto_bg\"\n            >\n\t        <ImageView\n\t            android:id=\"@+id/iv_voice\"\n\t            android:layout_centerInParent=\"true\"\n\t            android:paddingLeft=\"12dp\"\n\t            android:paddingRight=\"10dp\"\n\t            android:layout_width=\"wrap_content\"\n\t            android:layout_height=\"wrap_content\"\n\t            android:src=\"@drawable/chatto_voice_playing\" />\n\t\t</RelativeLayout>\n        <TextView\n            android:id=\"@+id/tv_length\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginRight=\"10dp\"\n            android:layout_toLeftOf=\"@id/bubble\"\n            android:gravity=\"center\" />\n        \n        <ImageView\n            android:id=\"@+id/msg_status\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/tv_length\"\n            android:clickable=\"true\"\n            android:src=\"@drawable/msg_state_failed_resend\"\n            android:visibility=\"gone\" />\n\n        <TextView\n            android:id=\"@+id/tv_ack_msg\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/tv_length\"\n            android:text=\"@string/text_ack_msg\"\n            android:textSize=\"12sp\"\n            android:visibility=\"invisible\" />\n\n        <TextView\n            android:id=\"@+id/tv_delivered\"\n            style=\"@style/chat_text_name_style\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/tv_length\"\n            android:text=\"@string/text_delivered_msg\"\n            android:textSize=\"12sp\"\n            android:visibility=\"invisible\" />\n          <ProgressBar \n            android:visibility=\"visible\"\n              style=\"@style/mProgress_circle\"\n            android:id=\"@+id/progress_bar\"\n            android:layout_width=\"28dp\"\n            android:layout_height=\"28dp\"\n              android:layout_centerVertical=\"true\"\n            android:layout_toLeftOf=\"@id/tv_length\"\n            />\n    </RelativeLayout>\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/widget_input_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_alignParentBottom=\"true\"\n    android:background=\"#f4f4f4\"\n    android:orientation=\"vertical\">\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0.5dp\"\n        android:background=\"#d4d4d4\" />\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"bottom\"\n        android:orientation=\"horizontal\"\n        android:padding=\"7dp\">\n\n        <LinearLayout\n            android:id=\"@+id/ll_press_to_input\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"1\"\n            android:gravity=\"bottom\"\n             android:orientation=\"horizontal\">\n             <LinearLayout\n                 android:layout_width=\"wrap_content\"\n                 android:layout_height=\"wrap_content\"\n                 android:gravity=\"bottom\"\n                 android:orientation=\"vertical\">\n            <Button\n                android:id=\"@+id/btn_set_mode_voice\"\n                android:layout_width=\"34dp\"\n                android:layout_height=\"34dp\"\n                android:layout_gravity=\"center\"\n                android:background=\"@drawable/chatting_setmode_voice_btn\" />\n             </LinearLayout>\n            <EditText\n                android:id=\"@+id/et_sendmessage\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center\"\n                android:layout_marginLeft=\"7dp\"\n                android:layout_marginRight=\"7dp\"\n                android:paddingBottom=\"3dp\"\n                android:background=\"@drawable/bg_et\"\n                android:maxLines=\"4\"\n                android:minHeight=\"34dp\"\n                android:paddingLeft=\"3dp\"\n                android:textSize=\"16sp\" />\n\n        </LinearLayout>\n\n\n\n        <LinearLayout\n            android:visibility=\"gone\"\n            android:id=\"@+id/ll_press_to_speak\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"bottom\"\n            android:layout_weight=\"1\"\n            android:gravity=\"bottom\"\n            android:orientation=\"horizontal\">\n\n\n\n            <Button\n                android:id=\"@+id/btn_set_mode_keyboard\"\n                android:layout_width=\"34dp\"\n                android:layout_gravity=\"center\"\n                android:layout_height=\"34dp\"\n                android:background=\"@drawable/chatting_setmode_keyboard_btn\" />\n            <Button\n                android:id=\"@+id/tv_recording\"\n                android:layout_width=\"0dp\"\n                android:layout_gravity=\"center\"\n                android:layout_height=\"34dp\"\n                android:layout_marginLeft=\"18dp\"\n                android:layout_marginRight=\"18dp\"\n                android:layout_weight=\"1\"\n                android:background=\"@drawable/chat_press_speak_btn\"\n                android:text=\"@string/button_pushtotalk\"\n                android:textColor=\"#666666\"\n                android:textSize=\"16sp\" />\n\n\n        </LinearLayout>\n\n\n\n            <Button\n                android:id=\"@+id/btn_emoticons_normal\"\n                android:layout_width=\"34dp\"\n                android:layout_height=\"34dp\"\n                android:layout_alignParentRight=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:layout_gravity=\"bottom\"\n                android:background=\"@drawable/chatting_biaoqing_btn_normal\"\n                android:scaleType=\"fitCenter\"\n                android:visibility=\"visible\" />\n\n            <Button\n                android:id=\"@+id/btn_emoticons_checked\"\n                android:layout_width=\"34dp\"\n                android:layout_height=\"34dp\"\n                android:layout_alignParentRight=\"true\"\n                android:layout_centerVertical=\"true\"\n                android:layout_gravity=\"bottom\"\n                android:background=\"@drawable/chatting_setmode_keyboard_btn\"\n                android:scaleType=\"fitCenter\"\n                android:visibility=\"gone\" />\n\n\n            <Button\n                android:id=\"@+id/btn_more\"\n                android:layout_width=\"34dp\"\n                android:layout_height=\"34dp\"\n                android:layout_gravity=\"bottom\"\n                android:layout_marginLeft=\"16dp\"\n                android:background=\"@drawable/btn_more_type_msg\" />\n\n            <Button\n                android:id=\"@+id/btn_send\"\n\n                android:layout_width=\"42dp\"\n                android:layout_height=\"34dp\"\n                android:layout_gravity=\"bottom\"\n                android:layout_marginLeft=\"10dp\"\n                android:background=\"@drawable/bg_btn_green\"\n                android:text=\"@string/button_send\"\n                android:textColor=\"#fff\"\n                android:textSize=\"14sp\"\n                android:visibility=\"gone\" />\n\n\n    </LinearLayout>\n\n\n    <LinearLayout\n        android:id=\"@+id/ll_more\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:showDividers=\"middle\"\n        android:visibility=\"gone\">\n\n\n        <LinearLayout\n            android:id=\"@+id/ll_emoji\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:showDividers=\"middle\"\n             >\n            <!-- 表情图片 -->\n            <android.support.v4.view.ViewPager\n                android:id=\"@+id/emoji_viewpager\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0dp\"\n                android:layout_weight=\"1\" />\n\n            <android.support.design.widget.TabLayout\n\n                android:id=\"@+id/tl_face_container\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"36dp\"\n                app:tabBackground=\"@drawable/emoji_bottom_bg\"\n                app:tabGravity=\"center\"\n                app:tabIndicatorHeight=\"0dp\"\n                app:tabMode=\"scrollable\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:id=\"@+id/ll_extend\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:showDividers=\"middle\"\n            android:visibility=\"gone\">\n            <!-- 图片，表情，名片等按钮 -->\n            <android.support.v4.view.ViewPager\n                android:id=\"@+id/extend_viewpager\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"0dp\"\n                android:layout_weight=\"1\"\n                />\n\n            <android.support.design.widget.TabLayout\n                android:id=\"@+id/tablelayout_extend\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:visibility=\"gone\"\n                app:tabGravity=\"fill\" />\n        </LinearLayout>\n\n    </LinearLayout>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/widget_main_button.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <Button\n        android:id=\"@+id/button\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@color/bottom_bar_normal_bg\"\n        android:drawableTop=\"@drawable/tab_chat_bg\"\n        android:paddingBottom=\"3dip\"\n        android:paddingTop=\"3dip\"\n        android:scaleType=\"matrix\"\n        android:text=\"@string/app_chat\"\n        android:textColor=\"@color/main_botton_text_color\"\n        android:textSize=\"12sp\" />\n\n    <TextView\n        android:layout_margin=\"3dp\"\n        android:visibility=\"invisible\"\n        android:id=\"@+id/unread_msg_number\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignRight=\"@id/button\"\n        android:background=\"@drawable/unread_count_bg\"\n        android:gravity=\"center\"\n        android:textColor=\"@android:color/white\"\n        android:textSize=\"10sp\" />\n</RelativeLayout>\n\n\n"
  },
  {
    "path": "app/src/main/res/layout/widget_switch_button.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\" >\n\n    <ImageView\n        android:id=\"@+id/iv_switch_open\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@drawable/open_icon\"\n        android:visibility=\"visible\" />\n\n    <ImageView\n        android:id=\"@+id/iv_switch_close\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@drawable/close_icon\"\n        android:visibility=\"invisible\" />\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/widget_voice_recorder.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"@drawable/recording_hint_bg\"\n     android:padding=\"10dp\"\n    android:orientation=\"vertical\">\n\n    <ImageView\n        android:id=\"@+id/mic_image\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerHorizontal=\"true\"\n        android:src=\"@drawable/record_animate_01\" />\n\n    <TextView\n        android:id=\"@+id/recording_hint\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/mic_image\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_marginTop=\"5dp\"\n        android:padding=\"2dp\"\n        android:text=\"@string/move_up_to_cancel\"\n        android:textSize=\"10sp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/widget_zbar_scan_capture.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\" >\n    <include layout=\"@layout/layout_title_bar\"></include>\n    <RelativeLayout\n        android:layout_below=\"@+id/title\"\n        android:id=\"@+id/capture_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" >\n\n        <FrameLayout\n            android:id=\"@+id/capture_preview\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\" />\n\n        <ImageView\n            android:id=\"@+id/capture_mask_top\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"100dp\"\n            android:layout_alignParentTop=\"true\"\n            android:background=\"@drawable/icon_qr_shadow\" />\n\n        <RelativeLayout\n            android:id=\"@+id/capture_crop_view\"\n            android:layout_width=\"250dp\"\n            android:layout_height=\"250dp\"\n            android:layout_centerHorizontal=\"true\"\n            android:layout_below=\"@id/capture_mask_top\"\n            android:background=\"@drawable/icon_qr_scan\" >\n\n            <ImageView\n                android:id=\"@+id/capture_scan_line\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_alignParentTop=\"true\"\n                android:layout_marginBottom=\"5dp\"\n                android:layout_marginTop=\"5dp\"\n                android:src=\"@drawable/icon_qr_scan_line\" />\n        </RelativeLayout>\n\n        <ImageView\n            android:id=\"@+id/capture_mask_bottom\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_below=\"@id/capture_crop_view\"\n            android:background=\"@drawable/icon_qr_shadow\" />\n\n        <ImageView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"match_parent\"\n            android:layout_above=\"@id/capture_mask_bottom\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_below=\"@id/capture_mask_top\"\n            android:layout_toLeftOf=\"@id/capture_crop_view\"\n            android:background=\"@drawable/icon_qr_shadow\" />\n\n        <ImageView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"match_parent\"\n            android:layout_above=\"@id/capture_mask_bottom\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_below=\"@id/capture_mask_top\"\n            android:layout_toRightOf=\"@id/capture_crop_view\"\n            android:background=\"@drawable/icon_qr_shadow\" />\n    </RelativeLayout>\n\n    <Button\n        android:id=\"@+id/capture_restart_scan\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\"\n        android:layout_alignParentBottom=\"true\"\n        android:background=\"#66ffcc00\"\n        android:gravity=\"center\"\n        android:text=\"@string/reset_scan\"\n        android:textColor=\"@android:color/white\"\n        android:textSize=\"14sp\"\n        android:visibility=\"invisible\" />\"\n\n    <TextView\n        android:id=\"@+id/capture_scan_result\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_above=\"@id/capture_restart_scan\"\n        android:layout_marginBottom=\"10dp\"\n        android:gravity=\"center\"\n        android:text=\"@string/Scanning\"\n        android:textColor=\"@android:color/white\"\n        android:textSize=\"14sp\" />\n    \n    <TextView\n        android:visibility=\"gone\"\n        android:layout_width=\"300dp\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_marginBottom=\"10dp\"\n        android:gravity=\"center\"\n        android:text=\"@string/scan_msg\"\n        android:textColor=\"@android:color/white\"\n        android:textSize=\"14sp\"\n         />\n\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/menu/menu_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item\n        android:id=\"@+id/item_search\"\n        android:icon=\"@drawable/icon_search\"\n        android:title=\"@string/search\"\n        app:showAsAction=\"ifRoom\" />\n\n\n    <item\n        android:id=\"@+id/item_add_group\"\n        android:icon=\"@drawable/icon_add_group\"\n        android:title=\"@string/Initiate_group_chat\"\n        app:showAsAction=\"never\" />\n    <item\n        android:id=\"@+id/item_add_friend\"\n        android:icon=\"@drawable/icon_add_friend\"\n        android:title=\"@string/add_friend\"\n        app:showAsAction=\"never\" />\n    <item\n        android:id=\"@+id/item_scan\"\n        android:icon=\"@drawable/icon_menu_scan\"\n\n        android:title=\"@string/scanning\"\n        app:showAsAction=\"never\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/values/arrays.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string-array name=\"country_code_list_en\" translatable=\"false\">\n        <item>Angola                     *+244  </item>\n        <item>Afghanistan                *+93   </item>\n        <item>Albania                    *+355  </item>\n        <item>Algeria                    *+213  </item>\n        <item>Andorra                    *+376  </item>\n        <item>Anguilla                   *+1264 </item>\n        <item>Antigua and Barbuda        *+1268 </item>\n        <item>Argentina                  *+54   </item>\n        <item>Armenia                    *+374  </item>\n        <item>Ascension                  *+247  </item>\n        <item>Australia                  *+61   </item>\n        <item>Austria                    *+43   </item>\n        <item>Azerbaijan                 *+994  </item>\n        <item>Bahamas                    *+1242 </item>\n        <item>Bahrain                    *+973  </item>\n        <item>Bangladesh                 *+880  </item>\n        <item>Barbados                   *+1246 </item>\n        <item>Belarus                    *+375  </item>\n        <item>Belgium                    *+32   </item>\n        <item>Belize                     *+501  </item>\n        <item>Benin                      *+229  </item>\n        <item>BermudaIs.                 *+1441 </item>\n        <item>Bolivia                    *+591  </item>\n        <item>Botswana                   *+267  </item>\n        <item>Brazil                     *+55   </item>\n        <item>Brunei                     *+673  </item>\n        <item>Bulgaria                   *+359  </item>\n        <item>Burkina-faso               *+226  </item>\n        <item>Burma                      *+95   </item>\n        <item>Burundi                    *+257  </item>\n        <item>Cameroon                   *+237  </item>\n        <item>Canada                     *+1    </item>\n        <item>Cayman Is.                 *+1345 </item>\n        <item>Central African Republic   *+236  </item>\n        <item>Chad                       *+235  </item>\n        <item>Chile                      *+56   </item>\n        <item>China                      *+86   </item>\n        <item>Colombia                   *+57   </item>\n        <item>Congo                      *+242  </item>\n        <item>Cook Is.                   *+682  </item>\n        <item>Costa Rica                 *+506  </item>\n        <item>Cuba                       *+53   </item>\n        <item>Cyprus                     *+357  </item>\n        <item>Czech Republic             *+420  </item>\n        <item>Denmark                    *+45   </item>\n        <item>Djibouti                   *+253  </item>\n        <item>Dominica Rep.              *+1890 </item>\n        <item>Ecuador                    *+593  </item>\n        <item>Egypt                      *+20   </item>\n        <item>EISalvador                 *+503  </item>\n        <item>Estonia                    *+372  </item>\n        <item>Ethiopia                   *+251  </item>\n        <item>Fiji                       *+679  </item>\n        <item>Finland                    *+358  </item>\n        <item>France                     *+33   </item>\n        <item>French Guiana              *+594  </item>\n        <item>Gabon                      *+241  </item>\n        <item>Gambia                     *+220  </item>\n        <item>Georgia                    *+995  </item>\n        <item>Germany                    *+49   </item>\n        <item>Ghana                      *+233  </item>\n        <item>Gibraltar                  *+350  </item>\n        <item>Greece                     *+30   </item>\n        <item>Grenada                    *+1809 </item>\n        <item>Guam                       *+1671 </item>\n        <item>Guatemala                  *+502  </item>\n        <item>Guinea                     *+224  </item>\n        <item>Guyana                     *+592  </item>\n        <item>Haiti                      *+509  </item>\n        <item>Honduras                   *+504  </item>\n        <item>Hongkong                   *+852  </item>\n        <item>Hungary                    *+36   </item>\n        <item>Iceland                    *+354  </item>\n        <item>India                      *+91   </item>\n        <item>Indonesia                  *+62   </item>\n        <item>Iran                       *+98   </item>\n        <item>Iraq                       *+964  </item>\n        <item>Ireland                    *+353  </item>\n        <item>Israel                     *+972  </item>\n        <item>Italy                      *+39   </item>\n        <item>IvoryCoast                 *+225  </item>\n        <item>Jamaica                    *+1876 </item>\n        <item>Japan                      *+81   </item>\n        <item>Jordan                     *+962  </item>\n        <item>Kampuchea (Cambodia )      *+855  </item>\n        <item>Kazakstan                  *+327  </item>\n        <item>Kenya                      *+254  </item>\n        <item>Korea                      *+82   </item>\n        <item>Kuwait                     *+965  </item>\n        <item>Kyrgyzstan                 *+331  </item>\n        <item>Laos                       *+856  </item>\n        <item>Latvia                     *+371  </item>\n        <item>Lebanon                    *+961  </item>\n        <item>Lesotho                    *+266  </item>\n        <item>Liberia                    *+231  </item>\n        <item>Libya                      *+218  </item>\n        <item>Liechtenstein              *+423  </item>\n        <item>Lithuania                  *+370  </item>\n        <item>Luxembourg                 *+352  </item>\n        <item>Macao                      *+853  </item>\n        <item>Madagascar                 *+261  </item>\n        <item>Malawi                     *+265  </item>\n        <item>Malaysia                   *+60   </item>\n        <item>Maldives                   *+960  </item>\n        <item>Mali                       *+223  </item>\n        <item>Malta                      *+356  </item>\n        <item>Mariana Is                 *+1670 </item>\n        <item>Martinique                 *+596  </item>\n        <item>Mauritius                  *+230  </item>\n        <item>Mexico                     *+52   </item>\n        <item>Moldova, Republic of       *+373  </item>\n        <item>Monaco                     *+377  </item>\n        <item>Mongolia                   *+976  </item>\n        <item>Montserrat Is              *+1664 </item>\n        <item>Morocco                    *+212  </item>\n        <item>Mozambique                 *+258  </item>\n        <item>Namibia                    *+264  </item>\n        <item>Nauru                      *+674  </item>\n        <item>Nepal                      *+977  </item>\n        <item>Netheriands Antilles       *+599  </item>\n        <item>Netherlands                *+31   </item>\n        <item>NewZealand                 *+64   </item>\n        <item>Nicaragua                  *+505  </item>\n        <item>Niger                      *+227  </item>\n        <item>Nigeria                    *+234  </item>\n        <item>North Korea                *+850  </item>\n        <item>Norway                     *+47   </item>\n        <item>Oman                       *+968  </item>\n        <item>Pakistan                   *+92   </item>\n        <item>Panama                     *+507  </item>\n        <item>Papua New Cuinea           *+675  </item>\n        <item>Paraguay                   *+595  </item>\n        <item>Peru                       *+51   </item>\n        <item>Philippines                *+63   </item>\n        <item>Poland                     *+48   </item>\n        <item>French Polynesia           *+689  </item>\n        <item>Portugal                   *+351  </item>\n        <item>PuertoRico                 *+1787 </item>\n        <item>Qatar                      *+974  </item>\n        <item>Reunion                    *+262  </item>\n        <item>Romania                    *+40   </item>\n        <item>Russia                     *+7    </item>\n        <item>Saint Lueia                *+1758 </item>\n        <item>Saint Vincent              *+1784 </item>\n        <item>Samoa Eastern              *+684  </item>\n        <item>Samoa Western              *+685  </item>\n        <item>San Marino                 *+378  </item>\n        <item>Sao Tome and Principe      *+239  </item>\n        <item>Saudi Arabia               *+966  </item>\n        <item>Senegal                    *+221  </item>\n        <item>Seychelles                 *+248  </item>\n        <item>Sierra Leone               *+232  </item>\n        <item>Singapore                  *+65   </item>\n        <item>Slovakia                   *+421  </item>\n        <item>Slovenia                   *+386  </item>\n        <item>Solomon Is                 *+677  </item>\n        <item>Somali                     *+252  </item>\n        <item>South Africa               *+27   </item>\n        <item>Spain                      *+34   </item>\n        <item>Sri Lanka                  *+94   </item>\n        <item>St.Lucia                   *+1758 </item>\n        <item>St.Vincent                 *+1784 </item>\n        <item>Sudan                      *+249  </item>\n        <item>Suriname                   *+597  </item>\n        <item>Swaziland                  *+268  </item>\n        <item>Sweden                     *+46   </item>\n        <item>Switzerland                *+41   </item>\n        <item>Syriaw                     *+963  </item>\n        <item>Taiwan                     *+886  </item>\n        <item>Tajikstan                  *+992  </item>\n        <item>Tanzania                   *+255  </item>\n        <item>Thailand                   *+66   </item>\n        <item>Togo                       *+228  </item>\n        <item>Tonga                      *+676  </item>\n        <item>Trinidad and Tobago        *+1809 </item>\n        <item>Tunisia                    *+216  </item>\n        <item>Turkey                     *+90   </item>\n        <item>Turkmenistan               *+993  </item>\n        <item>Uganda                     *+256  </item>\n        <item>Ukraine                    *+380  </item>\n        <item>United Arab Emirates       *+971  </item>\n        <item>United Kiongdom            *+44   </item>\n        <item>United States of America   *+1    </item>\n        <item>Uruguay                    *+598  </item>\n        <item>Uzbekistan                 *+233  </item>\n        <item>Venezuela                  *+58   </item>\n        <item>Vietnam                    *+84   </item>\n        <item>Yemen                      *+967  </item>\n        <item>Yugoslavia                 *+381  </item>\n        <item>South Africa               *+27   </item>\n        <item>Zimbabwe                   *+263  </item>\n        <item>Zaire                      *+243  </item>\n        <item>Zambia                     *+260  </item>\n    </string-array>\n    <string-array name=\"country_code_list_ch\" translatable=\"false\" >\n        <item>安哥拉             *+244  </item>\n        <item>阿富汗             *+93   </item>\n        <item>阿尔巴尼亚         *+355  </item>\n        <item>阿尔及利亚         *+213  </item>\n        <item>安道尔共和国       *+376  </item>\n        <item>安圭拉岛           *+1264 </item>\n        <item>安提瓜和巴布达     *+1268 </item>\n        <item>阿根廷             *+54   </item>\n        <item>亚美尼亚           *+374  </item>\n        <item>阿森松             *+247  </item>\n        <item>澳大利亚           *+61   </item>\n        <item>奥地利             *+43   </item>\n        <item>阿塞拜疆           *+994  </item>\n        <item>巴哈马             *+1242 </item>\n        <item>巴林               *+973  </item>\n        <item>孟加拉国           *+880  </item>\n        <item>巴巴多斯           *+1246 </item>\n        <item>白俄罗斯           *+375  </item>\n        <item>比利时             *+32   </item>\n        <item>伯利兹             *+501  </item>\n        <item>贝宁               *+229  </item>\n        <item>百慕大群岛         *+1441 </item>\n        <item>玻利维亚           *+591  </item>\n        <item>博茨瓦纳           *+267  </item>\n        <item>巴西               *+55   </item>\n        <item>文莱               *+673  </item>\n        <item>保加利亚           *+359  </item>\n        <item>布基纳法索         *+226  </item>\n        <item>缅甸               *+95   </item>\n        <item>布隆迪             *+257  </item>\n        <item>喀麦隆             *+237  </item>\n        <item>加拿大             *+1    </item>\n        <item>开曼群岛           *+1345 </item>\n        <item>中非共和国         *+236  </item>\n        <item>乍得               *+235  </item>\n        <item>智利               *+56   </item>\n        <item>中国               *+86   </item>\n        <item>哥伦比亚           *+57   </item>\n        <item>刚果               *+242  </item>\n        <item>库克群岛           *+682  </item>\n        <item>哥斯达黎加         *+506  </item>\n        <item>古巴               *+53   </item>\n        <item>塞浦路斯           *+357  </item>\n        <item>捷克               *+420  </item>\n        <item>丹麦               *+45   </item>\n        <item>吉布提             *+253  </item>\n        <item>多米尼加共和国     *+1890 </item>\n        <item>厄瓜多尔           *+593  </item>\n        <item>埃及               *+20   </item>\n        <item>萨尔瓦多           *+503  </item>\n        <item>爱沙尼亚           *+372  </item>\n        <item>埃塞俄比亚         *+251  </item>\n        <item>斐济               *+679  </item>\n        <item>芬兰               *+358  </item>\n        <item>法国               *+33   </item>\n        <item>法属圭亚那         *+594  </item>\n        <item>加蓬               *+241  </item>\n        <item>冈比亚             *+220  </item>\n        <item>格鲁吉亚           *+995  </item>\n        <item>德国               *+49   </item>\n        <item>加纳               *+233  </item>\n        <item>直布罗陀           *+350  </item>\n        <item>希腊               *+30   </item>\n        <item>格林纳达           *+1809 </item>\n        <item>关岛               *+1671 </item>\n        <item>危地马拉           *+502  </item>\n        <item>几内亚             *+224  </item>\n        <item>圭亚那             *+592  </item>\n        <item>海地               *+509  </item>\n        <item>洪都拉斯           *+504  </item>\n        <item>香港               *+852  </item>\n        <item>匈牙利             *+36   </item>\n        <item>冰岛               *+354  </item>\n        <item>印度               *+91   </item>\n        <item>印度尼西亚         *+62   </item>\n        <item>伊朗               *+98   </item>\n        <item>伊拉克             *+964  </item>\n        <item>爱尔兰             *+353  </item>\n        <item>以色列             *+972  </item>\n        <item>意大利             *+39   </item>\n        <item>科特迪瓦           *+225  </item>\n        <item>牙买加             *+1876 </item>\n        <item>日本               *+81   </item>\n        <item>约旦               *+962  </item>\n        <item>柬埔寨             *+855  </item>\n        <item>哈萨克斯坦         *+327  </item>\n        <item>肯尼亚             *+254  </item>\n        <item>韩国               *+82   </item>\n        <item>科威特             *+965  </item>\n        <item>吉尔吉斯坦         *+331  </item>\n        <item>老挝               *+856  </item>\n        <item>拉脱维亚           *+371  </item>\n        <item>黎巴嫩             *+961  </item>\n        <item>莱索托             *+266  </item>\n        <item>利比里亚           *+231  </item>\n        <item>利比亚             *+218  </item>\n        <item>列支敦士登         *+423  </item>\n        <item>立陶宛             *+370  </item>\n        <item>卢森堡             *+352  </item>\n        <item>澳门               *+853  </item>\n        <item>马达加斯加         *+261  </item>\n        <item>马拉维             *+265  </item>\n        <item>马来西亚           *+60   </item>\n        <item>马尔代夫           *+960  </item>\n        <item>马里               *+223  </item>\n        <item>马耳他             *+356  </item>\n        <item>马里亚那群岛       *+1670 </item>\n        <item>马提尼克           *+596  </item>\n        <item>毛里求斯           *+230  </item>\n        <item>墨西哥             *+52   </item>\n        <item>摩尔多瓦           *+373  </item>\n        <item>摩纳哥             *+377  </item>\n        <item>蒙古               *+976  </item>\n        <item>蒙特塞拉特岛       *+1664 </item>\n        <item>摩洛哥             *+212  </item>\n        <item>莫桑比克           *+258  </item>\n        <item>纳米比亚           *+264  </item>\n        <item>瑙鲁               *+674  </item>\n        <item>尼泊尔             *+977  </item>\n        <item>荷属安的列斯       *+599  </item>\n        <item>荷兰               *+31   </item>\n        <item>新西兰             *+64   </item>\n        <item>尼加拉瓜           *+505  </item>\n        <item>尼日尔             *+227  </item>\n        <item>尼日利亚           *+234  </item>\n        <item>朝鲜               *+850  </item>\n        <item>挪威               *+47   </item>\n        <item>阿曼               *+968  </item>\n        <item>巴基斯坦           *+92   </item>\n        <item>巴拿马             *+507  </item>\n        <item>巴布亚新几内亚     *+675  </item>\n        <item>巴拉圭             *+595  </item>\n        <item>秘鲁               *+51   </item>\n        <item>菲律宾             *+63   </item>\n        <item>波兰               *+48   </item>\n        <item>法属玻利尼西亚     *+689  </item>\n        <item>葡萄牙             *+351  </item>\n        <item>波多黎各           *+1787 </item>\n        <item>卡塔尔             *+974  </item>\n        <item>留尼旺             *+262  </item>\n        <item>罗马尼亚           *+40   </item>\n        <item>俄罗斯             *+7    </item>\n        <item>圣卢西亚           *+1758 </item>\n        <item>圣文森特岛         *+1784 </item>\n        <item>东萨摩亚(美)       *+684  </item>\n        <item>西萨摩亚           *+685  </item>\n        <item>圣马力诺           *+378  </item>\n        <item>圣多美和普林西比   *+239  </item>\n        <item>沙特阿拉伯         *+966  </item>\n        <item>塞内加尔           *+221  </item>\n        <item>塞舌尔             *+248  </item>\n        <item>塞拉利昂           *+232  </item>\n        <item>新加坡             *+65   </item>\n        <item>斯洛伐克           *+421  </item>\n        <item>斯洛文尼亚         *+386  </item>\n        <item>所罗门群岛         *+677  </item>\n        <item>索马里             *+252  </item>\n        <item>南非               *+27   </item>\n        <item>西班牙             *+34   </item>\n        <item>斯里兰卡           *+94   </item>\n        <item>圣卢西亚           *+1758 </item>\n        <item>圣文森特           *+1784 </item>\n        <item>苏丹               *+249  </item>\n        <item>苏里南             *+597  </item>\n        <item>斯威士兰           *+268  </item>\n        <item>瑞典               *+46   </item>\n        <item>瑞士               *+41   </item>\n        <item>叙利亚             *+963  </item>\n        <item>台湾省             *+886  </item>\n        <item>塔吉克斯坦         *+992  </item>\n        <item>坦桑尼亚           *+255  </item>\n        <item>泰国               *+66   </item>\n        <item>多哥               *+228  </item>\n        <item>汤加               *+676  </item>\n        <item>特立尼达和多巴哥   *+1809 </item>\n        <item>突尼斯             *+216  </item>\n        <item>土耳其             *+90   </item>\n        <item>土库曼斯坦         *+993  </item>\n        <item>乌干达             *+256  </item>\n        <item>乌克兰             *+380  </item>\n        <item>阿拉伯联合酋长国   *+971  </item>\n        <item>英国               *+44   </item>\n        <item>美国               *+1    </item>\n        <item>乌拉圭             *+598  </item>\n        <item>乌兹别克斯坦       *+233  </item>\n        <item>委内瑞拉           *+58   </item>\n        <item>越南               *+84   </item>\n        <item>也门               *+967  </item>\n        <item>南斯拉夫           *+381  </item>\n        <item>南非               *+27   </item>\n        <item>津巴布韦           *+263  </item>\n        <item>扎伊尔             *+243  </item>\n        <item>赞比亚             *+260  </item>\n        ></string-array>\n    <!-- 省、自治区、直辖市、特别行政区 -->\n    <string-array name=\"province_item\">\n        <item value=\"479\">北京</item>\n        <item value=\"480\">河北</item>\n        <item value=\"481\">山东</item>\n        <item value=\"482\">上海</item>\n        <item value=\"483\">广东</item>\n        <item value=\"484\">安徽</item>\n        <item value=\"485\">福建</item>\n        <item value=\"486\">甘肃</item>\n        <item value=\"487\">广西</item>\n        <item value=\"488\">贵州</item>\n        <item value=\"489\">海南</item>\n        <item value=\"490\">河南</item>\n        <item value=\"491\">黑龙江</item>\n        <item value=\"492\">湖北</item>\n        <item value=\"493\">湖南</item>\n        <item value=\"494\">吉林</item>\n        <item value=\"495\">江苏</item>\n        <item value=\"496\">江西</item>\n        <item value=\"497\">辽宁</item>\n        <item value=\"498\">内蒙古</item>\n        <item value=\"499\">宁夏</item>\n        <item value=\"500\">青海</item>\n        <item value=\"501\">山西</item>\n        <item value=\"502\">陕西</item>\n        <item value=\"503\">四川</item>\n        <item value=\"504\">天津</item>\n        <item value=\"505\">西藏</item>\n        <item value=\"506\">新疆</item>\n        <item value=\"507\">云南</item>\n        <item value=\"508\">浙江</item>\n        <item value=\"509\">重庆</item>\n        <item value=\"510\">台湾</item>\n        <item value=\"511\">香港</item>\n        <item value=\"512\">澳门</item>\n    </string-array>\n\n    <!-- 个地级市 -->\n    <string-array name=\"beijin_province_item\">\n        <item value=\"513\">西城区</item>\n        <item value=\"514\">东城区</item>\n        <item value=\"515\">昌平区</item>\n        <item value=\"516\">海淀区</item>\n        <item value=\"517\">崇文区</item>\n        <item value=\"518\">宣武区</item>\n        <item value=\"519\">顺义区</item>\n        <item value=\"520\">大兴区</item>\n        <item value=\"521\">怀柔区</item>\n        <item value=\"524\">延庆县</item>\n        <item value=\"525\">朝阳区</item>\n        <item value=\"526\">丰台区</item>\n        <item value=\"527\">石景山区</item>\n        <item value=\"528\">门头沟区</item>\n        <item value=\"529\">房山区</item>\n        <item value=\"530\">通州区</item>\n        <item value=\"1022\">平谷区</item>\n        <item value=\"1023\">密云县</item>\n    </string-array>\n    <string-array name=\"heibei_province_item\">\n        <item value=\"531\">保定</item>\n        <item value=\"532\">邯郸</item>\n        <item value=\"533\">沧州</item>\n        <item value=\"534\">邢台</item>\n        <item value=\"535\">廊坊</item>\n        <item value=\"536\">承德</item>\n        <item value=\"537\">张家口</item>\n        <item value=\"538\">衡水</item>\n        <item value=\"539\">秦皇岛</item>\n        <item value=\"540\">石家庄</item>\n        <item value=\"541\">唐山</item>\n    </string-array>\n    <string-array name=\"shandong_province_item\">\n        <item value=\"542\">邹城</item>\n        <item value=\"543\">济南</item>\n        <item value=\"544\">青岛</item>\n        <item value=\"545\">烟台</item>\n        <item value=\"546\">淄博</item>\n        <item value=\"547\">枣庄</item>\n        <item value=\"548\">滨州</item>\n        <item value=\"549\">德州</item>\n        <item value=\"550\">聊城</item>\n        <item value=\"551\">临沂</item>\n        <item value=\"552\">菏泽</item>\n        <item value=\"553\">莱芜</item>\n        <item value=\"554\">东营</item>\n        <item value=\"555\">潍坊</item>\n        <item value=\"556\">济宁</item>\n        <item value=\"557\">泰安</item>\n        <item value=\"558\">威海</item>\n        <item value=\"559\">日照</item>\n    </string-array>\n    <string-array name=\"shanghai_province_item\">\n        <item value=\"560\">黄浦区</item>\n        <item value=\"561\">浦东新区</item>\n        <item value=\"562\">徐汇区</item>\n        <item value=\"563\">长宁区</item>\n        <item value=\"564\">静安区</item>\n        <item value=\"565\">卢湾区</item>\n        <item value=\"566\">嘉定区</item>\n        <item value=\"567\">金山区</item>\n        <item value=\"568\">松江区</item>\n        <item value=\"569\">青浦区</item>\n        <item value=\"570\">奉贤区</item>\n        <item value=\"571\">崇明县</item>\n        <item value=\"572\">普陀区</item>\n        <item value=\"573\">闸北区</item>\n        <item value=\"574\">虹口区</item>\n        <item value=\"575\">杨浦区</item>\n        <item value=\"576\">闵行区</item>\n        <item value=\"577\">宝山区</item>\n    </string-array>\n    <string-array name=\"guangdong_province_item\">\n        <item value=\"578\">深圳</item>\n        <item value=\"579\">广州</item>\n        <item value=\"580\">东莞</item>\n        <item value=\"581\">珠海</item>\n        <item value=\"582\">汕头</item>\n        <item value=\"583\">佛山</item>\n        <item value=\"584\">潮州</item>\n        <item value=\"585\">揭阳</item>\n        <item value=\"586\">云浮</item>\n        <item value=\"587\">梅州</item>\n        <item value=\"588\">汕尾</item>\n        <item value=\"589\">河源</item>\n        <item value=\"590\">阳江</item>\n        <item value=\"591\">清远</item>\n        <item value=\"592\">中山</item>\n        <item value=\"593\">韶关</item>\n        <item value=\"594\">湛江</item>\n        <item value=\"595\">肇庆</item>\n        <item value=\"596\">江门</item>\n        <item value=\"597\">茂名</item>\n        <item value=\"598\">惠州</item>\n    </string-array>\n    <string-array name=\"anhui_province_item\">\n        <item value=\"599\">合肥</item>\n        <item value=\"600\">芜湖</item>\n        <item value=\"601\">蚌埠</item>\n        <item value=\"602\">淮南</item>\n        <item value=\"603\">安庆</item>\n        <item value=\"604\">阜阳</item>\n        <item value=\"605\">亳州</item>\n        <item value=\"606\">巢湖</item>\n        <item value=\"607\">六安</item>\n        <item value=\"608\">铜陵</item>\n        <item value=\"609\">马鞍山</item>\n        <item value=\"610\">滁州</item>\n        <item value=\"611\">黄山</item>\n        <item value=\"612\">宿州</item>\n        <item value=\"613\">淮北</item>\n    </string-array>\n    <string-array name=\"fujian_province_item\">\n        <item value=\"614\">福安</item>\n        <item value=\"615\">福清</item>\n        <item value=\"616\">晋江</item>\n        <item value=\"617\">石狮</item>\n        <item value=\"618\">福州</item>\n        <item value=\"619\">长乐</item>\n        <item value=\"620\">龙岩</item>\n        <item value=\"621\">宁德</item>\n        <item value=\"622\">厦门</item>\n        <item value=\"623\">莆田</item>\n        <item value=\"624\">三明</item>\n        <item value=\"625\">泉州</item>\n        <item value=\"626\">漳州</item>\n        <item value=\"627\">南平</item>\n    </string-array>\n    <string-array name=\"gansu_province_item\">\n        <item value=\"628\">庆阳</item>\n        <item value=\"629\">张掖</item>\n        <item value=\"630\">兰州</item>\n        <item value=\"631\">金昌</item>\n        <item value=\"632\">白银</item>\n        <item value=\"633\">天水</item>\n        <item value=\"634\">酒泉</item>\n    </string-array>\n    <string-array name=\"guangxi_province_item\">\n        <item value=\"635\">柳州</item>\n        <item value=\"636\">桂林</item>\n        <item value=\"637\">梧州</item>\n        <item value=\"638\">北海</item>\n        <item value=\"639\">防城港</item>\n        <item value=\"640\">钦州</item>\n        <item value=\"641\">崇左</item>\n        <item value=\"642\">南宁</item>\n        <item value=\"643\">贵港</item>\n        <item value=\"644\">玉林</item>\n        <item value=\"645\">百色</item>\n        <item value=\"646\">贺州</item>\n        <item value=\"647\">河池</item>\n        <item value=\"648\">来宾</item>\n    </string-array>\n    <string-array name=\"guizhou_province_item\">\n        <item value=\"649\">六盘水</item>\n        <item value=\"650\">遵义</item>\n        <item value=\"651\">安顺</item>\n        <item value=\"652\">铜仁</item>\n        <item value=\"653\">毕节</item>\n        <item value=\"654\">贵阳</item>\n    </string-array>\n    <string-array name=\"hainan_province_item\">\n        <item value=\"655\">海口</item>\n        <item value=\"656\">三亚</item>\n    </string-array>\n    <string-array name=\"henan_province_item\">\n        <item value=\"657\">郑州</item>\n        <item value=\"659\">平顶山</item>\n        <item value=\"660\">洛阳</item>\n        <item value=\"661\">商丘</item>\n        <item value=\"662\">安阳</item>\n        <item value=\"663\">三门峡</item>\n        <item value=\"664\">周口</item>\n        <item value=\"665\">驻马店</item>\n        <item value=\"666\">南阳</item>\n        <item value=\"667\">信阳</item>\n        <item value=\"668\">灵宝</item>\n        <item value=\"669\">新乡</item>\n        <item value=\"670\">许昌</item>\n        <item value=\"671\">鹤壁</item>\n        <item value=\"672\">焦作</item>\n        <item value=\"673\">濮阳</item>\n        <item value=\"674\">漯河</item>\n    </string-array>\n    <string-array name=\"heilongjiang_province_item\">\n        <item value=\"675\">齐齐哈尔</item>\n        <item value=\"676\">牡丹江</item>\n        <item value=\"677\">佳木斯</item>\n        <item value=\"678\">大庆</item>\n        <item value=\"679\">鸡西</item>\n        <item value=\"680\">双鸭山</item>\n        <item value=\"681\">伊春</item>\n        <item value=\"682\">七台河</item>\n        <item value=\"683\">鹤岗</item>\n        <item value=\"684\">黑河</item>\n        <item value=\"685\">绥化</item>\n        <item value=\"686\">哈尔滨</item>\n    </string-array>\n    <string-array name=\"hubei_province_item\">\n        <item value=\"687\">武汉</item>\n        <item value=\"688\">黄石</item>\n        <item value=\"689\">十堰</item>\n        <item value=\"690\">荆州</item>\n        <item value=\"691\">宜昌</item>\n        <item value=\"692\">襄阳</item>\n        <item value=\"693\">汉口</item>\n        <item value=\"694\">襄樊</item>\n        <item value=\"695\">鄂州</item>\n        <item value=\"696\">荆门</item>\n        <item value=\"697\">孝感</item>\n        <item value=\"698\">黄冈</item>\n        <item value=\"699\">咸宁</item>\n        <item value=\"700\">随州</item>\n    </string-array>\n    <string-array name=\"hunan_province_item\">\n        <item value=\"701\">长沙</item>\n        <item value=\"702\">株洲</item>\n        <item value=\"703\">湘潭</item>\n        <item value=\"704\">衡阳</item>\n        <item value=\"705\">邵阳</item>\n        <item value=\"706\">永州</item>\n        <item value=\"707\">怀化</item>\n        <item value=\"708\">岳阳</item>\n        <item value=\"709\">张家界</item>\n        <item value=\"710\">益阳</item>\n        <item value=\"711\">常德</item>\n        <item value=\"712\">娄底</item>\n        <item value=\"713\">郴州</item>\n    </string-array>\n    <string-array name=\"jilin_province_item\">\n        <item value=\"714\">吉林</item>\n        <item value=\"715\">四平</item>\n        <item value=\"716\">辽源</item>\n        <item value=\"717\">通化</item>\n        <item value=\"718\">白山</item>\n        <item value=\"719\">延边</item>\n        <item value=\"720\">延吉</item>\n        <item value=\"721\">长春</item>\n        <item value=\"722\">松原</item>\n        <item value=\"723\">白城</item>\n    </string-array>\n    <string-array name=\"jiangsu_province_item\">\n        <item value=\"724\">南京</item>\n        <item value=\"725\">苏州</item>\n        <item value=\"726\">常州</item>\n        <item value=\"727\">无锡</item>\n        <item value=\"728\">徐州</item>\n        <item value=\"729\">南通</item>\n        <item value=\"730\">吴江</item>\n        <item value=\"731\">宜兴</item>\n        <item value=\"732\">张家港</item>\n        <item value=\"733\">宿迁</item>\n        <item value=\"734\">常熟</item>\n        <item value=\"735\">江阴</item>\n        <item value=\"736\">靖江</item>\n        <item value=\"737\">昆山</item>\n        <item value=\"738\">太仓</item>\n        <item value=\"739\">连云港</item>\n        <item value=\"740\">淮安</item>\n        <item value=\"741\">盐城</item>\n        <item value=\"742\">扬州</item>\n        <item value=\"743\">镇江</item>\n        <item value=\"744\">泰州</item>\n    </string-array>\n    <string-array name=\"jiangxi_province_item\">\n        <item value=\"745\">南昌</item>\n        <item value=\"746\">上饶</item>\n        <item value=\"747\">九江</item>\n        <item value=\"748\">萍乡</item>\n        <item value=\"749\">新余</item>\n        <item value=\"750\">鹰潭</item>\n        <item value=\"751\">赣州</item>\n        <item value=\"752\">宜春</item>\n        <item value=\"753\">景德镇</item>\n        <item value=\"754\">吉安</item>\n        <item value=\"755\">抚州</item>\n    </string-array>\n    <string-array name=\"liaoning_province_item\">\n        <item value=\"756\">沈阳</item>\n        <item value=\"757\">大连</item>\n        <item value=\"758\">鞍山</item>\n        <item value=\"759\">抚顺</item>\n        <item value=\"760\">本溪</item>\n        <item value=\"761\">丹东</item>\n        <item value=\"762\">朝阳</item>\n        <item value=\"763\">葫芦岛</item>\n        <item value=\"764\">锦州</item>\n        <item value=\"765\">营口</item>\n        <item value=\"766\">阜新</item>\n        <item value=\"767\">辽阳</item>\n        <item value=\"768\">盘锦</item>\n        <item value=\"769\">铁岭</item>\n    </string-array>\n    <string-array name=\"neimenggu_province_item\">\n        <item value=\"770\">包头</item>\n        <item value=\"771\">乌海</item>\n        <item value=\"772\">赤峰</item>\n        <item value=\"773\">通辽</item>\n        <item value=\"774\">鄂尔多斯</item>\n        <item value=\"775\">呼伦贝尔</item>\n        <item value=\"776\">巴彦淖尔</item>\n        <item value=\"777\">乌兰察布</item>\n        <item value=\"778\">兴安盟 </item>\n        <item value=\"779\">锡林郭勒盟 </item>\n        <item value=\"780\">阿拉善盟 </item>\n        <item value=\"781\">呼和浩特</item>\n    </string-array>\n    <string-array name=\"ningxia_province_item\">\n        <item value=\"782\">银川</item>\n        <item value=\"783\">石嘴山</item>\n        <item value=\"784\">吴忠</item>\n        <item value=\"785\">固原</item>\n        <item value=\"786\">中卫</item>\n    </string-array>\n    <string-array name=\"qinghai_province_item\">\n        <item value=\"787\">西宁</item>\n        <item value=\"788\">玉树藏族自...</item>\n        <item value=\"789\">海西蒙古族...</item>\n        <item value=\"790\">海北藏族自...</item>\n        <item value=\"791\">黄南藏族自...</item>\n        <item value=\"792\">海南藏族自... </item>\n        <item value=\"793\">果洛藏族自...</item>\n    </string-array>\n    <string-array name=\"shanxi1_province_item\">\n        <item value=\"794\">太原</item>\n        <item value=\"795\">大同</item>\n        <item value=\"796\">阳泉</item>\n        <item value=\"797\">长治</item>\n        <item value=\"798\">晋城</item>\n        <item value=\"799\">朔州</item>\n        <item value=\"800\">晋中</item>\n        <item value=\"801\">运城</item>\n        <item value=\"802\">忻州</item>\n        <item value=\"803\">临汾</item>\n        <item value=\"804\">吕梁</item>\n    </string-array>\n    <string-array name=\"shanxi2_province_item\">\n        <item value=\"805\">西安</item>\n        <item value=\"806\">宝鸡</item>\n        <item value=\"807\">咸阳</item>\n        <item value=\"808\">渭南</item>\n        <item value=\"809\">铜川</item>\n        <item value=\"810\">延安</item>\n        <item value=\"811\">榆林</item>\n        <item value=\"812\">汉中</item>\n        <item value=\"813\">安康</item>\n        <item value=\"814\">商洛</item>\n    </string-array>\n    <string-array name=\"sichuan_province_item\">\n        <item value=\"815\">成都</item>\n        <item value=\"816\">自贡</item>\n        <item value=\"817\">攀枝花</item>\n        <item value=\"818\">泸州</item>\n        <item value=\"819\">德阳</item>\n        <item value=\"820\">绵阳</item>\n        <item value=\"821\">阿坝藏族羌... </item>\n        <item value=\"822\">甘孜藏族自...</item>\n        <item value=\"823\">凉山彝族自... </item>\n        <item value=\"824\">眉山</item>\n        <item value=\"825\">广安</item>\n        <item value=\"826\">达州</item>\n        <item value=\"827\">雅安</item>\n        <item value=\"828\">巴中</item>\n        <item value=\"829\">资阳</item>\n        <item value=\"830\">广元</item>\n        <item value=\"831\">遂宁</item>\n        <item value=\"832\">内江</item>\n        <item value=\"833\">乐山</item>\n        <item value=\"834\">南充</item>\n        <item value=\"835\">宜宾</item>\n    </string-array>\n    <string-array name=\"tianjin_province_item\">\n        <item value=\"836\">和平区</item>\n        <item value=\"837\">河东区</item>\n        <item value=\"838\">河西区</item>\n        <item value=\"839\">南开区</item>\n        <item value=\"840\">河北区</item>\n        <item value=\"841\">红桥区</item>\n        <item value=\"842\">静海县</item>\n        <item value=\"843\">蓟县</item>\n        <item value=\"844\">东丽区</item>\n        <item value=\"845\">西青区</item>\n        <item value=\"846\">北辰区</item>\n        <item value=\"847\">武清区</item>\n        <item value=\"848\">宝坻区</item>\n        <item value=\"849\">宁河县</item>\n    </string-array>\n    <string-array name=\"xizang_province_item\">\n        <item value=\"850\">昌都地区</item>\n        <item value=\"851\">林芝地区 </item>\n        <item value=\"852\">山南地区 </item>\n        <item value=\"853\">日喀则地区 </item>\n        <item value=\"854\">那曲地区</item>\n        <item value=\"855\">阿里地区 </item>\n        <item value=\"856\">拉萨</item>\n    </string-array>\n    <string-array name=\"xinjiang_province_item\">\n        <item value=\"857\">克拉玛依</item>\n        <item value=\"858\">吐鲁番地区</item>\n        <item value=\"859\">哈密地区</item>\n        <item value=\"860\">阿克苏地区</item>\n        <item value=\"861\">喀什地区 </item>\n        <item value=\"862\">和田地区</item>\n        <item value=\"863\">巴州</item>\n        <item value=\"864\">昌吉</item>\n        <item value=\"865\">奎屯</item>\n        <item value=\"866\">石河子</item>\n        <item value=\"867\">伊犁</item>\n        <item value=\"868\">乌鲁木齐</item>\n        <item value=\"869\">阿勒泰地区</item>\n        <item value=\"870\">昌吉回族自...</item>\n        <item value=\"871\">博尔塔拉蒙...</item>\n        <item value=\"872\">巴音郭楞蒙...</item>\n        <item value=\"873\">克孜勒苏柯...</item>\n        <item value=\"874\">伊犁哈萨克...</item>\n    </string-array>\n    <string-array name=\"yunnan_province_item\">\n        <item value=\"875\">昆明</item>\n        <item value=\"876\">曲靖</item>\n        <item value=\"877\">玉溪</item>\n        <item value=\"878\">保山</item>\n        <item value=\"879\">昭通</item>\n        <item value=\"880\">丽江</item>\n        <item value=\"881\">西双版纳</item>\n        <item value=\"882\">德宏</item>\n        <item value=\"883\">怒江</item>\n        <item value=\"884\">迪庆</item>\n        <item value=\"885\">普洱</item>\n        <item value=\"886\">临沧</item>\n        <item value=\"887\">楚雄</item>\n        <item value=\"888\">大理</item>\n        <item value=\"889\">红河</item>\n        <item value=\"890\">文山</item>\n    </string-array>\n    <string-array name=\"zhejiang_province_item\">\n        <item value=\"891\">杭州</item>\n        <item value=\"892\">宁波</item>\n        <item value=\"893\">温州</item>\n        <item value=\"894\">嘉兴</item>\n        <item value=\"895\">湖州</item>\n        <item value=\"896\">绍兴</item>\n        <item value=\"897\">嵊州</item>\n        <item value=\"898\">温岭</item>\n        <item value=\"899\">萧山</item>\n        <item value=\"900\">义乌</item>\n        <item value=\"901\">永康</item>\n        <item value=\"902\">诸暨</item>\n        <item value=\"903\">富阳</item>\n        <item value=\"904\">海宁</item>\n        <item value=\"905\">乐清</item>\n        <item value=\"906\">临海</item>\n        <item value=\"907\">瑞安</item>\n        <item value=\"908\">上虞</item>\n        <item value=\"909\">金华</item>\n        <item value=\"910\">衢州</item>\n        <item value=\"911\">舟山</item>\n        <item value=\"912\">台州</item>\n        <item value=\"913\">丽水</item>\n        <item value=\"914\">东阳</item>\n    </string-array>\n    <string-array name=\"chongqing_province_item\">\n        <item value=\"915\">渝中区</item>\n        <item value=\"916\">大渡口区</item>\n        <item value=\"917\">江北区</item>\n        <item value=\"918\">沙坪坝区</item>\n        <item value=\"919\">合川区</item>\n        <item value=\"920\">渝北区</item>\n        <item value=\"921\">秀山县</item>\n        <item value=\"922\">巫溪县</item>\n        <item value=\"923\">巫山县</item>\n        <item value=\"924\">奉节县</item>\n        <item value=\"925\">武隆县</item>\n        <item value=\"926\">云阳县</item>\n        <item value=\"927\">石柱县</item>\n        <item value=\"928\">城口县</item>\n        <item value=\"929\">彭水县</item>\n        <item value=\"930\">梁平县</item>\n        <item value=\"931\">酉阳县</item>\n        <item value=\"932\">开县</item>\n        <item value=\"933\">大足区</item>\n        <item value=\"934\">荣昌县</item>\n        <item value=\"935\">璧山县</item>\n        <item value=\"936\">垫江县</item>\n        <item value=\"937\">丰都县</item>\n        <item value=\"938\">忠县</item>\n        <item value=\"939\">南岸区</item>\n        <item value=\"940\">长寿区</item>\n        <item value=\"941\">江津区</item>\n        <item value=\"942\">綦江区</item>\n        <item value=\"943\">潼南县</item>\n        <item value=\"944\">铜梁县</item>\n        <item value=\"945\">永川区</item>\n        <item value=\"946\">南川区</item>\n        <item value=\"947\">九龙坡区</item>\n        <item value=\"948\">万州区</item>\n        <item value=\"949\">涪陵区</item>\n        <item value=\"950\">黔江区</item>\n    </string-array>\n    <string-array name=\"taiwan_province_item\">\n        <item value=\"951\">台北</item>\n        <item value=\"952\">台南</item>\n        <item value=\"953\">高雄</item>\n        <item value=\"954\">台湾</item>\n    </string-array>\n    <string-array name=\"hongkong_province_item\">\n        <item value=\"955\">香港</item>\n    </string-array>\n    <string-array name=\"aomen_province_item\">\n        <item value=\"956\">澳门</item>\n    </string-array>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"ContactItemView\">\n        <attr name=\"contactItemImage\" format=\"reference\"/>\n        <attr name=\"contactItemName\" format=\"string\"/>\n    </declare-styleable>\n\n\n    <declare-styleable name=\"EaseChatMessageList\">\n        <attr name=\"msgListMyBubbleBackground\" format=\"reference\"/>\n        <attr name=\"msgListOtherBubbleBackground\" format=\"reference\"/>\n        <attr name=\"msgListShowUserAvatar\" format=\"boolean\"/>\n        <attr name=\"msgListShowUserNick\" format=\"boolean\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"EaseConversationList\">\n        <attr name=\"cvsListPrimaryTextColor\" format=\"color\"/>\n        <attr name=\"cvsListSecondaryTextColor\" format=\"color\"/>\n        <attr name=\"cvsListTimeTextColor\" format=\"color\"/>\n        <attr name=\"cvsListPrimaryTextSize\" format=\"dimension\"/>\n        <attr name=\"cvsListSecondaryTextSize\" format=\"dimension\"/>\n        <attr name=\"cvsListTimeTextSize\" format=\"dimension\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"EaseContactList\">\n        <attr name=\"ctsListPrimaryTextColor\" format=\"color\"/>\n        <attr name=\"ctsListPrimaryTextSize\" format=\"dimension\"/>\n        <attr name=\"ctsListShowSiderBar\" format=\"boolean\"/>\n        <attr name=\"ctsListInitialLetterBg\" format=\"reference|color\"/>\n        <attr name=\"ctsListInitialLetterColor\" format=\"color\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"EmojiconMenu\">\n        <attr name=\"bigEmojiconRows\" format=\"integer\"/>\n        <attr name=\"emojiconColumns\" format=\"integer\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"ChatExtendMenu\">\n        <attr name=\"numColumns\" format=\"integer\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"EaseTitleBar\">\n        <attr name=\"titleBarTitle\" format=\"string\"/>\n        <attr name=\"titleBarLeftImage\" format=\"reference\"/>\n        <attr name=\"titleBarRightImage\" format=\"reference\"/>\n        <attr name=\"titleBarBackground\" format=\"reference|color\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"SwitchButton\">\n        <attr name=\"switchOpenImage\" format=\"reference\"/>\n        <attr name=\"switchCloseImage\" format=\"reference\"/>\n        <attr name=\"switchStatus\">\n            <enum name=\"open\" value=\"0\"/>\n            <enum name=\"close\" value=\"1\"/>\n        </attr>\n    </declare-styleable>\n\n    <declare-styleable name=\"EaseImageView\">\n        <attr name=\"ease_border_color\" format=\"color\" />\n        <attr name=\"ease_border_width\" format=\"dimension\" />\n        <attr name=\"ease_press_alpha\" format=\"integer\" />\n        <attr name=\"ease_press_color\" format=\"color\" />\n        <attr name=\"ease_radius\" format=\"dimension\" />\n        <attr name=\"ease_shape_type\" format=\"enum\">\n            <enum name=\"none\" value=\"0\" />\n            <enum name=\"round\" value=\"1\" />\n            <enum name=\"rectangle\" value=\"2\" />\n        </attr>\n    </declare-styleable>\n    <declare-styleable name=\"SwipyRefreshLayout\">\n        <attr name=\"direction\">\n            <enum name=\"top\" value=\"0\" />\n            <enum name=\"bottom\" value=\"1\" />\n            <enum name=\"both\" value=\"2\" />\n        </attr>\n    </declare-styleable>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <color name=\"btn_pressed_green_solid\">#B6DA53</color>\n    <color name=\"common_top_bar\">#393A3F</color>\n    <color name=\"error_item_color\">#F6EBE6</color>\n    <color name=\"bottom_bar_normal_bg\">#fcfcfc</color>\n    <color name=\"btn_gray_normal\">#c0c0c0</color>\n    <color name=\"btn_gray_pressed\">#666667</color>\n    <color name=\"gray_normal\">#D4D4D4</color>\n\n    <color name=\"icon_press\">#AD9149</color>\n    <color name=\"icon_numal\">#88AD9149</color>\n\n    <color name=\"divider_list\">#d4d4d4</color>\n    <color name=\"gray_pressed\">#b5b5b6</color>\n    <color name=\"black_deep\">#FF000000</color>\n    <color name=\"holo_green_light\">#ff99cc00</color>\n\n    <color name=\"transparent\">#00000000</color>\n    <color name=\"black\">#ff000000</color>\n    <color name=\"white\">#ffffffff</color>\n    <color name=\"gray\">#666666</color>\n    <!-- [begin]crop -->\n    <color name=\"crop__button_bar\">#f3f3f3</color>\n    <color name=\"crop__button_text\">#666666</color>\n    <color name=\"crop__selector_pressed\">#1a000000</color>\n    <color name=\"crop__selector_focused\">#77000000</color>\n    <!-- [end]crop -->\n\n    <!--Theme-->\n    <!--Theme-->\n    <color name=\"light_grey\">#ffbebebe</color>\n\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303030</color>\n    <color name=\"colorAccent\">#FF4081</color>\n\n    <color name=\"splash_bg\">#D3B548</color>\n    <color name=\"main_bottom_bg\">#fcfcfc</color>\n    <color name=\"main_bottom_split\">#D4D4D4</color>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n\n     <dimen name=\"height_top_bar\">48dp</dimen>\n    <dimen name=\"size_avatar\">48dp</dimen>\n    <dimen name=\"margin_chat_activity\">5dp</dimen>\n    <dimen name=\"chat_nick_margin_left\">17dp</dimen>\n    <dimen name=\"chat_nick_text_size\">12sp</dimen>\n\n    <dimen name=\"sider_bar_textsize\">18sp</dimen>\n    <dimen name=\"emoji_size\">18sp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!--通知-->\n    <!--<string name=\"has_more_msg\"> %1个联系人发来%2条消息</string>-->\n    <string name=\"zhongkuohao\">[</string>\n    <string name=\"zhongkuohao_msg\">条]</string>\n\n    <string name=\"app_name\">YiChatLite</string>\n    <string name=\"app_chat\">会话</string>\n    <string name=\"text_ack_msg\">已读</string>\n    <string name=\"text_delivered_msg\">送达</string>\n    <string name=\"button_pushtotalk\">按住说话</string>\n    <string name=\"button_send\">发送</string>\n    <string name=\"attach_picture\">图片</string>\n    <string name=\"attach_take_pic\">拍照</string>\n    <string name=\"address_book\">通讯录</string>\n    <string name=\"move_up_to_cancel\">手指上滑，取消发送</string>\n    <string name=\"release_to_cancel\">松开手指，取消发送</string>\n    <string name=\"button_logout\">退出登录</string>\n    <string name=\"ok\">确定</string>\n    <string name=\"cancel\">取消</string>\n    <string name=\"prompt\">提示</string>\n    <string name=\"search_header\">搜</string>\n    <string name=\"recoding_fail\">录音失败，请重试！</string>\n    <string name=\"connect_conflict\">同一帐号已在其他设备登录</string>\n    <string name=\"set\">设置</string>\n    <string name=\"notify\">新消息提醒</string>\n    <string name=\"newnotify\">开启新消息通知</string>\n    <string name=\"notify_set\">新消息设置</string>\n    <string name=\"numal_set\">常用设置</string>\n    <string name=\"voice\">声音</string>\n    <string name=\"shake\">震动</string>\n    <string name=\"chatset\">聊天设置</string>\n    <string name=\"yangshengqi\">使用扬声器播放语音</string>\n    <string name=\"book_black\">通讯录黑名单</string>\n    <string name=\"diagnose\">诊断</string>\n    <string name=\"push_nick\">iOS离线推送昵称</string>\n\n    <string name=\"sd_card_does_not_exist\">SD卡不存在，不能拍照</string>\n    <string name=\"cant_find_pictures\">找不到图片</string>\n    <string name=\"Send_voice_need_sdcard_support\">发送语音需要sdcard支持</string>\n    <string name=\"Recording_without_permission\">无录音权限</string>\n    <string name=\"The_recording_time_is_too_short\">录音时间太短</string>\n    <string name=\"send_failure_please\">发送失败，请检测服务器是否连接</string>\n    <string name=\"Login_failed\">登录失败</string>\n    <string name=\"Logoff_notification\">下线通知</string>\n    <string name=\"Are_logged_out\">正在退出登录..</string>\n    <string name=\"Is_download_voice_click_later\">正在下载语音，稍后点击</string>\n    <string name=\"were_mentioned\">[有人@我]</string>\n\n    <string name=\"chatroom_allow_owner_leave\"> 允许聊天室群主离开</string>\n    <string name=\"title_user_profile\">个人资料</string>\n\n    <string name=\"Days_ago\">天前</string>\n    <string name=\"An_hour_ago\">小时前</string>\n    <string name=\"just\">刚刚</string>\n    <string name=\"copy\">复制</string>\n    <string name=\"delete\">删除</string>\n    <string name=\"the_current_network\">当前网络不可用，请检查网络设置</string>\n    <string name=\"delete_msg_when_exit_group\">退出群组时删除聊天数据</string>\n    <string name=\"auto_accept_group_invitation\">自动同意群组加群邀请</string>\n    <string name=\"adaptive_video_encode\">视频自适应码率编码</string>\n    <!--ANyRTC相关-->\n    <string name=\"str_connect_hoster\">连麦</string>\n    <string name=\"str_send\">发送</string>\n    <!--登录-->\n    <string name=\"logining\">登录中...</string>\n    <string name=\"Account_does_not_exist\">账号不存在</string>\n    <string name=\"Incorrect_password\">密码不正确</string>\n    <string name=\"Account_has_been_disabled\">账号已被禁用</string>\n    <string name=\"Server_busy\">服务器繁忙请重试...</string>\n    <string name=\"login_success\">登录成功</string>\n    <string name=\"tel_is_not_allow_null\">手机号不能为空</string>\n    <string name=\"pwd_is_not_allow_null\">密码不能为空</string>\n    <string name=\"please_input_true_mobile\">请输入正确的手机号码!</string>\n    <string name=\"Incorrect_phone_number_format\">手机号码格式不正确!</string>\n    <!--注册-->\n    <string name=\"i_am\">我是</string>\n    <string name=\"press_top\">点击上面的</string>\n    <string name=\"btn_means_agree\">按钮,即表示你同意</string>\n    <string name=\"Secret_agreement\">《YiChat软件许可及服务协议》</string>\n    <string name=\"login\">登录</string>\n    <string name=\"password\">密码</string>\n    <string name=\"register\">用户注册</string>\n    <string name=\"confirmpassword\">确认密码</string>\n    <string name=\"nickname\">昵称</string>\n    <string name=\"code_is_send\">验证码已经发送</string>\n    <string name=\"has_code\">获取验证码</string>\n    <string name=\"Two_input_password\">两次输入的密码不一致，请重新输入!</string>\n    <string name=\"Is_the_registered\">正在注册...</string>\n    <string name=\"Registered_successfully\">注册成功!</string>\n    <string name=\"Registration_failed\">注册失败!</string>\n    <string name=\"country_code\">+86</string>\n    <string name=\"are_reset_password\">正在重置密码...</string>\n    <string name=\"password_reset_success\">密码重置成功！</string>\n    <string name=\"password_reset_failed\">密码重置失败!</string>\n    <string name=\"new_password_cannot_be_empty\">新密码不能为空!</string>\n    <string name=\"mobile_not_be_null\">手机号不能为空</string>\n    <string name=\"mobile_is_register\">该手机号码已被注册...</string>\n    <string name=\"image_manager\">相册</string>\n    <string name=\"Initiate_group_chat\">发起群聊</string>\n    <string name=\"scanning\">扫一扫</string>\n    <string name=\"new_friend\">新的朋友</string>\n    <string name=\"add_friend\">添加好友</string>\n    <string name=\"me\">我</string>\n    <string name=\"bottom_find\">发现</string>\n    <string name=\"secret_signal_or_phone_number\">YiChat号/手机号</string>\n    <string name=\"countries_and_regions\">国家</string>\n    <string name=\"china\">中国</string>\n    <string name=\"you_mobile\">你的手机号码</string>\n    <string name=\"input_pwd\">填写密码</string>\n    <string name=\"find_pwd\">找回密码</string>\n    <string name=\"login_by_mobile\">使用手机号登录</string>\n    <string name=\"example\">例如：陈晨</string>\n    <string name=\"Verification_Code\">验证码</string>\n    <string name=\"new_password\">新密码</string>\n    <string name=\"Head_portrait\">头像</string>\n    <string name=\"sex\">性别</string>\n    <string name=\"male\">男</string>\n    <string name=\"female\">女</string>\n    <string name=\"Personal_signature\">个性签名</string>\n    <string name=\"modify_name\">更改名字</string>\n    <string name=\"Detailed_information\">详细资料</string>\n    <string name=\"mobile\">手机号</string>\n    <string name=\"send_msg\">发送消息</string>\n    <string name=\"add_to_contacts\">添加到通讯录</string>\n    <string name=\"pass_or_no_by_send\">你需要发送验证申请，等对方通过</string>\n\n    <string name=\"group_chat\">群聊</string>\n\n    <string name=\"send_successful\">发送请求成功,等待对方验证</string>\n    <string name=\"Request_add_buddy_failure\">请求添加好友失败!</string>\n    <string name=\"Refused\">已拒绝</string>\n    <string name=\"Move_into_blacklist_success\">移入黑名单成功</string>\n    <string name=\"Move_into_blacklist_failure\">移入黑名单失败</string>\n    <string name=\"deleting\">正在删除...</string>\n    <string name=\"Delete_failed\">删除失败:</string>\n    <string name=\"Is_moved_into_blacklist\">正在移入黑名单...</string>\n    <string name=\"Is_sending_a_request\">正在发送请求...</string>\n    <string name=\"can_not_connect_chat_server_connection\">连接不到聊天服务器</string>\n    <string name=\"Into_the_blacklist\">移入到黑名单？</string>\n    <string name=\"Has_agreed_to_your_friend_request\">已同意你的好友请求</string>\n    <string name=\"Request_to_add_you_as_a_friend\">请求加你为好友</string>\n    <string name=\"Are_agree_with\">正在同意...</string>\n\n    <string name=\"Delete_the_contact\">删除联系人</string>\n\n    <string name=\"update_success\">更新成功</string>\n\n    <string name=\"app_id\">YiChat号：</string>\n    <string name=\"me_yichat_number\">我的YiChat号:</string>\n    <string name=\"not_set\">未设置</string>\n    <string name=\"region\">地区</string>\n    <string name=\"country\">国家或地区</string>\n    <string name=\"yichat_number\">YiChat号</string>\n    <string name=\"now_refresh_msg\">正在加载资料...</string>\n    <string name=\"are_finding_contact\">正在查找联系人...</string>\n    <string name=\"User_does_not_exis\">用户不存在</string>\n    <string name=\"server_is_busy_try_again\"> 服务器繁忙请重试...</string>\n    <string name=\"search\">搜索</string>\n    <string name=\"are_uploading\">正在更新...</string>\n    <string name=\"upload_failed\">更新失败,code:</string>\n    <string name=\"not_input\">未填写</string>\n    <string name=\"change_nick\">修改昵称</string>\n    <string name=\"change_mixin\">修改YiChat号</string>\n    <string name=\"change_personalized_signature\">修改个人签名</string>\n    <string name=\"mixin_can_not_has_chinese\">YiChat名不能包含中文</string>\n    <string name=\"string_not_30\">不能超过30个字符</string>\n    <string name=\"scan_title\">\"二维码/条码 扫描\"</string>\n    <string name=\"Scanning\">扫描中...</string>\n    <string name=\"code_is_not_invlide\">无效二维码</string>\n    <string name=\"scanning_image\">扫面二维码图片</string>\n    <string name=\"reset_scan\">重置扫描</string>\n    <string name=\"me_qrcode\">我的身份二维码</string>\n    <string name=\"scan_msg\">可进行二维码或条形码扫描\\n请使用下方扫描框对准商户终端二维码\\n或者机具条形码进行扫描</string>\n    <string name=\"request_add_friend\">请求加为好友</string>\n    <string name=\"add_friend_success\">同意好友成功！</string>\n    <string name=\"add_friend_failed\">同意好友失败</string>\n    <string name=\"already_rejected\">已拒绝你的好友申请</string>\n    <string name=\"Reasons\">申请理由：</string>\n    <string name=\"Already_added\">已添加</string>\n    <string name=\"accept\">接受</string>\n    <string name=\"has_rejected\">被拒绝</string>\n    <string name=\"save\">保存</string>\n    <string name=\"good_name\">好名字可以让你的好朋友更容易记得你</string>\n    <string name=\"logout_failed\">退出登录失败!</string>\n    <!--自动更新-->\n    <string name=\"check_update\">检查更新</string>\n    <string name=\"are_checking_update\">正在查询更新...</string>\n    <string name=\"has_update\">有新版本</string>\n    <string name=\"just_new_version\">已经是最新版本了!</string>\n    <string name=\"update_now\">现在升级</string>\n    <string name=\"update_later\">以后再说</string>\n    <!--好友圈-->\n    <string name=\"Circle_of_friends\">朋友圈</string>\n    <string name=\"resetPassword\">重置密码</string>\n    <string name=\"input_bind_mobile\">请输入登录手机号</string>\n\n    <!--关于活动-->\n\n    <string name=\"loading\">正在加载....</string>\n    <string name=\"delete_sucess\">删除成功!</string>\n    <string name=\"chat_msg\">聊天信息</string>\n\n    <string name=\"keep_live_setting\">体验Pro版</string>\n    <string name=\"donation_git\">Github开源地址</string>\n    <string name=\"donation_kaiyuan\">开源中国开源地址</string>\n    <string name=\"donation\">码云开源地址</string>\n    <string name=\"update_has\">现在升级(强制更新)</string>\n    <string name=\"forward\">转发</string>\n    <string name=\"reback\">撤回</string>\n    <string name=\"really_copy_and_send\">确定复制并发送这条消息吗?</string>\n    <string name=\"rebacking\">正在撤回...</string>\n    <string name=\"reback_failed\">撤回失败!</string>\n    <string name=\"reback_not_more_than_30\">超过2分钟的消息不支持撤回!</string>\n    <string name=\"copying\">正在复制...</string>\n    <string name=\"copy_success\">复制成功!</string>\n    <string name=\"copy_failed\">复制失败!</string>\n    <string name=\"please_check_contant\">请选择联系人!</string>\n    <string name=\"forword_people\">确定转发给1人吗?</string>\n    <string name=\"forword_always\">确定转发这条消息?</string>\n    <string name=\"forword_get\">获取转发信息中....</string>\n    <string name=\"resend_text\">重新发送这条消息吗?</string>\n    <string name=\"stick_conversation\">置顶会话</string>\n    <string name=\"cancle_stick_conversation\">取消置顶</string>\n    <string name=\"not_more_msg\">暂无更多消息!</string>\n    <string name=\"permission_ok\">get the permission successfull </string>\n    <string name=\"permission_error\">获取权限失败</string>\n    <string name=\"no_permission_camera\">未授权的权限</string>\n    <string name=\"people_time\">找一找</string>\n    <string name=\"load_failed\">加载失败,请重试!</string>\n    <string name=\"load_more_failed\">暂无更多数据!</string>\n    <string name=\"close_app\">关闭YiChat</string>\n    <string name=\"exit_this_user\">退出当前账号</string>\n    <string name=\"just_15\">15分钟前</string>\n    <string name=\"just_30\">30分钟前</string>\n    <string name=\"just_1hour\">1小时前</string>\n    <string name=\"more_people\">个联系人</string>\n    <string name=\"open_notice\">Open source version only single chat, no group chat!</string>\n    <string name=\"wait_do\">Waiting to do somethings!</string>\n    <string name=\"revoke_content_ed\">对方撤回了一条消息</string>\n    <string name=\"revoke_content\">你撤回了一条消息</string>\n    <string name=\"revoke_content_someone\">%s撤回了一条消息</string>\n\n</resources>\n\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- 右上角popupwindow -->\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n    <style name=\"HAppTheme\" parent=\"Theme.AppCompat.NoActionBar\" />\n\n\n    <style name=\"AppTheme\" parent=\"android:Theme.Light\" />\n\n\n    <style name=\"chat_content_date_style\">\n        <item name=\"android:minHeight\">50dp</item>\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:textColor\">#000000</item>\n        <item name=\"android:textSize\">15sp</item>\n        <item name=\"android:lineSpacingExtra\">2dp</item>\n        <item name=\"android:background\">#bfbfbf</item>\n    </style>\n\n    <style name=\"chat_text_name_style\">\n        <item name=\"android:textColor\">#818181</item>\n        <item name=\"android:textSize\">15sp</item>\n        <item name=\"android:gravity\">center</item>\n    </style>\n\n    <style name=\"chat_text_date_style\">\n        <item name=\"android:padding\">2dp</item>\n        <item name=\"android:paddingTop\">2dip</item>\n        <item name=\"android:paddingBottom\">2dip</item>\n        <item name=\"android:paddingLeft\">12dip</item>\n        <item name=\"android:paddingRight\">12dip</item>\n        <item name=\"android:layout_marginLeft\">40dip</item>\n        <item name=\"android:layout_marginRight\">40dip</item>\n        <item name=\"android:textColor\">@color/btn_gray_normal</item>\n        <item name=\"android:textSize\">12sp</item>\n        <item name=\"android:background\">@drawable/timestampe_bg</item>\n    </style>\n\n    <style name=\"AnimFade\" parent=\"@android:style/Animation.Activity\">\n        <item name=\"android:activityOpenEnterAnimation\">@anim/fade_in</item>\n        <item name=\"android:activityOpenExitAnimation\">@anim/hold</item>\n        <item name=\"android:activityCloseExitAnimation\">@anim/fade_out</item>\n    </style>\n\n    <style name=\"AnimFade2\" parent=\"@android:style/Animation.Activity\">\n        <item name=\"android:activityOpenEnterAnimation\">@anim/slide_in_from_right</item>\n        <item name=\"android:activityOpenExitAnimation\">@anim/slide_out_to_left</item>\n        <item name=\"android:activityCloseExitAnimation\">@anim/slide_out_to_right</item>\n        <item name=\"android:activityCloseEnterAnimation\">@anim/slide_in_from_left</item>\n    </style>\n\n    <style name=\"AnimBottom\" parent=\"@android:style/Animation\">\n        <item name=\"android:windowEnterAnimation\">@anim/push_bottom_in</item>\n        <item name=\"android:windowExitAnimation\">@anim/push_bottom_out</item>\n    </style>\n\n    <style name=\"AnimTop\" parent=\"@android:style/Animation\">\n        <item name=\"android:windowEnterAnimation\">@anim/push_top_in</item>\n        <item name=\"android:windowExitAnimation\">@anim/push_top_out</item>\n    </style>\n\n    <style name=\"AnimTop2\" parent=\"@android:style/Animation\">\n        <item name=\"android:windowEnterAnimation\">@anim/push_top_in2</item>\n        <item name=\"android:windowExitAnimation\">@anim/push_top_out2</item>\n    </style>\n\n    <style name=\"AnimHead\" parent=\"@android:style/Animation\">\n        <item name=\"android:windowEnterAnimation\">@anim/head_in</item>\n        <item name=\"android:windowExitAnimation\">@anim/head_out</item>\n    </style>\n\n    <style name=\"Anim_style\" parent=\"android:Theme.NoTitleBar.Fullscreen\">\n        <item name=\"android:windowAnimationStyle\">@style/AnimFade</item>\n    </style>\n\n    <style name=\"Anim_style2\" parent=\"android:Theme.NoTitleBar\">\n        <item name=\"android:windowAnimationStyle\">@style/AnimFade</item>\n    </style>\n\n    <style name=\"horizontal_slide\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"android:windowAnimationStyle\">@style/AnimFade2</item>\n    </style>\n\n    <style name=\"nornal_style\" parent=\"android:Theme.NoTitleBar\"></style>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme2\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n    <style name=\"AppTheme2.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme2.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n\n    <style name=\"AppTheme2.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n\n    <!--\n    <style name=\"horizontal_slide2\" parent=\"android:style/Theme.Holo.Light.NoActionBar\">\n        <item name=\"android:windowAnimationStyle\">@style/AnimFade2</item>\n    </style>\n    -->\n\n\n    <style name=\"MyAlertDialog\" parent=\"android:Theme.Dialog\">\n        <item name=\"android:windowBackground\">@android:color/transparent</item>\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <item name=\"android:windowNoTitle\">true</item>\n        <item name=\"android:windowContentOverlay\">@null</item>\n    </style>\n\n    <style name=\"MyDialogStyleBottom\" parent=\"android:Theme.Dialog\">\n        <item name=\"android:windowAnimationStyle\">@style/AnimBottom</item>\n        <item name=\"android:windowFrame\">@null</item>\n        <!-- 边框 -->\n        <item name=\"android:windowIsFloating\">true</item>\n        <!-- 是否浮现在activity之上 -->\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <!-- 半透明 -->\n        <item name=\"android:windowNoTitle\">true</item>\n        <!-- 无标题 -->\n        <item name=\"android:windowBackground\">@android:color/transparent</item>\n        <!-- 背景透明 -->\n        <item name=\"android:backgroundDimEnabled\">true</item>\n        <!-- 模糊 -->\n    </style>\n\n    <style name=\"MyDialogStyleTop\" parent=\"android:Theme.Dialog\">\n        <item name=\"android:windowAnimationStyle\">@style/AnimTop2</item>\n        <item name=\"android:windowFrame\">@null</item>\n        <!-- 边框 -->\n        <item name=\"android:windowIsFloating\">true</item>\n        <!-- 是否浮现在activity之上 -->\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <!-- 半透明 -->\n        <item name=\"android:windowNoTitle\">true</item>\n        <!-- 无标题 -->\n        <item name=\"android:windowBackground\">@android:color/transparent</item>\n        <!-- 背景透明 -->\n        <item name=\"android:backgroundDimEnabled\">false</item>\n        <!-- 模糊 -->\n    </style>\n\n    <style name=\"HeadScale\" parent=\"android:Theme.Dialog\">\n        <item name=\"android:windowAnimationStyle\">@style/AnimHead</item>\n        <item name=\"android:windowFrame\">@null</item>\n        <!-- 边框 -->\n        <item name=\"android:windowIsFloating\">true</item>\n        <!-- 是否浮现在activity之上 -->\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <!-- 半透明 -->\n        <item name=\"android:windowNoTitle\">true</item>\n        <!-- 无标题 -->\n        <item name=\"android:windowBackground\">@android:color/black</item>\n        <item name=\"android:backgroundDimEnabled\">false</item>\n        <!-- 模糊 -->\n    </style>\n\n    <!--更新的dialog-->\n    <style name=\"updateDialogStyle\" parent=\"Theme.AppCompat.Light.Dialog\">\n        <item name=\"android:windowFrame\">@null</item>\n        <item name=\"android:windowNoTitle\">true</item>\n        <item name=\"android:windowBackground\">@color/transparent</item>\n        <item name=\"android:windowIsFloating\">true</item> <!--是否浮在界面上-->\n        <item name=\"android:windowIsTranslucent\">true</item> <!-- 半透明 -->\n        <item name=\"android:colorBackgroundCacheHint\">@color/transparent</item>\n        <item name=\"android:windowContentOverlay\">@color/transparent</item><!-- 这两个属性不加上顶部会出现阴影 -->\n        <item name=\"android:windowActionModeOverlay\">true</item>\n    </style>\n\n\n    <style name=\"bottom_line_edit_text_style\" parent=\"@android:style/Widget.EditText\">\n        <item name=\"android:gravity\">center_vertical</item>\n        <item name=\"android:paddingLeft\">6.0dip</item>\n        <item name=\"android:paddingTop\">6.0dip</item>\n        <item name=\"android:paddingRight\">6.0dip</item>\n        <item name=\"android:paddingBottom\">6.0dip</item>\n        <item name=\"android:includeFontPadding\">false</item>\n        <item name=\"android:background\">@drawable/edit_text_bg</item>\n    </style>\n    <!-- 自定义loading dialog -->\n    <style name=\"loading_dialog\" parent=\"android:style/Theme.Dialog\">\n        <item name=\"android:windowFrame\">@null</item>\n        <item name=\"android:windowNoTitle\">true</item>\n        <item name=\"android:windowBackground\">@android:color/transparent</item>\n        <item name=\"android:windowIsFloating\">true</item>\n        <item name=\"android:windowContentOverlay\">@null</item>\n    </style>\n    <!--自定义圆形进度条-->\n    <style name=\"mProgress_circle\">\n        <item name=\"android:indeterminateDrawable\">@drawable/progressbar_white</item>\n        <item name=\"android:maxWidth\">60dp</item>\n        <item name=\"android:maxHeight\">60dp</item>\n    </style>\n    <!--直播样式-->\n\n\n    <style name=\"PopupMenu\" parent=\"ThemeOverlay.AppCompat.Light\" >\n        <item name=\"android:colorBackground\">@color/common_top_bar</item>\n        <item name=\"android:textColor\">@android:color/white</item>\n        <item name=\"overlapAnchor\">false</item>\n\n    </style>\n\n    <style name=\"Toolbar\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"actionOverflowButtonStyle\">@style/ActionButton.Overflow.yichat</item>\n    </style>\n\n    <style name=\"ActionButton.Overflow.yichat\" parent=\"android:style/Widget.Holo.Light.ActionButton.Overflow\">\n        <item name=\"android:src\">@drawable/icon_add_normal</item>\n        <!-- 用于修改item默认的分割线-->\n        <item name=\"android:dropDownListViewStyle\">@style/dropDownStyle</item>\n        <item name=\"dropDownListViewStyle\">@style/dropDownStyle</item>\n\n\n    </style>\n\n    <style name=\"Theme.ToolBar.Menu\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n\n        <!-- 设置-弹窗的背景-颜色-->\n        <item name=\"android:colorBackground\">@color/common_top_bar</item>\n        <!-- 字体的颜色-->\n        <item name=\"android:textColor\">#ffffff</item>\n        <!-- 字体大小-->\n        <item name=\"android:textSize\">16sp</item>\n\n        <!-- 用于替换菜单的三个小白点，换成自已的图片-->\n        <item name=\"actionOverflowButtonStyle\">@style/ActionButton.Overflow.Menu</item>\n\n        <!--用于控制menu弹出的位置，位于toolbar的下面，而不是上面-->\n        <item name=\"actionOverflowMenuStyle\">@style/OverflowMenuStyle</item>\n\n        <!-- 用于修改item默认的分割线-->\n        <item name=\"android:dropDownListViewStyle\">@style/dropDownStyle</item>\n        <item name=\"dropDownListViewStyle\">@style/dropDownStyle</item>\n\n        <!-- 用于控件popmenu的宽度-->\n        <!--<item name=\"android:width\">150dp</item>-->\n\n    </style>\n\n    <style name=\"ActionButton.Overflow.Menu\" parent=\"android:style/Widget.Holo.Light.ActionButton.Overflow\">\n        <item name=\"android:src\">@drawable/icon_add_normal</item>\n\n    </style>\n    <!--把该属性改为false即可使menu位置位于toolbar之下-->\n    <style name=\"OverflowMenuStyle\" parent=\"Widget.AppCompat.Light.PopupMenu.Overflow\">\n        <item name=\"overlapAnchor\">false</item>\n    </style>\n\n    <!--用于修改popmenu的分割线-->\n    <style name=\"dropDownStyle\" parent=\"android:style/Widget.Holo.ListView.DropDown\">\n        <item name=\"android:listSelector\">@color/colorPrimaryDark</item>\n        <item name=\"android:divider\">@color/black_deep</item>\n        <item name=\"android:dividerHeight\">0.5dp</item>\n    </style>\n\n    <style name=\"popupTextProfile\" parent=\"@style/TextAppearance.Widget.AppCompat.ExpandedMenu.Item\">\n        <item name=\"android:textColor\">@android:color/white</item>\n    </style>\n </resources>"
  },
  {
    "path": "app/src/main/res/values-hdpi/dimens.xml",
    "content": "<resources>\n\n    <dimen name=\"sider_bar_textsize\">14sp</dimen>\n    <dimen name=\"emoji_size\">19sp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-v21/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"horizontal_slide\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"android:statusBarColor\">#303135</item>\n        <item name=\"android:windowAnimationStyle\">@style/AnimFade2</item>\n    </style>\n</resources>"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.3'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n\n    }\n}\n\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri Jun 09 16:25:15 CST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.3-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "## Project-wide Gradle settings.\n#\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n#\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx1024m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n#\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n#Tue May 23 16:51:55 CST 2017\nsystemProp.http.proxyHost=127.0.0.1\norg.gradle.jvmargs=-Xmx1536m\nsystemProp.http.proxyPort=1080\nandroid.useDeprecatedNdk=true\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\n"
  }
]